| 1 | /* |
| 2 | catalog.h: the catalogue (schema 3), an index and pages. |
| 3 |
|
| 4 | catalog.json is the index: for each section (homebrew, theme, avatar) its |
| 5 | lists (homebrew: one per site category; themes and avatars: all, then one per |
| 6 | category or region), and for each list its pages of up to page_size items, a |
| 7 | search.txt and where each letter starts. Pages are fetched as the list reaches |
| 8 | them. An avatar list's items are packs: folders, each with a list of its own. |
| 9 | It may also name the newest PS3 World PKG ("app": version, url, size, sha256). |
| 10 | */ |
| 11 | #ifndef CATALOG_H |
| 12 | #define CATALOG_H |
| 13 |
|
| 14 | #include <stddef.h> |
| 15 |
|
| 16 | #define CATALOG_URL "https://dl.ps3.world/catalog/v1/catalog.json" |
| 17 | #define CATALOG_BASE "https://dl.ps3.world/" // every page, download and icon is under this |
| 18 | #define CATALOG_SCHEMA 3 // 3: avatar packs as folders (an older app would download a pack's page as an avatar) |
| 19 |
|
| 20 | enum { TYPE_HOMEBREW, TYPE_THEME, TYPE_AVATAR, NUM_TYPES }; |
| 21 | enum { REQ_ANY, REQ_HEN, REQ_CFW }; |
| 22 |
|
| 23 | // a file the index lists, with the sha256 it must have |
| 24 | typedef struct { |
| 25 | char url[160]; // relative to CATALOG_BASE |
| 26 | unsigned char sha256[32]; |
| 27 | } cat_file_t; |
| 28 |
|
| 29 | #define NUM_LETTERS 27 // '#', then A..Z |
| 30 | enum { SORT_AZ, SORT_NEWEST, SORT_LARGEST, NUM_SORTS }; |
| 31 | typedef struct cat_list_s { |
| 32 | char name[32]; // "Games", "Ports"...; "All themes", "Anime & Comics"...; "All avatars", "US"... |
| 33 | int count; |
| 34 | int num_pages; |
| 35 | cat_file_t *pages; |
| 36 | cat_file_t search; |
| 37 | int letter_first[NUM_LETTERS]; // where each letter starts in the list, -1 if none |
| 38 | struct cat_list_s *sorted; // the same items newest first, then largest first (NULL: none; 1.2.0 on) |
| 39 | int num_sorted; |
| 40 | } cat_list_t; |
| 41 |
|
| 42 | typedef struct { |
| 43 | char version[16]; // "" when the catalogue offers none |
| 44 | cat_file_t file; // the PKG |
| 45 | long long size; |
| 46 | } cat_app_t; |
| 47 |
|
| 48 | #define MAX_DESC_LANGS 16 |
| 49 | typedef struct { |
| 50 | char code[8]; // "es"... |
| 51 | cat_file_t file; // id: description, for homebrew |
| 52 | } cat_desc_t; |
| 53 |
|
| 54 | typedef struct { |
| 55 | char generated[32]; |
| 56 | cat_app_t app; // the newest PS3 World (the app checks it against its own version) |
| 57 | cat_desc_t desc[MAX_DESC_LANGS]; // homebrew's descriptions in other languages (1.2.0 on) |
| 58 | int num_desc; |
| 59 | int page_size; |
| 60 | int count[NUM_TYPES]; |
| 61 | int num_lists[NUM_TYPES]; |
| 62 | cat_list_t *lists[NUM_TYPES]; |
| 63 | } cat_index_t; |
| 64 |
|
| 65 | typedef struct { |
| 66 | // all in the page's string block; "" when the catalogue has none |
| 67 | const char *id, *title, *author, *version, *description, *group; |
| 68 | const char *url; // relative to CATALOG_BASE |
| 69 | const char *icon; // relative to CATALOG_BASE, "" for none |
| 70 | const char *preview; // a bigger picture (a theme's 480x270, an avatar's 240x240), "" for none |
| 71 | const char *list; // a folder (an avatar pack): its own list, as the index's JSON; "" for a file |
| 72 | const char *title_id; // homebrew: the PKG's title ID ("PSWD00001"), the folder it installs to in /dev_hdd0/game; "" if not known |
| 73 | long long size; // (a folder: all its files) |
| 74 | long long updated; // homebrew: when the catalogue's PKG last changed (seconds since 1970), 0 if it hasn't |
| 75 | unsigned char sha256[32]; |
| 76 | unsigned char type, requires; |
| 77 | } cat_item_t; |
| 78 |
|
| 79 | // one page of a list |
| 80 | typedef struct { |
| 81 | int count; |
| 82 | cat_item_t *items; |
| 83 | char *strings; |
| 84 | } catalog_t; |
| 85 |
|
| 86 | // NULL on failure, with the reason in err; items that don't check out are skipped (and logged) |
| 87 | cat_index_t *catalog_parse_index(const char *json, size_t len, char *err, int errsize); |
| 88 | void catalog_free_index(cat_index_t *ix); |
| 89 | catalog_t *catalog_parse_page(const char *json, size_t len, char *err, int errsize); |
| 90 | void catalog_free(catalog_t *c); |
| 91 | // a folder's list (its item's "list"); 0 if it doesn't check out. catalog_free_list frees and zeroes it |
| 92 | int catalog_parse_list(const char *json, cat_list_t *l); |
| 93 | void catalog_free_list(cat_list_t *l); |
| 94 |
|
| 95 | const char *catalog_type_name(int type); // "homebrew", "theme", "avatar" |
| 96 | int catalog_letter_slot(char letter); // '#' 0, 'A'..'Z' 1..26 |
| 97 | // a copy of an item that owns its strings (for the detail screen, after its page has gone) |
| 98 | cat_item_t *catalog_item_copy(const cat_item_t *it); |
| 99 |
|
| 100 | #endif |