Example #1
0
// Starts and ends with a "
// FIXME: utf8 compatibility
// FIXME: escaping characters
ExcelValue parseString(char **string) {
  assert(*string[0] == '"'); // We've started with a "
  (*string)++;
  char *start = *string;
  char currentCharacter;
  while(true) {
    currentCharacter = **string;
    if(currentCharacter == '\0') {
      return parseFailed("Expected to see a closing \" before reaching the end of the line", start-1); // -1 for opening "
    }

    if(currentCharacter == EOF) {
      return parseFailed("Expected to see a closing \" before reaching the end of the file", start-1); // -1 for opening "
    }

    if(currentCharacter == '"') { break; }
    (*string)++;
  }
  int numberOfCharacters = *string - start;
  (*string)++; // Advance over the closing "
  char *matchedString = malloc(numberOfCharacters+1); // +1 for closing \0
  if(matchedString == 0) { return parseFailed("Out of memory when allocating string", start-1); }
  memcpy(matchedString, start, numberOfCharacters);
  matchedString[numberOfCharacters] = '\0';
  free_later(matchedString);
  return EXCEL_STRING(matchedString);
}
Example #2
0
ExcelValue startArray(char **string) {
  char *start = *string; // For error reporting
  (*string)++; // Advance over the [
  ExcelValue *array = malloc(ARRAY_ALLOC_SIZE * sizeof(ExcelValue));
  if(array == 0) { return parseFailed("Out of memory allocating the array", start); }
  int length = 0; // The first empty slot in the array
  int allocatedLength = ARRAY_ALLOC_SIZE;
  int rows = 0;
  int columns = 0;
  char *previousPosition;

  while(true) {
    previousPosition = *string;
    ExcelValue nextExcelValue = parse(string);

    if(*string == previousPosition) {
      // We have not made any progress, aborting
      return parseFailed("Expected to see a closing ] before reaching the end of the file", start);
    }

    if(nextExcelValue.type == END_OF_ARRAY.type && nextExcelValue.number == END_OF_ARRAY.number) {
      if(allocatedLength > length) {
        // Shrink our memory allocation
        array = realloc(array, length * sizeof(ExcelValue));
      }
      // Retain the array
      free_later(array);
      // Fix the number of rows
      if(rows == 0 && length > 0) { rows = 1; }
      // Return the right sort of excel value
      return EXCEL_RANGE(array,rows, columns);

    } else if(nextExcelValue.type == ExcelRange) {
      // If we are here, then we are a multi dimentional array

      if(nextExcelValue.rows > 1) {
        return parseFailed("Excel arrays can be, at most 2 dimensional.", start);
      }

      if(length > 0 && nextExcelValue.columns != columns) {
        return parseFailed("Array rows must be identically sized.", start);
      }

      // We have a new row
      rows++;

      // If the first row, define the number of columns
      if(length == 0) { columns = nextExcelValue.columns; }

      // FIXME: Should always have 1 row?
      int nextValueLength = nextExcelValue.rows * nextExcelValue.columns;

      // Resize the array if we need to
      while((length + nextValueLength) > allocatedLength) {
        array = realloc(array, (allocatedLength + ARRAY_ALLOC_SIZE)*sizeof(ExcelValue));
        if(array == 0) { return parseFailed("Out of memory extending the array", start); }
        allocatedLength = allocatedLength + ARRAY_ALLOC_SIZE;
      }

      // Copy over the values
      memcpy(&array[length], nextExcelValue.array, nextValueLength * sizeof(ExcelValue));

      // Update our count
      length = length + nextValueLength;

      // Clean up
      free(nextExcelValue.array);

    } else {
      // If we are here, then we are just adding a normal value to the end of a row
      columns++;

      // Resize the array if we need to
      if(length >= allocatedLength) {
        array = realloc(array, (allocatedLength + ARRAY_ALLOC_SIZE)*sizeof(ExcelValue));
        if(array == 0) { return parseFailed("Out of memory extending the array", start); }
        allocatedLength = allocatedLength + ARRAY_ALLOC_SIZE;
      }

      // Then put this element onto the end of the array
      array[length] = nextExcelValue;

      // Increment our count
      length++;
    }
  } 
  return parseFailed("Expected to see a closing ] before reaching the end of the file", start);
}
Example #3
0
    virtual void process()
    {
        // This happens in the installer thread, so we cannot mess with
        // anything else.

        HZIP zip = NULL;

        try
        {
            g_debug( "STARTING INSTALL OF %s", info.source_file.c_str() );

            //.................................................................

            if ( ! verify_and_strip_signatures() )
            {
                throw String( "SIGNATURE CHECK FAILED" );
            }

            //.................................................................
            // Open the source file to make sure it is ok

            zip = OpenZip( info.source_file.c_str(), NULL );

            if ( ! zip )
            {
                throw String( "FAILED TO OPEN ZIP FILE" );
            }

            ZIPENTRY entry;

            //.................................................................
            // Figure out how many items are in the zip file

            if ( ZR_OK != GetZipItem( zip, -1, &entry ) )
            {
                throw String( "FAILED TO GET ZIP ENTRY COUNT" );
            }

            int entry_count = entry.index;

            if ( entry_count <= 0 )
            {
                throw String( "ZIP FILE HAS TOO FEW ENTRIES" );
            }

            //.................................................................
            // Now go through all the items in the zip file, figure out
            // their total uncompressed size and find the 'app' file.

            guint64 total_uncompressed_size = 0;

            String app_file_zip_path;

            int app_file_zip_index = -1;

            guint64 app_file_uncompressed_size = 0;

            for ( int i = 0; i < entry_count; ++i )
            {
                if ( ZR_OK != GetZipItem( zip, i, &entry ) )
                {
                    throw String( "FAILED TO GET ZIP ENTRY" );
                }

                total_uncompressed_size += entry.unc_size;

                // See if this is the app file

                if ( app_file_zip_path.empty() )
                {
                    // THIS IS PLATFORM SPECIFIC

                    if ( ! ( entry.attr & S_IFDIR ) )
                    {
                        gchar * basename = g_path_get_basename( entry.name );

                        if ( ! strcmp( basename , "app" ) )
                        {
                            app_file_zip_path = entry.name;

                            app_file_zip_index = i;

                            app_file_uncompressed_size = entry.unc_size;
                        }

                        g_free( basename );
                    }
                }
            }

            if ( app_file_zip_path.empty() )
            {
                throw String( "ZIP FILE IS MISSING APP FILE" );
            }

            if ( app_file_uncompressed_size == 0 )
            {
                throw String( "APP FILE UNCOMPRESSED SIZE IS INCORRECT" );
            }

            g_debug( "FOUND APP FILE IN ZIP AT %s", app_file_zip_path.c_str() );

            //.................................................................
            // Uncompress the app file to memory and load its metadata.
            // We must ensure it is valid and its app_id is the same as the
            // one passed in.

            // g_new0 serves to NULL-terminate the contents, which
            // load_metadata_from_data expects.

            gchar * app_file_buffer = g_new0( gchar, app_file_uncompressed_size * 2 );

            if ( ! app_file_buffer )
            {
                throw String( "FAILED TO ALLOCATE MEMORY TO UNCOMPRESS APP FILE" );
            }

            FreeLater free_later;

            free_later( app_file_buffer );

            if ( ZR_OK != UnzipItem( zip, app_file_zip_index, app_file_buffer, app_file_uncompressed_size * 2 ) )
            {
                throw String( "FAILED TO UNCOMPRESS APP FILE" );
            }

            App::Metadata metadata;

            if ( ! App::load_metadata_from_data( app_file_buffer, metadata ) )
            {
                throw String( "FAILED TO READ METADATA" );
            }

            if ( metadata.id != info.app_id )
            {
                throw String( "APP ID DOES NOT MATCH" );
            }

            //.................................................................
            // Figure out where to unzip it to
            // - should be in the same volume as the app's data directory
            //
            // The app may already live in  trickplay/apps/<id hash>/source
            //
            // We could unzip it to         trickplay/apps/installing/<id hash>
            //      The benefit of this is that it would be easy to clean up unfinished
            //      installations by deleting everything in "installing".
            //
            // We could unzip it to         trickplay/apps/<id hash>/installing
            //      This puts it event closer to its final destination, but we would
            //      have to do more work to clean up. CHOOSING THIS ONE FOR NOW

            gchar * unzip_path = g_build_filename( info.app_directory.c_str(), "installing", NULL );

            free_later( unzip_path );

            //.................................................................
            // If our destination directory already exists, it is probably
            // from a failed attempt to install this app. We need to get rid of it.

            if ( g_file_test( unzip_path, G_FILE_TEST_EXISTS ) )
            {
                g_debug( "DELETING OLD INSTALL DIRECTORY %s", unzip_path );

                if ( ! recursive_delete_path( unzip_path ) )
                {
                    throw String( "FAILED TO DELETE OLD INSTALL DIRECTORY" );
                }
            }

            if ( 0 != g_mkdir_with_parents( unzip_path, 0700 ) )
            {
                throw String( "FAILED TO CREATE INSTALL DIRECTORY" );
            }

            //.................................................................
            // TODO: We should now check for free space - and make sure we have at
            // least total_uncompressed_size available.


            //.................................................................
            // OK, everything seems to be in order.
            // We get the dirname of the path to the app file in the zip.
            // So, for example, inside the zip, the app file might be in
            // "foor/bar/app". We have to take all the files in the zip that
            // are in "foo/bar" and unzip them to our real destination.

            gchar * app_file_zip_dirname = g_path_get_dirname( app_file_zip_path.c_str() );
            g_assert(app_file_zip_dirname);

            free_later( app_file_zip_dirname );

            guint app_file_zip_dirname_length = strlen( app_file_zip_dirname );

            // If there is no dirname, the above gets set to "."

            bool no_zip_root = ! strcmp( app_file_zip_dirname, "." );

            // Now, it is time to unzip

            g_debug( "UNZIPPING TO %s", unzip_path );

            guint64 total_processed = 0;

            Util::GTimer progress_timer;

#ifndef TP_PRODUCTION

            static float slow = -1;

            if ( slow == -1 )
            {
                if ( const char * e = g_getenv( "TP_INSTALL_DELAY" ) )
                {
                    slow = atof( e );
                }
                else
                {
                    slow = 0;
                }
            }

#endif

            for ( int i = 0; i < entry_count; ++i )
            {

#ifndef TP_PRODUCTION

                if ( slow )
                {
                    usleep( slow * G_USEC_PER_SEC );
                }

#endif

                if ( ZR_OK != GetZipItem( zip, i, &entry ) )
                {
                    throw String( "FAILED TO GET ZIP ENTRY" );
                }

                gchar * destination_file_name = NULL;

                if ( no_zip_root )
                {
                    destination_file_name = g_build_filename( unzip_path, entry.name, NULL );
                }
                else if ( g_str_has_prefix( entry.name, app_file_zip_dirname ) )
                {
                    destination_file_name = g_build_filename( unzip_path, entry.name + app_file_zip_dirname_length, NULL );
                }

                if ( ! destination_file_name )
                {
                    g_debug( "  SKIPPING %s", entry.name );
                }
                else
                {
                    free_later( destination_file_name );

                    g_debug( "  UNZIPPING %s", entry.name );

                    if ( ZR_OK != UnzipItem( zip, i, destination_file_name ) )
                    {
                        throw String( "FAILED TO UNZIP" );
                    }
                }

                // Report progress

                total_processed += entry.unc_size;

                if ( progress_timer.elapsed() >= 1 )
                {
                    progress_timer.reset();

                    info.status = Installer::Info::INSTALLING;
                    info.percent_installed = gdouble( total_processed ) / gdouble( total_uncompressed_size ) * 100.0;

                    send_progress();
                }
            }

            //.................................................................
            // At this point, the app should be uncompressed to the "installing"
            // directory and ready to go.

            //.................................................................
            // Finally, under the right conditions, we delete the existing install
            // of the app and move the "installing" directory over it.

            info.moved = false;

            gchar * source_path = g_build_filename( info.app_directory.c_str(), "source", NULL );

            free_later( source_path );

            bool source_exists = g_file_test( source_path, G_FILE_TEST_EXISTS );

            // If the source directory exists and the app is locked, we can
            // delete the source directory

            if ( source_exists && info.locked )
            {
                if ( ! recursive_delete_path( source_path ) )
                {
                    throw String( "FAILED TO DELETE PREVIOUS APP SOURCE" );
                }

                source_exists = false;
            }

            // If the source directory does not already exist, or we deleted in the
            // previous step, we can rename the install directory.

            if ( ! source_exists )
            {
                if ( 0 != g_rename( unzip_path, source_path ) )
                {
                    throw String( "FAILED TO RENAME INSTALL DIRECTORY TO SOURCE DIRECTORY" );
                }

                info.moved = true;
            }

            // Once this is done, the caller needs to call 'complete_install'. This will
            // move the app to its final resting place (if necessary) and also add its
            // entry to the system database.

            g_debug( "FINISHED INSTALL OF %s TO %s", info.app_id.c_str(), info.moved ? source_path : unzip_path );

            info.status = Installer::Info::FINISHED;

            info.install_directory = unzip_path;

            info.app_directory = source_path;

            send_progress();

            // Caller is also reponsible for getting rid of the original zip file.
        }
        catch( const String & e )
        {
            g_warning( "FAILED TO INSTALL %s FROM %s : %s", info.app_id.c_str(), info.source_file.c_str(), e.c_str() );

            info.status = Installer::Info::FAILED;

            send_progress( );
        }

        // Close the zip file

        if ( zip )
        {
            CloseZip( zip );
        }

        // Always return true - to keep the thread running
    }
