Example #1
0
static int charset_processing(Msg *msg) 
{
    gw_assert(msg->type == sms);

    /* URL-decode first */
    if (octstr_url_decode(msg->sms.msgdata) == -1)
        return -1;
    if (octstr_url_decode(msg->sms.udhdata) == -1)
        return -1;
        
    /* If a specific character encoding has been indicated by the
     * user, then make sure we convert to our internal representations. */
    if (octstr_len(msg->sms.charset)) {
    
        if (msg->sms.coding == DC_7BIT) {
            /* For 7 bit, convert to UTF-8 */
            if (charset_convert(msg->sms.msgdata, octstr_get_cstr(msg->sms.charset), "UTF-8") < 0)
                return -1;
        } 
        else if (msg->sms.coding == DC_UCS2) {
            /* For UCS-2, convert to UTF-16BE */
            if (charset_convert(msg->sms.msgdata, octstr_get_cstr(msg->sms.charset), "UTF-16BE") < 0) 
                return -1;
        }
    }
    
    return 0;
}
Example #2
0
char *substr(const char *pstr, int start, int numchars)
{
    static char pnew[512];
    wchar_t *wc;
    char *wchar_type;
    char *c;
    memset(pnew, 0, sizeof(pnew));
    if (numchars < (int) sizeof(pnew))
    {
#ifdef _WIN32
        wchar_type = (sizeof(wchar_t) == 2) ? 
                    "UCS-2-INTERNAL" : "UCS-4-INTERNAL";
#else
        wchar_type = "WCHAR_T";
#endif
        wc = (wchar_t *) charset_convert((char *) pstr + start, 
                numchars, "UTF-8", wchar_type);
        c = charset_convert((char *) wc, 
                wcslen(wc) * sizeof(wchar_t), wchar_type, "UTF-8");
        strcpy(pnew, c);
        free(wc);
        free(c);
        return pnew;
    }
    return pnew;
}
Example #3
0
static void handle_status_update_track_callback(char *filename, int current_track, int total_tracks)
{
#ifdef _WIN32
    wchar_t *wide_filename = (wchar_t *) charset_convert(filename, strlen(filename), "UTF-8", sizeof(wchar_t) == 2 ? "UCS-2-INTERNAL" : "UCS-4-INTERNAL");
#else
    wchar_t *wide_filename = (wchar_t *) charset_convert(filename, strlen(filename), "UTF-8", "WCHAR_T");
#endif
    safe_fwprintf(stdout, L"\rProcessing [%ls] (%d/%d)..\n", wide_filename, current_track, total_tracks);
    free(wide_filename);
}
Example #4
0
/**
 * Get compile error info from SCU
 * @param bott      Result bott file
 * @return Compile error info
 */
string SCUJudger::getCEinfo(Bott * bott)
{
	prepareCurl();
	curl_easy_setopt(curl, CURLOPT_URL,
			 ("http://cstest.scu.edu.cn/soj/judge_message.action?id="
			  + bott->Getremote_runid()).c_str());
	performCurl();

	string info = loadAllFromFile(tmpfilename);
	string result;

	char *ce_info = new char[info.length() + 1];
	strcpy(ce_info, info.c_str());
	char *buffer = new char[info.length() * 2];
	// SCU is in GBK charset
	charset_convert("GBK", "UTF-8//TRANSLIT", ce_info, info.length() + 1,
			buffer, info.length() * 2);

	if (!RE2::PartialMatch(buffer, "(?s)<pre>(.*?)</pre>", &result)) {
		return "";
	}

	strcpy(buffer, result.c_str());
	decode_html_entities_utf8(buffer, NULL);
	result = buffer;
	delete[]ce_info;
	delete[]buffer;

	return result;
}
/**
 * Get compile error info
 * @param bott      Result bott file
 * @return Compile error info
 */
