static void custom_cell_renderer_flexi_init (CustomCellRendererFlexi *cellrendererflexi)
{
    /* default: GTK_CELL_RENDERER(cellrendererflexi)->mode = GTK_CELL_RENDERER_MODE_INERT; */
    gtk_cell_renderer_set_padding(GTK_CELL_RENDERER(cellrendererflexi), 2, 2);

    cellrendererflexi->raw_value = a_strnew(NULL);
    cellrendererflexi->alt_text  = a_strnew(NULL);
    cellrendererflexi->mime_type = a_strnew(NULL);
    cellrendererflexi->rendered_type = RENDER_NONE;
    cellrendererflexi->rendered_value = NULL;
    cellrendererflexi->default_width = -1;
    cellrendererflexi->default_line_height = -1;
}
int http_download(const char *src_url, const char *dst_filename)
{
    CURL *curl;
    CURLcode res;
    void *progress;  
    a_string_t *user_agent;
    a_string_t *progress_title;
    FILE *temp_fd;
    
    curl = curl_easy_init();
    
    if (!curl)
        return 0;

    progress_title    = a_strnew(NULL); 
    a_sprintf(progress_title,"Updating %s",dst_filename);
    
    user_agent = a_strnew(NULL);     
    a_sprintf(user_agent,"cardpeek/%s",VERSION);

    progress = ui_inprogress_new(a_strval(progress_title),"Please wait...");
    
    temp_fd = fopen(dst_filename,"wb");

    curl_easy_setopt(curl,CURLOPT_URL,src_url);
    curl_easy_setopt(curl,CURLOPT_WRITEDATA, temp_fd);
    curl_easy_setopt(curl,CURLOPT_USERAGENT, a_strval(user_agent));
    curl_easy_setopt(curl,CURLOPT_FAILONERROR, 1L);
    curl_easy_setopt(curl,CURLOPT_NOPROGRESS, 0L);
    curl_easy_setopt(curl,CURLOPT_PROGRESSFUNCTION, progress_download);
    curl_easy_setopt(curl,CURLOPT_PROGRESSDATA, progress);

    res = curl_easy_perform(curl);

    fclose(temp_fd);

    if (res!=CURLE_OK)
    {
        log_printf(LOG_ERROR,"Failed to fetch %s: %s", src_url, curl_easy_strerror(res));
        unlink(dst_filename);
    }

    curl_easy_cleanup(curl);

    ui_inprogress_free(progress);

    a_strfree(user_agent);
    a_strfree(progress_title);

    return (res==CURLE_OK);
} 
static int subr_iconv_iconv(lua_State *L)
{
    iconv_t ic = luaL_check_iconv(L,1);
    ICONV_CONST char *src = (ICONV_CONST char *)luaL_checkstring(L,2);
    size_t src_len = strlen(src);
    char conv_block[16];
    size_t conv_len;
    char *conv_block_ptr;
    a_string_t *dst = a_strnew(NULL);
        
    while (src_len>0)
    {
        conv_len = 16;
        conv_block_ptr = conv_block;
        if (iconv(ic, &src, &src_len, &conv_block_ptr, &conv_len)==(size_t)(-1))
        {                    
            if (errno!=E2BIG)            
            {
                a_strfree(dst);
                lua_pushnil(L);
                return 1;
            }
        }
        a_strncat(dst,16-conv_len,conv_block);
    } 
    lua_pushstring(L,a_strval(dst));
    a_strfree(dst);
    return 1;
}
Beispiel #4
0
int cardmanager_search_replay_readers(cardmanager_t *cm)
{
  a_string_t* fn;
  struct dirent **namelist;
  const char* log_folder = path_config_get_string(PATH_CONFIG_FOLDER_REPLAY); 
  int count,n;

  n = scandir(log_folder,&namelist,select_clf,alphasort);

  if (n<=0)
    return 0;
  count=0;
  
  cm->readers=(char **)realloc(cm->readers,sizeof(char*)*(cm->readers_count+n));
  while (n--)
  {
    count++;
    fn = a_strnew(NULL);
    a_sprintf(fn,"replay://%s",namelist[n]->d_name);
    cm->readers[cm->readers_count++]=a_strfinalize(fn);
    free(namelist[n]);
  }
  free(namelist);
  return count;
}
static gboolean internal_format(CustomCellRendererFlexi *cr, const a_string_t *a_src, int limit)
{
    int len_src 	= a_strlen(a_src);
    const char *src = a_strval(a_src);

    cr->rendered_type = RENDER_TEXT;
    cr->rendered_value = a_strnew(NULL);

    if (src==NULL || len_src<2) return FALSE;

    switch (src[0])
    {
        case '8':
        case '4':
        case '1':
            internal_format_raw(cr->rendered_value,len_src,src,limit);
            break;
        case 't':
            internal_format_alt(cr->rendered_value,len_src,src);
            break;
        default:
            return internal_render_error(cr,"Internal format error.");
    }
    return TRUE;
}
static gboolean internal_render_error(CustomCellRendererFlexi *cr, const char *msg)
{
    cr->rendered_type = RENDER_TEXT;
    cr->rendered_value = a_strnew("<span foreground='#7F0000'>Error: ");
    a_strcat(cr->rendered_value,msg);
    a_strcat(cr->rendered_value,"</span>");
    if (a_strlen(cr->mime_type)>2)
        log_printf(LOG_WARNING,"Rendering error for '%s' mime-type: %s",a_strval(cr->mime_type)+2,msg);
    else
        log_printf(LOG_WARNING,"Rendering error: %s",msg);
    return FALSE;
}
Beispiel #7
0
static void internal_cell_renderer_markup_cb (GtkTreeViewColumn *col,
        GtkCellRenderer   *renderer,
        GtkTreeModel      *model,
        GtkTreeIter       *iter,
        gpointer           user_data)
{
    a_string_t *markup_label_id;
    char *classname;
    char *id;
    char *label;
    UNUSED(col);
    UNUSED(user_data);

    gtk_tree_model_get(GTK_TREE_MODEL(model),
                       iter,
                       CC_CLASSNAME, &classname,
                       CC_LABEL, &label,
                       CC_ID, &id,
                       -1);

    /* TODO: escape markup characters that may appear in classname, id and label */

    markup_label_id = a_strnew(NULL);

    if (label && label[0]=='t')
        a_sprintf(markup_label_id,"<b>%s</b>",label+2);
    else
    {
        if (classname && classname[0]=='t')
            a_sprintf(markup_label_id,"<b>%s</b>",classname+2);
        else
            a_sprintf(markup_label_id,"<b>item</b>");
    }

    if (id && id[0]=='t')
    {
        a_strcat(markup_label_id," ");
        a_strcat(markup_label_id,id+2);
    }

    g_object_set(renderer, "markup", a_strval(markup_label_id), NULL);

    a_strfree(markup_label_id);

    g_free(classname);
    g_free(label);
    g_free(id);
}
Beispiel #8
0
char* cardtree_to_xml(cardtree_t* ct, const char *path)
{
  a_string_t *res;
  GtkTreeIter iter;
  gboolean path_exists;

  if (path==NULL)
    path_exists = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(ct->_store),&iter);
  else
    path_exists = gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(ct->_store),&iter,path);

  if (!path_exists)
    return NULL;

  res = a_strnew("<?xml version=\"1.0\"?>\n");
  a_strcat(res,"<cardtree>\n");
  node_to_xml(res,GTK_TREE_MODEL(ct->_store),&iter,1);
  a_strcat(res,"</cardtree>\n");
  return a_strfinalize(res);
}
static void menu_readerview_save_as_cb(GtkWidget *w, gpointer user_data)
{
  char** select_info;
  a_string_t *command;
  char *filename;
  UNUSED(w);
  UNUSED(user_data);

  select_info = ui_select_file("Save recorded data",path_config_get_string(PATH_CONFIG_FOLDER_REPLAY),"card.clf");
  if (select_info[1])
  {  
    filename = luax_escape_string(select_info[1]);
    command=a_strnew(NULL);
    a_sprintf(command,"card.log_save(\"%s\")",filename);
    luax_run_command(a_strval(command));
    a_strfree(command);
    g_free(select_info[0]);
    g_free(select_info[1]);
    g_free(filename);
  }
}
Beispiel #10
0
static void menu_cardview_save_as_cb(GtkWidget *w, gpointer user_data)
{
    char **select_info;
    a_string_t *command;
    char *filename;
    UNUSED(w);
    UNUSED(user_data);

    select_info = ui_select_file("Save xml card description",path_config_get_string(PATH_CONFIG_FOLDER_WORKING),"card.xml");
    if (select_info[1])
    {
        path_config_set_string(PATH_CONFIG_FOLDER_WORKING,select_info[0]);
        filename = luax_escape_string(select_info[1]);
        command=a_strnew(NULL);
        a_sprintf(command,"ui.save_view(\"%s\")",filename);
        luax_run_command(a_strval(command));
        a_strfree(command);
        g_free(select_info[0]);
        g_free(select_info[1]);
        g_free(filename);
    }
}
Beispiel #11
0
/* this should not be here but in pcsc_driver.c */
int cardmanager_search_pcsc_readers(cardmanager_t *cm)
{
  DWORD dwReaders;
  char *p;
  LONG hcontext = 0;
  long status;
  a_string_t *rlist;
  char *readers;
  unsigned r;

  
  status = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, 
				 &hcontext);
  
  if (status!=SCARD_S_SUCCESS)
  {
    log_printf(LOG_INFO,"Failed to establish PCSC card manager context");
    log_printf(LOG_INFO,"PCSC error code 0x%08X: %s",status,pcsc_stringify_error(status));
    if (cardmanager_check_pcscd_is_running()==0)
      log_printf(LOG_INFO,"The pcscd daemon does not seem to be running.");
    else
      log_printf(LOG_INFO,"The pcscd daemon seems to be running.");
    return 0;
  }

  status = SCardListReaders(hcontext, NULL, NULL, &dwReaders);
  if (status!=SCARD_S_SUCCESS)
  {
    log_printf(LOG_WARNING,"No PCSC reader connected");
    log_printf(LOG_INFO,"PCSC error code 0x%08X: %s",status,pcsc_stringify_error(status));
    return 0;
  }

  readers=(char *)malloc(dwReaders);
  status = SCardListReaders(hcontext, NULL, readers, &dwReaders);

  if (status!=SCARD_S_SUCCESS)
  {
    log_printf(LOG_WARNING,"PCSC Reader list failed");
    log_printf(LOG_INFO,"PCSC error code %lX: %s",status,pcsc_stringify_error(status));
    return 0;
  }

  p=readers;
  cm->readers_count=0;
  while (*p)
  {
    cm->readers_count++;
    p+=strlen(p)+1;
  }
  cm->readers=(char **)realloc(cm->readers,sizeof(char*)*cm->readers_count);

  rlist = a_strnew(NULL);
  p=readers;
  for (r=0;r<cm->readers_count;r++)
  {
    a_strcpy(rlist,"pcsc://");
    a_strcat(rlist,p);
    cm->readers[r]=strdup(a_strval(rlist));
    p+=strlen(p)+1;
  }
  a_strfree(rlist);
  free(readers);
  log_printf(LOG_DEBUG,"Found %i PCSC readers",cm->readers_count);

  status = SCardReleaseContext(hcontext);
  if (status!=SCARD_S_SUCCESS) 
  {
    log_printf(LOG_ERROR,"Failed to release PCSC context");
    log_printf(LOG_INFO,"PCSC error code %lX: %s",status,pcsc_stringify_error(status));
  }

  return cm->readers_count;
}
int cardpeek_update_perform(void)
{
    const char* cardpeek_update_file = path_config_get_string(PATH_CONFIG_FILE_CARDPEEK_UPDATE);
    a_string_t *contents;
    update_t *update;
    int remove;
    update_item_t *item;
    time_t now = time(NULL);
    int updated = 0;
    char *url = NULL;
    char *local_file;
    char *local_dnld;
    unsigned char digest[SHA256_DIGEST_LENGTH];
    a_string_t *url_request;
    unsigned first_update;

    first_update = (unsigned)luax_variable_get_integer("cardpeek.updates.first_update");
    
    /* STEP 1: get cardpeek.update file */

    url=luax_variable_get_strdup("cardpeek.updates.url");

    if (url==NULL)
        url = g_strdup(DEFAULT_UPDATE_URL);

    log_printf(LOG_INFO,"Fetching '%s'",url);

    url_request = a_strnew(NULL);
    a_sprintf(url_request,"%s?u=%x&v=%s",url,first_update,VERSION);

    if (http_download(a_strval(url_request),cardpeek_update_file)==0)
    {
        g_free(url);
        return 0;
    }
    g_free(url);
    a_strfree(url_request);


    /* STEP 2: parse file */

    if ((contents=file_get_contents(cardpeek_update_file))==NULL)
    {
        log_printf(LOG_ERROR,"failed to read update file information.");
        unlink(cardpeek_update_file);
        return 0;
    }

    update = update_new();

    if ((update_load(update,a_strval(contents),a_strlen(contents)))==0)
    {
        unlink(cardpeek_update_file);
        a_strfree(contents);
        update_free(update);
        return 0;
    }
    a_strfree(contents);

    /* log_printf(LOG_DEBUG,"Updates correctly loaded from '%s'",cardpeek_update_file); */
    if ((remove = update_filter_version(update,VERSION))>0)
        log_printf(LOG_WARNING,"%d updates will not be installed because they require a newer version of Cardpeek.");
    
    remove = update_filter_files(update);

    if (update->item_count)
        log_printf(LOG_INFO,"A total of %d files will be updated, %d files are kept unchanged.",update->item_count,remove);
    else
        log_printf(LOG_INFO,"No files will be updated, %d files are kept unchanged.",remove);

    item = update->items;

    while (item)
    {
        local_dnld = new_path(PATH_CONFIG_FOLDER_CARDPEEK,item->file,".download");
        local_file = new_path(PATH_CONFIG_FOLDER_CARDPEEK,item->file,NULL);

        if (http_download(item->url,local_dnld)!=0)
        {        
            if (sha256sum(local_dnld,digest))
            {
                if (memcmp(digest,bytestring_get_data(&item->digest),SHA256_DIGEST_LENGTH)==0)
                {
                    unlink(local_file);

                    if (rename(local_dnld,local_file)==0)
                    {
                        log_printf(LOG_INFO,"Successfuly updated %s", local_file);
                        updated++;
                    }
                    else
                    {
                        log_printf(LOG_ERROR,"Failed to copy %s to %s: %s", 
                                local_dnld,
                                local_file, 
                                strerror(errno));
                    }
                }
                else
                {
                    log_printf(LOG_WARNING,"File %s was not updated: authentication failed.",local_file);
                }
            }
            unlink(local_dnld);
        }
        g_free(local_dnld);
        g_free(local_file);
        item =  item->next; 
    }

    if (updated == update->item_count)
    {    
        luax_variable_set_integer("cardpeek.updates.next_update",(int)(now+7*(24*3600)));  
        luax_config_table_save();
    }

    unlink(cardpeek_update_file);
    update_free(update);

    /* STEP 3: finish */

    return 1;

}
Beispiel #13
0
int internal_cardtree_from_xml_file(cardtree_t *ct, GtkTreeIter *parent, FILE* F)
{
  /* quick and dirty, absolutely no checking ! */
  GtkTreeIter child;
  a_string_t *atr;
  a_string_t *elt;
  int retval = XML_ERROR;
  char *debug_msg;
  int in_element;
    
  elt = a_strnew(NULL);
  atr = a_strnew(NULL);

  while (!ferror(F))
  {
    in_element = TOK_TEXT;
    if (get_next_xml_token(F,elt,&in_element)!=XML_OK) goto clean_up;

    if (in_element==TOK_END)
    {
      retval = XML_OK;
      goto clean_up;
    }
    else if (a_strequal(elt,"<node"))
    {
      gtk_tree_store_append (ct->_store, &child, parent);
      gtk_tree_store_set (ct->_store, &child,
  			  C_LEAF, 0,
  			  -1);
      for (;;)
      {
	if (get_next_xml_token(F,elt,&in_element)!=XML_OK) goto clean_up;

	if (in_element != TOK_ATTRIBUTE) break;

	if (assert_next_xml_token(F,atr,&in_element,"=")!=XML_OK) goto clean_up;

	if (get_next_xml_token(F,atr,&in_element)!=XML_OK) goto clean_up;
	if (in_element != TOK_STRING) goto clean_up;

	if (a_strequal(elt,"name"))
	{
	  gtk_tree_store_set (ct->_store, &child,
			      C_NODE, a_strval(atr),
			      -1);
	}
	else if (a_strequal(elt,"id")) 
	{
	  gtk_tree_store_set (ct->_store, &child,
			      C_ID, a_strval(atr),
			      -1);
	}
	else if (a_strequal(elt,"length"))
	{
	  gtk_tree_store_set (ct->_store, &child,
			      C_LENGTH, a_strval(atr),
			      -1);
	}
	else if (a_strequal(elt,"comment"))
	{
	  gtk_tree_store_set (ct->_store, &child,
			      C_COMMENT, a_strval(atr),
			      -1);
	}
	else
	{
	  log_printf(LOG_ERROR,"Unexpected XML attribute '%s'",a_strval(elt));
	  retval = XML_ERROR;
	  goto clean_up;
	}
      }

      cardtree_create_markup(ct,&child);

      if (!a_strequal(elt,"/>")) 
      {
	if (!a_strequal(elt,">"))
	{
	  log_printf(LOG_ERROR,"Expected '>' or '/>'");
	  goto clean_up;
	}
	retval = internal_cardtree_from_xml_file(ct,&child,F);
	if (retval!=XML_OK) goto clean_up;
	/*if (assert_next_xml_token(F,elt,&in_element,"</node>")!=XML_OK) goto clean_up;*/
      }
    }
    else if (a_strequal(elt,"<data"))
    {
      gtk_tree_store_append (ct->_store, &child, parent);
      gtk_tree_store_set (ct->_store, &child,
  			  C_LEAF, 1,
  			  -1);

      if (get_next_xml_token(F,elt,&in_element)!=XML_OK) goto clean_up;
      if (a_strequal(elt,"/>")) continue;
      if (!a_strequal(elt,">"))
      {
	log_printf(LOG_ERROR,"Expected '>' or '/>'");
	goto clean_up;
      }
      if (get_next_xml_token(F,elt,&in_element)!=XML_OK) goto clean_up;
      if (in_element!=TOK_TEXT) 
      {
	log_printf(LOG_ERROR,"Expected text inside <data>...</data>, got %s instead.",
	     a_strval(elt));
	goto clean_up;
      }
      gtk_tree_store_set (ct->_store, &child,
	  		  C_NODE, a_strval(elt),
	  		  -1);
      cardtree_create_markup(ct,&child);
      if (assert_next_xml_token(F,elt,&in_element,"</>")!=XML_OK) goto clean_up;
    }
    else if (a_strequal(elt,"<cardtree"))
    {
      if (parent!=NULL)
      {
	log_printf(LOG_ERROR,"XML ERROR - cardtree must be root element");
	goto clean_up;
      }
      if (get_next_xml_token(F,elt,&in_element)!=XML_OK) goto clean_up;
      if (a_strequal(elt,"/>"))
      {
	retval = XML_OK;
	goto clean_up;
      }
      if (!a_strequal(elt,">"))
      {
	log_printf(LOG_ERROR,"Expected '>' or '/>'");
	goto clean_up;
      }
      retval = internal_cardtree_from_xml_file(ct,NULL,F);
      if (retval!=XML_OK) goto clean_up;
      /*retval = assert_next_xml_token(F,elt,&in_element,"</cardtree>");*/
      goto clean_up;
    }
    else if (in_element==TOK_INSTRUCTION)
    {
      /* NOP */
    }
    else
    {
      log_printf(LOG_ERROR,"Syntax error : %s",a_strval(elt));
      retval = XML_ERROR;
      goto clean_up;
    }
  }
  
  log_printf(LOG_ERROR,"Unexpected end-of-file or error in XML");
  retval = XML_ERROR;

clean_up:
  if (retval==XML_ERROR)
  {
    if (parent)
    {
      debug_msg = gtk_tree_model_get_string_from_iter(GTK_TREE_MODEL(ct->_store),parent);
      log_printf(LOG_ERROR,"Error in path '%s'",debug_msg);
      g_free(debug_msg);
    }
    else
      log_printf(LOG_ERROR,"Error in root");
  }
  a_strfree(atr);
  a_strfree(elt);
  return retval;
}
Beispiel #14
0
static int install_dot_file(void)
{
    const char* cardpeek_dir = path_config_get_string(PATH_CONFIG_FOLDER_CARDPEEK);
    const char* old_replay_dir = path_config_get_string(PATH_CONFIG_FOLDER_OLD_REPLAY);
    const char* new_replay_dir = path_config_get_string(PATH_CONFIG_FOLDER_REPLAY);
    const char* version_file = path_config_get_string(PATH_CONFIG_FILE_VERSION);
    GStatBuf sbuf;
    FILE* f;
    int status;
    a_string_t* astr;
    unsigned dot_version=0;
    int response;
    GResource* cardpeek_resources;
    GBytes* dot_cardpeek_tar_gz;
    unsigned char *dot_cardpeek_tar_gz_start;
    gsize dot_cardpeek_tar_gz_size;

    if (g_stat(cardpeek_dir,&sbuf)==0)
    {
        log_printf(LOG_DEBUG,"Found directory '%s'",cardpeek_dir);

        if ((f = g_fopen(version_file,"r"))!=NULL)
        {
            if (fscanf(f,"%u",&dot_version)!=1)
		dot_version=0;
            fclose(f);
            if (dot_version>=SCRIPT_VERSION)
            {
                log_printf(LOG_DEBUG,"Scripts are up to date.");
                return 1;
            }
        }
        astr = a_strnew(NULL);

        if (dot_version==0 && f==NULL)
            a_sprintf(astr,"This seems to be the first time you run Cardpeek, because '%s' does not exist\n"
                      "Do you want to install the necessary files in '%s'?",version_file,cardpeek_dir);
        else
            a_sprintf(astr,"Some scripts in '%s' seem to be outdated or missing\n"
                      "Do you want to upgrade these scripts?",cardpeek_dir);

        if ((response = gui_question(a_strval(astr),"Yes","No","No, don't ask me again",NULL))!=0)
        {
            log_printf(LOG_DEBUG,"The files in '%s' will not be upgraded.",cardpeek_dir);
            a_strfree(astr);

            if (response==2)
            {
                if ((f=g_fopen(version_file,"w"))!=NULL)
                {
                    fprintf(f,"%u\n",SCRIPT_VERSION);
                    fclose(f);
                }
            }
            return 0;
        }
        a_strfree(astr);
    }
    else
    {
        astr = a_strnew(NULL);
        a_sprintf(astr,"It seems this is the first time you run Cardpeek, because \n'%s' does not exit (%s).\n"
                  "Do you want to create '%s'?",cardpeek_dir,strerror(errno),cardpeek_dir);

        if (gui_question(a_strval(astr),"Yes","No",NULL)!=0)
        {
            log_printf(LOG_DEBUG,"'%s' will not be created",cardpeek_dir);
            a_strfree(astr);

            return 0;
        }

        a_strfree(astr);

#ifndef _WIN32
        if (mkdir(cardpeek_dir,0770)!=0)
#else
        if (mkdir(cardpeek_dir)!=0)
#endif
	{
            astr = a_strnew(NULL);
            a_sprintf(astr,"'%s' could not be created: %s",cardpeek_dir,strerror(errno));
            log_printf(LOG_ERROR,a_strval(astr));
            gui_question(a_strval(astr),"OK",NULL);
            a_strfree(astr);
            return 0;
        }
    }

    if (g_stat(old_replay_dir,&sbuf)==0)
    {
        if (rename(old_replay_dir,new_replay_dir)==0)
        {
            log_printf(LOG_INFO,"Renamed %s to %s.",
                       old_replay_dir, new_replay_dir);
        }
        else
        {
            log_printf(LOG_WARNING,"Failed to rename %s to %s: %s",
                       old_replay_dir, new_replay_dir, strerror(errno));
        }
    }

    cardpeek_resources = cardpeek_resources_get_resource();
    if (cardpeek_resources == NULL)
    {
        log_printf(LOG_ERROR,"Could not load cardpeek internal resources. This is not good.");
        return -1;
    }
    dot_cardpeek_tar_gz = g_resources_lookup_data("/cardpeek/dot_cardpeek.tar.gz",G_RESOURCE_LOOKUP_FLAGS_NONE,NULL);
    if (dot_cardpeek_tar_gz == NULL)
    {
        log_printf(LOG_ERROR,"Could not load .cardpeek.tar.gz");
        return -1;
    }
    dot_cardpeek_tar_gz_start = (unsigned char *)g_bytes_get_data(dot_cardpeek_tar_gz,&dot_cardpeek_tar_gz_size);

    if (chdir(cardpeek_dir)==-1)
    {
	log_printf(LOG_ERROR,"Could not change directory to '%s'",cardpeek_dir);
	return 0;
    }

    if ((f = g_fopen("dot_cardpeek.tar.gz","wb"))==NULL)
    {
        log_printf(LOG_ERROR,"Could not create dot_cardpeek.tar.gz in %s (%s)", cardpeek_dir, strerror(errno));
        gui_question("Could not create dot_cardpeek.tar.gz, aborting.","Ok",NULL);
        return 0;
    }

    if (fwrite(dot_cardpeek_tar_gz_start,dot_cardpeek_tar_gz_size,1,f)!=1)
    {
        log_printf(LOG_ERROR,"Could not write to dot_cardpeek.tar.gz in %s (%s)", cardpeek_dir, strerror(errno));
        gui_question("Could not write to dot_cardpeek.tar.gz, aborting.","Ok",NULL);
        fclose(f);
        return 0;
    }
    log_printf(LOG_DEBUG,"Wrote %i bytes to dot_cardpeek.tar.gz",dot_cardpeek_tar_gz_size);
    fclose(f);

    g_bytes_unref(dot_cardpeek_tar_gz);

    log_printf(LOG_INFO,"Created dot_cardpeek.tar.gz");
    log_printf(LOG_INFO,"Creating files in %s", cardpeek_dir);
    status = system("tar xzvf dot_cardpeek.tar.gz");
    log_printf(LOG_INFO,"'tar xzvf dot_cardpeek.tar.gz' returned %i",status);
    if (status!=0)
    {
        gui_question("Extraction of dot_cardpeek.tar.gz failed, aborting.","Ok",NULL);
        return 0;
    }
    status = system("rm dot_cardpeek.tar.gz");
    log_printf(LOG_INFO,"'rm dot_cardpeek.tar.gz' returned %i",status);

    gui_question("Note: The files have been created.\nIt is recommended that you quit and restart cardpeek, for changes to take effect.","Ok",NULL);
    return 1;
}