Example #4
0
int utf8_luacall_utf8_sub(lua_State *l) {
    /// Reimplements lua's sub, but with unicode char indexes (the regular
    /// sub is not unicode aware and supports byte indexes only).
    /// Will throw error for any strings that aren't valid utf-8.
    luaL_checkstack(l, 4, "");
    if (lua_type(l, 1) != LUA_TSTRING) {
        lua_pushstring(l, "invalid argument #1: not a string");
        return lua_error(l);
    }
    if (lua_type(l, 2) != LUA_TNUMBER) {
        lua_pushstring(l, "invalid argument #2: not a number");
        return lua_error(l);
    }
    if (lua_type(l, 3) != LUA_TNUMBER && lua_type(l, 3) != LUA_TNIL
            && lua_type(l, 3) != LUA_TNONE) {
        lua_pushstring(l, "invalid argument #3: not a number");
        return lua_error(l);
    }
    size_t bufsize;
    const unsigned char *buf = (unsigned char*)luaL_checklstring(l, 1,
        &bufsize);
    if (!utf8_is_valid(buf, bufsize)) {
        lua_pushstring(l, "not a valid utf-8 string");
        return lua_error(l);
    }

    // obtain start, end:
    int start = (int)lua_tonumber(l, 2);
    int end = -1;
    if (lua_type(l, 3) == LUA_TNUMBER) {
        end = (int)lua_tonumber(l, 3);
    }
    size_t length = utf8_length(buf, bufsize);
    if (start < 0) {
        start = (length + 1) + start;
    }
    if (end < 0) {
        end = (length + 1) + end;
    }

    // enforce sane limits:
    if (start < 1) {start = 1;}
    if (end > (int)length) {end = length;}
    if (start > (int)length || end < 1 || end < start) {
        // empty string.
        lua_pushstring(l, "");
        return 1;
    }

    // obtain the result:
    UChar32 c;
    size_t startbytepos, endbytepos;
    int currentpos = 1;
    int i = 0;
    while (i < (int)bufsize) {
        if (currentpos == start) {
            startbytepos = i;
        }
        if (currentpos == end) {
            endbytepos = i + 1;
            break;
        }
        U8_NEXT(buf, i, bufsize, c);
        currentpos = currentpos + 1;
    }
    assert(endbytepos > startbytepos);
    char *resultbuf = malloc(1 + endbytepos - startbytepos);
    if (!resultbuf) {
        lua_pushstring(l, "allocation of end result failed");
        return lua_error(l);
    }
    free_later(resultbuf);
    memcpy(resultbuf, buf + startbytepos, endbytepos - startbytepos);
    resultbuf[endbytepos - startbytepos] = 0;
    lua_pushstring(l, resultbuf);
    dont_free_later(resultbuf);
    free(resultbuf);
    return 1;
}
Example #5
0
    virtual int decode( const char * filename, TPImage * image )
    {
        if ( ! enabled() )
        {
            tplog( "  EXTERNAL IMAGE DECODER IS DISABLED" );

            return TP_IMAGE_UNSUPPORTED_FORMAT;
        }

        std::ifstream stream;

        stream.open( filename, std::ios_base::in | std::ios_base::binary );

        if ( ! stream.good() )
        {
            stream.close();
            return TP_IMAGE_DECODE_FAILED;
        }

        // We read the first few bytes of the file and pass that to the decoder
        // to see if it can detect the image format and tell us that it is
        // supported.

        // This attempts to optimize by not reading in the whole file before we
        // know whether the decoder supports it.

        static gsize header_size = 64;

        char header[ header_size ];

        stream.read( header, header_size );

        tplog( "  INVOKING EXTERNAL DECODER TO DETECT IMAGE FORMAT WITH %d BYTES", stream.gcount() );

        int r = decoder( header, stream.gcount(), NULL, decoder_data );

        tplog( "    EXTERNAL DECODER RETURNED %d", r );

        if ( r != TP_IMAGE_SUPPORTED_FORMAT )
        {
            stream.close();

            // Return unsupported format so that we will try other decoders

            return TP_IMAGE_UNSUPPORTED_FORMAT;
        }

        // The decoder says that it supports the format, so we load
        // the whole file into memory and call the decoder again.

        stream.seekg( 0, std::ios::end );

        if ( stream.fail() )
        {
            stream.close();
            return TP_IMAGE_DECODE_FAILED;
        }

        std::ios::streampos pos = stream.tellg();

        if ( pos == -1 )
        {
            stream.close();
            return TP_IMAGE_DECODE_FAILED;
        }

        gchar * buffer = g_new( gchar, pos );

        if ( ! buffer )
        {
            stream.close();
            return TP_IMAGE_DECODE_FAILED;
        }

        FreeLater free_later( buffer );

        stream.seekg( 0 );

        stream.read( buffer, pos );

        if ( stream.fail() )
        {
            stream.close();
            return TP_IMAGE_DECODE_FAILED;
        }

        return decode( buffer, pos, image );
    }