string NJUPTJudger::getCEinfo(Bott * bott)
{

	prepareCurl();
	curl_easy_setopt(curl, CURLOPT_URL,
			 ("http://acm.njupt.edu.cn/acmhome/compileError.do?id="
			  + bott->Getremote_runid()).c_str());
	performCurl();

	string info = loadAllFromFile(tmpfilename);
	string result;
	char *ce_info = new char[info.length() + 1];
	strcpy(ce_info, info.c_str());
	char *buffer = new char[info.length() * 2];
	// SCU is in GBK charset
	charset_convert("GBK", "UTF-8//TRANSLIT", ce_info, info.length() + 1,
			buffer, info.length() * 2);

	if (!RE2::PartialMatch(buffer,
			       "(?s)Details of Compile Error</strong></h2></div>(.*)<div align=\"center\">",
			       &result)) {
		return "";
	}

	strcpy(buffer, result.c_str());
	decode_html_entities_utf8(buffer, NULL);
	result = buffer;
	delete[]ce_info;
	delete[]buffer;

	return trim(result);
}
Example #6
0
gchar *eucjp_to_utf8(const gchar *eucjp) {
    gchar *utf8;
    g_return_val_if_fail(eucjp, NULL);

    /* XXX: must check wheter eucjp is really EUC-JP */
    utf8 = charset_convert(eucjp, "EUC-JP", "UTF-8");
    return utf8;
}
Example #7
0
gchar *utf8_to_eucjp(const gchar *utf8) {
    gchar *eucjp = NULL;
    g_return_val_if_fail(utf8, NULL);

    if (g_utf8_validate(utf8, -1, NULL)) {
	eucjp = charset_convert(utf8, "UTF-8", "EUC-JP");
    }

    /* XXX: must prepare fallbacks */
    return eucjp;
}
Example #8
0
static int httpsmsc_send(SMSCConn *conn, Msg *msg)
{
    ConnData *conndata = conn->data;
    Msg *sms;


    /* don't crash if no send_sms handle defined */
    if (!conndata || !conndata->callbacks->send_sms)
        return -1;

    sms = msg_duplicate(msg);
    /* convert character encoding if required */
    if (msg->sms.coding == DC_7BIT && conndata->alt_charset &&
        charset_convert(sms->sms.msgdata, DEFAULT_CHARSET,
                        octstr_get_cstr(conndata->alt_charset)) != 0) {
        error(0, "Failed to convert msgdata from charset <%s> to <%s>, will send as is.",
              DEFAULT_CHARSET, octstr_get_cstr(conndata->alt_charset));
    }

    gwlist_produce(conndata->msg_to_send, sms);

    return 0;
}
Example #9
0
static int calculate_header_and_footer(scarletbook_output_format_t *ft)
{
    form_dsd_chunk_t *form_dsd_chunk;
    property_chunk_t *property_chunk;
    uint8_t          *write_ptr, *prop_ptr;
    scarletbook_handle_t *sb_handle = ft->sb_handle;
    dsdiff_handle_t  *handle = (dsdiff_handle_t *) ft->priv;

    if (!handle->header)
        handle->header = (uint8_t *) calloc(DSDFIFF_BUFFER_SIZE, 1);
    if (!handle->footer)
        handle->footer = (uint8_t *) calloc(DSDFIFF_BUFFER_SIZE, 1);

    write_ptr = handle->header;

    // The Form DSD Chunk is required. It may appear only once in the file.
    form_dsd_chunk            = (form_dsd_chunk_t *) handle->header;
    form_dsd_chunk->chunk_id  = FRM8_MARKER;
    form_dsd_chunk->form_type = DSD_MARKER;
    write_ptr                 = (uint8_t *) handle->header + FORM_DSD_CHUNK_SIZE;

    // The Format Version Chunk is required and must be the first chunk in the Form DSD
    // Chunk. It may appear only once in the Form DSD Chunk.
    {
        format_version_chunk_t *format_version_chunk = (format_version_chunk_t *) write_ptr;
        format_version_chunk->chunk_id        = FVER_MARKER;
        format_version_chunk->chunk_data_size = CALC_CHUNK_SIZE(FORMAT_VERSION_CHUNK_SIZE - CHUNK_HEADER_SIZE);
        format_version_chunk->version         = hton32(DSDIFF_VERSION);
        write_ptr                            += FORMAT_VERSION_CHUNK_SIZE;
    }

    // The Property Chunk is required and must precede the Sound Data Chunk. It may appear
    // only once in the Form DSD Chunk.
    {
        prop_ptr                      = write_ptr;
        property_chunk                = (property_chunk_t *) write_ptr;
        property_chunk->chunk_id      = PROP_MARKER;
        property_chunk->property_type = SND_MARKER;
        write_ptr                    += PROPERTY_CHUNK_SIZE;
    }

    // The Sample Rate Chunk is required and may appear only once in the Property Chunk.
    {
        sample_rate_chunk_t *sample_rate_chunk = (sample_rate_chunk_t *) write_ptr;
        sample_rate_chunk->chunk_id        = FS_MARKER;
        sample_rate_chunk->chunk_data_size = CALC_CHUNK_SIZE(SAMPLE_RATE_CHUNK_SIZE - CHUNK_HEADER_SIZE);
        sample_rate_chunk->sample_rate     = hton32(SACD_SAMPLING_FREQUENCY);
        write_ptr                         += SAMPLE_RATE_CHUNK_SIZE;
    }

    // The Channels Chunk is required and may appear only once in the Property Chunk.
    {
        int              i;
        uint8_t          channel_count    = sb_handle->area[ft->area].area_toc->channel_count;
        channels_chunk_t * channels_chunk = (channels_chunk_t *) write_ptr;
        channels_chunk->chunk_id        = CHNL_MARKER;
        channels_chunk->chunk_data_size = CALC_CHUNK_SIZE(CHANNELS_CHUNK_SIZE - CHUNK_HEADER_SIZE + channel_count * sizeof(uint32_t));
        channels_chunk->channel_count   = hton16(channel_count);

        switch (channel_count)
        {
        case 2:
            channels_chunk->channel_ids[0] = SLFT_MARKER;
            channels_chunk->channel_ids[1] = SRGT_MARKER;
            break;
        case 5:
            channels_chunk->channel_ids[0] = MLFT_MARKER;
            channels_chunk->channel_ids[1] = MRGT_MARKER;
            channels_chunk->channel_ids[2] = C_MARKER;
            channels_chunk->channel_ids[3] = LS_MARKER;
            channels_chunk->channel_ids[4] = RS_MARKER;
            break;
        case 6:
            channels_chunk->channel_ids[0] = MLFT_MARKER;
            channels_chunk->channel_ids[1] = MRGT_MARKER;
            channels_chunk->channel_ids[2] = C_MARKER;
            channels_chunk->channel_ids[3] = LFE_MARKER;
            channels_chunk->channel_ids[4] = LS_MARKER;
            channels_chunk->channel_ids[5] = RS_MARKER;
            break;
        default:
            for (i = 0; i < channel_count; i++)
            {
                sprintf((char *) &channels_chunk->channel_ids[i], "C%03i", i);
            }
            break;
        }

        write_ptr += CHANNELS_CHUNK_SIZE + sizeof(uint32_t) * channel_count;
    }

    // The Compression Type Chunk is required and may appear only once in the Property
    // Chunk.
    {
        compression_type_chunk_t *compression_type_chunk = (compression_type_chunk_t *) write_ptr;
        compression_type_chunk->chunk_id         = CMPR_MARKER;
        if (ft->dsd_encoded_export)
        {
            compression_type_chunk->compression_type = DSD_MARKER;
            compression_type_chunk->count = 14;
            memcpy(compression_type_chunk->compression_name, "not compressed", 14);
        }
        else
        {
            compression_type_chunk->compression_type = DST_MARKER;
            compression_type_chunk->count = 11;
            memcpy(compression_type_chunk->compression_name, "DST Encoded", 11);
        }

        compression_type_chunk->chunk_data_size = CALC_CHUNK_SIZE(COMPRESSION_TYPE_CHUNK_SIZE - CHUNK_HEADER_SIZE + compression_type_chunk->count);
        write_ptr += CEIL_ODD_NUMBER(COMPRESSION_TYPE_CHUNK_SIZE + compression_type_chunk->count);
    }

    // The Loudspeaker Configuration Chunk is optional but if used it may appear only once in
    // the Property Chunk.
    {
        uint8_t channel_count = sb_handle->area[ft->area].area_toc->channel_count;
        loudspeaker_config_chunk_t *loudspeaker_config_chunk = (loudspeaker_config_chunk_t *) write_ptr;
        loudspeaker_config_chunk->chunk_id        = LSCO_MARKER;
        loudspeaker_config_chunk->chunk_data_size = CALC_CHUNK_SIZE(LOADSPEAKER_CONFIG_CHUNK_SIZE - CHUNK_HEADER_SIZE);

        switch (channel_count)
        {
        case 2:
            loudspeaker_config_chunk->loudspeaker_config = hton16(LS_CONFIG_2_CHNL);
            break;
        case 5:
            loudspeaker_config_chunk->loudspeaker_config = hton16(LS_CONFIG_5_CHNL);
            break;
        case 6:
            loudspeaker_config_chunk->loudspeaker_config = hton16(LS_CONFIG_6_CHNL);
            break;
        default:
            loudspeaker_config_chunk->loudspeaker_config = hton16(LS_CONFIG_UNDEFINED);
            break;
        }

        write_ptr += LOADSPEAKER_CONFIG_CHUNK_SIZE;
    }

    // all properties have been written, now set the property chunk size
    property_chunk->chunk_data_size = CALC_CHUNK_SIZE(write_ptr - prop_ptr - CHUNK_HEADER_SIZE);

    // Either the DSD or DST Sound Data chunk is required and may appear
    // only once in the Form DSD Chunk. The chunk must be placed after the Property Chunk.
    if (ft->dsd_encoded_export)
    {
        dsd_sound_data_chunk_t * dsd_sound_data_chunk;
        dsd_sound_data_chunk                  = (dsd_sound_data_chunk_t *) write_ptr;
        dsd_sound_data_chunk->chunk_id        = DSD_MARKER;
        dsd_sound_data_chunk->chunk_data_size = CALC_CHUNK_SIZE(handle->audio_data_size);

        write_ptr += CHUNK_HEADER_SIZE;
    }
    else
    {
        dst_sound_data_chunk_t *dst_sound_data_chunk;
        dst_frame_information_chunk_t *dst_frame_information_chunk;

        dst_sound_data_chunk                  = (dst_sound_data_chunk_t *) write_ptr;
        dst_sound_data_chunk->chunk_id        = DST_MARKER;

        write_ptr += DST_SOUND_DATA_CHUNK_SIZE;

        dst_frame_information_chunk           = (dst_frame_information_chunk_t *) write_ptr;
        dst_frame_information_chunk->chunk_id = FRTE_MARKER;
        dst_frame_information_chunk->frame_rate = hton16(SACD_FRAME_RATE);
        dst_frame_information_chunk->num_frames = hton32(handle->frame_count);
        dst_frame_information_chunk->chunk_data_size = CALC_CHUNK_SIZE(DST_FRAME_INFORMATION_CHUNK_SIZE - CHUNK_HEADER_SIZE);

        dst_sound_data_chunk->chunk_data_size = CALC_CHUNK_SIZE(handle->audio_data_size + DST_FRAME_INFORMATION_CHUNK_SIZE);
        write_ptr += DST_FRAME_INFORMATION_CHUNK_SIZE;
    }

    // start with a new footer
    handle->footer_size = 0;

    // DST Sound Index Chunk
    if (!ft->dsd_encoded_export && handle->frame_count > 0)
    {
        size_t frame;
        dst_sound_index_chunk_t *dst_sound_index_chunk;
        uint8_t *dsti_ptr;

        // resize the footer buffer
        handle->footer = realloc(handle->footer, DSDFIFF_BUFFER_SIZE + handle->frame_indexes_allocated * DST_FRAME_INDEX_SIZE);

        dsti_ptr = handle->footer + handle->footer_size;

        dst_sound_index_chunk                 = (dst_sound_index_chunk_t *) dsti_ptr;
        dst_sound_index_chunk->chunk_id       = DSTI_MARKER;

        dsti_ptr += DST_SOUND_INDEX_CHUNK_SIZE;

        for (frame = 0; frame < handle->frame_count; frame++)
        {
            dst_frame_index_t *dst_frame_index = (dst_frame_index_t *) dsti_ptr;
            dst_frame_index->length = hton32(handle->frame_indexes[frame].length);
            dst_frame_index->offset = hton64(handle->frame_indexes[frame].offset);
            dsti_ptr += DST_FRAME_INDEX_SIZE;
        }

        dst_sound_index_chunk->chunk_data_size = CALC_CHUNK_SIZE(handle->frame_count * DST_FRAME_INDEX_SIZE + DST_SOUND_INDEX_CHUNK_SIZE - CHUNK_HEADER_SIZE);
        handle->footer_size += CEIL_ODD_NUMBER(dsti_ptr - handle->footer - handle->footer_size);
    }

    // edit master information
    {
        uint8_t * em_ptr  = handle->footer + handle->footer_size;
        edited_master_information_chunk_t *edited_master_information_chunk = (edited_master_information_chunk_t *) em_ptr;
        edited_master_information_chunk->chunk_id = DIIN_MARKER;
        em_ptr += EDITED_MASTER_INFORMATION_CHUNK_SIZE;

        if (handle->edit_master)
        {
            int track;
            uint64_t abs_frames_start = 0, abs_frames_stop = 0;

            {
                // id is optional, but SADiE seems to require it
                edited_master_id_chunk_t *emid_chunk = (edited_master_id_chunk_t *) em_ptr;
                emid_chunk->chunk_id = EMID_MARKER;
                emid_chunk->chunk_data_size = CALC_CHUNK_SIZE(EDITED_MASTER_ID_CHUNK_SIZE - CHUNK_HEADER_SIZE);
                //strcpy(emid_chunk->emid, guid()); // TODO?, add guid functionality
                em_ptr += EDITED_MASTER_ID_CHUNK_SIZE;
            }

            for (track = 0; track < sb_handle->area[ft->area].area_toc->track_count; track++)
            {
                area_tracklist_time_t *time;
                uint16_t track_flags_stop, track_flags_start;

                time = &sb_handle->area[ft->area].area_tracklist_time->start[track];
                abs_frames_start = TIME_FRAMECOUNT(time);
                track_flags_start = time->track_flags_tmf4 << 0 
                    | time->track_flags_tmf1 << 1
                    | time->track_flags_tmf2 << 2
                    | time->track_flags_tmf3 << 3;

                time = &sb_handle->area[ft->area].area_tracklist_time->duration[track];
                abs_frames_stop = abs_frames_start + TIME_FRAMECOUNT(time);
                track_flags_stop = time->track_flags_tmf4 << 0 
                    | time->track_flags_tmf1 << 1
                    | time->track_flags_tmf2 << 2
                    | time->track_flags_tmf3 << 3;

                if (track == 0)
                {
                    // setting the programstart to 0 always seems incorrect, but produces correct results for SADiE
                    em_ptr = add_marker_chunk(em_ptr, ft, 0, MARK_MARKER_TYPE_PROGRAMSTART, track_flags_start);
                }

                em_ptr = add_marker_chunk(em_ptr, ft, abs_frames_start, MARK_MARKER_TYPE_TRACKSTART, track_flags_start);

                if (track == sb_handle->area[ft->area].area_toc->track_count - 1 
                 || (uint64_t) TIME_FRAMECOUNT(&sb_handle->area[ft->area].area_tracklist_time->start[track + 1]) > abs_frames_stop)
                {
                    em_ptr = add_marker_chunk(em_ptr, ft, abs_frames_stop, MARK_MARKER_TYPE_TRACKSTOP, track_flags_stop);
                }
            }
        }
        // Audiogate supports, Title and Artist information through an EM Chunk
        else
        {
            marker_chunk_t *marker_chunk = (marker_chunk_t *) em_ptr;
            area_tracklist_time_t *area_tracklist_time_duration = &sb_handle->area[ft->area].area_tracklist_time->duration[ft->track];
            marker_chunk->chunk_id = MARK_MARKER;
            marker_chunk->chunk_data_size = CALC_CHUNK_SIZE(EDITED_MASTER_MARKER_CHUNK_SIZE - CHUNK_HEADER_SIZE);
            marker_chunk->hours = hton16(area_tracklist_time_duration->minutes / 60);
            marker_chunk->minutes = area_tracklist_time_duration->minutes % 60;
            marker_chunk->seconds = area_tracklist_time_duration->seconds;
            marker_chunk->samples = hton32(area_tracklist_time_duration->frames * SAMPLES_PER_FRAME * 64);
            marker_chunk->offset = 0;
            marker_chunk->mark_type = hton16(MARK_MARKER_TYPE_INDEX_ENTRY);
            marker_chunk->mark_channel = hton16(COMT_TYPE_CHANNEL_ALL);
            marker_chunk->track_flags = 0;
            marker_chunk->count = 0;
            em_ptr += EDITED_MASTER_MARKER_CHUNK_SIZE;
        }

        {
            artist_chunk_t *artist_chunk = (artist_chunk_t *) em_ptr;
            char *c = 0;

            if (!handle->edit_master)
                c = sb_handle->area[ft->area].area_track_text[ft->track].track_type_performer;

            if (!c)
            {
                master_text_t *master_text = &sb_handle->master_text;

                if (master_text->album_artist)
                    c = master_text->album_artist;
                else if (master_text->album_artist_phonetic)
                    c = master_text->album_artist_phonetic;
                else if (master_text->disc_artist)
                    c = master_text->disc_artist;
                else if (master_text->disc_artist_phonetic)
                    c = master_text->disc_artist_phonetic;
                else if (master_text->album_title)
                    c = master_text->album_title; 
                else if (master_text->album_title_phonetic)
                    c = master_text->album_title_phonetic;
                else if (master_text->disc_title)
                    c = master_text->disc_title; 
                else if (master_text->disc_title_phonetic)
                    c = master_text->disc_title_phonetic;
            }

            if (c)
            {
                char *track_artist;
                int len;

                track_artist = charset_convert(c, strlen(c), "UTF-8", "ISO-8859-1");

                len = strlen(track_artist);
                artist_chunk->chunk_id = DIAR_MARKER;
                artist_chunk->chunk_data_size = CALC_CHUNK_SIZE(EDITED_MASTER_ARTIST_CHUNK_SIZE + len - CHUNK_HEADER_SIZE);
                artist_chunk->count = hton32(len);
                em_ptr += EDITED_MASTER_ARTIST_CHUNK_SIZE;
                memcpy(em_ptr, track_artist, len);
                em_ptr += CEIL_ODD_NUMBER(len);
                free(track_artist);
            }
        }

        {
            title_chunk_t   *title_chunk = (title_chunk_t *) em_ptr;
            char *c = 0;

            if (!handle->edit_master)
                c = sb_handle->area[ft->area].area_track_text[ft->track].track_type_title;

            if (!c)
            {
                master_text_t *master_text = &sb_handle->master_text;

                if (master_text->album_title)
                    c = master_text->album_title; 
                else if (master_text->album_title_phonetic)
                    c = master_text->album_title_phonetic;
                else if (master_text->disc_title)
                    c = master_text->disc_title; 
                else if (master_text->disc_title_phonetic)
                    c = master_text->disc_title_phonetic;
            }

            if (c)
            {
                int len;
                char *track_title;

                track_title = charset_convert(c, strlen(c), "UTF-8", "ISO-8859-1");
                len = strlen(track_title);

                title_chunk->chunk_id = DITI_MARKER;
                title_chunk->chunk_data_size = CALC_CHUNK_SIZE(EDITED_MASTER_TITLE_CHUNK_SIZE + len - CHUNK_HEADER_SIZE);
                title_chunk->count = hton32(len);
                em_ptr += EDITED_MASTER_TITLE_CHUNK_SIZE;
                memcpy(em_ptr, track_title, len);
                em_ptr += CEIL_ODD_NUMBER(len);
                free(track_title);
            }
        }

        edited_master_information_chunk->chunk_data_size = CALC_CHUNK_SIZE(em_ptr - handle->footer - handle->footer_size - CHUNK_HEADER_SIZE);
        handle->footer_size += CEIL_ODD_NUMBER(em_ptr - handle->footer - handle->footer_size);
    }

    // Now we write the COMT comment chunk to the footer buffer
    {
        time_t           rawtime;
        struct tm        * timeinfo;
        comment_t        * comment;
        char             data[512];
        char            *title;
        uint8_t          * comment_ptr  = handle->footer + handle->footer_size;
        comments_chunk_t *comment_chunk = (comments_chunk_t *) comment_ptr;
        comment_chunk->chunk_id    = COMT_MARKER;
        comment_chunk->numcomments = hton16(2);

        comment_ptr += COMMENTS_CHUNK_SIZE;

        time(&rawtime);
        timeinfo = localtime(&rawtime);

        comment                    = (comment_t *) comment_ptr;
        comment->timestamp_year    = hton16(sb_handle->master_toc->disc_date_year);
        comment->timestamp_month   = sb_handle->master_toc->disc_date_month;
        comment->timestamp_day     = sb_handle->master_toc->disc_date_day;
        comment->timestamp_hour    = 0;
        comment->timestamp_minutes = 0;
        comment->comment_type      = hton16(COMT_TYPE_FILE_HISTORY);
        comment->comment_reference = hton16(COMT_TYPE_CHANNEL_FILE_HISTORY_GENERAL);
        title = (char *) get_mtoc_title_text(sb_handle);
        title = charset_convert(title, strlen(title), "UTF-8", "ISO-8859-1");
        sprintf(data, "Material ripped from SACD: %s", title);
        free(title);
        comment->count = hton32(strlen(data));
        memcpy(comment->comment_text, data, strlen(data));

        comment_ptr += CEIL_ODD_NUMBER(COMMENT_SIZE + strlen(data));

        comment                    = (comment_t *) comment_ptr;
        comment->timestamp_year    = hton16(timeinfo->tm_year + 1900);
        comment->timestamp_month   = timeinfo->tm_mon;
        comment->timestamp_day     = timeinfo->tm_mday;
        comment->timestamp_hour    = timeinfo->tm_hour;
        comment->timestamp_minutes = timeinfo->tm_min;
        comment->comment_type      = hton16(COMT_TYPE_FILE_HISTORY);
        comment->comment_reference = hton16(COMT_TYPE_CHANNEL_FILE_HISTORY_CREATING_MACHINE);
        sprintf(data, SACD_RIPPER_VERSION_INFO);
        comment->count = hton32(strlen(data));
        memcpy(comment->comment_text, data, strlen(data));

        comment_ptr += CEIL_ODD_NUMBER(COMMENT_SIZE + strlen(data));

        comment_chunk->chunk_data_size = CALC_CHUNK_SIZE(comment_ptr - handle->footer - handle->footer_size - CHUNK_HEADER_SIZE);
        handle->footer_size           += CEIL_ODD_NUMBER(comment_ptr - handle->footer - handle->footer_size);
    }

    // we add a custom (unsupported) ID3 chunk to maintain all track information
    // within one file
    if (handle->edit_master)
    {
        int track;

        for (track = 0; track < sb_handle->area[ft->area].area_toc->track_count; track++)
        {
            chunk_header_t *id3_chunk;
            int            id3_chunk_size;
            uint8_t          * id3_ptr  = handle->footer + handle->footer_size;
            id3_chunk                  = (chunk_header_t *) id3_ptr;
            id3_chunk->chunk_id        = MAKE_MARKER('I', 'D', '3', ' ');
            id3_chunk_size             = scarletbook_id3_tag_render(sb_handle, id3_ptr + CHUNK_HEADER_SIZE, ft->area, track);
            id3_chunk->chunk_data_size = CALC_CHUNK_SIZE(id3_chunk_size);

            id3_ptr += CEIL_ODD_NUMBER(CHUNK_HEADER_SIZE + id3_chunk_size);

            handle->footer_size += CEIL_ODD_NUMBER(id3_ptr - handle->footer - handle->footer_size);
        }
    }
    else
    {
        chunk_header_t *id3_chunk;
        int            id3_chunk_size;
        uint8_t          * id3_ptr  = handle->footer + handle->footer_size;
        id3_chunk                  = (chunk_header_t *) id3_ptr;
        id3_chunk->chunk_id        = MAKE_MARKER('I', 'D', '3', ' ');
        id3_chunk_size             = scarletbook_id3_tag_render(sb_handle, id3_ptr + CHUNK_HEADER_SIZE, ft->area, ft->track);
        id3_chunk->chunk_data_size = CALC_CHUNK_SIZE(id3_chunk_size);

        id3_ptr += CEIL_ODD_NUMBER(CHUNK_HEADER_SIZE + id3_chunk_size);

        handle->footer_size += CEIL_ODD_NUMBER(id3_ptr - handle->footer - handle->footer_size);
    }

    handle->header_size = CEIL_ODD_NUMBER(write_ptr - handle->header);
    form_dsd_chunk->chunk_data_size = CALC_CHUNK_SIZE(handle->header_size + handle->footer_size + handle->audio_data_size - CHUNK_HEADER_SIZE);

    return 0;
}
Example #10
0
static int squatter_build_query(search_builder_t *bx, const char *query)
{
    tok_t tok = TOK_INITIALIZER(query, NULL, 0);
    char *p;
    char *q;
    int r = 0;
    int part;
    int utf8 = charset_lookupname("utf-8");

    while ((p = tok_next(&tok))) {
        if (!strncasecmp(p, "__begin:", 8)) {
            q = p + 8;
            if (!strcasecmp(q, "and"))
                bx->begin_boolean(bx, SEARCH_OP_AND);
            else if (!strcasecmp(q, "or"))
                bx->begin_boolean(bx, SEARCH_OP_OR);
            else if (!strcasecmp(q, "not"))
                bx->begin_boolean(bx, SEARCH_OP_NOT);
            else
                goto error;
            continue;
        }
        if (!strncasecmp(p, "__end:", 6)) {
            q = p + 6;
            if (!strcasecmp(q, "and"))
                bx->end_boolean(bx, SEARCH_OP_AND);
            else if (!strcasecmp(q, "or"))
                bx->end_boolean(bx, SEARCH_OP_OR);
            else if (!strcasecmp(q, "not"))
                bx->end_boolean(bx, SEARCH_OP_NOT);
            else
                goto error;
            continue;
        }

        /* everything else is a ->match() of some kind */
        q = strchr(p, ':');
        if (q) q++;
        if (!q) {
            part = SEARCH_PART_ANY;
            q = p;
        }
        else if (!strncasecmp(p, "to:", 3))
            part = SEARCH_PART_TO;
        else if (!strncasecmp(p, "from:", 5))
            part = SEARCH_PART_FROM;
        else if (!strncasecmp(p, "cc:", 3))
            part = SEARCH_PART_CC;
        else if (!strncasecmp(p, "bcc:", 4))
            part = SEARCH_PART_BCC;
        else if (!strncasecmp(p, "subject:", 8))
            part = SEARCH_PART_SUBJECT;
        else if (!strncasecmp(p, "listid:", 7))
            part = SEARCH_PART_LISTID;
        else if (!strncasecmp(p, "contenttype:", 12))
            part = SEARCH_PART_TYPE;
        else if (!strncasecmp(p, "header:", 7))
            part = SEARCH_PART_HEADERS;
        else if (!strncasecmp(p, "body:", 5))
            part = SEARCH_PART_BODY;
        else
            goto error;

        q = charset_convert(q, utf8, charset_flags);
        bx->match(bx, part, q);
        free(q);
    }
    r = 0;

out:
    tok_fini(&tok);
    return r;

error:
    syslog(LOG_ERR, "bad query expression at \"%s\"", p);
    r = IMAP_PROTOCOL_ERROR;
    goto out;
}
Example #11
0
/* {{{ flt_lf_parse_string */
int flt_lf_parse_string(u_char *str,u_char **pos,cf_template_t *tpl,flt_lf_node_t *node,flt_lf_node_t *root_node,cf_configuration_t *dc) {
  int ret = 0;
  flt_lf_node_t *current = NULL;
  u_char *forum_name = cf_hash_get(GlobalValues,"FORUM_NAME",10);
  cf_name_value_t *cs = cf_cfg_get_first_value(dc,forum_name,"DF:ExternCharset");

  while((ret = flt_lf_scanner(str,pos)) > 0) {
    current       = cf_alloc(NULL,1,sizeof(*current),CF_ALLOC_CALLOC);
    current->type = ret;

    switch(ret) {
      case TOK_STR:
      case TOK_ID:
        current->prec = PREC_ID;

        if(cf_strcasecmp(flt_lf_str.content,"true") == 0 && ret == TOK_ID) {
          current->content = (u_char *)1;
          cf_str_cleanup(&flt_lf_str);
        }
        else if(cf_strcasecmp(flt_lf_str.content,"false") == 0 && ret == TOK_ID) {
          current->content = (u_char *)0;
          cf_str_cleanup(&flt_lf_str);
        }
        else {
          if(cf_strcmp(cs->values[0],"UTF-8")) {
            if((current->content = charset_convert(flt_lf_str.content,flt_lf_str.len,cs->values[0],"UTF-8",NULL)) == NULL) {
              current->content = flt_lf_str.content;
              cf_str_init(&flt_lf_str);
            }
            else {
              cf_str_cleanup(&flt_lf_str);
            }
          }
          else {
            current->content = flt_lf_str.content;
            cf_str_init(&flt_lf_str);
          }
        }

        break;
      case TOK_LPAREN:
        current->prec     = PREC_PAREN;
        current->argument = cf_alloc(NULL,1,sizeof(*current->argument),CF_ALLOC_CALLOC);
        if((ret = flt_lf_parse_string(str,pos,tpl,NULL,current,dc)) != 0) return ret;
        break;
      case TOK_RPAREN:
        free(current);

        if(root_node->prec != PREC_PAREN) {
          flt_lf_success = 0;
          return 1;
        }

        return 0;
        break;
      case TOK_CONTAINS_NOT:
      case TOK_CONTAINS:
      case TOK_NE:
      case TOK_EQ:
        current->prec = PREC_EQ;
        break;
      case TOK_OR:
        current->prec = PREC_OR;
        break;
      case TOK_AND:
        current->prec = PREC_AND;
        break;
    }

    node = flt_lf_insert_node(node,current,root_node);
  }

  return 0;
}
Example #12
0
int write_cue_sheet(scarletbook_handle_t *handle, const char *filename, int area, char *cue_filename)
{
    FILE *fd;

#ifdef _WIN32
    {
        wchar_t *wide_filename = (wchar_t *) charset_convert(cue_filename, strlen(cue_filename), "UTF-8", "UCS-2-INTERNAL");
        fd = _wfopen(wide_filename, L"wb");
        free(wide_filename);
    }
#else
    fd = fopen(cue_filename, "wb");
#endif
    if (fd == 0)
    {
        return -1;
    }

    // Write UTF-8 BOM
    fputc(0xef, fd);
    fputc(0xbb, fd);
    fputc(0xbf, fd);
    fprintf(fd, "\nREM File created by SACD Extract, version: " SACD_RIPPER_VERSION_STRING "\n");

    if (handle->master_toc->disc_genre[0].genre > 0)
    {
        fprintf(fd, "REM GENRE %s\n", album_genre[handle->master_toc->disc_genre[0].genre]);
    }

    if (handle->master_toc->disc_date_year)
    {
        fprintf(fd, "REM DATE %04d-%02d-%02d\n", handle->master_toc->disc_date_year
                                               , handle->master_toc->disc_date_month
                                               , handle->master_toc->disc_date_day);
    }

    if (handle->master_text.disc_artist)
    {
        fprintf(fd, "PERFORMER \"%s\"\n", cue_escape(handle->master_text.disc_artist));
    }

    if (handle->master_text.disc_title)
    {
        fprintf(fd, "TITLE \"%s\"\n", cue_escape(handle->master_text.disc_title));
    }

    if (strlen(handle->master_toc->disc_catalog_number) > 0)
    {
        fprintf(fd, "CATALOG %s\n", cue_escape(substr(handle->master_toc->disc_catalog_number, 0, 16)));
    }

    fprintf(fd, "FILE \"%s\" WAVE\n", cue_escape(filename));
    {
        int track, track_count = handle->area[area].area_toc->track_count;
        uint64_t prev_abs_end = 0;

        for (track = 0; track < track_count; track++)
        {
            area_tracklist_time_t *time = &handle->area[area].area_tracklist_time->start[track];

            fprintf(fd, "  TRACK %02d AUDIO\n", track + 1);
            
            if (handle->area[area].area_track_text[track].track_type_title)
            {
                fprintf(fd, "      TITLE \"%s\"\n", cue_escape(handle->area[area].area_track_text[track].track_type_title));
            }

            if (handle->area[area].area_track_text[track].track_type_performer)
            {
                fprintf(fd, "      PERFORMER \"%s\"\n", cue_escape(handle->area[area].area_track_text[track].track_type_performer));
            }

            if (*handle->area[area].area_isrc_genre->isrc[track].country_code)
            {
                fprintf(fd, "      ISRC %s\n", cue_escape(substr(handle->area[area].area_isrc_genre->isrc[track].country_code, 0, 12)));
            }

            if ((uint64_t) TIME_FRAMECOUNT(&handle->area[area].area_tracklist_time->start[track]) > prev_abs_end)
            {
                int prev_sec = (int) (prev_abs_end / SACD_FRAME_RATE);

                fprintf(fd, "      INDEX 00 %02d:%02d:%02d\n", prev_sec / 60, (int) prev_sec % 60, (int) prev_abs_end % SACD_FRAME_RATE);
                fprintf(fd, "      INDEX 01 %02d:%02d:%02d\n", time->minutes, time->seconds, time->frames);
            }
            else
            {
                fprintf(fd, "      INDEX 01 %02d:%02d:%02d\n", time->minutes, time->seconds, time->frames);
            }

            prev_abs_end = TIME_FRAMECOUNT(&handle->area[area].area_tracklist_time->start[track]) + 
                             TIME_FRAMECOUNT(&handle->area[area].area_tracklist_time->duration[track]);
        }
    }

    fclose(fd);

    return 0;
}
Example #13
0
int csv_select_run_child(
	csv_parse_t *parse, csv_result_set_t *result, size_t table_pos
) {
	csv_select_t *select = parse->select;
	csv_table_def_t *table, *table2;
	char *s1, *s2;
	int ch, has_child = select->table_count - table_pos > 1;
	size_t i, j, k, l, m, rp = 0, nr = 0, l1;
	Expr *x1;
	ExprList *xl_cols = select->columns;
	csv_row_t *row;
	csv_var_t *v1, v2;
	csv_column_def_t *col;
	csv_t *csv = parse->csv;
	/* reset table */
	table = select->tables[table_pos];
	PerlIO_seek( table->dstream, table->header_offset, SEEK_SET );
	if( table->flags & TEXT_TABLE_COLNAMEHEADER ) {
		if( ! table->header_offset ) {
			do {
				ch = PerlIO_getc( table->dstream );
			} while( ch != EOF && ch != '\n' );
			table->header_offset = PerlIO_tell( table->dstream );
		}
	}
	table->row_pos = 0;
	/* read rows */
	while( (s1 = csv_read_row( table )) != NULL ) {
#ifdef CSV_DEBUG
		_debug( "table '%s' row %lu\n", table->name, table->row_pos );
#endif
		if( has_child ) {
			ch = csv_select_run_child( parse, result, table_pos + 1 );
			if( ch != CSV_OK )
				return ch;
			continue;
		}
		/* eval WHERE */
		if( (x1 = select->where) != NULL ) {
			ch = expr_eval( parse, x1 );
			if( ch != CSV_OK )
				return ch;
			if( x1->var.flags & VAR_HAS_IV ) {
				if( ! x1->var.iv )
					continue;
			}
			else if( x1->var.flags & VAR_HAS_NV ) {
				if( ! x1->var.nv )
					continue;
			}
			else if( x1->var.sv == NULL || x1->var.sv[0] == '0' )
				continue;
		}
		/* eval columns */
		for( i = 0; i < xl_cols->expr_count; i ++ ) {
			x1 = xl_cols->expr[i];
			if( (x1->flags & EXPR_IS_AGGR) == 0 ) {
				ch = expr_eval( parse, x1 );
				if( ch != CSV_OK )
					return ch;
			}
		}
		if( select->groupby == NULL )
			goto add_row;
		/* eval groupby */
		for( i = 0; i < select->groupby->expr_count; i ++ ) {
			ch = expr_eval( parse, select->groupby->expr[i] );
			if( ch != CSV_OK )
				return ch;
		}
		/* search groupby row */
		for( j = 0; j < result->row_count; j ++ ) {
			row = result->rows[j];
			for( i = 0; i < select->groupby->expr_count; i ++ ) {
				v1 = &row->groupby[i];
				x1 = select->groupby->expr[i];
				VAR_COMP_OP( v2, *v1, x1->var, ==, "==", 0, 0 );
				if( ! v2.iv )
					goto groupby_next;
			}
			goto eval_row;
groupby_next:
			continue;
		}
add_row:
		if( select->offset && rp < select->offset ) {
			rp ++;
			continue;
		}
		if( select->limit && rp - select->offset >= select->limit )
			goto finish;
		rp ++;
		Newxz( row, 1, csv_row_t );
		row->select = select;
		if( (result->row_count % ROW_COUNT_EXPAND) == 0 ) {
			Renew( result->rows, result->row_count + ROW_COUNT_EXPAND,
				csv_row_t * );
		}
		result->rows[result->row_count ++] = row;
		Newxz( row->data, result->column_count, csv_var_t );
		if( select->orderby != NULL )
			Newxz( row->orderby, select->orderby->expr_count, csv_var_t );
		if( select->groupby != NULL )
			Newxz( row->groupby, select->groupby->expr_count, csv_var_t );
		nr = 1;
eval_row:
		for( i = 0, j = 0; i < xl_cols->expr_count; i ++, j ++ ) {
			x1 = xl_cols->expr[i];
			if( x1->op == TK_TABLE ) {
				table2 = x1->table;
				for( l = 0; l < table2->column_count; l ++, j ++ ) {
					col = table2->columns + l;
					v1 = row->data + j;
					s1 = table->data + col->offset;
					l1 = col->length;
					if( l1 == 4 && strcmp( s1, "NULL" ) == 0 )
						continue;
					switch( col->type ) {
					case FIELD_TYPE_INTEGER:
						v1->iv = atoi( s1 );
						v1->flags = VAR_HAS_IV;
						break;
					case FIELD_TYPE_DOUBLE:
						if( table2->decimal_symbol != '.' ) {
							s2 = strchr( s1, table2->decimal_symbol );
							if( s2 != NULL )
								*s2 = '.';
						}
						v1->nv = atof( s1 );
						v1->flags = VAR_HAS_NV;
						break;
					case FIELD_TYPE_CHAR:
						v1->sv_len = charset_convert(
							s1, l1, table2->charset,
							csv->client_charset, &v1->sv
						);
						v1->flags = VAR_HAS_SV;
						break;
					case FIELD_TYPE_BLOB:
						if( l1 >= 2 && s1[0] == '0' && s1[1] == 'x' ) {
							l1 = (l1 - 2) / 2;
							if( ! l1 ) {
								v1->flags = 0;
								continue;
							}
							Renew( v1->sv, l1 + 1, char );
							for( m = 0, s1 += 2; m < l1; m ++ ) {
								ch = CHAR_FROM_HEX[*s1 & 0x7f] << 4;
								s1 ++;
								ch += CHAR_FROM_HEX[*s1 & 0x7f];
								s1 ++;
								v1->sv[m] = (char) ch;
							}
							v1->sv[l1] = '\0';
							v1->sv_len = l1;
							v1->flags = VAR_HAS_SV;
							break;
						}
					default:
						Renew( v1->sv, l1 + 1, char );
						Copy( s1, v1->sv, l1, char );
						v1->sv[l1] = '\0';
						v1->sv_len = l1;
						v1->flags = VAR_HAS_SV;
						break;
					}
				}
				continue;
			}
Example #14
0
int main(int argc, char* argv[]) 
{
    char *albumdir = 0, *musicfilename, *file_path = 0;
    int i, area_idx;
    sacd_reader_t *sacd_reader;

#ifdef PTW32_STATIC_LIB
    pthread_win32_process_attach_np();
    pthread_win32_thread_attach_np();
#endif

    init();
    if (parse_options(argc, argv)) 
    {
        setlocale(LC_ALL, "");
        if (fwide(stdout, 1) < 0)
        {
            fprintf(stderr, "ERROR: Output not set to wide.\n");
        }

        // default to 2 channel
        if (opts.two_channel == 0 && opts.multi_channel == 0) 
        {
            opts.two_channel = 1;
        }

        sacd_reader = sacd_open(opts.input_device);
        if (sacd_reader) 
        {

            handle = scarletbook_open(sacd_reader, 0);
            if (handle)
            {
                if (opts.print)
                {
                    scarletbook_print(handle);
                }

                if (opts.output_dsf || opts.output_iso || opts.output_dsdiff || opts.output_dsdiff_em || opts.export_cue_sheet)
                {
                    output = scarletbook_output_create(handle, handle_status_update_track_callback, handle_status_update_progress_callback, safe_fwprintf);

                    // select the channel area
                    area_idx = ((has_multi_channel(handle) && opts.multi_channel) || !has_two_channel(handle)) ? handle->mulch_area_idx : handle->twoch_area_idx;

                    albumdir = (strlen(opts.output_file) > 0 ? strdup(opts.output_file) : get_album_dir(handle));

                    if (opts.output_iso)
                    {
                        uint32_t total_sectors = sacd_get_total_sectors(sacd_reader);
#ifdef SECTOR_LIMIT
#define FAT32_SECTOR_LIMIT 2090000
                        uint32_t sector_size = FAT32_SECTOR_LIMIT;
                        uint32_t sector_offset = 0;
                        if (total_sectors > FAT32_SECTOR_LIMIT)
                        {
                            musicfilename = (char *) malloc(512);
                            file_path = make_filename(0, 0, albumdir, "iso");
                            for (i = 1; total_sectors != 0; i++)
                            {
                                sector_size = min(total_sectors, FAT32_SECTOR_LIMIT);
                                snprintf(musicfilename, 512, "%s.%03d", file_path, i);
                                scarletbook_output_enqueue_raw_sectors(output, sector_offset, sector_size, musicfilename, "iso");
                                sector_offset += sector_size;
                                total_sectors -= sector_size;
                            }
                            free(musicfilename);
                        }
                        else
#endif
                        {
                            get_unique_filename(&albumdir, "iso");
                            file_path = make_filename(0, 0, albumdir, "iso");
                            scarletbook_output_enqueue_raw_sectors(output, 0, total_sectors, file_path, "iso");
                        }
                    }
                    else if (opts.output_dsdiff_em)
                    {
                        get_unique_filename(&albumdir, "dff");
                        file_path = make_filename(0, 0, albumdir, "dff");

                        scarletbook_output_enqueue_track(output, area_idx, 0, file_path, "dsdiff_edit_master", 
                            (opts.convert_dst ? 1 : handle->area[area_idx].area_toc->frame_format != FRAME_FORMAT_DST));
                    }
                    else if (opts.output_dsf || opts.output_dsdiff)
                    {
                        // create the output folder
                        get_unique_dir(0, &albumdir);
                        recursive_mkdir(albumdir, 0774);

                        // fill the queue with items to rip
                        for (i = 0; i < handle->area[area_idx].area_toc->track_count; i++) 
                        {
                            if (opts.select_tracks && opts.selected_tracks[i] == 0)
                                continue;

                            musicfilename = get_music_filename(handle, area_idx, i, opts.output_file);

                            if (opts.output_dsf)
                            {
                                file_path = make_filename(0, albumdir, musicfilename, "dsf");
                                scarletbook_output_enqueue_track(output, area_idx, i, file_path, "dsf", 
                                    1 /* always decode to DSD */);
                            }
                            else if (opts.output_dsdiff)
                            {
                                file_path = make_filename(0, albumdir, musicfilename, "dff");
                                scarletbook_output_enqueue_track(output, area_idx, i, file_path, "dsdiff", 
                                    (opts.convert_dst ? 1 : handle->area[area_idx].area_toc->frame_format != FRAME_FORMAT_DST));
                            }

                            free(musicfilename);
                            free(file_path);
                            file_path = 0;
                        }
                    }

                    if (opts.export_cue_sheet)
                    {
                        char *cue_file_path = make_filename(0, 0, albumdir, "cue");
#ifdef _WIN32
                        wchar_t *wide_filename = (wchar_t *) charset_convert(cue_file_path, strlen(cue_file_path), "UTF-8", sizeof(wchar_t) == 2 ? "UCS-2-INTERNAL" : "UCS-4-INTERNAL");
#else
                        wchar_t *wide_filename = (wchar_t *) charset_convert(cue_file_path, strlen(cue_file_path), "UTF-8", "WCHAR_T");
#endif
                        fwprintf(stdout, L"Exporting CUE sheet [%ls]\n", wide_filename);
                        if (!file_path)
                            file_path = make_filename(0, 0, albumdir, "dff");
                        write_cue_sheet(handle, file_path, area_idx, cue_file_path);
                        free(cue_file_path);
                        free(wide_filename);
                    }

                    free(file_path);

                    started_processing = time(0);
                    scarletbook_output_start(output);
                    scarletbook_output_destroy(output);

                    fprintf(stdout, "\rWe are done..                                                          \n");
                }
                scarletbook_close(handle);

                free(albumdir);
            }
        }

        sacd_close(sacd_reader);

#ifndef _WIN32
        freopen(0, "w", stdout);
#endif
        if (fwide(stdout, -1) >= 0)
        {
            fprintf(stderr, "ERROR: Output not set to byte oriented.\n");
        }
    }

    free_lock(g_fwprintf_lock);
    destroy_logging();

#ifdef PTW32_STATIC_LIB
    pthread_win32_process_detach_np();
    pthread_win32_thread_detach_np();
#endif

    printf("\n");
    return 0;
}