/*
 * [ alcatel-ex.c by powerpork of netric (http://www.netric.org) ]
 *
 * Quick hack to extract files from the ramdisk image located in the
 * alcatel speedtouch home/pro modems. The format of these files
 * had to be reverse enginered and I only had 1 file to test on
 * so it might be utter crap.
 *
 * example: ./alcatel-ex GSV7AA3.270
 *
 * This will recursively extract all the files packed in this 
 * file into the current directory.
 *
 * Contact: powerpork@netric.org
 *
 */
  

#include <stdio.h>

#define STR_NOT_FOUND          0xFFFFFFFF

void * rfile(char * path, unsigned long * size);
unsigned int wfile(char * path, void * buf, unsigned int size);
unsigned int findstring(char * buffer, unsigned int bsize, char * key, int start);
int ppath(char * path);

int main(int argc, char ** argv[])
{
  unsigned long * fsize;
  unsigned int buf=0,c=0,ic=0,ifname=0,ifptr=0,ifsize=0;

  if(!(argc>=1)){
    printf("ERROR: No filename to process\n");
  }

  buf = (unsigned int)rfile(argv[1], fsize);
  if(buf == 0){
    printf("ERROR: read error\n");
    exit(1);
  }else{
    printf("[size=%u]\n", *fsize);
  }

  c=0;
  ic=0;
  while(c != STR_NOT_FOUND){
    if(c!=0){
      printf("[name=%s]\n", c+buf);
      ifname=(c+buf);
      if(((char *)buf+c)[strlen(((char *)c+buf))-1] == 47){
	c=findstring((char *)buf, *fsize, "active/", c+1);
      }else{      
	c=findstring((char *)buf, *fsize, "we2", c);
	for(c+=3;((char*)buf)[c]==0;c++){}
	//printf("[stub=%s]\n", c+buf);
	ifptr = (c+buf);
	ic=findstring((char *)buf, *fsize, "active/", c+1);
	if(ic==STR_NOT_FOUND){
	  ic = *fsize;
	}
	for(ic--;((char*)buf)[ic]==0;ic--){}
	ifsize = ((ic+buf)-ifptr+1);
	printf("[size=%u]\n", ifsize);
	wfile(ifname, ifptr, ifsize);
      }
    }
    c=findstring((char *)buf, *fsize, "active/", c+1);
  }
  
  //wfile("active/blaat2.txt", "blaat!", 5);

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

void * rfile(char * path, unsigned long * size)
{
  FILE * file;
  unsigned int rsize=0, buf=0;
  long fsize=0;

  file = fopen(path, "rb");
  if(file == NULL){ return 0; }

  fseek(file, 0, SEEK_END);
  fsize = ftell(file);
  *size = fsize;
  rewind(file);

  buf = malloc(size);
  *size = fread((void *)buf, 1, *size, file);
  if(*size == 0){ return 0; }

  fclose(file);
  return (void *)buf;
}

unsigned int findstring(char * buffer, unsigned int bsize, char * key, int start)
{
  int indexcounter=0;

  for(indexcounter=start;(indexcounter<bsize);indexcounter++){
    if(strncmp((((char*)buffer)+indexcounter), key, strlen(key))==0){
      return indexcounter;
    }
  }
  
  return STR_NOT_FOUND;
}

unsigned int wfile(char * path, void * buf, unsigned int size)
{
  FILE * file;
  unsigned int wsize=0;

  ppath(path);

  file = fopen(path, "wb");
  if(file == NULL){
    return 0;
  }

  wsize = fwrite(buf, 1, size, file);

  fclose(file);
  return wsize;
}

int ppath(char * path)
{
  int c=0;
  unsigned int pbuf=0,opbuf=0;

  pbuf = malloc(strlen(path));
  opbuf = pbuf;

  if(pbuf == 0){
    return -1;
  }
  strcpy(pbuf, path);

  while(c!=STR_NOT_FOUND){
    c=findstring(pbuf, strlen(pbuf), "/", c);
    if(c!=STR_NOT_FOUND){
      ((char*)pbuf)[c] = 0;
      mkdir((pbuf), 4095);
      ((char*)pbuf)[c] = 47;
      c++;
    }
  }

  free(opbuf);

  return 0;
}
