├── source ├── 7z.h ├── lumautils.h ├── 7z │ ├── Precomp.h │ ├── Compiler.h │ ├── Delta.h │ ├── 7zAlloc.h │ ├── 7zMemInStream.h │ ├── 7zBuf.c │ ├── 7zCrc.h │ ├── 7zBuf.h │ ├── Delta.c │ ├── 7zAlloc.c │ ├── Bra.c │ ├── Bra.h │ ├── LzHash.h │ ├── 7zMemInStream.c │ ├── Bra86.c │ ├── Lzma2Dec.h │ ├── 7zCrc.c │ ├── 7zCrcOpt.c │ ├── Bcj2.h │ ├── CpuArch.h │ ├── 7zStream.c │ ├── 7z.h │ ├── 7zTypes.h │ ├── Bcj2.c │ └── LzmaDec.h ├── update.h ├── libs.h ├── arnutil.h ├── version.h ├── archive.h ├── httpc.h ├── http.h ├── config.cpp ├── config.h ├── console.h ├── autoupdate.h ├── jsmn.h ├── minizip │ ├── ioapi_mem.h │ ├── crypt.h │ ├── ioapi_mem.c │ └── ioapi.h ├── release.h ├── main.h ├── http.cpp ├── utils.h ├── lumautils.cpp ├── archive.cpp ├── md5 │ └── md5.h ├── console.cpp ├── version.cpp ├── arnutil.cpp ├── utils.cpp ├── certs │ ├── cybertrust.h │ └── digicert.h ├── httpc.cpp ├── autoupdate.cpp ├── jsmn.c └── release.cpp ├── meta ├── icon.png ├── jingle.wav ├── luma.cgfx ├── logo.bcma.lz └── src │ ├── GLARE.bmp │ ├── GLARE.psd │ ├── icon.psd │ ├── COMMON.bmp │ ├── COMMON.psd │ ├── luma.wings │ ├── jingle.orig.wav │ ├── luma.merged.wings │ ├── LUMA.mtl │ └── luma.merged.mtl ├── qr codes ├── qrcode-v1.5.png ├── qrcode-v2.0.png ├── qrcode-v2.1.1.png ├── qrcode-v2.1.2.png ├── qrcode-v2.1.png ├── qrcode-v2.2.png └── qrcode-v2.3.png ├── lumaupdater.cfg ├── .gitignore ├── LICENSE.txt ├── LICENSE.minizip.txt ├── Makefile.config ├── LICENSE.libmd5-rfc.txt ├── LICENSE.jsmn.txt ├── .github └── issue_template.md ├── README.md ├── Makefile └── rominfo.rsf /source/7z.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 7z includes */ 4 | -------------------------------------------------------------------------------- /meta/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/meta/icon.png -------------------------------------------------------------------------------- /meta/jingle.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/meta/jingle.wav -------------------------------------------------------------------------------- /meta/luma.cgfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/meta/luma.cgfx -------------------------------------------------------------------------------- /meta/logo.bcma.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/meta/logo.bcma.lz -------------------------------------------------------------------------------- /meta/src/GLARE.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/meta/src/GLARE.bmp -------------------------------------------------------------------------------- /meta/src/GLARE.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/meta/src/GLARE.psd -------------------------------------------------------------------------------- /meta/src/icon.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/meta/src/icon.psd -------------------------------------------------------------------------------- /meta/src/COMMON.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/meta/src/COMMON.bmp -------------------------------------------------------------------------------- /meta/src/COMMON.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/meta/src/COMMON.psd -------------------------------------------------------------------------------- /meta/src/luma.wings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/meta/src/luma.wings -------------------------------------------------------------------------------- /meta/src/jingle.orig.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/meta/src/jingle.orig.wav -------------------------------------------------------------------------------- /meta/src/luma.merged.wings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/meta/src/luma.merged.wings -------------------------------------------------------------------------------- /qr codes/qrcode-v1.5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/qr codes/qrcode-v1.5.png -------------------------------------------------------------------------------- /qr codes/qrcode-v2.0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/qr codes/qrcode-v2.0.png -------------------------------------------------------------------------------- /qr codes/qrcode-v2.1.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/qr codes/qrcode-v2.1.1.png -------------------------------------------------------------------------------- /qr codes/qrcode-v2.1.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/qr codes/qrcode-v2.1.2.png -------------------------------------------------------------------------------- /qr codes/qrcode-v2.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/qr codes/qrcode-v2.1.png -------------------------------------------------------------------------------- /qr codes/qrcode-v2.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/qr codes/qrcode-v2.2.png -------------------------------------------------------------------------------- /qr codes/qrcode-v2.3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunoichiZ/lumaupdate/HEAD/qr codes/qrcode-v2.3.png -------------------------------------------------------------------------------- /lumaupdater.cfg: -------------------------------------------------------------------------------- 1 | payload type = sighax 2 | payload path = boot.firm 3 | log enable = yes 4 | selfupdate = yes 5 | backup = yes -------------------------------------------------------------------------------- /source/lumautils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libs.h" 4 | 5 | /*! \brief Migrate payload names to latest version 6 | * 7 | * \return true if everything succeeds, false otherwise 8 | */ 9 | bool lumaMigratePayloads(); -------------------------------------------------------------------------------- /source/7z/Precomp.h: -------------------------------------------------------------------------------- 1 | /* Precomp.h -- StdAfx 2 | 2013-11-12 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __7Z_PRECOMP_H 5 | #define __7Z_PRECOMP_H 6 | 7 | #include "Compiler.h" 8 | /* #include "7zTypes.h" */ 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /source/7z/Compiler.h: -------------------------------------------------------------------------------- 1 | /* Compiler.h 2 | 2015-08-02 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __7Z_COMPILER_H 5 | #define __7Z_COMPILER_H 6 | 7 | #define UNUSED_VAR(x) (void)x; 8 | /* #define UNUSED_VAR(x) x=x; */ 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /meta/src/LUMA.mtl: -------------------------------------------------------------------------------- 1 | # Exported from Wings 3D 2.0.3 2 | newmtl COMMON 3 | Ns 100.0 4 | d 1.0 5 | illum 2 6 | Kd 1.0 1.0 1.0 7 | Ka 1.0 1.0 1.0 8 | Ks 1.0 1.0 1.0 9 | Ke 0.0 0.0 0.0 10 | map_Kd COMMON.bmp 11 | 12 | newmtl GLARE 13 | Ns 100.0 14 | d 1.0 15 | illum 2 16 | Kd 1.0 1.0 1.0 17 | Ka 1.0 1.0 1.0 18 | Ks 1.0 1.0 1.0 19 | Ke 0.0 0.0 0.0 20 | map_Kd GLARE.bmp -------------------------------------------------------------------------------- /source/update.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libs.h" 4 | 5 | #include "main.h" 6 | #include "release.h" 7 | 8 | #define MAXPATHLEN 37 9 | 10 | struct UpdateResult { 11 | bool success; /*!< Wether the operation was a success */ 12 | std::string errcode; /*!< Error code if success is false */ 13 | }; 14 | 15 | UpdateResult update(const UpdateInfo& args); 16 | UpdateResult restore(const UpdateInfo& args); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build output 2 | *.3dsx 3 | *.elf 4 | *.smdh 5 | *.cia 6 | *.zip 7 | *.lst 8 | *.map 9 | out 10 | build 11 | archive 12 | 13 | # Visual studio stuff 14 | *.sln 15 | *.opendb 16 | *.sdf 17 | *.opensdf 18 | *.db 19 | *.vcxproj* 20 | Debug 21 | build 22 | *.cer 23 | .vs 24 | 25 | # Hamcha's terrible commands 26 | send.cmd 27 | 28 | # Bannertool.exe and makerom.exe 29 | *.exe 30 | 31 | # .txt files 32 | *.txt 33 | 34 | # external folder 35 | external -------------------------------------------------------------------------------- /source/7z/Delta.h: -------------------------------------------------------------------------------- 1 | /* Delta.h -- Delta converter 2 | 2013-01-18 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __DELTA_H 5 | #define __DELTA_H 6 | 7 | #include "7zTypes.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | #define DELTA_STATE_SIZE 256 12 | 13 | void Delta_Init(Byte *state); 14 | void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size); 15 | void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size); 16 | 17 | EXTERN_C_END 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /source/7z/7zAlloc.h: -------------------------------------------------------------------------------- 1 | /* 7zAlloc.h -- Allocation functions 2 | 2013-03-25 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __7Z_ALLOC_H 5 | #define __7Z_ALLOC_H 6 | 7 | #include 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | void *SzAlloc(void *p, size_t size); 14 | void SzFree(void *p, void *address); 15 | 16 | void *SzAllocTemp(void *p, size_t size); 17 | void SzFreeTemp(void *p, void *address); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /source/7z/7zMemInStream.h: -------------------------------------------------------------------------------- 1 | /* 7zMemInStream.h -- Memory input stream 2 | ** 2012 - Birunthan Mohanathas 3 | ** 4 | ** This file is public domain. 5 | */ 6 | 7 | #ifndef __7Z_MEMINSTREAM_H 8 | #define __7Z_MEMINSTREAM_H 9 | 10 | #include "7zTypes.h" 11 | 12 | EXTERN_C_BEGIN 13 | 14 | typedef struct 15 | { 16 | ILookInStream s; 17 | const Byte *begin; 18 | const Byte *pos; 19 | const Byte *end; 20 | } CMemInStream; 21 | 22 | void MemInStream_Init(CMemInStream *p, const void *begin, size_t length); 23 | 24 | EXTERN_C_END 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2016 Alessandro Gatti 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | 15 | -------------------------------------------------------------------------------- /source/libs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // STL includes 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | // CSTD includes 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | // CTRULIB includes 21 | #pragma GCC diagnostic push 22 | #pragma GCC diagnostic ignored "-Wpedantic" 23 | #include <3ds.h> 24 | #pragma GCC diagnostic pop 25 | 26 | //CURL includes 27 | #include -------------------------------------------------------------------------------- /meta/src/luma.merged.mtl: -------------------------------------------------------------------------------- 1 | # Exported from Wings 3D 2.0.3 2 | newmtl COMMON 3 | Ns 100.0 4 | d 1.0 5 | illum 2 6 | Kd 1.0 1.0 1.0 7 | Ka 1.0 1.0 1.0 8 | Ks 1.0 1.0 1.0 9 | Ke 0.0 0.0 0.0 10 | map_Kd Cube2_auv.bmp 11 | 12 | newmtl GLARE 13 | Ns 100.0 14 | d 1.0 15 | illum 2 16 | Kd 1.0 1.0 1.0 17 | Ka 1.0 1.0 1.0 18 | Ks 1.0 1.0 1.0 19 | Ke 0.0 0.0 0.0 20 | map_Kd box.png 21 | 22 | newmtl default 23 | Ns 0.0 24 | d 1.0 25 | illum 2 26 | Kd 0.8333333333333334 0.7428571428571428 0.6444444444444445 27 | Ka 0.8333333333333334 0.7428571428571428 0.6444444444444445 28 | Ks 0.0 0.0 0.0 29 | Ke 0.0 0.0 0.0 30 | 31 | -------------------------------------------------------------------------------- /source/7z/7zBuf.c: -------------------------------------------------------------------------------- 1 | /* 7zBuf.c -- Byte Buffer 2 | 2013-01-21 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "7zBuf.h" 7 | 8 | void Buf_Init(CBuf *p) 9 | { 10 | p->data = 0; 11 | p->size = 0; 12 | } 13 | 14 | int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc) 15 | { 16 | p->size = 0; 17 | if (size == 0) 18 | { 19 | p->data = 0; 20 | return 1; 21 | } 22 | p->data = (Byte *)alloc->Alloc(alloc, size); 23 | if (p->data != 0) 24 | { 25 | p->size = size; 26 | return 1; 27 | } 28 | return 0; 29 | } 30 | 31 | void Buf_Free(CBuf *p, ISzAlloc *alloc) 32 | { 33 | alloc->Free(alloc, p->data); 34 | p->data = 0; 35 | p->size = 0; 36 | } 37 | -------------------------------------------------------------------------------- /source/7z/7zCrc.h: -------------------------------------------------------------------------------- 1 | /* 7zCrc.h -- CRC32 calculation 2 | 2013-01-18 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __7Z_CRC_H 5 | #define __7Z_CRC_H 6 | 7 | #include "7zTypes.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | extern UInt32 g_CrcTable[]; 12 | 13 | /* Call CrcGenerateTable one time before other CRC functions */ 14 | void MY_FAST_CALL CrcGenerateTable(void); 15 | 16 | #define CRC_INIT_VAL 0xFFFFFFFF 17 | #define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL) 18 | #define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) 19 | 20 | UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); 21 | UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); 22 | 23 | EXTERN_C_END 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /source/arnutil.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libs.h" 4 | #include "version.h" 5 | 6 | /*! \brief Check if the specified version is before the name change 7 | * arnVersionCheck checks wether the version is lower than 5.2 8 | * (ie. before the name change from AuReiNand to Luma3DS) 9 | * 10 | * \param versionString Version string found in payload 11 | * 12 | * \return true if the payload is AuReiNand (<5.2), false otherwsie 13 | */ 14 | bool arnVersionCheck(const LumaVersion& versionString); 15 | 16 | /*! \brief Migrate AuReiNand install to Luma3DS 17 | * Migrate an AuReiNand install to a Luma3DS by renaming the aurei/ 18 | * folder to luma/ 19 | * 20 | * \return true if the migration was successful, false otherwise 21 | */ 22 | bool arnMigrate(); -------------------------------------------------------------------------------- /source/7z/7zBuf.h: -------------------------------------------------------------------------------- 1 | /* 7zBuf.h -- Byte Buffer 2 | 2013-01-18 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __7Z_BUF_H 5 | #define __7Z_BUF_H 6 | 7 | #include "7zTypes.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | typedef struct 12 | { 13 | Byte *data; 14 | size_t size; 15 | } CBuf; 16 | 17 | void Buf_Init(CBuf *p); 18 | int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc); 19 | void Buf_Free(CBuf *p, ISzAlloc *alloc); 20 | 21 | typedef struct 22 | { 23 | Byte *data; 24 | size_t size; 25 | size_t pos; 26 | } CDynBuf; 27 | 28 | void DynBuf_Construct(CDynBuf *p); 29 | void DynBuf_SeekToBeg(CDynBuf *p); 30 | int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); 31 | void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); 32 | 33 | EXTERN_C_END 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /LICENSE.minizip.txt: -------------------------------------------------------------------------------- 1 | Condition of use and distribution are the same as zlib: 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgement in the product documentation would be 14 | appreciated but is not required. 15 | 2. Altered source versions must be plainly marked as such, and must not be 16 | misrepresented as being the original software. 17 | 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------------- /Makefile.config: -------------------------------------------------------------------------------- 1 | # Homebrew info 2 | 3 | APP_TITLE := Luma3DS Updater 4 | APP_DESCRIPTION := Updater for Luma3DS releases 5 | APP_AUTHOR := KunoichiZ / Hamcha 6 | 7 | ICON := meta/icon.png 8 | 9 | 10 | # CIA info 11 | 12 | PRODUCT_CODE := CTR-L-UPDR 13 | UNIQUE_ID := 0x1deb 14 | 15 | BANNER_AUDIO := meta/jingle.wav 16 | BANNER_IMAGE := meta/luma.cgfx 17 | 18 | # Directories 19 | 20 | BINNAME := lumaupdater 21 | BINDIR := out 22 | BUILD := build 23 | SOURCES := source source/7z source/minizip source/md5 24 | DATA := data 25 | 26 | # Build info 27 | 28 | LIBRARIES := curl mbedtls mbedx509 mbedcrypto z ctru m 29 | 30 | ### HB-specific makefile code ### 31 | 32 | # Use fallbacks and mocks to compile a version that works on Citra if wanted 33 | ifdef CITRA 34 | EXTRACFLAGS := -DFAKEDL 35 | endif 36 | 37 | # Expose UNIQUE_ID (with padding) to updater for CIA detection 38 | EXTRACFLAGS += -DUNIQUE_ID=$(UNIQUE_ID)00 39 | -------------------------------------------------------------------------------- /source/version.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libs.h" 4 | 5 | /*! \brief Version data 6 | */ 7 | struct LumaVersion { 8 | std::string release; // Release number (ie. 6.1.1) 9 | std::string commit; // Commit hash (ie. 59ab44a8) 10 | bool isDev; // Is developer branch? 11 | 12 | const std::string toString(bool printBranch = true) const; 13 | bool isValid() const { return !release.empty(); } 14 | }; 15 | 16 | /*! \brief Tries to detect the current Luma3DS version by using SVC 0x2e (when supported) 17 | * 18 | * \return LumaVersion struct containing all the information that could be retrieved 19 | */ 20 | LumaVersion versionSvc(); 21 | 22 | /*! \brief Tries to detect currently installed Luma3DS/AuReiNand version by searching the payload 23 | * 24 | * \param path Path to existing payload 25 | * 26 | * \return LumaVersion struct containing all the information that could be found 27 | */ 28 | LumaVersion versionMemsearch(const std::string& path); -------------------------------------------------------------------------------- /LICENSE.libmd5-rfc.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgment in the product documentation would be 14 | appreciated but is not required. 15 | 2. Altered source versions must be plainly marked as such, and must not be 16 | misrepresented as being the original software. 17 | 3. This notice may not be removed or altered from any source distribution. 18 | 19 | L. Peter Deutsch 20 | ghost@aladdin.com -------------------------------------------------------------------------------- /source/archive.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libs.h" 4 | 5 | // 7z includes 6 | #include "7z/7z.h" 7 | #include "7z/7zAlloc.h" 8 | #include "7z/7zCrc.h" 9 | #include "7z/7zMemInStream.h" 10 | 11 | // minizip includes 12 | #include "minizip/ioapi_mem.h" 13 | #include "minizip/unzip.h" 14 | 15 | class ZipArchive { 16 | private: 17 | ourmemory_t unzmem = {}; 18 | zlib_filefunc_def filefunc32 = {}; 19 | unzFile zipfile = nullptr; 20 | 21 | public: 22 | ZipArchive(const u8* arcData, const u32 arcSize); 23 | ~ZipArchive(); 24 | 25 | void extractFile(std::string name, u8** fileData, size_t* fileSize); 26 | }; 27 | 28 | class SzArchive { 29 | private: 30 | CMemInStream memStream; 31 | CSzArEx db; 32 | ISzAlloc allocImp; 33 | ISzAlloc allocTempImp; 34 | 35 | std::map files; 36 | void buildFileIndex(); 37 | 38 | public: 39 | SzArchive(const u8* arcData, const u32 arcSize); 40 | ~SzArchive(); 41 | 42 | void extractFile(std::string name, u8** fileData, size_t* fileSize, size_t* offset); 43 | }; -------------------------------------------------------------------------------- /source/httpc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libs.h" 4 | 5 | class HTTPC{ 6 | public: 7 | Result Init(u32 mem); 8 | Result Exit(void); 9 | Result OpenContext(httpcContext *context, HTTPC_RequestMethod method, char *url, u32 use_defaultproxy); 10 | Result CloseContext(httpcContext *context); 11 | Result GetResponseStatusCode(httpcContext *context, u32 *statuscode); 12 | Result AddRequestHeaderField(httpcContext *context, char *name, char *url); 13 | Result BeginRequest(httpcContext *context); 14 | Result GetResponseHeader(httpcContext *context, char* _name, char* value, u32 valuebuf_maxsize); 15 | Result ReceiveData(httpcContext *context, u8 *buffer, u32 size); 16 | Result GetDownloadSizeState(httpcContext *context, u32 *downloadedsize, u32 *contentsize); 17 | Result SetSSLOpt(httpcContext *context, u32 option); 18 | private: 19 | void *socbuf = nullptr; 20 | CURL *handle; 21 | CURLcode res; 22 | struct curl_slist *header_chunk = nullptr; 23 | u32 downloaded_size; 24 | std::vector headers; 25 | }; 26 | 27 | extern HTTPC httpc; -------------------------------------------------------------------------------- /LICENSE.jsmn.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Serge A. Zaitsev 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | 21 | -------------------------------------------------------------------------------- /source/http.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libs.h" 4 | 5 | /*! \brief Optional extra httpGet informations */ 6 | struct HTTPResponseInfo { 7 | std::string etag; //!< ETag (for AWS S3 requests) 8 | }; 9 | 10 | /*! \brief Makes a GET HTTP request 11 | * This function will throw an exception if it encounters any error 12 | * 13 | * \param url URL to download 14 | * \param buf Output buffer (will be allocated by the function) 15 | * \param size Output buffer size 16 | * \param verbose OPTIONAL Write download progress to screen (via printf) 17 | * \param info OPTIONAL Pointer to HTTPResponseInfo struct to fill with extra data 18 | */ 19 | void httpGet(const char* url, u8** buf, u32* size, const bool verbose = false, HTTPResponseInfo* info = nullptr); 20 | 21 | /*! \brief Check for file integrity via ETag (MD5) 22 | * 23 | * \param etag ETag header string 24 | * \param fileData Pointer to file data to check 25 | * \param fileSize Size of the file to check 26 | * 27 | * \return true if the check succeeds (md5 match), false otherwise 28 | */ 29 | bool httpCheckETag(std::string etag, const u8* fileData, const u32 fileSize); -------------------------------------------------------------------------------- /source/config.cpp: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "utils.h" 4 | 5 | LoadConfigError Config::LoadFile(const std::string& path) { 6 | std::ifstream cfgfile(path); 7 | 8 | if (!cfgfile.is_open()) { 9 | return LoadConfigError::NotExists; 10 | } 11 | 12 | if (!cfgfile.good()) { 13 | return LoadConfigError::Unreadable; 14 | } 15 | 16 | std::string curLine; 17 | while (std::getline(cfgfile, curLine)) { 18 | size_t index = curLine.find('='); 19 | if (index != std::string::npos) { 20 | std::string key = curLine.substr(0, index); 21 | std::string value = curLine.substr(index + 1); 22 | trim(key); 23 | trim(value); 24 | values[key] = value; 25 | } else { 26 | logPrintf("Invalid line detected in config: %s\n", curLine.c_str()); 27 | return LoadConfigError::Malformed; 28 | } 29 | } 30 | 31 | return LoadConfigError::None; 32 | } 33 | 34 | bool Config::Has(const std::string& key) { 35 | auto it = values.find(key); 36 | return it != values.end(); 37 | } 38 | 39 | std::string Config::Get(const std::string& key, const std::string& fallback) { 40 | if (!this->Has(key)) { 41 | return fallback; 42 | } 43 | return values[key]; 44 | } -------------------------------------------------------------------------------- /source/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libs.h" 4 | 5 | /*! \brief Configuration error reasons 6 | */ 7 | enum class LoadConfigError { 8 | None, /*< No errors found */ 9 | NotExists, /*< Config file does not exist */ 10 | Unreadable, /*< Config file is unreadable */ 11 | Malformed, /*< Config file is malformed */ 12 | }; 13 | 14 | /*! \brief Configuration loader 15 | */ 16 | class Config { 17 | private: 18 | std::map values; 19 | 20 | public: 21 | /*! \brief Loads and parses a configuration file 22 | * 23 | * \param path Path to config file 24 | * 25 | * \return true if file exists and was parsed successfully, false otherwise 26 | */ 27 | LoadConfigError LoadFile(const std::string& path); 28 | 29 | /*! \brief Checks wether a property exists in the configuration file 30 | * 31 | * \param key Property name to check 32 | * 33 | * \return true if the property is found, false otherwise 34 | */ 35 | bool Has(const std::string& key); 36 | 37 | /*! \brief Gets the value of a property by key 38 | * 39 | * \param key Property name to get 40 | * \param fallback Default value to fall back to if the property doesn't exist 41 | * 42 | * \return Either the value of the property or the fallback value 43 | */ 44 | std::string Get(const std::string& key, const std::string& fallback); 45 | }; -------------------------------------------------------------------------------- /source/7z/Delta.c: -------------------------------------------------------------------------------- 1 | /* Delta.c -- Delta converter 2 | 2009-05-26 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "Delta.h" 7 | 8 | void Delta_Init(Byte *state) 9 | { 10 | unsigned i; 11 | for (i = 0; i < DELTA_STATE_SIZE; i++) 12 | state[i] = 0; 13 | } 14 | 15 | static void MyMemCpy(Byte *dest, const Byte *src, unsigned size) 16 | { 17 | unsigned i; 18 | for (i = 0; i < size; i++) 19 | dest[i] = src[i]; 20 | } 21 | 22 | void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size) 23 | { 24 | Byte buf[DELTA_STATE_SIZE]; 25 | unsigned j = 0; 26 | MyMemCpy(buf, state, delta); 27 | { 28 | SizeT i; 29 | for (i = 0; i < size;) 30 | { 31 | for (j = 0; j < delta && i < size; i++, j++) 32 | { 33 | Byte b = data[i]; 34 | data[i] = (Byte)(b - buf[j]); 35 | buf[j] = b; 36 | } 37 | } 38 | } 39 | if (j == delta) 40 | j = 0; 41 | MyMemCpy(state, buf + j, delta - j); 42 | MyMemCpy(state + delta - j, buf, j); 43 | } 44 | 45 | void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size) 46 | { 47 | Byte buf[DELTA_STATE_SIZE]; 48 | unsigned j = 0; 49 | MyMemCpy(buf, state, delta); 50 | { 51 | SizeT i; 52 | for (i = 0; i < size;) 53 | { 54 | for (j = 0; j < delta && i < size; i++, j++) 55 | { 56 | buf[j] = data[i] = (Byte)(buf[j] + data[i]); 57 | } 58 | } 59 | } 60 | if (j == delta) 61 | j = 0; 62 | MyMemCpy(state, buf + j, delta - j); 63 | MyMemCpy(state + delta - j, buf, j); 64 | } 65 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ### What model of system are you using? 8 | - [ ] Old 3DS 9 | - [ ] Old 3DS XL 10 | - [ ] 2DS (non-XL) 11 | - [ ] New 3DS 12 | - [ ] New 3DS XL 13 | - [ ] New 2DS XL 14 | 15 | ### What is your current Luma3DS version? 16 | If you are running an hourly version of Luma3DS, please manually update to a stable version as I will no longer deal with people who are using hourlies. 17 | 18 | - [ ] Luma3DS v7.1 + boot9strap v1.0/v1.1 19 | - [ ] Luma3DS v8.0 + boot9strap v1.2+ 20 | - [ ] Luma3DS v8.1 + boot9strap v1.2+ 21 | - [ ] Luma3DS v8.1.1 + boot9strap v1.2+ 22 | - [ ] Luma3DS v9.0 + boot9strap v1.2+ 23 | - [ ] Luma3DS v9.1 + boot9strap v1.2+ 24 | - [ ] Luma3DS v10.0+ + boot9strap v1.2+ 25 | 26 | ### What version of Luma Updater are you using? 27 | - [ ] v2.0 28 | - [ ] v2.1 29 | - [ ] v2.1.1 30 | - [ ] v2.1.2 31 | - [ ] v2.2 32 | - [ ] v2.3 33 | - [ ] v2.4 34 | - [ ] v2.5 35 | - [ ] v2.6 36 | 37 | ### How are you running Luma Updater? 38 | - [ ] .cia 39 | - [ ] .3dsx + HBL/Rosalina 40 | 41 | ### What problems are you experiencing? 42 | Please tell us what problems you are facing. 43 | 44 | ### What is the exact error code you are receiving? 45 | Please give the exact error code the app gives you. 46 | 47 | ### Steps to reproduce 48 | 49 | 1. 50 | 2. 51 | 3. 52 | -------------------------------------------------------------------------------- /source/console.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libs.h" 4 | 5 | /*! \brief Initializes top and bottom consoles */ 6 | void consoleInitEx(); 7 | 8 | /*! \brief Selects what screen to use for console operations */ 9 | void consoleScreen(const gfxScreen_t screen); 10 | 11 | /*! \brief Prints the menu header */ 12 | void consolePrintHeader(); 13 | 14 | /*! \brief Prints the menu footer */ 15 | void consolePrintFooter(); 16 | 17 | /*! \brief Moves console's cursor to a specified position 18 | * 19 | * \param x X position to move the cursor to (column) 20 | * \param y Y position to move the cursor to (row) 21 | */ 22 | void consoleMoveTo(const int x, const int y); 23 | 24 | /*! \brief Clears current console line */ 25 | void consoleClearLine(); 26 | 27 | /*! \brief Makes progress bar (aka loading) screen (with optional text and progress) 28 | * 29 | * \param header Progress bar header 30 | * \param text Text to put below the progress bar (optional) 31 | * \param progress Progress to set (optional) 32 | */ 33 | void consoleInitProgress(const char* header = "Loading", const char* text = "", const float progress = 0); 34 | 35 | /*! \brief Sets both text and value of a progress bar screen 36 | * \param text Text to put below the progress bar 37 | * \param progress Progress to set (from 0 to 1 inclusive) 38 | */ 39 | void consoleSetProgressData(const char* text, const float progress); 40 | 41 | /*! \brief Changes progress bar's text 42 | * 43 | * \param text Text to put below the progress bar 44 | */ 45 | void consoleSetProgressText(const char* text); 46 | 47 | /*! \brief Changes progress bar value 48 | * 49 | * \param progress Progress to set (from 0 to 1 inclusive) 50 | */ 51 | void consoleSetProgressValue(const float progress); -------------------------------------------------------------------------------- /source/7z/7zAlloc.c: -------------------------------------------------------------------------------- 1 | /* 7zAlloc.c -- Allocation functions 2 | 2015-11-09 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "7zAlloc.h" 7 | 8 | /* #define _SZ_ALLOC_DEBUG */ 9 | /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ 10 | 11 | #ifdef _SZ_ALLOC_DEBUG 12 | 13 | #ifdef _WIN32 14 | #include 15 | #endif 16 | 17 | #include 18 | int g_allocCount = 0; 19 | int g_allocCountTemp = 0; 20 | 21 | #endif 22 | 23 | void *SzAlloc(void *p, size_t size) 24 | { 25 | UNUSED_VAR(p); 26 | if (size == 0) 27 | return 0; 28 | #ifdef _SZ_ALLOC_DEBUG 29 | fprintf(stderr, "\nAlloc %10u bytes; count = %10d", (unsigned)size, g_allocCount); 30 | g_allocCount++; 31 | #endif 32 | return malloc(size); 33 | } 34 | 35 | void SzFree(void *p, void *address) 36 | { 37 | UNUSED_VAR(p); 38 | #ifdef _SZ_ALLOC_DEBUG 39 | if (address != 0) 40 | { 41 | g_allocCount--; 42 | fprintf(stderr, "\nFree; count = %10d", g_allocCount); 43 | } 44 | #endif 45 | free(address); 46 | } 47 | 48 | void *SzAllocTemp(void *p, size_t size) 49 | { 50 | UNUSED_VAR(p); 51 | if (size == 0) 52 | return 0; 53 | #ifdef _SZ_ALLOC_DEBUG 54 | fprintf(stderr, "\nAlloc_temp %10u bytes; count = %10d", (unsigned)size, g_allocCountTemp); 55 | g_allocCountTemp++; 56 | #ifdef _WIN32 57 | return HeapAlloc(GetProcessHeap(), 0, size); 58 | #endif 59 | #endif 60 | return malloc(size); 61 | } 62 | 63 | void SzFreeTemp(void *p, void *address) 64 | { 65 | UNUSED_VAR(p); 66 | #ifdef _SZ_ALLOC_DEBUG 67 | if (address != 0) 68 | { 69 | g_allocCountTemp--; 70 | fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); 71 | } 72 | #ifdef _WIN32 73 | HeapFree(GetProcessHeap(), 0, address); 74 | return; 75 | #endif 76 | #endif 77 | free(address); 78 | } 79 | -------------------------------------------------------------------------------- /source/7z/Bra.c: -------------------------------------------------------------------------------- 1 | /* Bra.c -- Converters for RISC code 2 | 2010-04-16 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "Bra.h" 7 | 8 | SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) 9 | { 10 | SizeT i; 11 | if (size < 4) 12 | return 0; 13 | size -= 4; 14 | ip += 8; 15 | for (i = 0; i <= size; i += 4) 16 | { 17 | if (data[i + 3] == 0xEB) 18 | { 19 | UInt32 dest; 20 | UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]); 21 | src <<= 2; 22 | if (encoding) 23 | dest = ip + (UInt32)i + src; 24 | else 25 | dest = src - (ip + (UInt32)i); 26 | dest >>= 2; 27 | data[i + 2] = (Byte)(dest >> 16); 28 | data[i + 1] = (Byte)(dest >> 8); 29 | data[i + 0] = (Byte)dest; 30 | } 31 | } 32 | return i; 33 | } 34 | 35 | SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) 36 | { 37 | SizeT i; 38 | if (size < 4) 39 | return 0; 40 | size -= 4; 41 | ip += 4; 42 | for (i = 0; i <= size; i += 2) 43 | { 44 | if ((data[i + 1] & 0xF8) == 0xF0 && 45 | (data[i + 3] & 0xF8) == 0xF8) 46 | { 47 | UInt32 dest; 48 | UInt32 src = 49 | (((UInt32)data[i + 1] & 0x7) << 19) | 50 | ((UInt32)data[i + 0] << 11) | 51 | (((UInt32)data[i + 3] & 0x7) << 8) | 52 | (data[i + 2]); 53 | 54 | src <<= 1; 55 | if (encoding) 56 | dest = ip + (UInt32)i + src; 57 | else 58 | dest = src - (ip + (UInt32)i); 59 | dest >>= 1; 60 | 61 | data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); 62 | data[i + 0] = (Byte)(dest >> 11); 63 | data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); 64 | data[i + 2] = (Byte)dest; 65 | i += 2; 66 | } 67 | } 68 | return i; 69 | } -------------------------------------------------------------------------------- /source/7z/Bra.h: -------------------------------------------------------------------------------- 1 | /* Bra.h -- Branch converters for executables 2 | 2013-01-18 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __BRA_H 5 | #define __BRA_H 6 | 7 | #include "7zTypes.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | /* 12 | These functions convert relative addresses to absolute addresses 13 | in CALL instructions to increase the compression ratio. 14 | 15 | In: 16 | data - data buffer 17 | size - size of data 18 | ip - current virtual Instruction Pinter (IP) value 19 | state - state variable for x86 converter 20 | encoding - 0 (for decoding), 1 (for encoding) 21 | 22 | Out: 23 | state - state variable for x86 converter 24 | 25 | Returns: 26 | The number of processed bytes. If you call these functions with multiple calls, 27 | you must start next call with first byte after block of processed bytes. 28 | 29 | Type Endian Alignment LookAhead 30 | 31 | x86 little 1 4 32 | ARMT little 2 2 33 | ARM little 4 0 34 | PPC big 4 0 35 | SPARC big 4 0 36 | IA64 little 16 0 37 | 38 | size must be >= Alignment + LookAhead, if it's not last block. 39 | If (size < Alignment + LookAhead), converter returns 0. 40 | 41 | Example: 42 | 43 | UInt32 ip = 0; 44 | for () 45 | { 46 | ; size must be >= Alignment + LookAhead, if it's not last block 47 | SizeT processed = Convert(data, size, ip, 1); 48 | data += processed; 49 | size -= processed; 50 | ip += processed; 51 | } 52 | */ 53 | 54 | #define x86_Convert_Init(state) { state = 0; } 55 | SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); 56 | SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); 57 | SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); 58 | 59 | EXTERN_C_END 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /source/autoupdate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libs.h" 4 | 5 | #include "update.h" 6 | 7 | //! Homebrew type (format) 8 | enum class HomebrewType { 9 | Unknown, //!< Can't detect what we are (?) 10 | Homebrew, //!< Running as .3dsx (hblauncher) 11 | CIA //!< Running as .cia (Homemenu) 12 | }; 13 | 14 | //! Homebrew location 15 | enum class HomebrewLocation { 16 | Unknown, //!< Can't detect where we are running from 17 | SDMC, //!< Loaded off the SD card (via sdmc) 18 | Remote //!< Loaded via 3dslink 19 | }; 20 | 21 | //! Luma3DS Updater install info 22 | struct UpdaterInfo { 23 | HomebrewType type; //!< Homebrew type (3dsx, cia, etc) 24 | HomebrewLocation location; //!< Homebrew location (SDMC, 3DSLink, NAND etc) 25 | std::string sdmcLoc; //!< Folder on SDMC (if homebrew) 26 | std::string sdmcName; //!< Name of the 3dsx file (if homebrew) 27 | }; 28 | 29 | //! Latest Luma3DS Updater version info 30 | struct LatestUpdaterInfo { 31 | std::string version; //!< Version number 32 | std::string url; //!< Download URL 33 | std::string changelog; //!< Changelog 34 | bool isNewer; //!< Is version newer than the currently installed one 35 | size_t fileSize; //!< Archive size 36 | }; 37 | 38 | /*! \brief Get currently installed homebrew info 39 | * 40 | * \param path Path to currently executing homebrew, usually argv[0] 41 | * 42 | * \return Detected install parameters (if any) 43 | */ 44 | UpdaterInfo updaterGetInfo(const char* path = nullptr); 45 | 46 | /*! \brief Get latest available release of Luma3DS Updater 47 | * 48 | * \return Latest release available on Github 49 | */ 50 | LatestUpdaterInfo updaterGetLatest(); 51 | 52 | /*! \brief Update to latest version 53 | * 54 | * \param latest Latest release info (for downloading) 55 | * \param current Current updater install info (for installing) 56 | */ 57 | UpdateResult updaterDoUpdate(LatestUpdaterInfo latest, UpdaterInfo current); -------------------------------------------------------------------------------- /source/jsmn.h: -------------------------------------------------------------------------------- 1 | #ifndef __JSMN_H_ 2 | #define __JSMN_H_ 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /** 11 | * JSON type identifier. Basic types are: 12 | * o Object 13 | * o Array 14 | * o String 15 | * o Other primitive: number, boolean (true/false) or null 16 | */ 17 | typedef enum { 18 | JSMN_UNDEFINED = 0, 19 | JSMN_OBJECT = 1, 20 | JSMN_ARRAY = 2, 21 | JSMN_STRING = 3, 22 | JSMN_PRIMITIVE = 4 23 | } jsmntype_t; 24 | 25 | enum jsmnerr { 26 | /* Not enough tokens were provided */ 27 | JSMN_ERROR_NOMEM = -1, 28 | /* Invalid character inside JSON string */ 29 | JSMN_ERROR_INVAL = -2, 30 | /* The string is not a full JSON packet, more bytes expected */ 31 | JSMN_ERROR_PART = -3 32 | }; 33 | 34 | /** 35 | * JSON token description. 36 | * @param type type (object, array, string etc.) 37 | * @param start start position in JSON data string 38 | * @param end end position in JSON data string 39 | */ 40 | typedef struct { 41 | jsmntype_t type; 42 | int start; 43 | int end; 44 | int size; 45 | #ifdef JSMN_PARENT_LINKS 46 | int parent; 47 | #endif 48 | } jsmntok_t; 49 | 50 | /** 51 | * JSON parser. Contains an array of token blocks available. Also stores 52 | * the string being parsed now and current position in that string 53 | */ 54 | typedef struct { 55 | unsigned int pos; /* offset in the JSON string */ 56 | unsigned int toknext; /* next token to allocate */ 57 | int toksuper; /* superior token node, e.g parent object or array */ 58 | } jsmn_parser; 59 | 60 | /** 61 | * Create JSON parser over an array of tokens 62 | */ 63 | void jsmn_init(jsmn_parser *parser); 64 | 65 | /** 66 | * Run JSON parser. It parses a JSON data string into and array of tokens, each describing 67 | * a single JSON object. 68 | */ 69 | int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, 70 | jsmntok_t *tokens, unsigned int num_tokens); 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif /* __JSMN_H_ */ 77 | -------------------------------------------------------------------------------- /source/minizip/ioapi_mem.h: -------------------------------------------------------------------------------- 1 | /* ioapi_mem.h -- IO base function header for compress/uncompress .zip 2 | files using zlib + zip or unzip API 3 | 4 | This version of ioapi is designed to access memory rather than files. 5 | We do use a region of memory to put data in to and take it out of. 6 | 7 | Copyright (C) 1998-2003 Gilles Vollant 8 | (C) 2003 Justin Fletcher 9 | 10 | This program is distributed under the terms of the same license as zlib. 11 | See the accompanying LICENSE file for the full text of the license. 12 | */ 13 | 14 | #ifndef _IOAPI_MEM_H 15 | #define _IOAPI_MEM_H 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "zlib.h" 22 | #include "ioapi.h" 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | voidpf ZCALLBACK fopen_mem_func OF((voidpf opaque,const char* filename,int mode)); 29 | voidpf ZCALLBACK fopendisk_mem_func OF((voidpf opaque, voidpf stream, int number_disk, int mode)); 30 | uLong ZCALLBACK fread_mem_func OF((voidpf opaque,voidpf stream,void* buf,uLong size)); 31 | uLong ZCALLBACK fwrite_mem_func OF((voidpf opaque,voidpf stream,const void* buf,uLong size)); 32 | long ZCALLBACK ftell_mem_func OF((voidpf opaque,voidpf stream)); 33 | long ZCALLBACK fseek_mem_func OF((voidpf opaque,voidpf stream,uLong offset,int origin)); 34 | int ZCALLBACK fclose_mem_func OF((voidpf opaque,voidpf stream)); 35 | int ZCALLBACK ferror_mem_func OF((voidpf opaque,voidpf stream)); 36 | 37 | typedef struct ourmemory_s { 38 | char *base; /* Base of the region of memory we're using */ 39 | uLong size; /* Size of the region of memory we're using */ 40 | uLong limit; /* Furthest we've written */ 41 | uLong cur_offset; /* Current offset in the area */ 42 | int grow; /* Growable memory buffer */ 43 | } ourmemory_t; 44 | 45 | void fill_memory_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def, ourmemory_t *ourmem)); 46 | 47 | #ifdef __cplusplus 48 | } 49 | #endif 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /source/7z/LzHash.h: -------------------------------------------------------------------------------- 1 | /* LzHash.h -- HASH functions for LZ algorithms 2 | 2015-04-12 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __LZ_HASH_H 5 | #define __LZ_HASH_H 6 | 7 | #define kHash2Size (1 << 10) 8 | #define kHash3Size (1 << 16) 9 | #define kHash4Size (1 << 20) 10 | 11 | #define kFix3HashSize (kHash2Size) 12 | #define kFix4HashSize (kHash2Size + kHash3Size) 13 | #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) 14 | 15 | #define HASH2_CALC hv = cur[0] | ((UInt32)cur[1] << 8); 16 | 17 | #define HASH3_CALC { \ 18 | UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ 19 | h2 = temp & (kHash2Size - 1); \ 20 | hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } 21 | 22 | #define HASH4_CALC { \ 23 | UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ 24 | h2 = temp & (kHash2Size - 1); \ 25 | temp ^= ((UInt32)cur[2] << 8); \ 26 | h3 = temp & (kHash3Size - 1); \ 27 | hv = (temp ^ (p->crc[cur[3]] << 5)) & p->hashMask; } 28 | 29 | #define HASH5_CALC { \ 30 | UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ 31 | h2 = temp & (kHash2Size - 1); \ 32 | temp ^= ((UInt32)cur[2] << 8); \ 33 | h3 = temp & (kHash3Size - 1); \ 34 | temp ^= (p->crc[cur[3]] << 5); \ 35 | h4 = temp & (kHash4Size - 1); \ 36 | hv = (temp ^ (p->crc[cur[4]] << 3)) & p->hashMask; } 37 | 38 | /* #define HASH_ZIP_CALC hv = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ 39 | #define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; 40 | 41 | 42 | #define MT_HASH2_CALC \ 43 | h2 = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); 44 | 45 | #define MT_HASH3_CALC { \ 46 | UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ 47 | h2 = temp & (kHash2Size - 1); \ 48 | h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } 49 | 50 | #define MT_HASH4_CALC { \ 51 | UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ 52 | h2 = temp & (kHash2Size - 1); \ 53 | temp ^= ((UInt32)cur[2] << 8); \ 54 | h3 = temp & (kHash3Size - 1); \ 55 | h4 = (temp ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /source/7z/7zMemInStream.c: -------------------------------------------------------------------------------- 1 | /* 7zMemInStream.c -- Memory input stream 2 | ** 2012 - Birunthan Mohanathas 3 | ** 4 | ** This file is public domain. 5 | */ 6 | 7 | #include "7zMemInStream.h" 8 | #include 9 | 10 | static SRes MemInStream_Look(void *pp, const void **buf, size_t *size) 11 | { 12 | CMemInStream *p = (CMemInStream *)pp; 13 | size_t remaining = p->end - p->pos; 14 | if (remaining == 0 && *size > 0) 15 | { 16 | // Restart stream. 17 | p->pos = 0; 18 | remaining = *size; 19 | } 20 | 21 | if (remaining < *size) 22 | { 23 | *size = remaining; 24 | } 25 | 26 | *buf = p->pos; 27 | return SZ_OK; 28 | } 29 | 30 | static SRes MemInStream_Skip(void *pp, size_t offset) 31 | { 32 | CMemInStream *p = (CMemInStream *)pp; 33 | p->pos += offset; 34 | return SZ_OK; 35 | } 36 | 37 | static SRes MemInStream_Read(void *pp, void *buf, size_t *size) 38 | { 39 | CMemInStream *p = (CMemInStream *)pp; 40 | size_t remaining = p->end - p->pos; 41 | if (remaining == 0) 42 | { 43 | // End of stream. 44 | *size = 0; 45 | } 46 | else 47 | { 48 | if (remaining > *size) 49 | { 50 | remaining = *size; 51 | } 52 | 53 | memcpy(buf, p->pos, remaining); 54 | p->pos += remaining; 55 | *size = remaining; 56 | } 57 | 58 | return SZ_OK; 59 | } 60 | 61 | static SRes MemInStream_Seek(void *pp, Int64 *pos, ESzSeek origin) 62 | { 63 | CMemInStream *p = (CMemInStream *)pp; 64 | switch (origin) 65 | { 66 | case SZ_SEEK_SET: p->pos = p->begin + *pos; break; 67 | case SZ_SEEK_CUR: p->pos += *pos; break; 68 | case SZ_SEEK_END: p->pos = p->end + *pos; break; 69 | default: return 1; 70 | } 71 | 72 | *pos = p->pos - p->begin; 73 | return SZ_OK; 74 | } 75 | 76 | void MemInStream_Init(CMemInStream *p, const void *begin, size_t length) 77 | { 78 | p->begin = p->pos = (Byte *)begin; 79 | p->end = p->begin + length; 80 | 81 | p->s.Look = MemInStream_Look; 82 | p->s.Skip = MemInStream_Skip; 83 | p->s.Read = MemInStream_Read; 84 | p->s.Seek = MemInStream_Seek; 85 | } 86 | -------------------------------------------------------------------------------- /source/7z/Bra86.c: -------------------------------------------------------------------------------- 1 | /* Bra86.c -- Converter for x86 code (BCJ) 2 | 2013-11-12 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "Bra.h" 7 | 8 | #define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0) 9 | 10 | SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) 11 | { 12 | SizeT pos = 0; 13 | UInt32 mask = *state & 7; 14 | if (size < 5) 15 | return 0; 16 | size -= 4; 17 | ip += 5; 18 | 19 | for (;;) 20 | { 21 | Byte *p = data + pos; 22 | const Byte *limit = data + size; 23 | for (; p < limit; p++) 24 | if ((*p & 0xFE) == 0xE8) 25 | break; 26 | 27 | { 28 | SizeT d = (SizeT)(p - data - pos); 29 | pos = (SizeT)(p - data); 30 | if (p >= limit) 31 | { 32 | *state = (d > 2 ? 0 : mask >> (unsigned)d); 33 | return pos; 34 | } 35 | if (d > 2) 36 | mask = 0; 37 | else 38 | { 39 | mask >>= (unsigned)d; 40 | if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(mask >> 1) + 1]))) 41 | { 42 | mask = (mask >> 1) | 4; 43 | pos++; 44 | continue; 45 | } 46 | } 47 | } 48 | 49 | if (Test86MSByte(p[4])) 50 | { 51 | UInt32 v = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); 52 | UInt32 cur = ip + (UInt32)pos; 53 | pos += 5; 54 | if (encoding) 55 | v += cur; 56 | else 57 | v -= cur; 58 | if (mask != 0) 59 | { 60 | unsigned sh = (mask & 6) << 2; 61 | if (Test86MSByte((Byte)(v >> sh))) 62 | { 63 | v ^= (((UInt32)0x100 << sh) - 1); 64 | if (encoding) 65 | v += cur; 66 | else 67 | v -= cur; 68 | } 69 | mask = 0; 70 | } 71 | p[1] = (Byte)v; 72 | p[2] = (Byte)(v >> 8); 73 | p[3] = (Byte)(v >> 16); 74 | p[4] = (Byte)(0 - ((v >> 24) & 1)); 75 | } 76 | else 77 | { 78 | mask = (mask >> 1) | 4; 79 | pos++; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /source/release.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libs.h" 4 | 5 | #define DEFAULT_SIGHAX_PATH "boot.firm" 6 | //#define DEFAULT_MHAX_PATH "Luma3DS.dat" 7 | //#define DEFAULT_3DSX_PATH "3DS/Luma3DS/Luma3DS.3dsx" 8 | 9 | enum class PayloadType { 10 | SIGHAX, /*!< sighax payload (boot.firm) */ 11 | /*Menuhax, !< menuhax payload (Luma3DS.dat) */ 12 | /*Homebrew !< hblauncher payload (Luma3DS.3dsx/smdh) */ 13 | }; 14 | 15 | struct ReleaseVer { 16 | std::string filename; 17 | std::string friendlyName; 18 | std::string url; 19 | size_t fileSize; 20 | }; 21 | 22 | struct ReleaseInfo { 23 | std::string name = ""; 24 | std::string description = ""; 25 | std::vector versions = {}; 26 | std::map commits = {}; 27 | }; 28 | 29 | /* \brief Gets last official release (from Aurora's Github) 30 | * 31 | * \return ReleaseInfo containing the last release name and available versions 32 | */ 33 | ReleaseInfo releaseGetLatestStable(); 34 | 35 | /* \brief Gets the latest available nightly build (from astronautlevel2's website) 36 | * 37 | * \return ReleaseInfo containing the last nightly 38 | */ 39 | ReleaseInfo releaseGetLatestHourly(); 40 | 41 | /* \brief Update to stable version 42 | * Gets the chosen payload (A9LH/Menuhax/3dsx) file from either a stable release or a nightly 43 | * The buffer must be free'd after used. If the release is not an nightly, the `payloadData` pointer must 44 | * increased by `offset` to get the correct bytes 45 | * 46 | * \param type Payload type to fetch 47 | * \param release Release data 48 | * \param isHourly Wether the release is a nightly (.zip) or stable (.7z) 49 | * \param payloadData Pointer to fill with the payload bytes (should be nullptr when passing) 50 | * \param offset Pointer to fill with the offset to the correct bytes (if 7z) 51 | * \param payloadSize Pointer to fill with size (in bytes) of the payload 52 | * 53 | * \return true if everything succeeds, false otherwise 54 | */ 55 | bool releaseGetPayload(const PayloadType type, const ReleaseVer& release, const bool isHourly, u8** payloadData, size_t* offset, size_t* payloadSize); -------------------------------------------------------------------------------- /source/main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libs.h" 4 | 5 | #include "release.h" 6 | #include "version.h" 7 | 8 | /* States */ 9 | 10 | enum UpdateState { 11 | UpdateConfirmationScreen, 12 | Updating, 13 | UpdateComplete, 14 | UpdateFailed, 15 | Restoring, 16 | RestoreComplete, 17 | RestoreFailed 18 | }; 19 | 20 | enum class ChoiceType { 21 | NoChoice, 22 | UpdatePayload, 23 | RestoreBackup 24 | }; 25 | 26 | enum class SelfUpdateChoice { 27 | NoChoice, 28 | SelfUpdate, 29 | IgnoreUpdate, 30 | }; 31 | 32 | struct UpdateChoice { 33 | ChoiceType type = ChoiceType::NoChoice; 34 | ReleaseVer chosenVersion = ReleaseVer{}; 35 | bool isHourly = false; 36 | 37 | explicit UpdateChoice(const ChoiceType type) 38 | :type(type) {} 39 | UpdateChoice(const ChoiceType type, const ReleaseVer& ver, const bool hourly) 40 | :type(type), chosenVersion(ver), isHourly(hourly) {} 41 | }; 42 | 43 | struct UpdateInfo { 44 | // Detected options 45 | LumaVersion currentVersion; 46 | LumaVersion backupVersion; 47 | bool migrateARN = false; 48 | bool backupExists = false; 49 | 50 | // Configuration options 51 | PayloadType payloadType = PayloadType::SIGHAX; 52 | std::string payloadPath = "/boot.firm"; 53 | bool backupExisting = true; 54 | bool selfUpdate = true; 55 | bool writeLog = true; 56 | 57 | // Available data 58 | ReleaseInfo* stable = nullptr; 59 | ReleaseInfo* hourly = nullptr; 60 | 61 | // Chosen settings 62 | UpdateChoice choice = UpdateChoice(ChoiceType::NoChoice); 63 | 64 | ReleaseVer chosenVersion() const { return choice.chosenVersion; } 65 | bool isHourly = choice.isHourly; 66 | }; 67 | 68 | struct PromptStatus { 69 | // Redraw queries 70 | bool redrawTop = false; 71 | bool redrawBottom = false; 72 | bool partialredraw = false; 73 | bool redrawRequired() { return redrawTop || redrawBottom || partialredraw; } 74 | void resetRedraw() { redrawTop = redrawBottom = partialredraw = false; } 75 | 76 | // Selection and paging 77 | int selected = 0; 78 | int currentPage = 0; 79 | int pageCount = 0; 80 | 81 | // Prompt choice taken? 82 | bool optionChosen = false; 83 | }; -------------------------------------------------------------------------------- /source/7z/Lzma2Dec.h: -------------------------------------------------------------------------------- 1 | /* Lzma2Dec.h -- LZMA2 Decoder 2 | 2015-05-13 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __LZMA2_DEC_H 5 | #define __LZMA2_DEC_H 6 | 7 | #include "LzmaDec.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | /* ---------- State Interface ---------- */ 12 | 13 | typedef struct 14 | { 15 | CLzmaDec decoder; 16 | UInt32 packSize; 17 | UInt32 unpackSize; 18 | unsigned state; 19 | Byte control; 20 | Bool needInitDic; 21 | Bool needInitState; 22 | Bool needInitProp; 23 | } CLzma2Dec; 24 | 25 | #define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder) 26 | #define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc); 27 | #define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc); 28 | 29 | SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc); 30 | SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc); 31 | void Lzma2Dec_Init(CLzma2Dec *p); 32 | 33 | 34 | /* 35 | finishMode: 36 | It has meaning only if the decoding reaches output limit (*destLen or dicLimit). 37 | LZMA_FINISH_ANY - use smallest number of input bytes 38 | LZMA_FINISH_END - read EndOfStream marker after decoding 39 | 40 | Returns: 41 | SZ_OK 42 | status: 43 | LZMA_STATUS_FINISHED_WITH_MARK 44 | LZMA_STATUS_NOT_FINISHED 45 | LZMA_STATUS_NEEDS_MORE_INPUT 46 | SZ_ERROR_DATA - Data error 47 | */ 48 | 49 | SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, 50 | const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); 51 | 52 | SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, 53 | const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); 54 | 55 | 56 | /* ---------- One Call Interface ---------- */ 57 | 58 | /* 59 | finishMode: 60 | It has meaning only if the decoding reaches output limit (*destLen). 61 | LZMA_FINISH_ANY - use smallest number of input bytes 62 | LZMA_FINISH_END - read EndOfStream marker after decoding 63 | 64 | Returns: 65 | SZ_OK 66 | status: 67 | LZMA_STATUS_FINISHED_WITH_MARK 68 | LZMA_STATUS_NOT_FINISHED 69 | SZ_ERROR_DATA - Data error 70 | SZ_ERROR_MEM - Memory allocation error 71 | SZ_ERROR_UNSUPPORTED - Unsupported properties 72 | SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). 73 | */ 74 | 75 | SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, 76 | Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); 77 | 78 | EXTERN_C_END 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /source/http.cpp: -------------------------------------------------------------------------------- 1 | #include "http.h" 2 | #include "httpc.h" 3 | 4 | #include "utils.h" 5 | 6 | // libmd5-rfc includes 7 | #include "md5/md5.h" 8 | 9 | HTTPC httpc; 10 | void httpGet(const char* url, u8** buf, u32* size, const bool verbose, HTTPResponseInfo* info) { 11 | httpcContext context; 12 | CHECK(httpc.OpenContext(&context, HTTPC_METHOD_GET, (char*)url, 0), "Could not open HTTP context"); 13 | // Add User Agent field (required by Github API calls) 14 | CHECK(httpc.AddRequestHeaderField(&context, (char*)"User-Agent", (char*)"LUMA-UPDATER"), "Could not set User Agent"); 15 | 16 | CHECK(httpc.BeginRequest(&context), "Could not begin request"); 17 | 18 | u32 statuscode = 0; 19 | CHECK(httpc.GetResponseStatusCode(&context, &statuscode), "Could not get status code"); 20 | if (statuscode != 200) { 21 | // Handle 3xx codes 22 | if (statuscode >= 300 && statuscode < 400) { 23 | char newUrl[1024]; 24 | CHECK(httpc.GetResponseHeader(&context, (char*)"location", newUrl, 1024), "Could not get Location header for 3xx reply"); 25 | CHECK(httpc.CloseContext(&context), "Could not close HTTP context"); 26 | httpGet(newUrl, buf, size, verbose, info); 27 | return; 28 | } 29 | throw std::runtime_error(formatErrMessage("Non-200 status code", statuscode)); 30 | } 31 | 32 | // Retrieve extra info if required 33 | if (info != nullptr) { 34 | char etagChr[512] = { 0 }; 35 | if (httpc.GetResponseHeader(&context, (char*)"ETag", etagChr, 512) == 0) { 36 | info->etag = std::string(etagChr); 37 | } 38 | } 39 | 40 | u32 pos = 0; 41 | u32 dlstartpos = 0; 42 | u32 dlpos = 0; 43 | Result dlret = HTTPC_RESULTCODE_DOWNLOADPENDING; 44 | 45 | CHECK(httpc.GetDownloadSizeState(&context, &dlstartpos, size), "Could not get file size"); 46 | 47 | *buf = (u8*)std::malloc(*size); 48 | if (*buf == NULL) throw std::runtime_error(formatErrMessage("Could not allocate enough memory", *size)); 49 | std::memset(*buf, 0, *size); 50 | 51 | while (pos < *size && dlret == (s32)HTTPC_RESULTCODE_DOWNLOADPENDING) 52 | { 53 | u32 sz = *size - pos; 54 | dlret = httpc.ReceiveData(&context, *buf + pos, sz); 55 | CHECK(httpc.GetDownloadSizeState(&context, &dlpos, NULL), "Could not get file size"); 56 | pos = dlpos - dlstartpos; 57 | if (verbose) { 58 | logPrintf("Download progress: %lu / %lu", dlpos, *size); 59 | gfxFlushBuffers(); 60 | } 61 | } 62 | 63 | if (verbose) { 64 | logPrintf("\n"); 65 | } 66 | 67 | CHECK(httpc.CloseContext(&context), "Could not close HTTP context"); 68 | } 69 | 70 | 71 | bool httpCheckETag(std::string etag, const u8* fileData, const u32 fileSize) { 72 | // Strip quotes from either side of the etag 73 | if (etag[0] == '"') { 74 | etag = etag.substr(1, etag.length() - 2); 75 | } 76 | 77 | // Get MD5 bytes from Etag header 78 | md5_byte_t expected[16]; 79 | const char* etagchr = etag.c_str(); 80 | for (u8 i = 0; i < 16; i++) { 81 | std::sscanf(etagchr + (i * 2), "%02x", &expected[i]); 82 | } 83 | 84 | // Calculate MD5 hash of downloaded archive 85 | md5_state_t state; 86 | md5_byte_t result[16]; 87 | md5_init(&state); 88 | md5_append(&state, (const md5_byte_t *)fileData, fileSize); 89 | md5_finish(&state, result); 90 | 91 | return memcmp(expected, result, 16) == 0; 92 | } 93 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Luma Updater 2 | 3 | Development on this has stopped. Please stop opening new issues. 4 | 5 | Formerly known as "ARN Updater" 6 | 7 | A `boot.firm` updater for Luma3DS and boot9strap (formerly AuReiNand) as a 3DS homebrew (no more SD swaps!) 8 | 9 | ## Usage 10 | 11 | Originally from [Hamcha's wiki](https://github.com/Hamcha/lumaupdate/wiki): 12 | 13 | For boot9strap Users: 14 | 1. Install Luma Updater's CIA then launch it. 15 | 2. Select latest stable version. 16 | 17 | For HBL/Rosalina Users: 18 | 1. Enable Patch ARM9 access in your Luma3DS configuration (may not be needed depending on your Luma version). 19 | 2. Launch the HBL then Luma Updater. 20 | 3. Select latest stable version. 21 | 22 | ## To possibly work on 23 | * N/A 24 | 25 | ## Compiling Requirements 26 | 27 | - Your usual 3DS compilation environment 28 | - Latest* ctrulib (the one currently bundled with devKitPro won't cut it) 29 | - [makerom](http://3dbrew.org/wiki/Makerom) and [bannertool](https://github.com/Steveice10/bannertool) somewhere in your `PATH` environment 30 | 31 | #### Optional 32 | 33 | - `zip` binary for generating release archives (`make pkg`) 34 | 35 | ## Compiling 36 | 37 | `make` should create the output folder and fill it with both the 3dsx and the cia builds 38 | 39 | `make 3dsx` will only build the 3dsx version [outdated] 40 | 41 | #### Extra flags 42 | 43 | `make CITRA=1` disables features that aren't properly emulated on Citra (HTTPc) for easier testing 44 | 45 | `make DEBUG=1` will disable compile-time optimizations entirely 46 | 47 | ## License 48 | 49 | The assets and code for the homebrew (code under `source/` and assets under `meta/`) are licensed under the **WTFPL**. 50 | Refer to `LICENSE.txt` for the full text. 51 | 52 | This project uses [jsmn](https://github.com/zserge/jsmn), which is licensed under the MIT license. 53 | Refer to `LICENSE.jsmn.txt` for the full text. 54 | 55 | This project uses [minizip](https://github.com/nmoinvaz/minizip), which is licensed under the zlib license. 56 | Refer to `LICENSE.minizip.txt` for the full text. 57 | 58 | This project uses [libmd5-rfc](https://sourceforge.net/projects/libmd5-rfc/), which is licensed under the BSD license. 59 | Refer to `LICENSE.libmd5-rfc.txt` for the full text. 60 | 61 | ## Credits 62 | 63 | - Luma3DS builds (and development) by [Aurora Wright](https://github.com/AuroraWright), [TuxSH](https://github.com/TuxSH) and [other contributors](https://github.com/AuroraWright/Luma3DS/graphs/contributors) 64 | - Hourlies built and provided by [astronautlevel](https://github.com/astronautlevel2) 65 | - Makefiles are somewhat derived by stripping down [Steveice10](https://github.com/Steveice10)'s buildtools 66 | - CIA jingle by [Cydon @ FreeSound](https://www.freesound.org/people/cydon/) 67 | - Original code by [Hamcha](https://github.com/Hamcha/lumaupdate) 68 | - Modifications to code by [chenzw95](https://github.com/chenzw95), [Pirater12](https://github.com/pirater12), and [gnmmarechal](https://github.com/gnmmarechal) 69 | - Custom boot animation by [mariohackandglitch](https://github.com/mariohackandglitch) 70 | - issue_template.md based off of the issue_template made by [Robz8 in TWLoader's repo](https://github.com/Robz8/TWLoader/blob/master/.github/issue_template.md) 71 | -------------------------------------------------------------------------------- /source/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libs.h" 4 | 5 | #ifdef __GNUC__ 6 | #define NAKED __attribute__((naked)) 7 | #define UNUSED __attribute__((unused)) 8 | #else 9 | // Visual studio really hates GCC-specific syntax (I mean, it's right) 10 | #undef PACKED 11 | #define PACKED 12 | #define NAKED 13 | #define UNUSED 14 | #endif 15 | 16 | #define CHECK(val, msg) if (val != 0) { throw std::runtime_error(formatErrMessage(msg, val)); } 17 | 18 | /*! \brief Formats error messages so they are more readable as exceptions 19 | * 20 | * \param msg Error message 21 | * \param val Result from function call 22 | * 23 | * \return Formatted error string for exceptions 24 | */ 25 | std::string formatErrMessage(const char* msg, const Result& val); 26 | 27 | /*! \brief Checks whether a file exists or not 28 | * 29 | * \param path Full path to file 30 | * 31 | * \return true if it exists and can be opened, false otherwise 32 | */ 33 | bool fileExists(const std::string& path); 34 | 35 | /*! \brief Trim whitespace around strings (in-place) 36 | * 37 | * \param s String to trim whitespace from 38 | */ 39 | void trim(std::string& s); 40 | 41 | /*! \brief Unescape string sequences 42 | * 43 | * \param s String to unescape sequences from 44 | * 45 | * \return Unescaped string 46 | */ 47 | std::string unescape(const std::string& s); 48 | 49 | /*! \brief Strip Markdown formatting 50 | * 51 | * \param text Text to strip markdown from 52 | * 53 | * \return Text without markdown links and formatting 54 | */ 55 | std::string stripMarkdown(std::string text); 56 | 57 | /*! \brief Indent multiline text 58 | * 59 | * \param text Text to indent 60 | * \param cols Number of columns (for word wrapping) 61 | * 62 | * \return Text indented and wrapped 63 | */ 64 | std::string indent(const std::string& text, const size_t cols); 65 | 66 | /*! \brief Get how many pages a multiline text makes 67 | * 68 | * \param text Text to count pages from 69 | * \param rows Number of lines per page 70 | * 71 | * \return Number of pages the text forms 72 | */ 73 | int getPageCount(const std::string& text, const int rows); 74 | 75 | /*! \brief Get one specific page of a multiline text 76 | * 77 | * \param text Text to extract specific page from 78 | * \param num Page number 79 | * \param rows Number of lines per page 80 | * 81 | * \return Requested page, or blank string if it's an inexistant page 82 | */ 83 | std::string getPage(const std::string& text, const int num, const int rows); 84 | 85 | /*! \brief Initialize log file 86 | * \param path Log file path 87 | */ 88 | void logInit(const char* path); 89 | 90 | /*! \brief Closes log file and cleans up resources */ 91 | void logExit(); 92 | 93 | /*! \brief Print information on both screen and logfile */ 94 | void logPrintf(const char* format, ...); 95 | 96 | /*! \brief Alternative to_string implementation (workaround for mingw) 97 | * 98 | * \param n Input parameter 99 | * 100 | * \return String representation of the input parameter 101 | */ 102 | template std::string tostr(const T& n) { 103 | std::ostringstream stm; 104 | stm << n; 105 | return stm.str(); 106 | } -------------------------------------------------------------------------------- /source/lumautils.cpp: -------------------------------------------------------------------------------- 1 | #include "lumautils.h" 2 | 3 | #include "utils.h" 4 | 5 | static const std::string PayloadPath = "/luma/payloads/"; 6 | 7 | std::vector listPayloads() { 8 | std::vector files = {}; 9 | FS_Archive sdmcArchive; 10 | 11 | // Open SD card 12 | if (FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, NULL)) != 0) { 13 | logPrintf("\nCould not access SD Card (?)\n\n"); 14 | return files; 15 | } 16 | 17 | // Open source directory 18 | Handle directory = 0; 19 | if (FSUSER_OpenDirectory(&directory, sdmcArchive, fsMakePath(PATH_ASCII, "/luma/payloads")) != 0) { 20 | logPrintf("\nCould not open /luma/payloads\n\n"); 21 | FSUSER_CloseArchive(sdmcArchive); 22 | return files; 23 | } 24 | 25 | u32 fileRead = 0; 26 | while (true) { 27 | FS_DirectoryEntry entry = {}; 28 | FSDIR_Read(directory, &fileRead, 1, &entry); 29 | if (!fileRead) { 30 | break; 31 | } 32 | 33 | // Convert name to ASCII (just cut the other bytes) and compare with prefix 34 | char name8[262] = { 0 }; 35 | for (size_t i = 0; i < 262; i++) { 36 | name8[i] = entry.name[i] % 0xff; 37 | } 38 | 39 | files.push_back(std::string(name8)); 40 | } 41 | 42 | FSUSER_CloseArchive(sdmcArchive); 43 | return files; 44 | } 45 | 46 | bool hasPrefix(const std::string& name, const std::string& prefix) { 47 | if (name.length() < prefix.length()) { 48 | return false; 49 | } 50 | 51 | return name.substr(0, prefix.length()) == prefix; 52 | } 53 | 54 | bool findAndRename(const char* oldName, const char* newName) { 55 | const std::string oldPath = PayloadPath + oldName; 56 | const std::string newPath = PayloadPath + newName; 57 | 58 | if (fileExists(oldPath)) { 59 | return std::rename(oldPath.c_str(), newPath.c_str()) == 0; 60 | } 61 | return true; 62 | } 63 | 64 | bool findAndRenamePrefix(const std::vector& files, const std::string& oldPrefix, const std::string& newPrefix) { 65 | const size_t oldPrefixLen = oldPrefix.length(); 66 | for (std::string file : files) { 67 | logPrintf("Considering %s\n", file.c_str()); 68 | if (hasPrefix(file, oldPrefix)) { 69 | std::string newName = PayloadPath + newPrefix + file.substr(oldPrefixLen); 70 | file = PayloadPath + file; 71 | logPrintf("%s -> %s", file.c_str(), newName.c_str()); 72 | if (std::rename(file.c_str(), newName.c_str()) != 0) { 73 | std::perror((std::string("Could not rename ") + newName).c_str()); 74 | } 75 | } 76 | } 77 | return true; 78 | } 79 | 80 | bool lumaMigratePayloads() { 81 | // Default is now def (5.1) 82 | if (!findAndRename("default.bin", "def.bin")) { 83 | std::perror("\nCould not rename default.bin"); 84 | return false; 85 | } 86 | 87 | const std::vector files = listPayloads(); 88 | 89 | // Default is now Start (5.4) 90 | if (!findAndRenamePrefix(files, "def", "start")) { 91 | std::perror("\nCould not rename def_ to start_"); 92 | return false; 93 | } 94 | 95 | // Sel is now Select (5.4) 96 | // Hacky thing: Match sel/sel_, but not select! 97 | if (!findAndRename("sel.bin", "select.bin")) { 98 | std::perror("\nCould not rename sel.bin"); 99 | return false; 100 | } 101 | if (!findAndRenamePrefix(files, "sel_", "select_")) { 102 | std::perror("\nCould not rename sel_ to select_"); 103 | return false; 104 | } 105 | 106 | return true; 107 | } -------------------------------------------------------------------------------- /source/archive.cpp: -------------------------------------------------------------------------------- 1 | #include "archive.h" 2 | #include "utils.h" 3 | 4 | ZipArchive::ZipArchive(const u8* arcData, const u32 arcSize) { 5 | unzmem.size = arcSize; 6 | unzmem.base = (char*)malloc(unzmem.size); 7 | std::memcpy(unzmem.base, arcData, unzmem.size); 8 | fill_memory_filefunc(&filefunc32, &unzmem); 9 | zipfile = unzOpen2("__notused__", &filefunc32); 10 | } 11 | 12 | ZipArchive::~ZipArchive() { 13 | unzCloseCurrentFile(zipfile); 14 | unzClose(zipfile); 15 | } 16 | 17 | void ZipArchive::extractFile(std::string name, u8** fileData, size_t* fileSize) { 18 | int res = unzLocateFile(zipfile, name.c_str(), nullptr); 19 | if (res == UNZ_END_OF_LIST_OF_FILE) { 20 | throw std::runtime_error("Could not find " + name + " in zip file"); 21 | } 22 | 23 | unz_file_info payloadInfo = {}; 24 | res = unzGetCurrentFileInfo(zipfile, &payloadInfo, nullptr, 0, nullptr, 0, nullptr, 0); 25 | if (res != UNZ_OK) { 26 | throw std::runtime_error("Could not read metadata for " + name); 27 | } 28 | *fileSize = payloadInfo.uncompressed_size; 29 | 30 | res = unzOpenCurrentFile(zipfile); 31 | if (res != UNZ_OK) { 32 | throw std::runtime_error("Could not open " + name + " for reading"); 33 | } 34 | 35 | *fileData = (u8*)malloc(*fileSize); 36 | res = unzReadCurrentFile(zipfile, *fileData, *fileSize); 37 | if (res < 0) { 38 | throw std::runtime_error("Could not read " + name + " (" + tostr(res) + ")"); 39 | } 40 | 41 | if (res != (int)*fileSize) { 42 | throw std::runtime_error("Extracted size does not match expected! (got " + tostr(res) + " expected " + tostr(*fileSize) + ")"); 43 | } 44 | } 45 | 46 | SzArchive::SzArchive(const u8* arcData, const u32 arcSize) { 47 | MemInStream_Init(&memStream, arcData, arcSize); 48 | 49 | allocImp.Alloc = SzAlloc; 50 | allocImp.Free = SzFree; 51 | allocTempImp.Alloc = SzAllocTemp; 52 | allocTempImp.Free = SzFreeTemp; 53 | 54 | CrcGenerateTable(); 55 | SzArEx_Init(&db); 56 | 57 | SRes res = SzArEx_Open(&db, &memStream.s, &allocImp, &allocTempImp); 58 | if (res != SZ_OK) { 59 | throw std::runtime_error("Could not open archive (SzArEx_Open)\n"); 60 | } 61 | 62 | buildFileIndex(); 63 | } 64 | 65 | void SzArchive::buildFileIndex() { 66 | for (u32 i = 0; i < db.NumFiles; ++i) { 67 | // Skip directories 68 | unsigned isDir = SzArEx_IsDir(&db, i); 69 | if (isDir) { 70 | continue; 71 | } 72 | 73 | // Get name 74 | size_t len; 75 | len = SzArEx_GetFileNameUtf16(&db, i, NULL); 76 | // Super long filename? Just skip it.. 77 | if (len >= 256) { 78 | continue; 79 | } 80 | u16 name[256] = { 0 }; 81 | SzArEx_GetFileNameUtf16(&db, i, name); 82 | 83 | // Convert name to ASCII (just cut the other bytes) 84 | char name8[256] = { 0 }; 85 | for (size_t j = 0; j < len; ++j) { 86 | name8[j] = name[j] % 0xff; 87 | } 88 | 89 | std::string nameStr(name8); 90 | files[nameStr] = i; 91 | } 92 | } 93 | 94 | SzArchive::~SzArchive() { 95 | SzArEx_Free(&db, &allocImp); 96 | } 97 | 98 | void SzArchive::extractFile(std::string name, u8** fileData, size_t* fileSize, size_t* offset) { 99 | auto it = files.find(name); 100 | if (it == files.end()) { 101 | throw std::runtime_error("Could not find " + name); 102 | } 103 | 104 | UInt32 blockIndex = UINT32_MAX; 105 | size_t fileBufSize = 0; 106 | 107 | SRes res = SzArEx_Extract( 108 | &db, 109 | &memStream.s, 110 | it->second, 111 | &blockIndex, 112 | fileData, 113 | &fileBufSize, 114 | offset, 115 | fileSize, 116 | &allocImp, 117 | &allocTempImp 118 | ); 119 | if (res != SZ_OK) { 120 | throw std::runtime_error("Could not extract " + name); 121 | } 122 | } -------------------------------------------------------------------------------- /source/md5/md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgment in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | 20 | L. Peter Deutsch 21 | ghost@aladdin.com 22 | 23 | */ 24 | /* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ 25 | /* 26 | Independent implementation of MD5 (RFC 1321). 27 | 28 | This code implements the MD5 Algorithm defined in RFC 1321, whose 29 | text is available at 30 | http://www.ietf.org/rfc/rfc1321.txt 31 | The code is derived from the text of the RFC, including the test suite 32 | (section A.5) but excluding the rest of Appendix A. It does not include 33 | any code or documentation that is identified in the RFC as being 34 | copyrighted. 35 | 36 | The original and principal author of md5.h is L. Peter Deutsch 37 | . Other authors are noted in the change history 38 | that follows (in reverse chronological order): 39 | 40 | 2002-04-13 lpd Removed support for non-ANSI compilers; removed 41 | references to Ghostscript; clarified derivation from RFC 1321; 42 | now handles byte order either statically or dynamically. 43 | 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 44 | 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); 45 | added conditionalization for C++ compilation from Martin 46 | Purschke . 47 | 1999-05-03 lpd Original version. 48 | */ 49 | 50 | #ifndef md5_INCLUDED 51 | # define md5_INCLUDED 52 | 53 | /* 54 | * This package supports both compile-time and run-time determination of CPU 55 | * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be 56 | * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is 57 | * defined as non-zero, the code will be compiled to run only on big-endian 58 | * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to 59 | * run on either big- or little-endian CPUs, but will run slightly less 60 | * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. 61 | */ 62 | 63 | typedef unsigned char md5_byte_t; /* 8-bit byte */ 64 | typedef unsigned int md5_word_t; /* 32-bit word */ 65 | 66 | /* Define the state of the MD5 Algorithm. */ 67 | typedef struct md5_state_s { 68 | md5_word_t count[2]; /* message length in bits, lsw first */ 69 | md5_word_t abcd[4]; /* digest buffer */ 70 | md5_byte_t buf[64]; /* accumulate block */ 71 | } md5_state_t; 72 | 73 | #ifdef __cplusplus 74 | extern "C" 75 | { 76 | #endif 77 | 78 | /* Initialize the algorithm. */ 79 | void md5_init(md5_state_t *pms); 80 | 81 | /* Append a string to the message. */ 82 | void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); 83 | 84 | /* Finish the message and return the digest. */ 85 | void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); 86 | 87 | #ifdef __cplusplus 88 | } /* end extern "C" */ 89 | #endif 90 | 91 | #endif /* md5_INCLUDED */ 92 | -------------------------------------------------------------------------------- /source/7z/7zCrc.c: -------------------------------------------------------------------------------- 1 | /* 7zCrc.c -- CRC32 init 2 | 2015-03-10 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "7zCrc.h" 7 | #include "CpuArch.h" 8 | 9 | #define kCrcPoly 0xEDB88320 10 | 11 | #ifdef MY_CPU_LE 12 | #define CRC_NUM_TABLES 8 13 | #else 14 | #define CRC_NUM_TABLES 9 15 | 16 | #define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) 17 | 18 | UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table); 19 | UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table); 20 | #endif 21 | 22 | #ifndef MY_CPU_BE 23 | UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); 24 | UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); 25 | #endif 26 | 27 | typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); 28 | 29 | CRC_FUNC g_CrcUpdateT4; 30 | CRC_FUNC g_CrcUpdateT8; 31 | CRC_FUNC g_CrcUpdate; 32 | 33 | UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; 34 | 35 | UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) 36 | { 37 | return g_CrcUpdate(v, data, size, g_CrcTable); 38 | } 39 | 40 | UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) 41 | { 42 | return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL; 43 | } 44 | 45 | #define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) 46 | 47 | UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table) 48 | { 49 | const Byte *p = (const Byte *)data; 50 | const Byte *pEnd = p + size; 51 | for (; p != pEnd; p++) 52 | v = CRC_UPDATE_BYTE_2(v, *p); 53 | return v; 54 | } 55 | 56 | void MY_FAST_CALL CrcGenerateTable() 57 | { 58 | UInt32 i; 59 | for (i = 0; i < 256; i++) 60 | { 61 | UInt32 r = i; 62 | unsigned j; 63 | for (j = 0; j < 8; j++) 64 | r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); 65 | g_CrcTable[i] = r; 66 | } 67 | for (; i < 256 * CRC_NUM_TABLES; i++) 68 | { 69 | UInt32 r = g_CrcTable[i - 256]; 70 | g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); 71 | } 72 | 73 | #if CRC_NUM_TABLES < 4 74 | 75 | g_CrcUpdate = CrcUpdateT1; 76 | 77 | #else 78 | 79 | #ifdef MY_CPU_LE 80 | 81 | g_CrcUpdateT4 = CrcUpdateT4; 82 | g_CrcUpdate = CrcUpdateT4; 83 | 84 | #if CRC_NUM_TABLES >= 8 85 | g_CrcUpdateT8 = CrcUpdateT8; 86 | 87 | #ifdef MY_CPU_X86_OR_AMD64 88 | if (!CPU_Is_InOrder()) 89 | g_CrcUpdate = CrcUpdateT8; 90 | #endif 91 | #endif 92 | 93 | #else 94 | { 95 | #ifndef MY_CPU_BE 96 | UInt32 k = 0x01020304; 97 | const Byte *p = (const Byte *)&k; 98 | if (p[0] == 4 && p[1] == 3) 99 | { 100 | g_CrcUpdateT4 = CrcUpdateT4; 101 | g_CrcUpdate = CrcUpdateT4; 102 | #if CRC_NUM_TABLES >= 8 103 | g_CrcUpdateT8 = CrcUpdateT8; 104 | // g_CrcUpdate = CrcUpdateT8; 105 | #endif 106 | } 107 | else if (p[0] != 1 || p[1] != 2) 108 | g_CrcUpdate = CrcUpdateT1; 109 | else 110 | #endif 111 | { 112 | for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--) 113 | { 114 | UInt32 x = g_CrcTable[i - 256]; 115 | g_CrcTable[i] = CRC_UINT32_SWAP(x); 116 | } 117 | g_CrcUpdateT4 = CrcUpdateT1_BeT4; 118 | g_CrcUpdate = CrcUpdateT1_BeT4; 119 | #if CRC_NUM_TABLES >= 8 120 | g_CrcUpdateT8 = CrcUpdateT1_BeT8; 121 | // g_CrcUpdate = CrcUpdateT1_BeT8; 122 | #endif 123 | } 124 | } 125 | #endif 126 | 127 | #endif 128 | } 129 | -------------------------------------------------------------------------------- /source/7z/7zCrcOpt.c: -------------------------------------------------------------------------------- 1 | /* 7zCrcOpt.c -- CRC32 calculation 2 | 2015-03-01 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "CpuArch.h" 7 | 8 | #ifndef MY_CPU_BE 9 | 10 | #define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) 11 | 12 | UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) 13 | { 14 | const Byte *p = (const Byte *)data; 15 | for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) 16 | v = CRC_UPDATE_BYTE_2(v, *p); 17 | for (; size >= 4; size -= 4, p += 4) 18 | { 19 | v ^= *(const UInt32 *)p; 20 | v = 21 | table[0x300 + ((v ) & 0xFF)] 22 | ^ table[0x200 + ((v >> 8) & 0xFF)] 23 | ^ table[0x100 + ((v >> 16) & 0xFF)] 24 | ^ table[0x000 + ((v >> 24))]; 25 | } 26 | for (; size > 0; size--, p++) 27 | v = CRC_UPDATE_BYTE_2(v, *p); 28 | return v; 29 | } 30 | 31 | UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table) 32 | { 33 | const Byte *p = (const Byte *)data; 34 | for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++) 35 | v = CRC_UPDATE_BYTE_2(v, *p); 36 | for (; size >= 8; size -= 8, p += 8) 37 | { 38 | UInt32 d; 39 | v ^= *(const UInt32 *)p; 40 | v = 41 | table[0x700 + ((v ) & 0xFF)] 42 | ^ table[0x600 + ((v >> 8) & 0xFF)] 43 | ^ table[0x500 + ((v >> 16) & 0xFF)] 44 | ^ table[0x400 + ((v >> 24))]; 45 | d = *((const UInt32 *)p + 1); 46 | v ^= 47 | table[0x300 + ((d ) & 0xFF)] 48 | ^ table[0x200 + ((d >> 8) & 0xFF)] 49 | ^ table[0x100 + ((d >> 16) & 0xFF)] 50 | ^ table[0x000 + ((d >> 24))]; 51 | } 52 | for (; size > 0; size--, p++) 53 | v = CRC_UPDATE_BYTE_2(v, *p); 54 | return v; 55 | } 56 | 57 | #endif 58 | 59 | 60 | #ifndef MY_CPU_LE 61 | 62 | #define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) 63 | 64 | #define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(((crc) >> 24) ^ (b))] ^ ((crc) << 8)) 65 | 66 | UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table) 67 | { 68 | const Byte *p = (const Byte *)data; 69 | table += 0x100; 70 | v = CRC_UINT32_SWAP(v); 71 | for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) 72 | v = CRC_UPDATE_BYTE_2_BE(v, *p); 73 | for (; size >= 4; size -= 4, p += 4) 74 | { 75 | v ^= *(const UInt32 *)p; 76 | v = 77 | table[0x000 + ((v ) & 0xFF)] 78 | ^ table[0x100 + ((v >> 8) & 0xFF)] 79 | ^ table[0x200 + ((v >> 16) & 0xFF)] 80 | ^ table[0x300 + ((v >> 24))]; 81 | } 82 | for (; size > 0; size--, p++) 83 | v = CRC_UPDATE_BYTE_2_BE(v, *p); 84 | return CRC_UINT32_SWAP(v); 85 | } 86 | 87 | UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table) 88 | { 89 | const Byte *p = (const Byte *)data; 90 | table += 0x100; 91 | v = CRC_UINT32_SWAP(v); 92 | for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++) 93 | v = CRC_UPDATE_BYTE_2_BE(v, *p); 94 | for (; size >= 8; size -= 8, p += 8) 95 | { 96 | UInt32 d; 97 | v ^= *(const UInt32 *)p; 98 | v = 99 | table[0x400 + ((v ) & 0xFF)] 100 | ^ table[0x500 + ((v >> 8) & 0xFF)] 101 | ^ table[0x600 + ((v >> 16) & 0xFF)] 102 | ^ table[0x700 + ((v >> 24))]; 103 | d = *((const UInt32 *)p + 1); 104 | v ^= 105 | table[0x000 + ((d ) & 0xFF)] 106 | ^ table[0x100 + ((d >> 8) & 0xFF)] 107 | ^ table[0x200 + ((d >> 16) & 0xFF)] 108 | ^ table[0x300 + ((d >> 24))]; 109 | } 110 | for (; size > 0; size--, p++) 111 | v = CRC_UPDATE_BYTE_2_BE(v, *p); 112 | return CRC_UINT32_SWAP(v); 113 | } 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /source/7z/Bcj2.h: -------------------------------------------------------------------------------- 1 | /* Bcj2.h -- BCJ2 Converter for x86 code 2 | 2014-11-10 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __BCJ2_H 5 | #define __BCJ2_H 6 | 7 | #include "7zTypes.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | #define BCJ2_NUM_STREAMS 4 12 | 13 | enum 14 | { 15 | BCJ2_STREAM_MAIN, 16 | BCJ2_STREAM_CALL, 17 | BCJ2_STREAM_JUMP, 18 | BCJ2_STREAM_RC 19 | }; 20 | 21 | enum 22 | { 23 | BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS, 24 | BCJ2_DEC_STATE_ORIG_1, 25 | BCJ2_DEC_STATE_ORIG_2, 26 | BCJ2_DEC_STATE_ORIG_3, 27 | 28 | BCJ2_DEC_STATE_ORIG, 29 | BCJ2_DEC_STATE_OK 30 | }; 31 | 32 | enum 33 | { 34 | BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS, 35 | BCJ2_ENC_STATE_OK 36 | }; 37 | 38 | 39 | #define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP) 40 | 41 | /* 42 | CBcj2Dec / CBcj2Enc 43 | bufs sizes: 44 | BUF_SIZE(n) = lims[n] - bufs[n] 45 | bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be mutliply of 4: 46 | (BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0 47 | (BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0 48 | */ 49 | 50 | /* 51 | CBcj2Dec: 52 | dest is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions: 53 | bufs[BCJ2_STREAM_MAIN] >= dest && 54 | bufs[BCJ2_STREAM_MAIN] - dest >= tempReserv + 55 | BUF_SIZE(BCJ2_STREAM_CALL) + 56 | BUF_SIZE(BCJ2_STREAM_JUMP) 57 | tempReserv = 0 : for first call of Bcj2Dec_Decode 58 | tempReserv = 4 : for any other calls of Bcj2Dec_Decode 59 | overlap with offset = 1 is not allowed 60 | */ 61 | 62 | typedef struct 63 | { 64 | const Byte *bufs[BCJ2_NUM_STREAMS]; 65 | const Byte *lims[BCJ2_NUM_STREAMS]; 66 | Byte *dest; 67 | const Byte *destLim; 68 | 69 | unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */ 70 | 71 | UInt32 ip; 72 | Byte temp[4]; 73 | UInt32 range; 74 | UInt32 code; 75 | UInt16 probs[2 + 256]; 76 | } CBcj2Dec; 77 | 78 | void Bcj2Dec_Init(CBcj2Dec *p); 79 | 80 | /* Returns: SZ_OK or SZ_ERROR_DATA */ 81 | SRes Bcj2Dec_Decode(CBcj2Dec *p); 82 | 83 | #define Bcj2Dec_IsFinished(_p_) ((_p_)->code == 0) 84 | 85 | 86 | 87 | typedef enum 88 | { 89 | BCJ2_ENC_FINISH_MODE_CONTINUE, 90 | BCJ2_ENC_FINISH_MODE_END_BLOCK, 91 | BCJ2_ENC_FINISH_MODE_END_STREAM 92 | } EBcj2Enc_FinishMode; 93 | 94 | typedef struct 95 | { 96 | Byte *bufs[BCJ2_NUM_STREAMS]; 97 | const Byte *lims[BCJ2_NUM_STREAMS]; 98 | const Byte *src; 99 | const Byte *srcLim; 100 | 101 | unsigned state; 102 | EBcj2Enc_FinishMode finishMode; 103 | 104 | Byte prevByte; 105 | 106 | Byte cache; 107 | UInt32 range; 108 | UInt64 low; 109 | UInt64 cacheSize; 110 | 111 | UInt32 ip; 112 | 113 | /* 32-bit ralative offset in JUMP/CALL commands is 114 | - (mod 4 GB) in 32-bit mode 115 | - signed Int32 in 64-bit mode 116 | We use (mod 4 GB) check for fileSize. 117 | Use fileSize up to 2 GB, if you want to support 32-bit and 64-bit code conversion. */ 118 | UInt32 fileIp; 119 | UInt32 fileSize; /* (fileSize <= ((UInt32)1 << 31)), 0 means no_limit */ 120 | UInt32 relatLimit; /* (relatLimit <= ((UInt32)1 << 31)), 0 means desable_conversion */ 121 | 122 | UInt32 tempTarget; 123 | unsigned tempPos; 124 | Byte temp[4 * 2]; 125 | 126 | unsigned flushPos; 127 | 128 | UInt16 probs[2 + 256]; 129 | } CBcj2Enc; 130 | 131 | void Bcj2Enc_Init(CBcj2Enc *p); 132 | void Bcj2Enc_Encode(CBcj2Enc *p); 133 | 134 | #define Bcj2Enc_Get_InputData_Size(p) ((SizeT)((p)->srcLim - (p)->src) + (p)->tempPos) 135 | #define Bcj2Enc_IsFinished(p) ((p)->flushPos == 5) 136 | 137 | 138 | #define BCJ2_RELAT_LIMIT_NUM_BITS 26 139 | #define BCJ2_RELAT_LIMIT ((UInt32)1 << BCJ2_RELAT_LIMIT_NUM_BITS) 140 | 141 | /* limit for CBcj2Enc::fileSize variable */ 142 | #define BCJ2_FileSize_MAX ((UInt32)1 << 31) 143 | 144 | EXTERN_C_END 145 | 146 | #endif 147 | -------------------------------------------------------------------------------- /source/console.cpp: -------------------------------------------------------------------------------- 1 | #include "console.h" 2 | 3 | #ifndef GIT_VER 4 | #define GIT_VER "v2.2" 5 | #endif 6 | 7 | PrintConsole* consoleCurrent = nullptr; 8 | PrintConsole consoleTop, consoleBottom; 9 | 10 | #define LINE_BLANK " " 11 | 12 | void consoleInitEx() { 13 | consoleInit(GFX_TOP, &consoleTop); 14 | consoleInit(GFX_BOTTOM, &consoleBottom); 15 | } 16 | 17 | void consoleScreen(const gfxScreen_t screen) { 18 | switch (screen) { 19 | case GFX_TOP: 20 | consoleCurrent = &consoleTop; 21 | break; 22 | case GFX_BOTTOM: 23 | consoleCurrent = &consoleBottom; 24 | break; 25 | default: 26 | // uh?! 27 | throw "Trying to select inexistant console screen"; 28 | } 29 | consoleSelect(consoleCurrent); 30 | } 31 | 32 | void consolePrintHeader() { 33 | consoleMoveTo(2, 1); 34 | consoleCurrent->cursorX = 2; 35 | consoleCurrent->cursorY = 1; 36 | std::printf("%sLuma Updater %s%s\n\n", CONSOLE_YELLOW, GIT_VER, CONSOLE_RESET); 37 | } 38 | 39 | void consolePrintFooter() { 40 | consoleMoveTo(2, consoleCurrent->consoleHeight - 2); 41 | std::printf("\x18\x19 select options A choose START quit"); 42 | } 43 | 44 | void consoleMoveTo(const int x, const int y) { 45 | consoleCurrent->cursorX = x; 46 | consoleCurrent->cursorY = y; 47 | } 48 | 49 | void consoleClearLine() { 50 | consoleCurrent->cursorX = 0; 51 | std::printf("%.*s", consoleCurrent->consoleWidth, LINE_BLANK); 52 | consoleCurrent->cursorX = 0; 53 | } 54 | 55 | /* Progress bar functions */ 56 | #define ProgressBarPadding 4 57 | 58 | void consoleInitProgress(const char* header, const char* text, const float progress) { 59 | consoleClear(); 60 | 61 | // Print progress bar borders 62 | int progressBarY = consoleCurrent->consoleHeight / 2 - 1; 63 | consoleCurrent->cursorY = progressBarY; 64 | 65 | int startX = ProgressBarPadding; 66 | int endX = consoleCurrent->consoleWidth - ProgressBarPadding + 1; 67 | 68 | int startY = progressBarY; 69 | 70 | for (int i = startX; i < endX; i++) { 71 | // Draw left and right border 72 | for (int j = 0; j < 12; j++) { 73 | consoleCurrent->frameBuffer[((startX * 8 - 3) * 240) + (230 - (startY * 8)) + j] = 0xffff; 74 | consoleCurrent->frameBuffer[((endX * 8 - 6) * 240) + (230 - (startY * 8)) + j] = 0xffff; 75 | } 76 | // Draw top and bottom borders 77 | for (int j = 0; j < (i < endX - 1 ? 8 : 6); j++) { 78 | consoleCurrent->frameBuffer[((i * 8 + j - 3) * 240) + (239 - (startY * 8 - 3))] = 0xffff; 79 | consoleCurrent->frameBuffer[((i * 8 + j - 3) * 240) + (239 - ((startY + 1) * 8 + 2))] = 0xffff; 80 | } 81 | } 82 | 83 | // Print header 84 | consoleCurrent->cursorY = progressBarY - 2; 85 | consoleCurrent->cursorX = ProgressBarPadding; 86 | std::printf("%s%s%s", CONSOLE_YELLOW, header, CONSOLE_RESET); 87 | 88 | // Set data 89 | consoleSetProgressData(text, progress); 90 | } 91 | 92 | void consoleSetProgressData(const char* text, const float progress) { 93 | consoleSetProgressText(text); 94 | consoleSetProgressValue(progress); 95 | } 96 | 97 | void consoleSetProgressText(const char* text) { 98 | // Move to approriate row 99 | int progressBarY = consoleCurrent->consoleHeight / 2 - 1; 100 | consoleCurrent->cursorY = progressBarY + 2; 101 | 102 | // Clear line 103 | consoleCurrent->cursorX = 0; 104 | std::printf("%.*s", consoleCurrent->consoleWidth, LINE_BLANK); 105 | 106 | // Write text 107 | consoleCurrent->cursorX = ProgressBarPadding; 108 | std::printf("%s...", text); 109 | } 110 | 111 | void consoleSetProgressValue(const float progress) { 112 | // Move to approriate row 113 | consoleCurrent->cursorY = consoleCurrent->consoleHeight / 2 - 1; 114 | 115 | // Move to beginning of progress bar 116 | int progressBarLength = consoleCurrent->consoleWidth - ProgressBarPadding*2; 117 | consoleCurrent->cursorX = ProgressBarPadding; 118 | 119 | // Fill progress 120 | int progressBarFill = (int)(progressBarLength * progress); 121 | consoleCurrent->flags |= CONSOLE_COLOR_REVERSE; 122 | std::printf("%.*s", progressBarFill, LINE_BLANK); 123 | consoleCurrent->flags &= ~CONSOLE_COLOR_REVERSE; 124 | std::printf("%.*s", progressBarLength - progressBarFill, LINE_BLANK); 125 | } -------------------------------------------------------------------------------- /source/version.cpp: -------------------------------------------------------------------------------- 1 | #include "version.h" 2 | 3 | #include "utils.h" 4 | #include 5 | #include 6 | 7 | std::string getCommit(std::string commitString) { 8 | std::string commit = ""; 9 | for (int i = 0; i < 7; i++) 10 | { 11 | commit += commitString[i]; 12 | } 13 | return commit; 14 | } 15 | 16 | const std::string LumaVersion::toString(bool printBranch) const { 17 | std::string currentVersionStr = release; 18 | if (!commit.empty()) 19 | currentVersionStr += "-" + getCommit(commit); 20 | 21 | return currentVersionStr; 22 | } 23 | 24 | /* Luma3DS 0x2e svc version struct */ 25 | struct PACKED SvcLumaVersion { 26 | char magic[4]; 27 | uint8_t major; 28 | uint8_t minor; 29 | uint8_t build; 30 | uint8_t flags; 31 | uint32_t commit; 32 | uint32_t unused; 33 | }; 34 | 35 | 36 | int NAKED svcGetLumaVersion(SvcLumaVersion UNUSED *info) { 37 | asm volatile( 38 | "svc 0x2E\n" 39 | "bx lr" 40 | ); 41 | } 42 | 43 | 44 | LumaVersion versionSvc() { 45 | SvcLumaVersion info; 46 | if (svcGetLumaVersion(&info) != 0) { 47 | return LumaVersion{}; 48 | } 49 | 50 | LumaVersion version; 51 | 52 | std::stringstream releaseBuilder; 53 | releaseBuilder << (int)info.major << "." << (int)info.minor; 54 | if (info.build > 0) { 55 | releaseBuilder << "." << (int)info.build; 56 | } 57 | version.release = releaseBuilder.str(); 58 | 59 | if (info.commit > 0) { 60 | std::stringstream commitBuilder; 61 | commitBuilder << std::hex << info.commit; 62 | version.commit = commitBuilder.str(); 63 | } 64 | 65 | version.isDev = (info.flags & 0x1) == 0x1; 66 | 67 | logPrintf("%s\n", version.toString().c_str()); 68 | return version; 69 | } 70 | 71 | LumaVersion versionMemsearch(const std::string& path) { 72 | const static char searchString[] = "Luma3DS v"; 73 | const static size_t searchStringLen = sizeof(searchString)/sizeof(char) - 1; 74 | 75 | std::ifstream payloadFile(path, std::ios::binary | std::ios::ate); 76 | if (!payloadFile) { 77 | logPrintf("Could not open existing payload, does it exists?\n"); 78 | return LumaVersion{}; 79 | } 80 | 81 | /* Load entire file into local buffer */ 82 | size_t payloadSize = payloadFile.tellg(); 83 | payloadFile.seekg(0, std::ios::beg); 84 | char* payloadData = (char*)std::malloc(payloadSize); 85 | payloadFile.read(payloadData, payloadSize); 86 | payloadFile.close(); 87 | 88 | logPrintf("Loaded existing payload in memory, searching for version number...\n"); 89 | 90 | size_t curProposedOffset = 0; 91 | unsigned short curStringIndex = 0; 92 | bool found = false; 93 | std::string versionString = ""; 94 | 95 | // Byte-by-byte search. (memcmp might be faster?) 96 | // Since " " (1st char) is only used once in the whole string we can search in O(n) 97 | for (size_t offset = 0; offset < payloadSize - searchStringLen; ++offset) { 98 | if (payloadData[offset] == searchString[curStringIndex]) { 99 | if (curStringIndex == searchStringLen - 1) { 100 | found = true; 101 | break; 102 | } 103 | if (curStringIndex == 0) { 104 | curProposedOffset = offset; 105 | } 106 | curStringIndex++; 107 | } 108 | else { 109 | if (curStringIndex > 0) { 110 | curStringIndex = 0; 111 | } 112 | } 113 | } 114 | 115 | if (found) { 116 | // Version is what comes after " v" and before " configuration" 117 | curProposedOffset += searchStringLen; 118 | size_t verOffset = curProposedOffset; 119 | for (; verOffset < payloadSize; ++verOffset) { 120 | if (payloadData[verOffset] == 'c' && payloadData[verOffset-1] == ' ') { 121 | break; 122 | } 123 | } 124 | // Get full version string 125 | versionString = std::string(payloadData + curProposedOffset, verOffset - curProposedOffset - 1); 126 | } 127 | 128 | std::free(payloadData); 129 | 130 | const size_t separator = versionString.find("-"); 131 | if (separator == std::string::npos) { 132 | return LumaVersion{ versionString, "", false }; 133 | } 134 | 135 | LumaVersion version; 136 | version.release = versionString.substr(0, separator); 137 | 138 | const size_t end = versionString.find(" ", separator); 139 | if (end == std::string::npos) { 140 | version.commit = versionString.substr(separator + 1); 141 | version.isDev = false; 142 | } else { 143 | version.commit = versionString.substr(separator + 1, end - separator - 1); 144 | version.isDev = versionString.find("(dev)", separator) != std::string::npos; 145 | } 146 | 147 | return version; 148 | } -------------------------------------------------------------------------------- /source/arnutil.cpp: -------------------------------------------------------------------------------- 1 | #include "arnutil.h" 2 | 3 | #include "utils.h" 4 | 5 | bool renameRecursive(const FS_Archive& archive, const std::string& source, const std::string& target); 6 | 7 | bool arnVersionCheck(const LumaVersion& version) { 8 | // Bound checking before trying to do naughty things 9 | if (version.release.empty()) { 10 | logPrintf("Weird version string: it's empty (?)\n"); 11 | return false; 12 | } 13 | 14 | // Parse release number 15 | std::string releaseStr = version.release; 16 | bool hasMajor = false; 17 | size_t relSeparator = version.release.find('.'); 18 | 19 | // "." found, get only release part and set major version flag 20 | if (relSeparator != std::string::npos) { 21 | releaseStr = version.release.substr(0, relSeparator); 22 | hasMajor = true; 23 | } 24 | int release = std::atoi(releaseStr.c_str()); 25 | 26 | // Check major version if found and release is 5.x 27 | if (release == 5 && hasMajor) { 28 | // Parse major version number 29 | std::string majorStr = version.release.substr(relSeparator+1); 30 | size_t minSeparator = majorStr.find('.'); 31 | 32 | // "." found, get only release part and set major version flag 33 | if (minSeparator != std::string::npos) { 34 | majorStr = majorStr.substr(0, minSeparator); 35 | } 36 | 37 | int major = std::atoi(majorStr.c_str()); 38 | 39 | // Check if major is lower than 2 40 | return major < 2; 41 | } else { 42 | // If version if not 5.x (or is 5.0) just check if it's <= 5 43 | return release <= 5; 44 | } 45 | } 46 | 47 | bool arnMigrate() { 48 | const static FS_Path aurei = fsMakePath(PATH_ASCII, "/aurei"); 49 | const static FS_Path luma = fsMakePath(PATH_ASCII, "/luma"); 50 | FS_Archive sdmcArchive; 51 | 52 | if (FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, NULL)) != 0) { 53 | logPrintf("\nCould not access SD Card (?)\n\n"); 54 | return false; 55 | } 56 | 57 | // Check if /luma already existsHandle directory = { 0 }; 58 | if (FSUSER_OpenDirectory(NULL, sdmcArchive, luma) == 0) { 59 | logPrintf("Luma directory already exists, skipping migration..\n"); 60 | return true; 61 | } 62 | 63 | if (!renameRecursive(sdmcArchive, "/aurei", "/luma")) { 64 | FSUSER_CloseArchive(sdmcArchive); 65 | return false; 66 | } 67 | 68 | // Delete the source directory and check if it succeeds 69 | Result res = FSUSER_DeleteDirectoryRecursively(sdmcArchive, aurei); 70 | if (res != 0) { 71 | logPrintf("\nWARN: Could not delete original /aurei (%ld)!\n\n", res); 72 | } 73 | 74 | FSUSER_CloseArchive(sdmcArchive); 75 | return true; 76 | } 77 | 78 | bool renameRecursive(const FS_Archive& archive, const std::string& source, const std::string& target) { 79 | const FS_Path sourcePath = fsMakePath(PATH_ASCII, source.c_str()); 80 | const FS_Path targetPath = fsMakePath(PATH_ASCII, target.c_str()); 81 | 82 | // Open source directory 83 | Handle directory = 0; 84 | if (FSUSER_OpenDirectory(&directory, archive, sourcePath) != 0) { 85 | logPrintf("\nCould not open %s\n\n", source.c_str()); 86 | return false; 87 | } 88 | 89 | // Make target directory 90 | if (FSUSER_CreateDirectory(archive, targetPath, FS_ATTRIBUTE_DIRECTORY) != 0) { 91 | logPrintf("\nCould not create %s\n\n", target.c_str()); 92 | return false; 93 | } 94 | 95 | u32 fileRead = 0; 96 | while (true) { 97 | FS_DirectoryEntry entry = {}; 98 | FSDIR_Read(directory, &fileRead, 1, &entry); 99 | if (!fileRead) { 100 | break; 101 | } 102 | 103 | // Convert name to ASCII (just cut the other bytes) 104 | char name8[262] = { 0 }; 105 | for (size_t i = 0; i < 262; i++) { 106 | name8[i] = entry.name[i] % 0xff; 107 | } 108 | std::string filePath = std::string("/") + name8; 109 | std::string from = source + filePath; 110 | std::string to = target + filePath; 111 | 112 | // Is a directory? Recurse rename 113 | if (entry.attributes & FS_ATTRIBUTE_DIRECTORY) { 114 | logPrintf(" %s -> %s (DIR)\n", from.c_str(), to.c_str()); 115 | if (!renameRecursive(archive, source + filePath, target + filePath)) { 116 | return false; 117 | } 118 | } else { 119 | FS_Path sourceFilePath = fsMakePath(PATH_ASCII, from.c_str()); 120 | FS_Path targetFilePath = fsMakePath(PATH_ASCII, to.c_str()); 121 | if (FSUSER_RenameFile(archive, sourceFilePath, archive, targetFilePath) != 0) { 122 | logPrintf("\nCould not rename %s\n\n", (char*)sourceFilePath.data); 123 | return false; 124 | } 125 | logPrintf(" %s -> %s\n", (char*)sourceFilePath.data, (char*)targetFilePath.data); 126 | } 127 | } 128 | 129 | return true; 130 | } -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .SUFFIXES: 2 | 3 | ifeq ($(strip $(DEVKITARM)),) 4 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 5 | endif 6 | 7 | include $(DEVKITARM)/3ds_rules 8 | 9 | CFGFILE ?= Makefile.config 10 | include $(CURDIR)/$(CFGFILE) 11 | 12 | TARGET := $(BINDIR)/$(BINNAME) 13 | 14 | LIBS := $(foreach lib,$(LIBRARIES),-l$(lib)) 15 | LIBDIRS := $(CTRULIB) $(PORTLIBS) 16 | 17 | OUTPUT := $(CURDIR)/$(TARGET) 18 | 19 | VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) 20 | 21 | DEPSDIR := $(CURDIR)/$(BUILD) 22 | 23 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 24 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 25 | OFILES := $(addprefix $(BUILD)/, $(CPPFILES:.cpp=.o) $(CFILES:.c=.o)) 26 | 27 | LD := $(CXX) 28 | 29 | INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 30 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 31 | $(foreach dir,$(CURDIR),-I$(dir)/external/include) \ 32 | -I$(CURDIR)/$(BUILD) 33 | 34 | LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ 35 | $(foreach dir,$(CURDIR),-L$(dir)/external/libs) 36 | 37 | APP_ICON := $(CURDIR)/$(ICON) 38 | 39 | _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh 40 | 41 | # Compiler flags 42 | 43 | ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft 44 | 45 | CFLAGS := -g -w -pedantic -mword-relocations \ 46 | -fomit-frame-pointer -ffunction-sections \ 47 | $(ARCH) $(EXTRACFLAGS) 48 | 49 | CFLAGS += $(INCLUDE) -DARM11 -D_3DS 50 | 51 | # Enable optimization outside debug builds 52 | ifndef DEBUG 53 | CFLAGS += -Ofast 54 | endif 55 | 56 | # Get a version number based on Git tags and stuff 57 | GIT_VER := $(shell git describe --dirty --always --tags) 58 | ifneq ($(strip $(GIT_VER)),) 59 | CFLAGS += -DGIT_VER=\"$(GIT_VER)\" 60 | endif 61 | 62 | CXXFLAGS := $(CFLAGS) -fno-rtti -fexceptions -std=gnu++11 63 | 64 | LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) 65 | 66 | ZIPNAME = lumaupdater-$(shell git describe --tags | tr -d 'v').zip 67 | 68 | # Shortcuts 69 | 70 | all : prereq $(OUTPUT).3dsx $(OUTPUT).cia 71 | 3dsx: prereq $(OUTPUT).3dsx 72 | cia : prereq $(OUTPUT).cia 73 | pkg : prereq $(ZIPNAME) 74 | 75 | prereq: 76 | @[ -d $(CURDIR)/$(BUILD) ] || mkdir -p $(CURDIR)/$(BUILD) 77 | @[ -d $(CURDIR)/$(BINDIR) ] || mkdir -p $(CURDIR)/$(BINDIR) 78 | 79 | clean: 80 | @echo clean ... 81 | @rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).cia $(OUTPUT).smdh $(TARGET).elf 82 | 83 | # Archive 84 | 85 | $(ZIPNAME): $(OUTPUT).cia $(OUTPUT).3dsx $(OUTPUT).smdh 86 | mkdir -p $(CURDIR)/archive/3DS/lumaupdater 87 | cp $(CURDIR)/lumaupdater.cfg $(CURDIR)/archive 88 | cp $(OUTPUT).cia $(CURDIR)/archive 89 | cp $(OUTPUT).3dsx $(OUTPUT).smdh $(CURDIR)/archive/3DS/lumaupdater 90 | @(cd archive; zip -r -9 ../$(ZIPNAME) .) 91 | rm -rf $(CURDIR)/archive 92 | @echo 93 | @echo "built ... $(ZIPNAME)" 94 | 95 | # Output 96 | 97 | MAKEROM ?= makerom 98 | 99 | $(OUTPUT).elf: $(OFILES) 100 | 101 | $(OUTPUT).3dsx: $(OUTPUT).elf $(OUTPUT).smdh 102 | 103 | $(OUTPUT).cia: $(OUTPUT).elf $(BUILD)/banner.bnr $(BUILD)/icon.icn 104 | $(MAKEROM) -f cia -o $@ -elf $< -rsf $(CURDIR)/rominfo.rsf -target t -exefslogo -logo meta/logo.bcma.lz -banner $(BUILD)/banner.bnr -icon $(BUILD)/icon.icn -DAPP_TITLE="$(APP_TITLE)" -DPRODUCT_CODE="$(PRODUCT_CODE)" -DUNIQUE_ID="$(UNIQUE_ID)" 105 | @echo "built ... $(BINNAME).cia" 106 | 107 | # Banner 108 | 109 | BANNERTOOL ?= bannertool 110 | 111 | ifeq ($(suffix $(BANNER_IMAGE)),.cgfx) 112 | BANNER_IMAGE_ARG := -ci 113 | else 114 | BANNER_IMAGE_ARG := -i 115 | endif 116 | 117 | ifeq ($(suffix $(BANNER_AUDIO)),.cwav) 118 | BANNER_AUDIO_ARG := -ca 119 | else 120 | BANNER_AUDIO_ARG := -a 121 | endif 122 | 123 | $(BUILD)/%.bnr: $(BANNER_IMAGE) $(BANNER_AUDIO) 124 | $(BANNERTOOL) makebanner $(BANNER_IMAGE_ARG) $(BANNER_IMAGE) $(BANNER_AUDIO_ARG) $(BANNER_AUDIO) -o $@ 125 | 126 | $(BUILD)/%.icn: $(ICON) 127 | $(BANNERTOOL) makesmdh -s "$(APP_TITLE)" -l "$(APP_DESCRIPTION)" -p "$(APP_AUTHOR)" -i $(ICON) -f visible,extendedbanner,nosavebackups,ratingrequired --cero 153 --esrb 153 --usk 153 --pegigen 153 --pegiptr 153 --pegibbfc 153 --cob 153 --grb 153 --cgsrr 153 -o $@ 128 | 129 | # Source 130 | 131 | DEPENDS := $(OFILES:.o=.d) 132 | 133 | $(BUILD)/%.o: %.cpp 134 | @echo $(notdir $<) 135 | $(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER) 136 | 137 | $(BUILD)/%.o: %.c 138 | @echo $(notdir $<) 139 | $(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) -c $< -o $@ $(ERROR_FILTER) 140 | 141 | -include $(DEPENDS) -------------------------------------------------------------------------------- /source/7z/CpuArch.h: -------------------------------------------------------------------------------- 1 | /* CpuArch.h -- CPU specific code 2 | 2015-12-01: Igor Pavlov : Public domain */ 3 | 4 | #ifndef __CPU_ARCH_H 5 | #define __CPU_ARCH_H 6 | 7 | #include "7zTypes.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | /* 12 | MY_CPU_LE means that CPU is LITTLE ENDIAN. 13 | MY_CPU_BE means that CPU is BIG ENDIAN. 14 | If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform. 15 | 16 | MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. 17 | */ 18 | 19 | #if defined(__AARCH64EL__) \ 20 | || defined(__AARCH64EB__) 21 | #define MY_CPU_64BIT 22 | #endif 23 | 24 | #if defined(_M_ARM) \ 25 | || defined(__ARMEL__) \ 26 | || defined(__THUMBEL__) \ 27 | || defined(__ARMEB__) \ 28 | || defined(__THUMBEB__) 29 | #define MY_CPU_32BIT 30 | #endif 31 | 32 | #if defined(MY_CPU_ARM_LE) \ 33 | || defined(__LITTLE_ENDIAN__) \ 34 | || defined(__ARMEL__) \ 35 | || defined(__THUMBEL__) \ 36 | || defined(__AARCH64EL__) \ 37 | || defined(__MIPSEL__) \ 38 | || defined(__MIPSEL) \ 39 | || defined(_MIPSEL) \ 40 | || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) 41 | #define MY_CPU_LE 42 | #endif 43 | 44 | #if defined(__BIG_ENDIAN__) \ 45 | || defined(__ARMEB__) \ 46 | || defined(__THUMBEB__) \ 47 | || defined(__AARCH64EB__) \ 48 | || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) 49 | #define MY_CPU_BE 50 | #endif 51 | 52 | #if defined(MY_CPU_LE) && defined(MY_CPU_BE) 53 | Stop_Compiling_Bad_Endian 54 | #endif 55 | 56 | #ifdef MY_CPU_LE_UNALIGN 57 | 58 | #define GetUi16(p) (*(const UInt16 *)(const void *)(p)) 59 | #define GetUi32(p) (*(const UInt32 *)(const void *)(p)) 60 | #define GetUi64(p) (*(const UInt64 *)(const void *)(p)) 61 | 62 | #define SetUi16(p, v) { *(UInt16 *)(p) = (v); } 63 | #define SetUi32(p, v) { *(UInt32 *)(p) = (v); } 64 | #define SetUi64(p, v) { *(UInt64 *)(p) = (v); } 65 | 66 | #else 67 | 68 | #define GetUi16(p) ( (UInt16) ( \ 69 | ((const Byte *)(p))[0] | \ 70 | ((UInt16)((const Byte *)(p))[1] << 8) )) 71 | 72 | #define GetUi32(p) ( \ 73 | ((const Byte *)(p))[0] | \ 74 | ((UInt32)((const Byte *)(p))[1] << 8) | \ 75 | ((UInt32)((const Byte *)(p))[2] << 16) | \ 76 | ((UInt32)((const Byte *)(p))[3] << 24)) 77 | 78 | #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) 79 | 80 | #define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ 81 | _ppp_[0] = (Byte)_vvv_; \ 82 | _ppp_[1] = (Byte)(_vvv_ >> 8); } 83 | 84 | #define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ 85 | _ppp_[0] = (Byte)_vvv_; \ 86 | _ppp_[1] = (Byte)(_vvv_ >> 8); \ 87 | _ppp_[2] = (Byte)(_vvv_ >> 16); \ 88 | _ppp_[3] = (Byte)(_vvv_ >> 24); } 89 | 90 | #define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \ 91 | SetUi32(_ppp2_ , (UInt32)_vvv2_); \ 92 | SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); } 93 | 94 | #endif 95 | 96 | 97 | #if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300) 98 | 99 | /* Note: we use bswap instruction, that is unsupported in 386 cpu */ 100 | 101 | #include 102 | 103 | #pragma intrinsic(_byteswap_ulong) 104 | #pragma intrinsic(_byteswap_uint64) 105 | #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) 106 | #define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) 107 | 108 | #define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v) 109 | 110 | #elif defined(MY_CPU_LE_UNALIGN) && defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) 111 | 112 | #define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p)) 113 | #define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p)) 114 | 115 | #define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v) 116 | 117 | #else 118 | 119 | #define GetBe32(p) ( \ 120 | ((UInt32)((const Byte *)(p))[0] << 24) | \ 121 | ((UInt32)((const Byte *)(p))[1] << 16) | \ 122 | ((UInt32)((const Byte *)(p))[2] << 8) | \ 123 | ((const Byte *)(p))[3] ) 124 | 125 | #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) 126 | 127 | #define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ 128 | _ppp_[0] = (Byte)(_vvv_ >> 24); \ 129 | _ppp_[1] = (Byte)(_vvv_ >> 16); \ 130 | _ppp_[2] = (Byte)(_vvv_ >> 8); \ 131 | _ppp_[3] = (Byte)_vvv_; } 132 | 133 | #endif 134 | 135 | 136 | #define GetBe16(p) ( (UInt16) ( \ 137 | ((UInt16)((const Byte *)(p))[0] << 8) | \ 138 | ((const Byte *)(p))[1] )) 139 | 140 | 141 | EXTERN_C_END 142 | 143 | #endif 144 | -------------------------------------------------------------------------------- /source/7z/7zStream.c: -------------------------------------------------------------------------------- 1 | /* 7zStream.c -- 7z Stream functions 2 | 2013-11-12 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include 7 | 8 | #include "7zTypes.h" 9 | 10 | SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) 11 | { 12 | while (size != 0) 13 | { 14 | size_t processed = size; 15 | RINOK(stream->Read(stream, buf, &processed)); 16 | if (processed == 0) 17 | return errorType; 18 | buf = (void *)((Byte *)buf + processed); 19 | size -= processed; 20 | } 21 | return SZ_OK; 22 | } 23 | 24 | SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size) 25 | { 26 | return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); 27 | } 28 | 29 | SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf) 30 | { 31 | size_t processed = 1; 32 | RINOK(stream->Read(stream, buf, &processed)); 33 | return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; 34 | } 35 | 36 | SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset) 37 | { 38 | Int64 t = offset; 39 | return stream->Seek(stream, &t, SZ_SEEK_SET); 40 | } 41 | 42 | SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) 43 | { 44 | const void *lookBuf; 45 | if (*size == 0) 46 | return SZ_OK; 47 | RINOK(stream->Look(stream, &lookBuf, size)); 48 | memcpy(buf, lookBuf, *size); 49 | return stream->Skip(stream, *size); 50 | } 51 | 52 | SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType) 53 | { 54 | while (size != 0) 55 | { 56 | size_t processed = size; 57 | RINOK(stream->Read(stream, buf, &processed)); 58 | if (processed == 0) 59 | return errorType; 60 | buf = (void *)((Byte *)buf + processed); 61 | size -= processed; 62 | } 63 | return SZ_OK; 64 | } 65 | 66 | SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size) 67 | { 68 | return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); 69 | } 70 | 71 | static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size) 72 | { 73 | SRes res = SZ_OK; 74 | CLookToRead *p = (CLookToRead *)pp; 75 | size_t size2 = p->size - p->pos; 76 | if (size2 == 0 && *size > 0) 77 | { 78 | p->pos = 0; 79 | size2 = LookToRead_BUF_SIZE; 80 | res = p->realStream->Read(p->realStream, p->buf, &size2); 81 | p->size = size2; 82 | } 83 | if (size2 < *size) 84 | *size = size2; 85 | *buf = p->buf + p->pos; 86 | return res; 87 | } 88 | 89 | static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size) 90 | { 91 | SRes res = SZ_OK; 92 | CLookToRead *p = (CLookToRead *)pp; 93 | size_t size2 = p->size - p->pos; 94 | if (size2 == 0 && *size > 0) 95 | { 96 | p->pos = 0; 97 | if (*size > LookToRead_BUF_SIZE) 98 | *size = LookToRead_BUF_SIZE; 99 | res = p->realStream->Read(p->realStream, p->buf, size); 100 | size2 = p->size = *size; 101 | } 102 | if (size2 < *size) 103 | *size = size2; 104 | *buf = p->buf + p->pos; 105 | return res; 106 | } 107 | 108 | static SRes LookToRead_Skip(void *pp, size_t offset) 109 | { 110 | CLookToRead *p = (CLookToRead *)pp; 111 | p->pos += offset; 112 | return SZ_OK; 113 | } 114 | 115 | static SRes LookToRead_Read(void *pp, void *buf, size_t *size) 116 | { 117 | CLookToRead *p = (CLookToRead *)pp; 118 | size_t rem = p->size - p->pos; 119 | if (rem == 0) 120 | return p->realStream->Read(p->realStream, buf, size); 121 | if (rem > *size) 122 | rem = *size; 123 | memcpy(buf, p->buf + p->pos, rem); 124 | p->pos += rem; 125 | *size = rem; 126 | return SZ_OK; 127 | } 128 | 129 | static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin) 130 | { 131 | CLookToRead *p = (CLookToRead *)pp; 132 | p->pos = p->size = 0; 133 | return p->realStream->Seek(p->realStream, pos, origin); 134 | } 135 | 136 | void LookToRead_CreateVTable(CLookToRead *p, int lookahead) 137 | { 138 | p->s.Look = lookahead ? 139 | LookToRead_Look_Lookahead : 140 | LookToRead_Look_Exact; 141 | p->s.Skip = LookToRead_Skip; 142 | p->s.Read = LookToRead_Read; 143 | p->s.Seek = LookToRead_Seek; 144 | } 145 | 146 | void LookToRead_Init(CLookToRead *p) 147 | { 148 | p->pos = p->size = 0; 149 | } 150 | 151 | static SRes SecToLook_Read(void *pp, void *buf, size_t *size) 152 | { 153 | CSecToLook *p = (CSecToLook *)pp; 154 | return LookInStream_LookRead(p->realStream, buf, size); 155 | } 156 | 157 | void SecToLook_CreateVTable(CSecToLook *p) 158 | { 159 | p->s.Read = SecToLook_Read; 160 | } 161 | 162 | static SRes SecToRead_Read(void *pp, void *buf, size_t *size) 163 | { 164 | CSecToRead *p = (CSecToRead *)pp; 165 | return p->realStream->Read(p->realStream, buf, size); 166 | } 167 | 168 | void SecToRead_CreateVTable(CSecToRead *p) 169 | { 170 | p->s.Read = SecToRead_Read; 171 | } 172 | -------------------------------------------------------------------------------- /source/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | #include 3 | #include 4 | 5 | std::string formatErrMessage(const char* msg, const Result& val) { 6 | std::ostringstream os; 7 | os << msg << "\nRet code: " << std::hex << val; 8 | return os.str(); 9 | } 10 | 11 | bool fileExists(const std::string& path) { 12 | std::ifstream file(path); 13 | bool isok = file.is_open(); 14 | file.close(); 15 | return isok; 16 | } 17 | 18 | void trim(std::string &s) { 19 | s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); 20 | s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); 21 | } 22 | 23 | std::string unescape(const std::string& s) { 24 | std::string res; 25 | auto it = s.begin(); 26 | while (it != s.end()) { 27 | char c = *it++; 28 | if (c == '\\' && it != s.end()) { 29 | switch (*it++) { 30 | case '\\': c = '\\'; break; 31 | case 'n': c = '\n'; break; 32 | case 'r': c = '\r'; break; 33 | case 't': c = '\t'; break; 34 | case '"': c = '"'; break; 35 | default: continue; 36 | } 37 | } 38 | res += c; 39 | } 40 | return res; 41 | } 42 | 43 | std::string stripMarkdown(std::string text) { 44 | // Strip links 45 | size_t offset = 0; 46 | while (true) { 47 | size_t index = text.find('[', offset); 48 | if (index == std::string::npos) { 49 | // No more open square brackets, exit 50 | break; 51 | } 52 | 53 | if (index != 0 && text[index - 1] == '\\') { 54 | // Bracket is escaped, skip 55 | offset = index + 1; 56 | continue; 57 | } 58 | 59 | // Get link name 60 | size_t closing = text.find(']', index + 1); 61 | if (closing == std::string::npos) { 62 | // None? Not a link then. Skip to next one 63 | offset = index + 1; 64 | continue; 65 | } 66 | 67 | std::string linkName = text.substr(index + 1, closing - index - 1); 68 | 69 | // Get link end 70 | size_t linkEnd = text.find(')', closing + 1); 71 | if (linkEnd == std::string::npos) { 72 | // None? Not a link then. Skip to next one 73 | offset = closing + 1; 74 | continue; 75 | } 76 | 77 | // Replace everything with the link name 78 | text.replace(index, linkEnd - index + 1, linkName); 79 | } 80 | 81 | // Strip \r 82 | offset = 0; 83 | while (true) { 84 | offset = text.find('\r', offset); 85 | if (offset == std::string::npos) { 86 | // No more \r, exit 87 | break; 88 | } 89 | 90 | // Replace with blank 91 | text.replace(offset, 1, ""); 92 | } 93 | 94 | return text; 95 | } 96 | 97 | std::string indent(const std::string& text, const size_t cols) { 98 | static const std::string indent = " "; 99 | static const std::string nlindent = indent + indent; 100 | 101 | std::string out = ""; 102 | size_t offset = 0; 103 | bool hasMore = true; 104 | 105 | while (hasMore) { 106 | size_t index = text.find('\n', offset); 107 | if (index == std::string::npos) { 108 | // Last line, break after this cycle 109 | hasMore = false; 110 | index = text.length(); 111 | } 112 | 113 | bool fstline = true; 114 | while (index - offset >= cols - 2) { 115 | size_t textamt = cols - 2; 116 | textamt -= (fstline ? indent.length() : nlindent.length()); 117 | 118 | // Search for nearby whitespace (word wrapping) 119 | size_t lastWhitespace = text.find_last_of(' ', offset + textamt); 120 | size_t distance = (offset + cols) - lastWhitespace; 121 | if (lastWhitespace != std::string::npos && distance < 15) { 122 | // Nearby space found, wrap word to next line 123 | std::string curline = text.substr(offset, lastWhitespace - offset); 124 | out += (fstline ? indent : nlindent) + curline + "\n"; 125 | textamt = lastWhitespace - offset + 1; 126 | } else { 127 | // No nearby space found, truncate word 128 | std::string curline = text.substr(offset, textamt); 129 | out += (fstline ? indent : nlindent) + curline + "-\n"; 130 | } 131 | offset += textamt; 132 | fstline = false; 133 | } 134 | 135 | out += (fstline ? indent : nlindent) + text.substr(offset, index - offset) + "\n"; 136 | offset = index + 1; 137 | } 138 | 139 | return out; 140 | } 141 | 142 | int getPageCount(const std::string& text, const int rows) { 143 | return ceil(std::count(text.begin(), text.end(), '\n') / (float)rows); 144 | } 145 | 146 | std::string getPage(const std::string& text, const int num, const int rows) { 147 | const int startAtIndex = rows * num; 148 | const int stopAtIndex = rows * (num + 1); 149 | 150 | std::size_t startIndex = 0; 151 | for (int i = 0; i < startAtIndex; i++) { 152 | startIndex = text.find('\n', startIndex + 1); 153 | if (startIndex == std::string::npos) { 154 | return ""; 155 | } 156 | } 157 | 158 | std::size_t endIndex = startIndex; 159 | for (int i = startAtIndex; i < stopAtIndex; i++) { 160 | endIndex = text.find('\n', endIndex + 1); 161 | if (endIndex == std::string::npos) { 162 | break; 163 | } 164 | } 165 | 166 | return text.substr(startIndex == 0 ? 0 : startIndex + 1, endIndex - startIndex); 167 | } 168 | 169 | FILE* _logfile = nullptr; 170 | 171 | void logInit(const char* path) { 172 | _logfile = fopen(path, "w+"); 173 | } 174 | void logExit() { 175 | if (_logfile != nullptr) { 176 | fclose(_logfile); 177 | } 178 | } 179 | 180 | void logPrintf(const char* format, ...) { 181 | va_list args; 182 | va_start(args, format); 183 | if (_logfile != nullptr) { 184 | vfprintf(_logfile, format, args); 185 | } 186 | vprintf(format, args); 187 | va_end(args); 188 | } -------------------------------------------------------------------------------- /source/minizip/crypt.h: -------------------------------------------------------------------------------- 1 | /* crypt.h -- base code for traditional PKWARE encryption 2 | Version 1.01e, February 12th, 2005 3 | 4 | Copyright (C) 1998-2005 Gilles Vollant 5 | Modifications for Info-ZIP crypting 6 | Copyright (C) 2003 Terry Thorsen 7 | 8 | This code is a modified version of crypting code in Info-ZIP distribution 9 | 10 | Copyright (C) 1990-2000 Info-ZIP. All rights reserved. 11 | 12 | See the Info-ZIP LICENSE file version 2000-Apr-09 or later for terms of use 13 | which also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html 14 | 15 | The encryption/decryption parts of this source code (as opposed to the 16 | non-echoing password parts) were originally written in Europe. The 17 | whole source package can be freely distributed, including from the USA. 18 | (Prior to January 2000, re-export from the US was a violation of US law.) 19 | 20 | This encryption code is a direct transcription of the algorithm from 21 | Roger Schlafly, described by Phil Katz in the file appnote.txt. This 22 | file (appnote.txt) is distributed with the PKZIP program (even in the 23 | version without encryption capabilities). 24 | 25 | If you don't need crypting in your application, just define symbols 26 | NOCRYPT and NOUNCRYPT. 27 | 28 | Mar 8th, 2016 - Lucio Cosmo 29 | Fixed support for 64bit builds for archives with "PKWARE" password. 30 | Changed long, unsigned long, unsigned to unsigned int in 31 | access functions to crctables and pkeys 32 | 33 | */ 34 | 35 | #define CRC32(c, b) ((*(pcrc_32_tab+(((unsigned int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) 36 | 37 | /*********************************************************************** 38 | * Return the next byte in the pseudo-random sequence 39 | */ 40 | static int decrypt_byte(unsigned int* pkeys) 41 | { 42 | unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an 43 | * unpredictable manner on 16-bit systems; not a problem 44 | * with any known compiler so far, though */ 45 | 46 | temp = ((unsigned int)(*(pkeys+2)) & 0xffff) | 2; 47 | return (unsigned int)(((temp * (temp ^ 1)) >> 8) & 0xff); 48 | } 49 | 50 | /*********************************************************************** 51 | * Update the encryption keys with the next byte of plain text 52 | */ 53 | static int update_keys(unsigned int* pkeys,const unsigned int* pcrc_32_tab,int c) 54 | { 55 | (*(pkeys+0)) = CRC32((*(pkeys+0)), c); 56 | (*(pkeys+1)) += (*(pkeys+0)) & 0xff; 57 | (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; 58 | { 59 | register int keyshift = (int)((*(pkeys+1)) >> 24); 60 | (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); 61 | } 62 | return c; 63 | } 64 | 65 | 66 | /*********************************************************************** 67 | * Initialize the encryption keys and the random header according to 68 | * the given password. 69 | */ 70 | static void init_keys(const char* passwd,unsigned int* pkeys,const unsigned int* pcrc_32_tab) 71 | { 72 | *(pkeys+0) = 305419896L; 73 | *(pkeys+1) = 591751049L; 74 | *(pkeys+2) = 878082192L; 75 | while (*passwd != 0) 76 | { 77 | update_keys(pkeys,pcrc_32_tab,(int)*passwd); 78 | passwd++; 79 | } 80 | } 81 | 82 | #define zdecode(pkeys,pcrc_32_tab,c) \ 83 | (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys))) 84 | 85 | #define zencode(pkeys,pcrc_32_tab,c,t) \ 86 | (t=decrypt_byte(pkeys), update_keys(pkeys,pcrc_32_tab,c), t^(c)) 87 | 88 | #ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED 89 | 90 | #define RAND_HEAD_LEN 12 91 | /* "last resort" source for second part of crypt seed pattern */ 92 | # ifndef ZCR_SEED2 93 | # define ZCR_SEED2 3141592654UL /* use PI as default pattern */ 94 | # endif 95 | 96 | static int crypthead(const char* passwd, /* password string */ 97 | unsigned char* buf, /* where to write header */ 98 | int bufSize, 99 | unsigned int* pkeys, 100 | const unsigned int* pcrc_32_tab, 101 | unsigned int crcForCrypting) 102 | { 103 | int n; /* index in random header */ 104 | int t; /* temporary */ 105 | int c; /* random byte */ 106 | unsigned char header[RAND_HEAD_LEN-2]; /* random header */ 107 | static unsigned calls = 0; /* ensure different random header each time */ 108 | 109 | if (bufSize < RAND_HEAD_LEN) 110 | return 0; 111 | 112 | /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the 113 | * output of rand() to get less predictability, since rand() is 114 | * often poorly implemented. 115 | */ 116 | if (++calls == 1) 117 | { 118 | srand((unsigned)(time(NULL) ^ ZCR_SEED2)); 119 | } 120 | init_keys(passwd, pkeys, pcrc_32_tab); 121 | for (n = 0; n < RAND_HEAD_LEN-2; n++) 122 | { 123 | c = (rand() >> 7) & 0xff; 124 | header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); 125 | } 126 | /* Encrypt random header (last two bytes is high word of crc) */ 127 | init_keys(passwd, pkeys, pcrc_32_tab); 128 | for (n = 0; n < RAND_HEAD_LEN-2; n++) 129 | { 130 | buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); 131 | } 132 | buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); 133 | buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); 134 | return n; 135 | } 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /source/certs/cybertrust.h: -------------------------------------------------------------------------------- 1 | unsigned char cybertrust_cer[] = { 2 | 0x30, 0x82, 0x03, 0x77, 0x30, 0x82, 0x02, 0x5f, 0xa0, 0x03, 0x02, 0x01, 3 | 0x02, 0x02, 0x04, 0x02, 0x00, 0x00, 0xb9, 0x30, 0x0d, 0x06, 0x09, 0x2a, 4 | 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x5a, 5 | 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 6 | 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x09, 7 | 0x42, 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x6f, 0x72, 0x65, 0x31, 0x13, 0x30, 8 | 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x43, 0x79, 0x62, 0x65, 9 | 0x72, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 10 | 0x55, 0x04, 0x03, 0x13, 0x19, 0x42, 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x6f, 11 | 0x72, 0x65, 0x20, 0x43, 0x79, 0x62, 0x65, 0x72, 0x54, 0x72, 0x75, 0x73, 12 | 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x30, 13 | 0x30, 0x35, 0x31, 0x32, 0x31, 0x38, 0x34, 0x36, 0x30, 0x30, 0x5a, 0x17, 14 | 0x0d, 0x32, 0x35, 0x30, 0x35, 0x31, 0x32, 0x32, 0x33, 0x35, 0x39, 0x30, 15 | 0x30, 0x5a, 0x30, 0x5a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 16 | 0x06, 0x13, 0x02, 0x49, 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 17 | 0x04, 0x0a, 0x13, 0x09, 0x42, 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x6f, 0x72, 18 | 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 19 | 0x43, 0x79, 0x62, 0x65, 0x72, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x22, 20 | 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x42, 0x61, 0x6c, 21 | 0x74, 0x69, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x43, 0x79, 0x62, 0x65, 0x72, 22 | 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x30, 0x82, 23 | 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 24 | 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 25 | 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa3, 0x04, 0xbb, 0x22, 0xab, 26 | 0x98, 0x3d, 0x57, 0xe8, 0x26, 0x72, 0x9a, 0xb5, 0x79, 0xd4, 0x29, 0xe2, 27 | 0xe1, 0xe8, 0x95, 0x80, 0xb1, 0xb0, 0xe3, 0x5b, 0x8e, 0x2b, 0x29, 0x9a, 28 | 0x64, 0xdf, 0xa1, 0x5d, 0xed, 0xb0, 0x09, 0x05, 0x6d, 0xdb, 0x28, 0x2e, 29 | 0xce, 0x62, 0xa2, 0x62, 0xfe, 0xb4, 0x88, 0xda, 0x12, 0xeb, 0x38, 0xeb, 30 | 0x21, 0x9d, 0xc0, 0x41, 0x2b, 0x01, 0x52, 0x7b, 0x88, 0x77, 0xd3, 0x1c, 31 | 0x8f, 0xc7, 0xba, 0xb9, 0x88, 0xb5, 0x6a, 0x09, 0xe7, 0x73, 0xe8, 0x11, 32 | 0x40, 0xa7, 0xd1, 0xcc, 0xca, 0x62, 0x8d, 0x2d, 0xe5, 0x8f, 0x0b, 0xa6, 33 | 0x50, 0xd2, 0xa8, 0x50, 0xc3, 0x28, 0xea, 0xf5, 0xab, 0x25, 0x87, 0x8a, 34 | 0x9a, 0x96, 0x1c, 0xa9, 0x67, 0xb8, 0x3f, 0x0c, 0xd5, 0xf7, 0xf9, 0x52, 35 | 0x13, 0x2f, 0xc2, 0x1b, 0xd5, 0x70, 0x70, 0xf0, 0x8f, 0xc0, 0x12, 0xca, 36 | 0x06, 0xcb, 0x9a, 0xe1, 0xd9, 0xca, 0x33, 0x7a, 0x77, 0xd6, 0xf8, 0xec, 37 | 0xb9, 0xf1, 0x68, 0x44, 0x42, 0x48, 0x13, 0xd2, 0xc0, 0xc2, 0xa4, 0xae, 38 | 0x5e, 0x60, 0xfe, 0xb6, 0xa6, 0x05, 0xfc, 0xb4, 0xdd, 0x07, 0x59, 0x02, 39 | 0xd4, 0x59, 0x18, 0x98, 0x63, 0xf5, 0xa5, 0x63, 0xe0, 0x90, 0x0c, 0x7d, 40 | 0x5d, 0xb2, 0x06, 0x7a, 0xf3, 0x85, 0xea, 0xeb, 0xd4, 0x03, 0xae, 0x5e, 41 | 0x84, 0x3e, 0x5f, 0xff, 0x15, 0xed, 0x69, 0xbc, 0xf9, 0x39, 0x36, 0x72, 42 | 0x75, 0xcf, 0x77, 0x52, 0x4d, 0xf3, 0xc9, 0x90, 0x2c, 0xb9, 0x3d, 0xe5, 43 | 0xc9, 0x23, 0x53, 0x3f, 0x1f, 0x24, 0x98, 0x21, 0x5c, 0x07, 0x99, 0x29, 44 | 0xbd, 0xc6, 0x3a, 0xec, 0xe7, 0x6e, 0x86, 0x3a, 0x6b, 0x97, 0x74, 0x63, 45 | 0x33, 0xbd, 0x68, 0x18, 0x31, 0xf0, 0x78, 0x8d, 0x76, 0xbf, 0xfc, 0x9e, 46 | 0x8e, 0x5d, 0x2a, 0x86, 0xa7, 0x4d, 0x90, 0xdc, 0x27, 0x1a, 0x39, 0x02, 47 | 0x03, 0x01, 0x00, 0x01, 0xa3, 0x45, 0x30, 0x43, 0x30, 0x1d, 0x06, 0x03, 48 | 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xe5, 0x9d, 0x59, 0x30, 0x82, 49 | 0x47, 0x58, 0xcc, 0xac, 0xfa, 0x08, 0x54, 0x36, 0x86, 0x7b, 0x3a, 0xb5, 50 | 0x04, 0x4d, 0xf0, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 51 | 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x03, 0x30, 52 | 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 53 | 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 54 | 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x85, 55 | 0x0c, 0x5d, 0x8e, 0xe4, 0x6f, 0x51, 0x68, 0x42, 0x05, 0xa0, 0xdd, 0xbb, 56 | 0x4f, 0x27, 0x25, 0x84, 0x03, 0xbd, 0xf7, 0x64, 0xfd, 0x2d, 0xd7, 0x30, 57 | 0xe3, 0xa4, 0x10, 0x17, 0xeb, 0xda, 0x29, 0x29, 0xb6, 0x79, 0x3f, 0x76, 58 | 0xf6, 0x19, 0x13, 0x23, 0xb8, 0x10, 0x0a, 0xf9, 0x58, 0xa4, 0xd4, 0x61, 59 | 0x70, 0xbd, 0x04, 0x61, 0x6a, 0x12, 0x8a, 0x17, 0xd5, 0x0a, 0xbd, 0xc5, 60 | 0xbc, 0x30, 0x7c, 0xd6, 0xe9, 0x0c, 0x25, 0x8d, 0x86, 0x40, 0x4f, 0xec, 61 | 0xcc, 0xa3, 0x7e, 0x38, 0xc6, 0x37, 0x11, 0x4f, 0xed, 0xdd, 0x68, 0x31, 62 | 0x8e, 0x4c, 0xd2, 0xb3, 0x01, 0x74, 0xee, 0xbe, 0x75, 0x5e, 0x07, 0x48, 63 | 0x1a, 0x7f, 0x70, 0xff, 0x16, 0x5c, 0x84, 0xc0, 0x79, 0x85, 0xb8, 0x05, 64 | 0xfd, 0x7f, 0xbe, 0x65, 0x11, 0xa3, 0x0f, 0xc0, 0x02, 0xb4, 0xf8, 0x52, 65 | 0x37, 0x39, 0x04, 0xd5, 0xa9, 0x31, 0x7a, 0x18, 0xbf, 0xa0, 0x2a, 0xf4, 66 | 0x12, 0x99, 0xf7, 0xa3, 0x45, 0x82, 0xe3, 0x3c, 0x5e, 0xf5, 0x9d, 0x9e, 67 | 0xb5, 0xc8, 0x9e, 0x7c, 0x2e, 0xc8, 0xa4, 0x9e, 0x4e, 0x08, 0x14, 0x4b, 68 | 0x6d, 0xfd, 0x70, 0x6d, 0x6b, 0x1a, 0x63, 0xbd, 0x64, 0xe6, 0x1f, 0xb7, 69 | 0xce, 0xf0, 0xf2, 0x9f, 0x2e, 0xbb, 0x1b, 0xb7, 0xf2, 0x50, 0x88, 0x73, 70 | 0x92, 0xc2, 0xe2, 0xe3, 0x16, 0x8d, 0x9a, 0x32, 0x02, 0xab, 0x8e, 0x18, 71 | 0xdd, 0xe9, 0x10, 0x11, 0xee, 0x7e, 0x35, 0xab, 0x90, 0xaf, 0x3e, 0x30, 72 | 0x94, 0x7a, 0xd0, 0x33, 0x3d, 0xa7, 0x65, 0x0f, 0xf5, 0xfc, 0x8e, 0x9e, 73 | 0x62, 0xcf, 0x47, 0x44, 0x2c, 0x01, 0x5d, 0xbb, 0x1d, 0xb5, 0x32, 0xd2, 74 | 0x47, 0xd2, 0x38, 0x2e, 0xd0, 0xfe, 0x81, 0xdc, 0x32, 0x6a, 0x1e, 0xb5, 75 | 0xee, 0x3c, 0xd5, 0xfc, 0xe7, 0x81, 0x1d, 0x19, 0xc3, 0x24, 0x42, 0xea, 76 | 0x63, 0x39, 0xa9 77 | }; 78 | unsigned int cybertrust_cer_len = 891; 79 | -------------------------------------------------------------------------------- /source/minizip/ioapi_mem.c: -------------------------------------------------------------------------------- 1 | /* ioapi_mem.h -- IO base function header for compress/uncompress .zip 2 | files using zlib + zip or unzip API 3 | 4 | This version of ioapi is designed to access memory rather than files. 5 | We do use a region of memory to put data in to and take it out of. We do 6 | not have auto-extending buffers and do not inform anyone else that the 7 | data has been written. It is really intended for accessing a zip archive 8 | embedded in an application such that I can write an installer with no 9 | external files. Creation of archives has not been attempted, although 10 | parts of the framework are present. 11 | 12 | Based on Unzip ioapi.c version 0.22, May 19th, 2003 13 | 14 | Copyright (C) 1998-2003 Gilles Vollant 15 | (C) 2003 Justin Fletcher 16 | 17 | This file is under the same license as the Unzip tool it is distributed 18 | with. 19 | */ 20 | 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "zlib.h" 27 | #include "ioapi.h" 28 | 29 | #include "ioapi_mem.h" 30 | 31 | #ifndef IOMEM_BUFFERSIZE 32 | # define IOMEM_BUFFERSIZE (64 * 1024) 33 | #endif 34 | 35 | voidpf ZCALLBACK fopen_mem_func (opaque, filename, mode) 36 | voidpf opaque; 37 | const char* filename; 38 | int mode; 39 | { 40 | ourmemory_t *mem = (ourmemory_t *)opaque; 41 | if (mem == NULL) 42 | return NULL; /* Mem structure passed in was null */ 43 | 44 | if (mode & ZLIB_FILEFUNC_MODE_CREATE) 45 | { 46 | if (mem->grow) 47 | { 48 | mem->size = IOMEM_BUFFERSIZE; 49 | mem->base = (char *)malloc(mem->size); 50 | } 51 | 52 | mem->limit = 0; /* When writing we start with 0 bytes written */ 53 | } 54 | else 55 | mem->limit = mem->size; 56 | 57 | mem->cur_offset = 0; 58 | 59 | return mem; 60 | } 61 | 62 | voidpf ZCALLBACK fopendisk_mem_func (opaque, stream, number_disk, mode) 63 | voidpf opaque; 64 | voidpf stream; 65 | int number_disk; 66 | int mode; 67 | { 68 | /* Not used */ 69 | return NULL; 70 | } 71 | 72 | uLong ZCALLBACK fread_mem_func (opaque, stream, buf, size) 73 | voidpf opaque; 74 | voidpf stream; 75 | void* buf; 76 | uLong size; 77 | { 78 | ourmemory_t *mem = (ourmemory_t *)stream; 79 | 80 | if (size > mem->size - mem->cur_offset) 81 | size = mem->size - mem->cur_offset; 82 | 83 | memcpy(buf, mem->base + mem->cur_offset, size); 84 | mem->cur_offset += size; 85 | 86 | return size; 87 | } 88 | 89 | 90 | uLong ZCALLBACK fwrite_mem_func (opaque, stream, buf, size) 91 | voidpf opaque; 92 | voidpf stream; 93 | const void* buf; 94 | uLong size; 95 | { 96 | ourmemory_t *mem = (ourmemory_t *)stream; 97 | char *newbase = NULL; 98 | uLong newmemsize = 0; 99 | 100 | if (size > mem->size - mem->cur_offset) 101 | { 102 | if (mem->grow) 103 | { 104 | newmemsize = mem->size; 105 | if (size < IOMEM_BUFFERSIZE) 106 | newmemsize += IOMEM_BUFFERSIZE; 107 | else 108 | newmemsize += size; 109 | newbase = (char *)malloc(newmemsize); 110 | memcpy(newbase, mem->base, mem->size); 111 | free(mem->base); 112 | mem->base = newbase; 113 | mem->size = newmemsize; 114 | } 115 | else 116 | size = mem->size - mem->cur_offset; 117 | } 118 | memcpy(mem->base + mem->cur_offset, buf, size); 119 | mem->cur_offset += size; 120 | if (mem->cur_offset > mem->limit) 121 | mem->limit = mem->cur_offset; 122 | 123 | return size; 124 | } 125 | 126 | long ZCALLBACK ftell_mem_func (opaque, stream) 127 | voidpf opaque; 128 | voidpf stream; 129 | { 130 | ourmemory_t *mem = (ourmemory_t *)stream; 131 | return mem->cur_offset; 132 | } 133 | 134 | long ZCALLBACK fseek_mem_func (opaque, stream, offset, origin) 135 | voidpf opaque; 136 | voidpf stream; 137 | uLong offset; 138 | int origin; 139 | { 140 | ourmemory_t *mem = (ourmemory_t *)stream; 141 | uLong new_pos; 142 | switch (origin) 143 | { 144 | case ZLIB_FILEFUNC_SEEK_CUR: 145 | new_pos = mem->cur_offset + offset; 146 | break; 147 | case ZLIB_FILEFUNC_SEEK_END: 148 | new_pos = mem->limit + offset; 149 | break; 150 | case ZLIB_FILEFUNC_SEEK_SET: 151 | new_pos = offset; 152 | break; 153 | default: 154 | return -1; 155 | } 156 | 157 | if (new_pos > mem->size) 158 | return 1; /* Failed to seek that far */ 159 | mem->cur_offset = new_pos; 160 | return 0; 161 | } 162 | 163 | int ZCALLBACK fclose_mem_func (opaque, stream) 164 | voidpf opaque; 165 | voidpf stream; 166 | { 167 | /* Even with grow = 1, caller must always free() memory */ 168 | return 0; 169 | } 170 | 171 | int ZCALLBACK ferror_mem_func (opaque, stream) 172 | voidpf opaque; 173 | voidpf stream; 174 | { 175 | /* We never return errors */ 176 | return 0; 177 | } 178 | 179 | void fill_memory_filefunc (pzlib_filefunc_def, ourmem) 180 | zlib_filefunc_def* pzlib_filefunc_def; 181 | ourmemory_t *ourmem; 182 | { 183 | pzlib_filefunc_def->zopen_file = fopen_mem_func; 184 | pzlib_filefunc_def->zopendisk_file = fopendisk_mem_func; 185 | pzlib_filefunc_def->zread_file = fread_mem_func; 186 | pzlib_filefunc_def->zwrite_file = fwrite_mem_func; 187 | pzlib_filefunc_def->ztell_file = ftell_mem_func; 188 | pzlib_filefunc_def->zseek_file = fseek_mem_func; 189 | pzlib_filefunc_def->zclose_file = fclose_mem_func; 190 | pzlib_filefunc_def->zerror_file = ferror_mem_func; 191 | pzlib_filefunc_def->opaque = ourmem; 192 | } 193 | -------------------------------------------------------------------------------- /source/7z/7z.h: -------------------------------------------------------------------------------- 1 | /* 7z.h -- 7z interface 2 | 2015-11-18 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __7Z_H 5 | #define __7Z_H 6 | 7 | #include "7zTypes.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | #define k7zStartHeaderSize 0x20 12 | #define k7zSignatureSize 6 13 | 14 | extern const Byte k7zSignature[k7zSignatureSize]; 15 | 16 | typedef struct 17 | { 18 | const Byte *Data; 19 | size_t Size; 20 | } CSzData; 21 | 22 | /* CSzCoderInfo & CSzFolder support only default methods */ 23 | 24 | typedef struct 25 | { 26 | size_t PropsOffset; 27 | UInt32 MethodID; 28 | Byte NumStreams; 29 | Byte PropsSize; 30 | } CSzCoderInfo; 31 | 32 | typedef struct 33 | { 34 | UInt32 InIndex; 35 | UInt32 OutIndex; 36 | } CSzBond; 37 | 38 | #define SZ_NUM_CODERS_IN_FOLDER_MAX 4 39 | #define SZ_NUM_BONDS_IN_FOLDER_MAX 3 40 | #define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4 41 | 42 | typedef struct 43 | { 44 | UInt32 NumCoders; 45 | UInt32 NumBonds; 46 | UInt32 NumPackStreams; 47 | UInt32 UnpackStream; 48 | UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX]; 49 | CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX]; 50 | CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX]; 51 | } CSzFolder; 52 | 53 | 54 | SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd); 55 | 56 | typedef struct 57 | { 58 | UInt32 Low; 59 | UInt32 High; 60 | } CNtfsFileTime; 61 | 62 | typedef struct 63 | { 64 | Byte *Defs; /* MSB 0 bit numbering */ 65 | UInt32 *Vals; 66 | } CSzBitUi32s; 67 | 68 | typedef struct 69 | { 70 | Byte *Defs; /* MSB 0 bit numbering */ 71 | // UInt64 *Vals; 72 | CNtfsFileTime *Vals; 73 | } CSzBitUi64s; 74 | 75 | #define SzBitArray_Check(p, i) (((p)[(i) >> 3] & (0x80 >> ((i) & 7))) != 0) 76 | 77 | #define SzBitWithVals_Check(p, i) ((p)->Defs && ((p)->Defs[(i) >> 3] & (0x80 >> ((i) & 7))) != 0) 78 | 79 | typedef struct 80 | { 81 | UInt32 NumPackStreams; 82 | UInt32 NumFolders; 83 | 84 | UInt64 *PackPositions; // NumPackStreams + 1 85 | CSzBitUi32s FolderCRCs; // NumFolders 86 | 87 | size_t *FoCodersOffsets; // NumFolders + 1 88 | UInt32 *FoStartPackStreamIndex; // NumFolders + 1 89 | UInt32 *FoToCoderUnpackSizes; // NumFolders + 1 90 | Byte *FoToMainUnpackSizeIndex; // NumFolders 91 | UInt64 *CoderUnpackSizes; // for all coders in all folders 92 | 93 | Byte *CodersData; 94 | } CSzAr; 95 | 96 | UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex); 97 | 98 | SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, 99 | ILookInStream *stream, UInt64 startPos, 100 | Byte *outBuffer, size_t outSize, 101 | ISzAlloc *allocMain); 102 | 103 | typedef struct 104 | { 105 | CSzAr db; 106 | 107 | UInt64 startPosAfterHeader; 108 | UInt64 dataPos; 109 | 110 | UInt32 NumFiles; 111 | 112 | UInt64 *UnpackPositions; // NumFiles + 1 113 | // Byte *IsEmptyFiles; 114 | Byte *IsDirs; 115 | CSzBitUi32s CRCs; 116 | 117 | CSzBitUi32s Attribs; 118 | // CSzBitUi32s Parents; 119 | CSzBitUi64s MTime; 120 | CSzBitUi64s CTime; 121 | 122 | UInt32 *FolderToFile; // NumFolders + 1 123 | UInt32 *FileToFolder; // NumFiles 124 | 125 | size_t *FileNameOffsets; /* in 2-byte steps */ 126 | Byte *FileNames; /* UTF-16-LE */ 127 | } CSzArEx; 128 | 129 | #define SzArEx_IsDir(p, i) (SzBitArray_Check((p)->IsDirs, i)) 130 | 131 | #define SzArEx_GetFileSize(p, i) ((p)->UnpackPositions[(i) + 1] - (p)->UnpackPositions[i]) 132 | 133 | void SzArEx_Init(CSzArEx *p); 134 | void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); 135 | UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); 136 | int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); 137 | 138 | /* 139 | if dest == NULL, the return value specifies the required size of the buffer, 140 | in 16-bit characters, including the null-terminating character. 141 | if dest != NULL, the return value specifies the number of 16-bit characters that 142 | are written to the dest, including the null-terminating character. */ 143 | 144 | size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest); 145 | 146 | /* 147 | size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex); 148 | UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest); 149 | */ 150 | 151 | 152 | 153 | /* 154 | SzArEx_Extract extracts file from archive 155 | 156 | *outBuffer must be 0 before first call for each new archive. 157 | 158 | Extracting cache: 159 | If you need to decompress more than one file, you can send 160 | these values from previous call: 161 | *blockIndex, 162 | *outBuffer, 163 | *outBufferSize 164 | You can consider "*outBuffer" as cache of solid block. If your archive is solid, 165 | it will increase decompression speed. 166 | 167 | If you use external function, you can declare these 3 cache variables 168 | (blockIndex, outBuffer, outBufferSize) as static in that external function. 169 | 170 | Free *outBuffer and set *outBuffer to 0, if you want to flush cache. 171 | */ 172 | 173 | SRes SzArEx_Extract( 174 | const CSzArEx *db, 175 | ILookInStream *inStream, 176 | UInt32 fileIndex, /* index of file */ 177 | UInt32 *blockIndex, /* index of solid block */ 178 | Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ 179 | size_t *outBufferSize, /* buffer size for output buffer */ 180 | size_t *offset, /* offset of stream for required file in *outBuffer */ 181 | size_t *outSizeProcessed, /* size of file in *outBuffer */ 182 | ISzAlloc *allocMain, 183 | ISzAlloc *allocTemp); 184 | 185 | 186 | /* 187 | SzArEx_Open Errors: 188 | SZ_ERROR_NO_ARCHIVE 189 | SZ_ERROR_ARCHIVE 190 | SZ_ERROR_UNSUPPORTED 191 | SZ_ERROR_MEM 192 | SZ_ERROR_CRC 193 | SZ_ERROR_INPUT_EOF 194 | SZ_ERROR_FAIL 195 | */ 196 | 197 | SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, 198 | ISzAlloc *allocMain, ISzAlloc *allocTemp); 199 | 200 | EXTERN_C_END 201 | 202 | #endif 203 | -------------------------------------------------------------------------------- /source/certs/digicert.h: -------------------------------------------------------------------------------- 1 | unsigned char digicert_cer[] = { 2 | 0x30, 0x82, 0x03, 0xc5, 0x30, 0x82, 0x02, 0xad, 0xa0, 0x03, 0x02, 0x01, 3 | 0x02, 0x02, 0x10, 0x02, 0xac, 0x5c, 0x26, 0x6a, 0x0b, 0x40, 0x9b, 0x8f, 4 | 0x0b, 0x79, 0xf2, 0xae, 0x46, 0x25, 0x77, 0x30, 0x0d, 0x06, 0x09, 0x2a, 5 | 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x6c, 6 | 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 7 | 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 8 | 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63, 9 | 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, 10 | 0x77, 0x77, 0x2e, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2e, 11 | 0x63, 0x6f, 0x6d, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 12 | 0x13, 0x22, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x48, 13 | 0x69, 0x67, 0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61, 0x6e, 0x63, 14 | 0x65, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 15 | 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x31, 0x31, 0x31, 0x30, 0x30, 0x30, 16 | 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x31, 0x31, 0x31, 0x31, 17 | 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x6c, 0x31, 0x0b, 18 | 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 19 | 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x44, 0x69, 20 | 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x19, 21 | 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, 0x77, 0x77, 22 | 0x2e, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x63, 0x6f, 23 | 0x6d, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 24 | 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x48, 0x69, 0x67, 25 | 0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x20, 26 | 0x45, 0x56, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 27 | 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 28 | 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 29 | 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc6, 0xcc, 0xe5, 0x73, 0xe6, 30 | 0xfb, 0xd4, 0xbb, 0xe5, 0x2d, 0x2d, 0x32, 0xa6, 0xdf, 0xe5, 0x81, 0x3f, 31 | 0xc9, 0xcd, 0x25, 0x49, 0xb6, 0x71, 0x2a, 0xc3, 0xd5, 0x94, 0x34, 0x67, 32 | 0xa2, 0x0a, 0x1c, 0xb0, 0x5f, 0x69, 0xa6, 0x40, 0xb1, 0xc4, 0xb7, 0xb2, 33 | 0x8f, 0xd0, 0x98, 0xa4, 0xa9, 0x41, 0x59, 0x3a, 0xd3, 0xdc, 0x94, 0xd6, 34 | 0x3c, 0xdb, 0x74, 0x38, 0xa4, 0x4a, 0xcc, 0x4d, 0x25, 0x82, 0xf7, 0x4a, 35 | 0xa5, 0x53, 0x12, 0x38, 0xee, 0xf3, 0x49, 0x6d, 0x71, 0x91, 0x7e, 0x63, 36 | 0xb6, 0xab, 0xa6, 0x5f, 0xc3, 0xa4, 0x84, 0xf8, 0x4f, 0x62, 0x51, 0xbe, 37 | 0xf8, 0xc5, 0xec, 0xdb, 0x38, 0x92, 0xe3, 0x06, 0xe5, 0x08, 0x91, 0x0c, 38 | 0xc4, 0x28, 0x41, 0x55, 0xfb, 0xcb, 0x5a, 0x89, 0x15, 0x7e, 0x71, 0xe8, 39 | 0x35, 0xbf, 0x4d, 0x72, 0x09, 0x3d, 0xbe, 0x3a, 0x38, 0x50, 0x5b, 0x77, 40 | 0x31, 0x1b, 0x8d, 0xb3, 0xc7, 0x24, 0x45, 0x9a, 0xa7, 0xac, 0x6d, 0x00, 41 | 0x14, 0x5a, 0x04, 0xb7, 0xba, 0x13, 0xeb, 0x51, 0x0a, 0x98, 0x41, 0x41, 42 | 0x22, 0x4e, 0x65, 0x61, 0x87, 0x81, 0x41, 0x50, 0xa6, 0x79, 0x5c, 0x89, 43 | 0xde, 0x19, 0x4a, 0x57, 0xd5, 0x2e, 0xe6, 0x5d, 0x1c, 0x53, 0x2c, 0x7e, 44 | 0x98, 0xcd, 0x1a, 0x06, 0x16, 0xa4, 0x68, 0x73, 0xd0, 0x34, 0x04, 0x13, 45 | 0x5c, 0xa1, 0x71, 0xd3, 0x5a, 0x7c, 0x55, 0xdb, 0x5e, 0x64, 0xe1, 0x37, 46 | 0x87, 0x30, 0x56, 0x04, 0xe5, 0x11, 0xb4, 0x29, 0x80, 0x12, 0xf1, 0x79, 47 | 0x39, 0x88, 0xa2, 0x02, 0x11, 0x7c, 0x27, 0x66, 0xb7, 0x88, 0xb7, 0x78, 48 | 0xf2, 0xca, 0x0a, 0xa8, 0x38, 0xab, 0x0a, 0x64, 0xc2, 0xbf, 0x66, 0x5d, 49 | 0x95, 0x84, 0xc1, 0xa1, 0x25, 0x1e, 0x87, 0x5d, 0x1a, 0x50, 0x0b, 0x20, 50 | 0x12, 0xcc, 0x41, 0xbb, 0x6e, 0x0b, 0x51, 0x38, 0xb8, 0x4b, 0xcb, 0x02, 51 | 0x03, 0x01, 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0e, 0x06, 0x03, 52 | 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 53 | 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 54 | 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 55 | 0x04, 0x16, 0x04, 0x14, 0xb1, 0x3e, 0xc3, 0x69, 0x03, 0xf8, 0xbf, 0x47, 56 | 0x01, 0xd4, 0x98, 0x26, 0x1a, 0x08, 0x02, 0xef, 0x63, 0x64, 0x2b, 0xc3, 57 | 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 58 | 0x14, 0xb1, 0x3e, 0xc3, 0x69, 0x03, 0xf8, 0xbf, 0x47, 0x01, 0xd4, 0x98, 59 | 0x26, 0x1a, 0x08, 0x02, 0xef, 0x63, 0x64, 0x2b, 0xc3, 0x30, 0x0d, 0x06, 60 | 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 61 | 0x03, 0x82, 0x01, 0x01, 0x00, 0x1c, 0x1a, 0x06, 0x97, 0xdc, 0xd7, 0x9c, 62 | 0x9f, 0x3c, 0x88, 0x66, 0x06, 0x08, 0x57, 0x21, 0xdb, 0x21, 0x47, 0xf8, 63 | 0x2a, 0x67, 0xaa, 0xbf, 0x18, 0x32, 0x76, 0x40, 0x10, 0x57, 0xc1, 0x8a, 64 | 0xf3, 0x7a, 0xd9, 0x11, 0x65, 0x8e, 0x35, 0xfa, 0x9e, 0xfc, 0x45, 0xb5, 65 | 0x9e, 0xd9, 0x4c, 0x31, 0x4b, 0xb8, 0x91, 0xe8, 0x43, 0x2c, 0x8e, 0xb3, 66 | 0x78, 0xce, 0xdb, 0xe3, 0x53, 0x79, 0x71, 0xd6, 0xe5, 0x21, 0x94, 0x01, 67 | 0xda, 0x55, 0x87, 0x9a, 0x24, 0x64, 0xf6, 0x8a, 0x66, 0xcc, 0xde, 0x9c, 68 | 0x37, 0xcd, 0xa8, 0x34, 0xb1, 0x69, 0x9b, 0x23, 0xc8, 0x9e, 0x78, 0x22, 69 | 0x2b, 0x70, 0x43, 0xe3, 0x55, 0x47, 0x31, 0x61, 0x19, 0xef, 0x58, 0xc5, 70 | 0x85, 0x2f, 0x4e, 0x30, 0xf6, 0xa0, 0x31, 0x16, 0x23, 0xc8, 0xe7, 0xe2, 71 | 0x65, 0x16, 0x33, 0xcb, 0xbf, 0x1a, 0x1b, 0xa0, 0x3d, 0xf8, 0xca, 0x5e, 72 | 0x8b, 0x31, 0x8b, 0x60, 0x08, 0x89, 0x2d, 0x0c, 0x06, 0x5c, 0x52, 0xb7, 73 | 0xc4, 0xf9, 0x0a, 0x98, 0xd1, 0x15, 0x5f, 0x9f, 0x12, 0xbe, 0x7c, 0x36, 74 | 0x63, 0x38, 0xbd, 0x44, 0xa4, 0x7f, 0xe4, 0x26, 0x2b, 0x0a, 0xc4, 0x97, 75 | 0x69, 0x0d, 0xe9, 0x8c, 0xe2, 0xc0, 0x10, 0x57, 0xb8, 0xc8, 0x76, 0x12, 76 | 0x91, 0x55, 0xf2, 0x48, 0x69, 0xd8, 0xbc, 0x2a, 0x02, 0x5b, 0x0f, 0x44, 77 | 0xd4, 0x20, 0x31, 0xdb, 0xf4, 0xba, 0x70, 0x26, 0x5d, 0x90, 0x60, 0x9e, 78 | 0xbc, 0x4b, 0x17, 0x09, 0x2f, 0xb4, 0xcb, 0x1e, 0x43, 0x68, 0xc9, 0x07, 79 | 0x27, 0xc1, 0xd2, 0x5c, 0xf7, 0xea, 0x21, 0xb9, 0x68, 0x12, 0x9c, 0x3c, 80 | 0x9c, 0xbf, 0x9e, 0xfc, 0x80, 0x5c, 0x9b, 0x63, 0xcd, 0xec, 0x47, 0xaa, 81 | 0x25, 0x27, 0x67, 0xa0, 0x37, 0xf3, 0x00, 0x82, 0x7d, 0x54, 0xd7, 0xa9, 82 | 0xf8, 0xe9, 0x2e, 0x13, 0xa3, 0x77, 0xe8, 0x1f, 0x4a 83 | }; 84 | unsigned int digicert_cer_len = 969; 85 | -------------------------------------------------------------------------------- /source/httpc.cpp: -------------------------------------------------------------------------------- 1 | #include "httpc.h" 2 | #include 3 | #include 4 | 5 | static size_t s_size_to_recieve = 0; 6 | static size_t s_content_length = 0; 7 | 8 | static size_t header_function(char* b, size_t size, size_t nitems, void *userdata) 9 | { 10 | size_t numbytes = size * nitems; 11 | std::string tmp_string(b, numbytes); 12 | tmp_string.erase(tmp_string.size() - 2); 13 | if(tmp_string.empty()) 14 | return 0; // This will get us only the headers even if its a GET request 15 | std::vector *data = static_cast*>(userdata); 16 | data->push_back(tmp_string); 17 | return size * nitems; 18 | } 19 | 20 | 21 | static size_t write_function(void *ptr, size_t size, size_t nmemb, void *stream) { 22 | ((std::string*)stream)->append((char*)ptr, size * nmemb); 23 | return size * nmemb; 24 | } 25 | 26 | Result HTTPC::Init(u32 mem) 27 | { 28 | this->socbuf = (void*)memalign(0x1000, 0x100000); 29 | if(socbuf == nullptr) return 0xDED26; 30 | return socInit((u32*)socbuf, 0x100000); 31 | } 32 | 33 | Result HTTPC::OpenContext(httpcContext *context, HTTPC_RequestMethod method, char* url, u32 use_defaultproxy) 34 | { 35 | this->headers.clear(); 36 | this->handle = curl_easy_init(); 37 | curl_easy_setopt(this->handle, CURLOPT_URL, url); 38 | curl_easy_setopt(this->handle, CURLOPT_VERBOSE, 0L); 39 | curl_easy_setopt(this->handle, CURLOPT_SSL_VERIFYPEER, 0L); 40 | curl_easy_setopt(this->handle, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS); 41 | curl_easy_setopt(this->handle, CURLOPT_HEADERFUNCTION, header_function); 42 | curl_easy_setopt(this->handle, CURLOPT_HEADERDATA, &this->headers); 43 | s_size_to_recieve = 0; 44 | 45 | switch(method) 46 | { 47 | case HTTPC_METHOD_GET: 48 | curl_easy_setopt(this->handle, CURLOPT_CUSTOMREQUEST, (char*)"GET"); //But we do not want the body right now 49 | break; 50 | case HTTPC_METHOD_HEAD: 51 | curl_easy_setopt(this->handle, CURLOPT_CUSTOMREQUEST, (char*)"HEAD"); 52 | break; 53 | case HTTPC_METHOD_POST: 54 | curl_easy_setopt(this->handle, CURLOPT_CUSTOMREQUEST, (char*)"POST"); 55 | break; 56 | case HTTPC_METHOD_PUT: 57 | curl_easy_setopt(this->handle, CURLOPT_CUSTOMREQUEST, (char*)"PUT"); 58 | break; 59 | case HTTPC_METHOD_DELETE: 60 | curl_easy_setopt(this->handle, CURLOPT_CUSTOMREQUEST, (char*)"DELETE"); 61 | break; 62 | default: 63 | return 0xDED53; 64 | } 65 | return 0; 66 | } 67 | 68 | 69 | Result HTTPC::AddRequestHeaderField(httpcContext *context, char *name, char *value) 70 | { 71 | char *tmp_header = (char*)malloc((strlen(name) + strlen(value)) * sizeof(char*)); 72 | sprintf(tmp_header, "%s: %s", name, value); 73 | this->header_chunk = curl_slist_append(this->header_chunk, tmp_header); 74 | free(tmp_header); 75 | return 0; 76 | } 77 | 78 | Result HTTPC::BeginRequest(httpcContext *context) 79 | { 80 | curl_easy_setopt(this->handle, CURLOPT_HTTPHEADER, this->header_chunk); 81 | this->res = curl_easy_perform(this->handle); 82 | if(this->res == CURLE_WRITE_ERROR) this->res = CURLE_OK; 83 | return this->res; 84 | } 85 | 86 | Result HTTPC::GetResponseHeader(httpcContext *context, char* _name, char* _value, u32 valuebuf_maxsize) 87 | { // Headers are not case sensitive: https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 88 | char lowercasename[1024]; 89 | int namelen = 0; 90 | unsigned char s; 91 | do 92 | { 93 | lowercasename[namelen] = s = std::tolower(_name[namelen]); 94 | namelen++; 95 | } while (s != '\0'); 96 | namelen--; 97 | 98 | for(int i = 0; i < this->headers.size(); i++) 99 | { 100 | std::string lowerhdr = this->headers[i]; 101 | std::transform(lowerhdr.begin(), lowerhdr.end(), lowerhdr.begin(), [](unsigned char c){ return std::tolower(c); }); 102 | size_t pos = lowerhdr.find(lowercasename); 103 | if(pos != std::string::npos) 104 | { 105 | this->headers[i].erase(pos, namelen + 1); 106 | const char* val = this->headers[i].c_str(); 107 | while (*val == ' ') val++; // Header values may or may not have any number of spaces prior to the actual value. 108 | strcpy(_value, val); 109 | return 0; 110 | } 111 | } 112 | return 0xDED92; 113 | } 114 | 115 | Result HTTPC::GetResponseStatusCode(httpcContext *context, u32 *statuscode) 116 | { 117 | if(this->res != CURLE_OK) 118 | return 0xDED65; 119 | curl_easy_getinfo(this->handle, CURLINFO_RESPONSE_CODE, statuscode); 120 | return 0; 121 | } 122 | 123 | Result HTTPC::GetDownloadSizeState(httpcContext *context, u32 *downloadedsize, u32 *contentsize) 124 | { 125 | char val[10]; 126 | if(contentsize != nullptr) 127 | { 128 | this->GetResponseHeader(context, "Content-Length", val, 10); 129 | sscanf(val, "%d", contentsize); 130 | } 131 | if(downloadedsize != nullptr) *downloadedsize = s_size_to_recieve; 132 | return 0; 133 | } 134 | 135 | Result HTTPC::ReceiveData(httpcContext *context, u8 *buffer, u32 size) 136 | { 137 | this->headers.clear(); 138 | char *tmp_range = (char*)std::malloc(10); 139 | sprintf(tmp_range, "%d-%d", s_size_to_recieve, size); 140 | curl_easy_setopt(this->handle, CURLOPT_RANGE, tmp_range); 141 | free(tmp_range); 142 | // We don't need to deal with headers any longer 143 | curl_easy_setopt(this->handle, CURLOPT_HEADERDATA, nullptr); 144 | curl_easy_setopt(this->handle, CURLOPT_HEADERFUNCTION, nullptr); 145 | 146 | curl_easy_setopt(this->handle, CURLOPT_HTTPGET, 1L); //Now get the body 147 | curl_easy_setopt(this->handle, CURLOPT_WRITEFUNCTION, write_function); 148 | std::string stream; 149 | curl_easy_setopt(this->handle, CURLOPT_WRITEDATA, &stream); 150 | this->res = curl_easy_perform(this->handle); 151 | std::memmove(buffer, stream.c_str(), size); 152 | s_size_to_recieve += size; 153 | return this->res; 154 | } 155 | 156 | Result HTTPC::SetSSLOpt(httpcContext *context, u32 option) 157 | { 158 | switch(option) 159 | { 160 | case (1 << 8): 161 | break; 162 | } 163 | return 0; 164 | } 165 | 166 | Result HTTPC::CloseContext(httpcContext *context) 167 | { 168 | //for(int i = 0; i < this->headers.size(); i++) std::cout << "Header: " << this->headers[i] << '\n'; 169 | curl_slist_free_all(this->header_chunk); 170 | this->header_chunk = nullptr; 171 | curl_easy_cleanup(this->handle); 172 | return 0; 173 | } 174 | 175 | Result HTTPC::Exit(void) 176 | { 177 | Result res = socExit(); 178 | free(this->socbuf); 179 | return res; 180 | } -------------------------------------------------------------------------------- /source/7z/7zTypes.h: -------------------------------------------------------------------------------- 1 | /* 7zTypes.h -- Basic types 2 | 2013-11-12 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __7Z_TYPES_H 5 | #define __7Z_TYPES_H 6 | 7 | #ifdef _WIN32 8 | /* #include */ 9 | #endif 10 | 11 | #include 12 | 13 | #ifndef EXTERN_C_BEGIN 14 | #ifdef __cplusplus 15 | #define EXTERN_C_BEGIN extern "C" { 16 | #define EXTERN_C_END } 17 | #else 18 | #define EXTERN_C_BEGIN 19 | #define EXTERN_C_END 20 | #endif 21 | #endif 22 | 23 | EXTERN_C_BEGIN 24 | 25 | #define SZ_OK 0 26 | 27 | #define SZ_ERROR_DATA 1 28 | #define SZ_ERROR_MEM 2 29 | #define SZ_ERROR_CRC 3 30 | #define SZ_ERROR_UNSUPPORTED 4 31 | #define SZ_ERROR_PARAM 5 32 | #define SZ_ERROR_INPUT_EOF 6 33 | #define SZ_ERROR_OUTPUT_EOF 7 34 | #define SZ_ERROR_READ 8 35 | #define SZ_ERROR_WRITE 9 36 | #define SZ_ERROR_PROGRESS 10 37 | #define SZ_ERROR_FAIL 11 38 | #define SZ_ERROR_THREAD 12 39 | 40 | #define SZ_ERROR_ARCHIVE 16 41 | #define SZ_ERROR_NO_ARCHIVE 17 42 | 43 | typedef int SRes; 44 | 45 | #ifdef _WIN32 46 | /* typedef DWORD WRes; */ 47 | typedef unsigned WRes; 48 | #else 49 | typedef int WRes; 50 | #endif 51 | 52 | #ifndef RINOK 53 | #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } 54 | #endif 55 | 56 | typedef unsigned char Byte; 57 | typedef short Int16; 58 | typedef unsigned short UInt16; 59 | 60 | #ifdef _LZMA_UINT32_IS_ULONG 61 | typedef long Int32; 62 | typedef unsigned long UInt32; 63 | #else 64 | typedef int Int32; 65 | typedef unsigned int UInt32; 66 | #endif 67 | 68 | #ifdef _SZ_NO_INT_64 69 | 70 | /* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. 71 | NOTES: Some code will work incorrectly in that case! */ 72 | 73 | typedef long Int64; 74 | typedef unsigned long UInt64; 75 | 76 | #else 77 | 78 | #if defined(_MSC_VER) || defined(__BORLANDC__) 79 | typedef __int64 Int64; 80 | typedef unsigned __int64 UInt64; 81 | #define UINT64_CONST(n) n 82 | #else 83 | typedef long long int Int64; 84 | typedef unsigned long long int UInt64; 85 | #define UINT64_CONST(n) n ## ULL 86 | #endif 87 | 88 | #endif 89 | 90 | #ifdef _LZMA_NO_SYSTEM_SIZE_T 91 | typedef UInt32 SizeT; 92 | #else 93 | typedef size_t SizeT; 94 | #endif 95 | 96 | typedef int Bool; 97 | #define True 1 98 | #define False 0 99 | 100 | 101 | #ifdef _WIN32 102 | #define MY_STD_CALL __stdcall 103 | #else 104 | #define MY_STD_CALL 105 | #endif 106 | 107 | #ifdef _MSC_VER 108 | 109 | #if _MSC_VER >= 1300 110 | #define MY_NO_INLINE __declspec(noinline) 111 | #else 112 | #define MY_NO_INLINE 113 | #endif 114 | 115 | #define MY_CDECL __cdecl 116 | #define MY_FAST_CALL __fastcall 117 | 118 | #else 119 | 120 | #define MY_NO_INLINE 121 | #define MY_CDECL 122 | #define MY_FAST_CALL 123 | 124 | #endif 125 | 126 | 127 | /* The following interfaces use first parameter as pointer to structure */ 128 | 129 | typedef struct 130 | { 131 | Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */ 132 | } IByteIn; 133 | 134 | typedef struct 135 | { 136 | void (*Write)(void *p, Byte b); 137 | } IByteOut; 138 | 139 | typedef struct 140 | { 141 | SRes (*Read)(void *p, void *buf, size_t *size); 142 | /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. 143 | (output(*size) < input(*size)) is allowed */ 144 | } ISeqInStream; 145 | 146 | /* it can return SZ_ERROR_INPUT_EOF */ 147 | SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); 148 | SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); 149 | SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); 150 | 151 | typedef struct 152 | { 153 | size_t (*Write)(void *p, const void *buf, size_t size); 154 | /* Returns: result - the number of actually written bytes. 155 | (result < size) means error */ 156 | } ISeqOutStream; 157 | 158 | typedef enum 159 | { 160 | SZ_SEEK_SET = 0, 161 | SZ_SEEK_CUR = 1, 162 | SZ_SEEK_END = 2 163 | } ESzSeek; 164 | 165 | typedef struct 166 | { 167 | SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ 168 | SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); 169 | } ISeekInStream; 170 | 171 | typedef struct 172 | { 173 | SRes (*Look)(void *p, const void **buf, size_t *size); 174 | /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. 175 | (output(*size) > input(*size)) is not allowed 176 | (output(*size) < input(*size)) is allowed */ 177 | SRes (*Skip)(void *p, size_t offset); 178 | /* offset must be <= output(*size) of Look */ 179 | 180 | SRes (*Read)(void *p, void *buf, size_t *size); 181 | /* reads directly (without buffer). It's same as ISeqInStream::Read */ 182 | SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); 183 | } ILookInStream; 184 | 185 | SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); 186 | SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); 187 | 188 | /* reads via ILookInStream::Read */ 189 | SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); 190 | SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); 191 | 192 | #define LookToRead_BUF_SIZE (1 << 14) 193 | 194 | typedef struct 195 | { 196 | ILookInStream s; 197 | ISeekInStream *realStream; 198 | size_t pos; 199 | size_t size; 200 | Byte buf[LookToRead_BUF_SIZE]; 201 | } CLookToRead; 202 | 203 | void LookToRead_CreateVTable(CLookToRead *p, int lookahead); 204 | void LookToRead_Init(CLookToRead *p); 205 | 206 | typedef struct 207 | { 208 | ISeqInStream s; 209 | ILookInStream *realStream; 210 | } CSecToLook; 211 | 212 | void SecToLook_CreateVTable(CSecToLook *p); 213 | 214 | typedef struct 215 | { 216 | ISeqInStream s; 217 | ILookInStream *realStream; 218 | } CSecToRead; 219 | 220 | void SecToRead_CreateVTable(CSecToRead *p); 221 | 222 | typedef struct 223 | { 224 | SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); 225 | /* Returns: result. (result != SZ_OK) means break. 226 | Value (UInt64)(Int64)-1 for size means unknown value. */ 227 | } ICompressProgress; 228 | 229 | typedef struct 230 | { 231 | void *(*Alloc)(void *p, size_t size); 232 | void (*Free)(void *p, void *address); /* address can be 0 */ 233 | } ISzAlloc; 234 | 235 | #define IAlloc_Alloc(p, size) (p)->Alloc((p), size) 236 | #define IAlloc_Free(p, a) (p)->Free((p), a) 237 | 238 | #ifdef _WIN32 239 | 240 | #define CHAR_PATH_SEPARATOR '\\' 241 | #define WCHAR_PATH_SEPARATOR L'\\' 242 | #define STRING_PATH_SEPARATOR "\\" 243 | #define WSTRING_PATH_SEPARATOR L"\\" 244 | 245 | #else 246 | 247 | #define CHAR_PATH_SEPARATOR '/' 248 | #define WCHAR_PATH_SEPARATOR L'/' 249 | #define STRING_PATH_SEPARATOR "/" 250 | #define WSTRING_PATH_SEPARATOR L"/" 251 | 252 | #endif 253 | 254 | EXTERN_C_END 255 | 256 | #endif 257 | -------------------------------------------------------------------------------- /rominfo.rsf: -------------------------------------------------------------------------------- 1 | BasicInfo: 2 | Title : $(APP_TITLE) 3 | ProductCode : $(PRODUCT_CODE) 4 | Logo : Homebrew 5 | 6 | TitleInfo: 7 | Category : Application 8 | UniqueId : $(UNIQUE_ID) 9 | 10 | Option: 11 | UseOnSD : true 12 | FreeProductCode : true 13 | MediaFootPadding : false 14 | EnableCrypt : false 15 | EnableCompress : true 16 | 17 | AccessControlInfo: 18 | CoreVersion : 2 19 | DescVersion : 2 20 | ReleaseKernelMajor : "02" 21 | ReleaseKernelMinor : "46" 22 | UseExtSaveData : false 23 | 24 | FileSystemAccess: 25 | - DirectSdmc 26 | - Core 27 | - CtrNandRo 28 | - CtrNandRw 29 | - CtrNandRoWrite 30 | IoAccessControl: 31 | - FsMountNand 32 | - FsMountNandRoWrite 33 | - FsMountTwln 34 | - FsMountWnand 35 | - FsMountCardSpi 36 | 37 | MemoryType : Application 38 | SystemMode : 64MB 39 | IdealProcessor : 0 40 | AffinityMask : 1 41 | Priority : 16 42 | MaxCpu : 0x9E 43 | HandleTableSize : 0x200 44 | DisableDebug : true 45 | EnableForceDebug : false 46 | CanWriteSharedPage : true 47 | CanUsePrivilegedPriority : false 48 | CanUseNonAlphabetAndNumber : true 49 | PermitMainFunctionArgument : true 50 | CanShareDeviceMemory : true 51 | RunnableOnSleep : false 52 | SpecialMemoryArrange : true 53 | 54 | SystemModeExt : Legacy 55 | CpuSpeed : 268MHz 56 | EnableL2Cache : false 57 | CanAccessCore2 : false 58 | 59 | IORegisterMapping: 60 | - 1ff00000-1ff7ffff 61 | 62 | MemoryMapping: 63 | - 1f000000-1f5fffff:r 64 | 65 | SystemCallAccess: 66 | ControlMemory: 1 67 | QueryMemory: 2 68 | ExitProcess: 3 69 | GetProcessAffinityMask: 4 70 | SetProcessAffinityMask: 5 71 | GetProcessIdealProcessor: 6 72 | SetProcessIdealProcessor: 7 73 | CreateThread: 8 74 | ExitThread: 9 75 | SleepThread: 10 76 | GetThreadPriority: 11 77 | SetThreadPriority: 12 78 | GetThreadAffinityMask: 13 79 | SetThreadAffinityMask: 14 80 | GetThreadIdealProcessor: 15 81 | SetThreadIdealProcessor: 16 82 | GetCurrentProcessorNumber: 17 83 | Run: 18 84 | CreateMutex: 19 85 | ReleaseMutex: 20 86 | CreateSemaphore: 21 87 | ReleaseSemaphore: 22 88 | CreateEvent: 23 89 | SignalEvent: 24 90 | ClearEvent: 25 91 | CreateTimer: 26 92 | SetTimer: 27 93 | CancelTimer: 28 94 | ClearTimer: 29 95 | CreateMemoryBlock: 30 96 | MapMemoryBlock: 31 97 | UnmapMemoryBlock: 32 98 | CreateAddressArbiter: 33 99 | ArbitrateAddress: 34 100 | CloseHandle: 35 101 | WaitSynchronization1: 36 102 | WaitSynchronizationN: 37 103 | SignalAndWait: 38 104 | DuplicateHandle: 39 105 | GetSystemTick: 40 106 | GetHandleInfo: 41 107 | GetSystemInfo: 42 108 | GetProcessInfo: 43 109 | GetThreadInfo: 44 110 | ConnectToPort: 45 111 | SendSyncRequest1: 46 112 | SendSyncRequest2: 47 113 | SendSyncRequest3: 48 114 | SendSyncRequest4: 49 115 | SendSyncRequest: 50 116 | OpenProcess: 51 117 | OpenThread: 52 118 | GetProcessId: 53 119 | GetProcessIdOfThread: 54 120 | GetThreadId: 55 121 | GetResourceLimit: 56 122 | GetResourceLimitLimitValues: 57 123 | GetResourceLimitCurrentValues: 58 124 | GetThreadContext: 59 125 | Break: 60 126 | OutputDebugString: 61 127 | ControlPerformanceCounter: 62 128 | CreatePort: 71 129 | CreateSessionToPort: 72 130 | CreateSession: 73 131 | AcceptSession: 74 132 | ReplyAndReceive1: 75 133 | ReplyAndReceive2: 76 134 | ReplyAndReceive3: 77 135 | ReplyAndReceive4: 78 136 | ReplyAndReceive: 79 137 | BindInterrupt: 80 138 | UnbindInterrupt: 81 139 | InvalidateProcessDataCache: 82 140 | StoreProcessDataCache: 83 141 | FlushProcessDataCache: 84 142 | StartInterProcessDma: 85 143 | StopDma: 86 144 | GetDmaState: 87 145 | RestartDma: 88 146 | DebugActiveProcess: 96 147 | BreakDebugProcess: 97 148 | TerminateDebugProcess: 98 149 | GetProcessDebugEvent: 99 150 | ContinueDebugEvent: 100 151 | GetProcessList: 101 152 | GetThreadList: 102 153 | GetDebugThreadContext: 103 154 | SetDebugThreadContext: 104 155 | QueryDebugProcessMemory: 105 156 | ReadProcessMemory: 106 157 | WriteProcessMemory: 107 158 | SetHardwareBreakPoint: 108 159 | GetDebugThreadParam: 109 160 | ControlProcessMemory: 112 161 | MapProcessMemory: 113 162 | UnmapProcessMemory: 114 163 | CreateCodeSet: 115 164 | CreateProcess: 117 165 | TerminateProcess: 118 166 | SetProcessResourceLimits: 119 167 | CreateResourceLimit: 120 168 | SetResourceLimitValues: 121 169 | AddCodeSegment: 122 170 | Backdoor: 123 171 | KernelSetState: 124 172 | QueryProcessMemory: 125 173 | 174 | ServiceAccessControl: 175 | - APT:U 176 | - ac:u 177 | - am:net 178 | - boss:U 179 | #- cam:u 180 | - cecd:u 181 | #- cfg:nor 182 | #- cfg:u 183 | #- csnd:SND 184 | #- dsp::DSP 185 | #- frd:u 186 | - fs:USER 187 | - gsp::Gpu 188 | - hid:USER 189 | - http:C 190 | #- ir:rst 191 | #- ir:u 192 | #- ir:USER 193 | #- mic:u 194 | - ndm:u 195 | #- news:s 196 | - nwm::UDS 197 | #- ptm:u 198 | - pxi:dev 199 | - soc:U 200 | - ssl:C 201 | - y2r:u 202 | 203 | SystemControlInfo: 204 | SaveDataSize: 0KB 205 | RemasterVersion: 2 206 | StackSize: 0x40000 207 | 208 | Dependency: 209 | ac: 0x0004013000002402 210 | #act: 0x0004013000003802 211 | am: 0x0004013000001502 212 | boss: 0x0004013000003402 213 | #camera: 0x0004013000001602 214 | cecd: 0x0004013000002602 215 | #cfg: 0x0004013000001702 216 | codec: 0x0004013000001802 217 | #csnd: 0x0004013000002702 218 | dlp: 0x0004013000002802 219 | dsp: 0x0004013000001a02 220 | #friends: 0x0004013000003202 221 | gpio: 0x0004013000001b02 222 | gsp: 0x0004013000001c02 223 | hid: 0x0004013000001d02 224 | http: 0x0004013000002902 225 | i2c: 0x0004013000001e02 226 | #ir: 0x0004013000003302 227 | mcu: 0x0004013000001f02 228 | #mic: 0x0004013000002002 229 | ndm: 0x0004013000002b02 230 | #news: 0x0004013000003502 231 | #nfc: 0x0004013000004002 232 | nim: 0x0004013000002c02 233 | nwm: 0x0004013000002d02 234 | pdn: 0x0004013000002102 235 | #ps: 0x0004013000003102 236 | #ptm: 0x0004013000002202 237 | #qtm: 0x0004013020004202 238 | ro: 0x0004013000003702 239 | socket: 0x0004013000002e02 240 | spi: 0x0004013000002302 241 | ssl: 0x0004013000002f02 242 | -------------------------------------------------------------------------------- /source/minizip/ioapi.h: -------------------------------------------------------------------------------- 1 | /* ioapi.h -- IO base function header for compress/uncompress .zip 2 | part of the MiniZip project 3 | 4 | Copyright (C) 1998-2010 Gilles Vollant 5 | http://www.winimage.com/zLibDll/minizip.html 6 | Modifications for Zip64 support 7 | Copyright (C) 2009-2010 Mathias Svensson 8 | http://result42.com 9 | 10 | This program is distributed under the terms of the same license as zlib. 11 | See the accompanying LICENSE file for the full text of the license. 12 | */ 13 | 14 | #ifndef _ZLIBIOAPI64_H 15 | #define _ZLIBIOAPI64_H 16 | 17 | #if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) 18 | # ifndef __USE_FILE_OFFSET64 19 | # define __USE_FILE_OFFSET64 20 | # endif 21 | # ifndef __USE_LARGEFILE64 22 | # define __USE_LARGEFILE64 23 | # endif 24 | # ifndef _LARGEFILE64_SOURCE 25 | # define _LARGEFILE64_SOURCE 26 | # endif 27 | # ifndef _FILE_OFFSET_BIT 28 | # define _FILE_OFFSET_BIT 64 29 | # endif 30 | #endif 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | 37 | #define fopen64 fopen 38 | #define ftello64 ftell 39 | #define fseeko64 fseek 40 | 41 | /* a type choosen by DEFINE */ 42 | #ifdef HAVE_64BIT_INT_CUSTOM 43 | typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; 44 | #else 45 | # ifdef HAVE_STDINT_H 46 | # include "stdint.h" 47 | typedef uint64_t ZPOS64_T; 48 | # else 49 | # if defined(_MSC_VER) || defined(__BORLANDC__) 50 | typedef unsigned __int64 ZPOS64_T; 51 | # else 52 | typedef unsigned long long int ZPOS64_T; 53 | # endif 54 | # endif 55 | #endif 56 | 57 | #ifdef __cplusplus 58 | extern "C" { 59 | #endif 60 | 61 | #define ZLIB_FILEFUNC_SEEK_CUR (1) 62 | #define ZLIB_FILEFUNC_SEEK_END (2) 63 | #define ZLIB_FILEFUNC_SEEK_SET (0) 64 | 65 | #define ZLIB_FILEFUNC_MODE_READ (1) 66 | #define ZLIB_FILEFUNC_MODE_WRITE (2) 67 | #define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) 68 | #define ZLIB_FILEFUNC_MODE_EXISTING (4) 69 | #define ZLIB_FILEFUNC_MODE_CREATE (8) 70 | 71 | #ifndef ZCALLBACK 72 | # if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || \ 73 | defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) 74 | # define ZCALLBACK CALLBACK 75 | # else 76 | # define ZCALLBACK 77 | # endif 78 | #endif 79 | 80 | typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); 81 | typedef voidpf (ZCALLBACK *opendisk_file_func) OF((voidpf opaque, voidpf stream, int number_disk, int mode)); 82 | typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); 83 | typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); 84 | typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); 85 | typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); 86 | 87 | typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); 88 | typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); 89 | 90 | /* here is the "old" 32 bits structure structure */ 91 | typedef struct zlib_filefunc_def_s 92 | { 93 | open_file_func zopen_file; 94 | opendisk_file_func zopendisk_file; 95 | read_file_func zread_file; 96 | write_file_func zwrite_file; 97 | tell_file_func ztell_file; 98 | seek_file_func zseek_file; 99 | close_file_func zclose_file; 100 | testerror_file_func zerror_file; 101 | voidpf opaque; 102 | } zlib_filefunc_def; 103 | 104 | typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); 105 | typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); 106 | typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); 107 | typedef voidpf (ZCALLBACK *opendisk64_file_func)OF((voidpf opaque, voidpf stream, int number_disk, int mode)); 108 | 109 | typedef struct zlib_filefunc64_def_s 110 | { 111 | open64_file_func zopen64_file; 112 | opendisk64_file_func zopendisk64_file; 113 | read_file_func zread_file; 114 | write_file_func zwrite_file; 115 | tell64_file_func ztell64_file; 116 | seek64_file_func zseek64_file; 117 | close_file_func zclose_file; 118 | testerror_file_func zerror_file; 119 | voidpf opaque; 120 | } zlib_filefunc64_def; 121 | 122 | void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); 123 | void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); 124 | 125 | /* now internal definition, only for zip.c and unzip.h */ 126 | typedef struct zlib_filefunc64_32_def_s 127 | { 128 | zlib_filefunc64_def zfile_func64; 129 | open_file_func zopen32_file; 130 | opendisk_file_func zopendisk32_file; 131 | tell_file_func ztell32_file; 132 | seek_file_func zseek32_file; 133 | } zlib_filefunc64_32_def; 134 | 135 | #define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) 136 | #define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) 137 | /*#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))*/ 138 | /*#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))*/ 139 | #define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) 140 | #define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) 141 | 142 | voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); 143 | voidpf call_zopendisk64 OF((const zlib_filefunc64_32_def* pfilefunc, voidpf filestream, int number_disk, int mode)); 144 | long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); 145 | ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); 146 | 147 | void fill_zlib_filefunc64_32_def_from_filefunc32 OF((zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32)); 148 | 149 | #define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) 150 | #define ZOPENDISK64(filefunc,filestream,diskn,mode) (call_zopendisk64((&(filefunc)),(filestream),(diskn),(mode))) 151 | #define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) 152 | #define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode))) 153 | 154 | #ifdef __cplusplus 155 | } 156 | #endif 157 | 158 | #endif 159 | -------------------------------------------------------------------------------- /source/7z/Bcj2.c: -------------------------------------------------------------------------------- 1 | /* Bcj2.c -- BCJ2 Decoder (Converter for x86 code) 2 | 2015-08-01 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "Bcj2.h" 7 | #include "CpuArch.h" 8 | 9 | #define CProb UInt16 10 | 11 | #define kTopValue ((UInt32)1 << 24) 12 | #define kNumModelBits 11 13 | #define kBitModelTotal (1 << kNumModelBits) 14 | #define kNumMoveBits 5 15 | 16 | #define _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound) 17 | #define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); 18 | #define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits)); 19 | 20 | void Bcj2Dec_Init(CBcj2Dec *p) 21 | { 22 | unsigned i; 23 | 24 | p->state = BCJ2_DEC_STATE_OK; 25 | p->ip = 0; 26 | p->temp[3] = 0; 27 | p->range = 0; 28 | p->code = 0; 29 | for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++) 30 | p->probs[i] = kBitModelTotal >> 1; 31 | } 32 | 33 | SRes Bcj2Dec_Decode(CBcj2Dec *p) 34 | { 35 | if (p->range <= 5) 36 | { 37 | p->state = BCJ2_DEC_STATE_OK; 38 | for (; p->range != 5; p->range++) 39 | { 40 | if (p->range == 1 && p->code != 0) 41 | return SZ_ERROR_DATA; 42 | 43 | if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC]) 44 | { 45 | p->state = BCJ2_STREAM_RC; 46 | return SZ_OK; 47 | } 48 | 49 | p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; 50 | } 51 | 52 | if (p->code == 0xFFFFFFFF) 53 | return SZ_ERROR_DATA; 54 | 55 | p->range = 0xFFFFFFFF; 56 | } 57 | else if (p->state >= BCJ2_DEC_STATE_ORIG_0) 58 | { 59 | while (p->state <= BCJ2_DEC_STATE_ORIG_3) 60 | { 61 | Byte *dest = p->dest; 62 | if (dest == p->destLim) 63 | return SZ_OK; 64 | *dest = p->temp[p->state++ - BCJ2_DEC_STATE_ORIG_0]; 65 | p->dest = dest + 1; 66 | } 67 | } 68 | 69 | /* 70 | if (BCJ2_IS_32BIT_STREAM(p->state)) 71 | { 72 | const Byte *cur = p->bufs[p->state]; 73 | if (cur == p->lims[p->state]) 74 | return SZ_OK; 75 | p->bufs[p->state] = cur + 4; 76 | 77 | { 78 | UInt32 val; 79 | Byte *dest; 80 | SizeT rem; 81 | 82 | p->ip += 4; 83 | val = GetBe32(cur) - p->ip; 84 | dest = p->dest; 85 | rem = p->destLim - dest; 86 | if (rem < 4) 87 | { 88 | SizeT i; 89 | SetUi32(p->temp, val); 90 | for (i = 0; i < rem; i++) 91 | dest[i] = p->temp[i]; 92 | p->dest = dest + rem; 93 | p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem; 94 | return SZ_OK; 95 | } 96 | SetUi32(dest, val); 97 | p->temp[3] = (Byte)(val >> 24); 98 | p->dest = dest + 4; 99 | p->state = BCJ2_DEC_STATE_OK; 100 | } 101 | } 102 | */ 103 | 104 | for (;;) 105 | { 106 | if (BCJ2_IS_32BIT_STREAM(p->state)) 107 | p->state = BCJ2_DEC_STATE_OK; 108 | else 109 | { 110 | if (p->range < kTopValue) 111 | { 112 | if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC]) 113 | { 114 | p->state = BCJ2_STREAM_RC; 115 | return SZ_OK; 116 | } 117 | p->range <<= 8; 118 | p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; 119 | } 120 | 121 | { 122 | const Byte *src = p->bufs[BCJ2_STREAM_MAIN]; 123 | const Byte *srcLim; 124 | Byte *dest; 125 | SizeT num = p->lims[BCJ2_STREAM_MAIN] - src; 126 | 127 | if (num == 0) 128 | { 129 | p->state = BCJ2_STREAM_MAIN; 130 | return SZ_OK; 131 | } 132 | 133 | dest = p->dest; 134 | if (num > (SizeT)(p->destLim - dest)) 135 | { 136 | num = p->destLim - dest; 137 | if (num == 0) 138 | { 139 | p->state = BCJ2_DEC_STATE_ORIG; 140 | return SZ_OK; 141 | } 142 | } 143 | 144 | srcLim = src + num; 145 | 146 | if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80) 147 | *dest = src[0]; 148 | else for (;;) 149 | { 150 | Byte b = *src; 151 | *dest = b; 152 | if (b != 0x0F) 153 | { 154 | if ((b & 0xFE) == 0xE8) 155 | break; 156 | dest++; 157 | if (++src != srcLim) 158 | continue; 159 | break; 160 | } 161 | dest++; 162 | if (++src == srcLim) 163 | break; 164 | if ((*src & 0xF0) != 0x80) 165 | continue; 166 | *dest = *src; 167 | break; 168 | } 169 | 170 | num = src - p->bufs[BCJ2_STREAM_MAIN]; 171 | 172 | if (src == srcLim) 173 | { 174 | p->temp[3] = src[-1]; 175 | p->bufs[BCJ2_STREAM_MAIN] = src; 176 | p->ip += (UInt32)num; 177 | p->dest += num; 178 | p->state = 179 | p->bufs[BCJ2_STREAM_MAIN] == 180 | p->lims[BCJ2_STREAM_MAIN] ? 181 | (unsigned)BCJ2_STREAM_MAIN : 182 | (unsigned)BCJ2_DEC_STATE_ORIG; 183 | return SZ_OK; 184 | } 185 | 186 | { 187 | UInt32 bound, ttt; 188 | CProb *prob; 189 | Byte b = src[0]; 190 | Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]); 191 | 192 | p->temp[3] = b; 193 | p->bufs[BCJ2_STREAM_MAIN] = src + 1; 194 | num++; 195 | p->ip += (UInt32)num; 196 | p->dest += num; 197 | 198 | prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0)); 199 | 200 | _IF_BIT_0 201 | { 202 | _UPDATE_0 203 | continue; 204 | } 205 | _UPDATE_1 206 | 207 | } 208 | } 209 | } 210 | 211 | { 212 | UInt32 val; 213 | unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP; 214 | const Byte *cur = p->bufs[cj]; 215 | Byte *dest; 216 | SizeT rem; 217 | 218 | if (cur == p->lims[cj]) 219 | { 220 | p->state = cj; 221 | break; 222 | } 223 | 224 | val = GetBe32(cur); 225 | p->bufs[cj] = cur + 4; 226 | 227 | p->ip += 4; 228 | val -= p->ip; 229 | dest = p->dest; 230 | rem = p->destLim - dest; 231 | 232 | if (rem < 4) 233 | { 234 | SizeT i; 235 | SetUi32(p->temp, val); 236 | for (i = 0; i < rem; i++) 237 | dest[i] = p->temp[i]; 238 | p->dest = dest + rem; 239 | p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem; 240 | break; 241 | } 242 | 243 | SetUi32(dest, val); 244 | p->temp[3] = (Byte)(val >> 24); 245 | p->dest = dest + 4; 246 | } 247 | } 248 | 249 | if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC]) 250 | { 251 | p->range <<= 8; 252 | p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; 253 | } 254 | 255 | return SZ_OK; 256 | } 257 | -------------------------------------------------------------------------------- /source/7z/LzmaDec.h: -------------------------------------------------------------------------------- 1 | /* LzmaDec.h -- LZMA Decoder 2 | 2013-01-18 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __LZMA_DEC_H 5 | #define __LZMA_DEC_H 6 | 7 | #include "7zTypes.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | /* #define _LZMA_PROB32 */ 12 | /* _LZMA_PROB32 can increase the speed on some CPUs, 13 | but memory usage for CLzmaDec::probs will be doubled in that case */ 14 | 15 | #ifdef _LZMA_PROB32 16 | #define CLzmaProb UInt32 17 | #else 18 | #define CLzmaProb UInt16 19 | #endif 20 | 21 | 22 | /* ---------- LZMA Properties ---------- */ 23 | 24 | #define LZMA_PROPS_SIZE 5 25 | 26 | typedef struct _CLzmaProps 27 | { 28 | unsigned lc, lp, pb; 29 | UInt32 dicSize; 30 | } CLzmaProps; 31 | 32 | /* LzmaProps_Decode - decodes properties 33 | Returns: 34 | SZ_OK 35 | SZ_ERROR_UNSUPPORTED - Unsupported properties 36 | */ 37 | 38 | SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); 39 | 40 | 41 | /* ---------- LZMA Decoder state ---------- */ 42 | 43 | /* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. 44 | Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ 45 | 46 | #define LZMA_REQUIRED_INPUT_MAX 20 47 | 48 | typedef struct 49 | { 50 | CLzmaProps prop; 51 | CLzmaProb *probs; 52 | Byte *dic; 53 | const Byte *buf; 54 | UInt32 range, code; 55 | SizeT dicPos; 56 | SizeT dicBufSize; 57 | UInt32 processedPos; 58 | UInt32 checkDicSize; 59 | unsigned state; 60 | UInt32 reps[4]; 61 | unsigned remainLen; 62 | int needFlush; 63 | int needInitState; 64 | UInt32 numProbs; 65 | unsigned tempBufSize; 66 | Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; 67 | } CLzmaDec; 68 | 69 | #define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } 70 | 71 | void LzmaDec_Init(CLzmaDec *p); 72 | 73 | /* There are two types of LZMA streams: 74 | 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. 75 | 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ 76 | 77 | typedef enum 78 | { 79 | LZMA_FINISH_ANY, /* finish at any point */ 80 | LZMA_FINISH_END /* block must be finished at the end */ 81 | } ELzmaFinishMode; 82 | 83 | /* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! 84 | 85 | You must use LZMA_FINISH_END, when you know that current output buffer 86 | covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. 87 | 88 | If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, 89 | and output value of destLen will be less than output buffer size limit. 90 | You can check status result also. 91 | 92 | You can use multiple checks to test data integrity after full decompression: 93 | 1) Check Result and "status" variable. 94 | 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 95 | 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. 96 | You must use correct finish mode in that case. */ 97 | 98 | typedef enum 99 | { 100 | LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ 101 | LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ 102 | LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ 103 | LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ 104 | LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ 105 | } ELzmaStatus; 106 | 107 | /* ELzmaStatus is used only as output value for function call */ 108 | 109 | 110 | /* ---------- Interfaces ---------- */ 111 | 112 | /* There are 3 levels of interfaces: 113 | 1) Dictionary Interface 114 | 2) Buffer Interface 115 | 3) One Call Interface 116 | You can select any of these interfaces, but don't mix functions from different 117 | groups for same object. */ 118 | 119 | 120 | /* There are two variants to allocate state for Dictionary Interface: 121 | 1) LzmaDec_Allocate / LzmaDec_Free 122 | 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs 123 | You can use variant 2, if you set dictionary buffer manually. 124 | For Buffer Interface you must always use variant 1. 125 | 126 | LzmaDec_Allocate* can return: 127 | SZ_OK 128 | SZ_ERROR_MEM - Memory allocation error 129 | SZ_ERROR_UNSUPPORTED - Unsupported properties 130 | */ 131 | 132 | SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); 133 | void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); 134 | 135 | SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); 136 | void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); 137 | 138 | /* ---------- Dictionary Interface ---------- */ 139 | 140 | /* You can use it, if you want to eliminate the overhead for data copying from 141 | dictionary to some other external buffer. 142 | You must work with CLzmaDec variables directly in this interface. 143 | 144 | STEPS: 145 | LzmaDec_Constr() 146 | LzmaDec_Allocate() 147 | for (each new stream) 148 | { 149 | LzmaDec_Init() 150 | while (it needs more decompression) 151 | { 152 | LzmaDec_DecodeToDic() 153 | use data from CLzmaDec::dic and update CLzmaDec::dicPos 154 | } 155 | } 156 | LzmaDec_Free() 157 | */ 158 | 159 | /* LzmaDec_DecodeToDic 160 | 161 | The decoding to internal dictionary buffer (CLzmaDec::dic). 162 | You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! 163 | 164 | finishMode: 165 | It has meaning only if the decoding reaches output limit (dicLimit). 166 | LZMA_FINISH_ANY - Decode just dicLimit bytes. 167 | LZMA_FINISH_END - Stream must be finished after dicLimit. 168 | 169 | Returns: 170 | SZ_OK 171 | status: 172 | LZMA_STATUS_FINISHED_WITH_MARK 173 | LZMA_STATUS_NOT_FINISHED 174 | LZMA_STATUS_NEEDS_MORE_INPUT 175 | LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK 176 | SZ_ERROR_DATA - Data error 177 | */ 178 | 179 | SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, 180 | const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); 181 | 182 | 183 | /* ---------- Buffer Interface ---------- */ 184 | 185 | /* It's zlib-like interface. 186 | See LzmaDec_DecodeToDic description for information about STEPS and return results, 187 | but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need 188 | to work with CLzmaDec variables manually. 189 | 190 | finishMode: 191 | It has meaning only if the decoding reaches output limit (*destLen). 192 | LZMA_FINISH_ANY - Decode just destLen bytes. 193 | LZMA_FINISH_END - Stream must be finished after (*destLen). 194 | */ 195 | 196 | SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, 197 | const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); 198 | 199 | 200 | /* ---------- One Call Interface ---------- */ 201 | 202 | /* LzmaDecode 203 | 204 | finishMode: 205 | It has meaning only if the decoding reaches output limit (*destLen). 206 | LZMA_FINISH_ANY - Decode just destLen bytes. 207 | LZMA_FINISH_END - Stream must be finished after (*destLen). 208 | 209 | Returns: 210 | SZ_OK 211 | status: 212 | LZMA_STATUS_FINISHED_WITH_MARK 213 | LZMA_STATUS_NOT_FINISHED 214 | LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK 215 | SZ_ERROR_DATA - Data error 216 | SZ_ERROR_MEM - Memory allocation error 217 | SZ_ERROR_UNSUPPORTED - Unsupported properties 218 | SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). 219 | */ 220 | 221 | SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, 222 | const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, 223 | ELzmaStatus *status, ISzAlloc *alloc); 224 | 225 | EXTERN_C_END 226 | 227 | #endif 228 | -------------------------------------------------------------------------------- /source/autoupdate.cpp: -------------------------------------------------------------------------------- 1 | #include "autoupdate.h" 2 | 3 | // jsmn includes 4 | #include "jsmn.h" 5 | 6 | // Internal includes 7 | #include "archive.h" 8 | #include "console.h" 9 | #include "http.h" 10 | #include "utils.h" 11 | 12 | UpdaterInfo updaterGetInfo(const char* path) { 13 | HomebrewLocation location = HomebrewLocation::Unknown; 14 | HomebrewType type = HomebrewType::Unknown; 15 | std::string sdmcLoc, smdcName; 16 | 17 | if (path != nullptr) { 18 | std::string source(path); 19 | 20 | // Check for SDMC or 3DSLINK 21 | if (source.compare(0, 5, "sdmc:") == 0) { 22 | location = HomebrewLocation::SDMC; 23 | } else if (source.compare(0, 8, "3dslink:") == 0) { 24 | location = HomebrewLocation::Remote; 25 | } 26 | 27 | // Check for Homebrew 28 | if (source.find(".3dsx") != std::string::npos) { 29 | type = HomebrewType::Homebrew; 30 | size_t start = source.find_first_of(':') + 1; 31 | size_t end = source.find_last_of('/'); 32 | sdmcLoc = source.substr(start, end - start); 33 | 34 | size_t extEnd = source.find_last_of('.'); 35 | smdcName = source.substr(end + 1, extEnd - end - 1); 36 | } 37 | } 38 | 39 | #ifdef UNIQUE_ID 40 | // Check for CIA 41 | u64 appid = 0; 42 | if (APT_GetProgramID(&appid) == 0) { 43 | if ((appid & UNIQUE_ID) == UNIQUE_ID) { 44 | type = HomebrewType::CIA; 45 | } 46 | } 47 | #endif 48 | 49 | return { type, location, sdmcLoc, smdcName }; 50 | } 51 | 52 | #ifndef FAKEDL 53 | static int jsoneq(const char *json, jsmntok_t *tok, const char *s) { 54 | if (tok->type == JSMN_STRING && (int)strlen(s) == tok->end - tok->start && 55 | std::strncmp(json + tok->start, s, tok->end - tok->start) == 0) { 56 | return 0; 57 | } 58 | return -1; 59 | } 60 | #endif 61 | 62 | LatestUpdaterInfo updaterGetLatest() { 63 | #ifdef FAKEDL 64 | return {}; 65 | #else 66 | static const char* ReleaseURL = "https://api.github.com/repos/KunoichiZ/lumaupdate/releases/latest"; 67 | 68 | jsmn_parser p = {}; 69 | jsmn_init(&p); 70 | 71 | u8* apiReqData = nullptr; 72 | u32 apiReqSize = 0; 73 | 74 | logPrintf("Downloading %s...\n", ReleaseURL); 75 | 76 | httpGet(ReleaseURL, &apiReqData, &apiReqSize, true); 77 | 78 | logPrintf("Downloaded %lu bytes\n", apiReqSize); 79 | gfxFlushBuffers(); 80 | 81 | jsmntok_t t[512] = {}; 82 | int r = jsmn_parse(&p, (const char*)apiReqData, apiReqSize, t, sizeof(t) / sizeof(t[0])); 83 | if (r < 0) { 84 | throw formatErrMessage("Failed to parse JSON", r); 85 | } 86 | logPrintf("JSON parsed successfully!\n"); 87 | gfxFlushBuffers(); 88 | 89 | bool namefound = false, bodyfound = false, inassets = false; 90 | LatestUpdaterInfo latest; 91 | for (int i = 0; i < r; i++) { 92 | if (!namefound && jsoneq((const char*)apiReqData, &t[i], "tag_name") == 0) { 93 | jsmntok_t val = t[i + 1]; 94 | latest.version = std::string((const char*)apiReqData + val.start, val.end - val.start); 95 | logPrintf("Release found: %s\n", latest.version.c_str()); 96 | namefound = true; 97 | } 98 | if (!bodyfound && jsoneq((const char*)apiReqData, &t[i], "body") == 0) { 99 | jsmntok_t val = t[i + 1]; 100 | latest.changelog = unescape(std::string((const char*)apiReqData + val.start, val.end - val.start)); 101 | logPrintf("Changelog found.\n"); 102 | bodyfound = true; 103 | } 104 | if (!inassets && jsoneq((const char*)apiReqData, &t[i], "assets") == 0) { 105 | inassets = true; 106 | } 107 | if (inassets) { 108 | if (jsoneq((const char*)apiReqData, &t[i], "browser_download_url") == 0) { 109 | jsmntok_t val = t[i + 1]; 110 | std::string url = std::string((const char*)apiReqData + val.start, val.end - val.start); 111 | if (url.find(".zip") != std::string::npos) { 112 | latest.url = url; 113 | } 114 | } 115 | } 116 | } 117 | 118 | gfxFlushBuffers(); 119 | std::free(apiReqData); 120 | 121 | #ifdef GIT_VER 122 | latest.isNewer = latest.version > GIT_VER; 123 | #else 124 | latest.isNewer = false; 125 | #endif 126 | 127 | return latest; 128 | #endif 129 | } 130 | 131 | static void installCIA(const u8* ciaData, const size_t ciaSize) { 132 | Handle handle; 133 | AM_QueryAvailableExternalTitleDatabase(NULL); 134 | CHECK(AM_StartCiaInstall(MEDIATYPE_SD, &handle), "Cannot initialize CIA install"); 135 | try { 136 | CHECK(FSFILE_Write(handle, NULL, 0, ciaData, (u32)ciaSize, 0), "Cannot write CIA data to handle"); 137 | CHECK(AM_FinishCiaInstall(handle), "Cannot finalize CIA install"); 138 | } catch (const std::runtime_error& e) { 139 | // Abort CIA install and re-throw 140 | CHECK(AM_CancelCIAInstall(handle), "Cannot cancel CIA install"); 141 | throw; 142 | } 143 | } 144 | 145 | static void copyToFile(const std::string& path, const u8* fileData, const size_t fileSize) { 146 | std::ofstream fout(path, std::ios::binary | std::ios::out); 147 | fout.write((const char*)fileData, fileSize); 148 | fout.close(); 149 | } 150 | 151 | UpdateResult updaterDoUpdate(LatestUpdaterInfo latest, UpdaterInfo current) { 152 | consoleScreen(GFX_TOP); 153 | consoleInitProgress("Updating Luma3DS Updater", "Downloading archive", 0.2); 154 | 155 | consoleScreen(GFX_BOTTOM); 156 | consoleClear(); 157 | 158 | u8* archiveData = nullptr; 159 | u32 archiveSize = 0; 160 | HTTPResponseInfo info; 161 | 162 | try { 163 | logPrintf("Downloading %s...\n", latest.url.c_str()); 164 | httpGet(latest.url.c_str(), &archiveData, &archiveSize, true, &info); 165 | logPrintf("Download complete! Size: %lu\n", archiveSize); 166 | } catch (const std::runtime_error& e) { 167 | logPrintf("\nFATAL: %s", e.what()); 168 | return { false, "DOWNLOAD FAILED" }; 169 | } 170 | 171 | consoleScreen(GFX_TOP); 172 | consoleSetProgressData("Checking archive integrity", 0.5); 173 | consoleScreen(GFX_BOTTOM); 174 | 175 | if (!info.etag.empty()) { 176 | logPrintf("Performing integrity check... "); 177 | if (!httpCheckETag(info.etag, archiveData, archiveSize)) { 178 | logPrintf(" ERR\nMD5 mismatch between server's and local file!\n"); 179 | return { false, "DOWNLOAD FAILED" }; 180 | } 181 | logPrintf(" OK\n"); 182 | } else { 183 | logPrintf("Skipping integrity check (no ETag found)\n"); 184 | } 185 | 186 | consoleScreen(GFX_TOP); 187 | consoleSetProgressData("Extracting archive contents", 0.8); 188 | consoleScreen(GFX_BOTTOM); 189 | 190 | try { 191 | ZipArchive archive(archiveData, archiveSize); 192 | 193 | switch (current.type) { 194 | case HomebrewType::CIA: 195 | // Extract CIA from archive, install it 196 | u8* ciaData; 197 | size_t ciaSize; 198 | logPrintf("Extracting lumaupdater.cia"); 199 | archive.extractFile("lumaupdater.cia", &ciaData, &ciaSize); 200 | logPrintf(" [OK] (%u bytes)\n", ciaSize); 201 | try { 202 | logPrintf("Installing lumaupdater.cia"); 203 | installCIA(ciaData, ciaSize); 204 | logPrintf(" [OK]\n"); 205 | } catch (const std::runtime_error& e) { 206 | logPrintf(" [ERR]\n\nFATAL: %s", e.what()); 207 | return { false, "CIA INSTALL FAILED" }; 208 | } 209 | break; 210 | case HomebrewType::Homebrew: { 211 | // Extract 3dsx/smdh from archive 212 | u8* hbData; 213 | size_t hbSize; 214 | logPrintf("Extracting lumaupdater.3dsx"); 215 | archive.extractFile("3ds/lumaupdater/lumaupdater.3dsx", &hbData, &hbSize); 216 | logPrintf(" [OK] (%u bytes)\n", hbSize); 217 | 218 | 219 | const std::string targetHb = current.sdmcLoc + "/" + current.sdmcName + ".3dsx"; 220 | logPrintf("Copying to %s", targetHb.c_str()); 221 | copyToFile(targetHb, hbData, hbSize); 222 | logPrintf(" [OK]\n"); 223 | std::free(hbData); 224 | 225 | u8* smdhData; 226 | size_t smdhSize; 227 | logPrintf("Extracting lumaupdater.3dsx"); 228 | archive.extractFile("3ds/lumaupdater/lumaupdater.smdh", &smdhData, &smdhSize); 229 | logPrintf(" [OK] (%u bytes)\n", smdhSize); 230 | 231 | const std::string targetSMDH = current.sdmcLoc + "/" + current.sdmcName + ".smdh"; 232 | logPrintf("Copying to %s", targetSMDH.c_str()); 233 | copyToFile(targetSMDH, smdhData, smdhSize); 234 | logPrintf(" [OK]\n"); 235 | std::free(smdhData); 236 | break; 237 | } 238 | default: 239 | return { false, "UNKNOWN INSTALL" }; 240 | } 241 | } catch (const std::runtime_error& e) { 242 | logPrintf("[ERR]\n\nFATAL: %s", e.what()); 243 | return { false, "EXTRACT FAILED" }; 244 | } 245 | 246 | return { true, "NO ERROR" }; 247 | } -------------------------------------------------------------------------------- /source/jsmn.c: -------------------------------------------------------------------------------- 1 | #include "jsmn.h" 2 | 3 | /** 4 | * Allocates a fresh unused token from the token pull. 5 | */ 6 | static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, 7 | jsmntok_t *tokens, size_t num_tokens) { 8 | jsmntok_t *tok; 9 | if (parser->toknext >= num_tokens) { 10 | return NULL; 11 | } 12 | tok = &tokens[parser->toknext++]; 13 | tok->start = tok->end = -1; 14 | tok->size = 0; 15 | #ifdef JSMN_PARENT_LINKS 16 | tok->parent = -1; 17 | #endif 18 | return tok; 19 | } 20 | 21 | /** 22 | * Fills token type and boundaries. 23 | */ 24 | static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, 25 | int start, int end) { 26 | token->type = type; 27 | token->start = start; 28 | token->end = end; 29 | token->size = 0; 30 | } 31 | 32 | /** 33 | * Fills next available token with JSON primitive. 34 | */ 35 | static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, 36 | size_t len, jsmntok_t *tokens, size_t num_tokens) { 37 | jsmntok_t *token; 38 | int start; 39 | 40 | start = parser->pos; 41 | 42 | for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 43 | switch (js[parser->pos]) { 44 | #ifndef JSMN_STRICT 45 | /* In strict mode primitive must be followed by "," or "}" or "]" */ 46 | case ':': 47 | #endif 48 | case '\t' : case '\r' : case '\n' : case ' ' : 49 | case ',' : case ']' : case '}' : 50 | goto found; 51 | } 52 | if (js[parser->pos] < 32 || js[parser->pos] >= 127) { 53 | parser->pos = start; 54 | return JSMN_ERROR_INVAL; 55 | } 56 | } 57 | #ifdef JSMN_STRICT 58 | /* In strict mode primitive must be followed by a comma/object/array */ 59 | parser->pos = start; 60 | return JSMN_ERROR_PART; 61 | #endif 62 | 63 | found: 64 | if (tokens == NULL) { 65 | parser->pos--; 66 | return 0; 67 | } 68 | token = jsmn_alloc_token(parser, tokens, num_tokens); 69 | if (token == NULL) { 70 | parser->pos = start; 71 | return JSMN_ERROR_NOMEM; 72 | } 73 | jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); 74 | #ifdef JSMN_PARENT_LINKS 75 | token->parent = parser->toksuper; 76 | #endif 77 | parser->pos--; 78 | return 0; 79 | } 80 | 81 | /** 82 | * Fills next token with JSON string. 83 | */ 84 | static int jsmn_parse_string(jsmn_parser *parser, const char *js, 85 | size_t len, jsmntok_t *tokens, size_t num_tokens) { 86 | jsmntok_t *token; 87 | 88 | int start = parser->pos; 89 | 90 | parser->pos++; 91 | 92 | /* Skip starting quote */ 93 | for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 94 | char c = js[parser->pos]; 95 | 96 | /* Quote: end of string */ 97 | if (c == '\"') { 98 | if (tokens == NULL) { 99 | return 0; 100 | } 101 | token = jsmn_alloc_token(parser, tokens, num_tokens); 102 | if (token == NULL) { 103 | parser->pos = start; 104 | return JSMN_ERROR_NOMEM; 105 | } 106 | jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); 107 | #ifdef JSMN_PARENT_LINKS 108 | token->parent = parser->toksuper; 109 | #endif 110 | return 0; 111 | } 112 | 113 | /* Backslash: Quoted symbol expected */ 114 | if (c == '\\' && parser->pos + 1 < len) { 115 | int i; 116 | parser->pos++; 117 | switch (js[parser->pos]) { 118 | /* Allowed escaped symbols */ 119 | case '\"': case '/' : case '\\' : case 'b' : 120 | case 'f' : case 'r' : case 'n' : case 't' : 121 | break; 122 | /* Allows escaped symbol \uXXXX */ 123 | case 'u': 124 | parser->pos++; 125 | for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) { 126 | /* If it isn't a hex character we have an error */ 127 | if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ 128 | (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ 129 | (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ 130 | parser->pos = start; 131 | return JSMN_ERROR_INVAL; 132 | } 133 | parser->pos++; 134 | } 135 | parser->pos--; 136 | break; 137 | /* Unexpected symbol */ 138 | default: 139 | parser->pos = start; 140 | return JSMN_ERROR_INVAL; 141 | } 142 | } 143 | } 144 | parser->pos = start; 145 | return JSMN_ERROR_PART; 146 | } 147 | 148 | /** 149 | * Parse JSON string and fill tokens. 150 | */ 151 | int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, 152 | jsmntok_t *tokens, unsigned int num_tokens) { 153 | int r; 154 | int i; 155 | jsmntok_t *token; 156 | int count = parser->toknext; 157 | 158 | for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 159 | char c; 160 | jsmntype_t type; 161 | 162 | c = js[parser->pos]; 163 | switch (c) { 164 | case '{': case '[': 165 | count++; 166 | if (tokens == NULL) { 167 | break; 168 | } 169 | token = jsmn_alloc_token(parser, tokens, num_tokens); 170 | if (token == NULL) 171 | return JSMN_ERROR_NOMEM; 172 | if (parser->toksuper != -1) { 173 | tokens[parser->toksuper].size++; 174 | #ifdef JSMN_PARENT_LINKS 175 | token->parent = parser->toksuper; 176 | #endif 177 | } 178 | token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); 179 | token->start = parser->pos; 180 | parser->toksuper = parser->toknext - 1; 181 | break; 182 | case '}': case ']': 183 | if (tokens == NULL) 184 | break; 185 | type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); 186 | #ifdef JSMN_PARENT_LINKS 187 | if (parser->toknext < 1) { 188 | return JSMN_ERROR_INVAL; 189 | } 190 | token = &tokens[parser->toknext - 1]; 191 | for (;;) { 192 | if (token->start != -1 && token->end == -1) { 193 | if (token->type != type) { 194 | return JSMN_ERROR_INVAL; 195 | } 196 | token->end = parser->pos + 1; 197 | parser->toksuper = token->parent; 198 | break; 199 | } 200 | if (token->parent == -1) { 201 | break; 202 | } 203 | token = &tokens[token->parent]; 204 | } 205 | #else 206 | for (i = parser->toknext - 1; i >= 0; i--) { 207 | token = &tokens[i]; 208 | if (token->start != -1 && token->end == -1) { 209 | if (token->type != type) { 210 | return JSMN_ERROR_INVAL; 211 | } 212 | parser->toksuper = -1; 213 | token->end = parser->pos + 1; 214 | break; 215 | } 216 | } 217 | /* Error if unmatched closing bracket */ 218 | if (i == -1) return JSMN_ERROR_INVAL; 219 | for (; i >= 0; i--) { 220 | token = &tokens[i]; 221 | if (token->start != -1 && token->end == -1) { 222 | parser->toksuper = i; 223 | break; 224 | } 225 | } 226 | #endif 227 | break; 228 | case '\"': 229 | r = jsmn_parse_string(parser, js, len, tokens, num_tokens); 230 | if (r < 0) return r; 231 | count++; 232 | if (parser->toksuper != -1 && tokens != NULL) 233 | tokens[parser->toksuper].size++; 234 | break; 235 | case '\t' : case '\r' : case '\n' : case ' ': 236 | break; 237 | case ':': 238 | parser->toksuper = parser->toknext - 1; 239 | break; 240 | case ',': 241 | if (tokens != NULL && parser->toksuper != -1 && 242 | tokens[parser->toksuper].type != JSMN_ARRAY && 243 | tokens[parser->toksuper].type != JSMN_OBJECT) { 244 | #ifdef JSMN_PARENT_LINKS 245 | parser->toksuper = tokens[parser->toksuper].parent; 246 | #else 247 | for (i = parser->toknext - 1; i >= 0; i--) { 248 | if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { 249 | if (tokens[i].start != -1 && tokens[i].end == -1) { 250 | parser->toksuper = i; 251 | break; 252 | } 253 | } 254 | } 255 | #endif 256 | } 257 | break; 258 | #ifdef JSMN_STRICT 259 | /* In strict mode primitives are: numbers and booleans */ 260 | case '-': case '0': case '1' : case '2': case '3' : case '4': 261 | case '5': case '6': case '7' : case '8': case '9': 262 | case 't': case 'f': case 'n' : 263 | /* And they must not be keys of the object */ 264 | if (tokens != NULL && parser->toksuper != -1) { 265 | jsmntok_t *t = &tokens[parser->toksuper]; 266 | if (t->type == JSMN_OBJECT || 267 | (t->type == JSMN_STRING && t->size != 0)) { 268 | return JSMN_ERROR_INVAL; 269 | } 270 | } 271 | #else 272 | /* In non-strict mode every unquoted value is a primitive */ 273 | default: 274 | #endif 275 | r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); 276 | if (r < 0) return r; 277 | count++; 278 | if (parser->toksuper != -1 && tokens != NULL) 279 | tokens[parser->toksuper].size++; 280 | break; 281 | 282 | #ifdef JSMN_STRICT 283 | /* Unexpected char in strict mode */ 284 | default: 285 | return JSMN_ERROR_INVAL; 286 | #endif 287 | } 288 | } 289 | 290 | if (tokens != NULL) { 291 | for (i = parser->toknext - 1; i >= 0; i--) { 292 | /* Unmatched opened object or array */ 293 | if (tokens[i].start != -1 && tokens[i].end == -1) { 294 | return JSMN_ERROR_PART; 295 | } 296 | } 297 | } 298 | 299 | return count; 300 | } 301 | 302 | /** 303 | * Creates a new parser based over a given buffer with an array of tokens 304 | * available. 305 | */ 306 | void jsmn_init(jsmn_parser *parser) { 307 | parser->pos = 0; 308 | parser->toknext = 0; 309 | parser->toksuper = -1; 310 | } 311 | 312 | -------------------------------------------------------------------------------- /source/release.cpp: -------------------------------------------------------------------------------- 1 | #include "release.h" 2 | 3 | // jsmn includes 4 | #include "jsmn.h" 5 | 6 | // Internal includes 7 | #include "archive.h" 8 | #include "http.h" 9 | #include "utils.h" 10 | 11 | #ifndef FAKEDL 12 | static int jsoneq(const char *json, const jsmntok_t *tok, const char *s) { 13 | if (tok->type == JSMN_STRING && (int)strlen(s) == tok->end - tok->start && 14 | std::strncmp(json + tok->start, s, tok->end - tok->start) == 0) { 15 | return 0; 16 | } 17 | return -1; 18 | } 19 | #endif 20 | 21 | ReleaseInfo releaseGetLatestStable() { 22 | ReleaseInfo release; 23 | 24 | #ifdef FAKEDL 25 | // Citra doesn't support HTTPc right now, so just fake a successful request 26 | release.name = "5.2"; 27 | release.description = "- Remade the chainloader to only try to load the right payload for the pressed button. Now the only buttons which have a matching payload will actually do something during boot\r\n- Got rid of the default payload (start now boots \"start_NAME.bin\")\r\n- sel_NAME.bin is now select_NAME.bin as there are no more SFN/8.3 limitations anymore\r\n\r\nRefer to [the wiki](https://github.com/AuroraWright/Luma3DS/wiki/Installation-and-Upgrade#upgrading-from-v531) for upgrade instructions."; 28 | release.versions.push_back(ReleaseVer{ "CITRA", "CITRA", "https://github.com/LumaTeam/Luma3DS/releases/download/v5.2/Luma3DSv5.2.7z", 143234 }); 29 | #else 30 | 31 | static const char* ReleaseURL = "https://api.github.com/repos/LumaTeam/Luma3DS/releases/latest"; 32 | 33 | jsmn_parser p = {}; 34 | jsmn_init(&p); 35 | 36 | u8* apiReqData = nullptr; 37 | u32 apiReqSize = 0; 38 | 39 | logPrintf("Downloading %s...\n", ReleaseURL); 40 | 41 | httpGet(ReleaseURL, &apiReqData, &apiReqSize, true); 42 | 43 | logPrintf("Downloaded %lu bytes\n", apiReqSize); 44 | gfxFlushBuffers(); 45 | 46 | jsmntok_t t[512] = {}; 47 | int r = jsmn_parse(&p, (const char*)apiReqData, apiReqSize, t, sizeof(t) / sizeof(t[0])); 48 | if (r < 0) { 49 | throw formatErrMessage("Failed to parse JSON", r); 50 | } 51 | logPrintf("JSON parsed successfully!\n"); 52 | gfxFlushBuffers(); 53 | 54 | bool namefound = false, bodyfound = false, inassets = false; 55 | bool verHasName = false, verHasURL = false, verHasSize = false, isDev = false; 56 | ReleaseVer current; 57 | for (int i = 0; i < r; i++) { 58 | if (!namefound && jsoneq((const char*)apiReqData, &t[i], "tag_name") == 0) { 59 | jsmntok_t val = t[i+1]; 60 | // Strip the "v" in front of the version name 61 | if (apiReqData[val.start] == 'v') { 62 | val.start += 1; 63 | } 64 | release.name = std::string((const char*)apiReqData + val.start, val.end - val.start); 65 | logPrintf("Release found: %s\n", release.name.c_str()); 66 | namefound = true; 67 | } 68 | if (!bodyfound && jsoneq((const char*)apiReqData, &t[i], "body") == 0) { 69 | jsmntok_t val = t[i+1]; 70 | release.description = unescape(std::string((const char*)apiReqData + val.start, val.end - val.start)); 71 | logPrintf("Release description found.\n"); 72 | bodyfound = true; 73 | } 74 | if (!inassets && jsoneq((const char*)apiReqData, &t[i], "assets") == 0) { 75 | inassets = true; 76 | } 77 | if (inassets) { 78 | if (jsoneq((const char*)apiReqData, &t[i], "name") == 0) { 79 | jsmntok_t val = t[i+1]; 80 | current.filename = std::string((const char*)apiReqData + val.start, val.end - val.start); 81 | isDev = current.filename.find("-dev.") < std::string::npos; 82 | current.friendlyName = isDev ? "developer version" : "stable version"; 83 | verHasName = true; 84 | } 85 | if (jsoneq((const char*)apiReqData, &t[i], "browser_download_url") == 0) { 86 | jsmntok_t val = t[i+1]; 87 | current.url = std::string((const char*)apiReqData + val.start, val.end - val.start); 88 | verHasURL = true; 89 | } 90 | if (jsoneq((const char*)apiReqData, &t[i], "size") == 0) { 91 | jsmntok_t val = t[i + 1]; 92 | std::string sizeStr = std::string((const char*)apiReqData + val.start, val.end - val.start); 93 | current.fileSize = std::atoi(sizeStr.c_str()); 94 | verHasSize = true; 95 | } 96 | if (verHasName && verHasURL && verHasSize) { 97 | logPrintf("Found version: %s\n", current.filename.c_str()); 98 | ReleaseVer version = ReleaseVer{ current.filename, current.friendlyName, current.url, current.fileSize }; 99 | // Put normal version in front, dev on back 100 | if (!isDev) { 101 | release.versions.insert(release.versions.begin(), version); 102 | } else { 103 | release.versions.push_back(version); 104 | } 105 | verHasName = verHasURL = verHasSize = isDev = false; 106 | } 107 | } 108 | } 109 | 110 | gfxFlushBuffers(); 111 | std::free(apiReqData); 112 | 113 | #endif 114 | 115 | return release; 116 | } 117 | 118 | ReleaseInfo releaseGetLatestHourly() { 119 | ReleaseInfo hourly; 120 | 121 | #ifdef FAKEDL 122 | // Citra doesn't support HTTPc right now, so just fake a successful request 123 | hourly.name = "aaaaaaa"; 124 | hourly.versions.push_back(ReleaseVer{ "CITRA", "latest hourly (aaaaaaa)", "https://github.com/LumaTeam/Luma3DS/releases/download/v5.2/Luma3DSv5.2.7z", 143234 });*/ 125 | 126 | #else 127 | 128 | static const char* LastCommitURL = 129 | "http://astronautlevel2.github.io/Luma3DS/lastCommit"; 130 | 131 | /*static const char* LastDevCommitURL = "https://raw.githubusercontent.com/astronautlevel2/Luma3DSDev/gh-pages/lastCommit";*/ 132 | 133 | /*static const char* versions[] = { LastCommitURL, LastDevCommitURL }; 134 | static const char* vertypes[] = { "hourly", "dev hourly" }; 135 | static const std::string verurls[] = { 136 | "http://astronautlevel2.github.io/Luma3DS/latest.zip", 137 | "http://astronautlevel2.github.io/Luma3DS/builds/Luma3DS-", 138 | "https://astronautlevel2.github.io/Luma3DSDev/builds/Luma3DS-" 139 | };*/ 140 | 141 | static const char* versions[] = { LastCommitURL}; 142 | static const char* vertypes[] = { "hourly" }; 143 | static const std::string verurls[] = { 144 | "http://astronautlevel2.github.io/Luma3DS/latest.zip", 145 | }; 146 | 147 | 148 | static const int versionCount = sizeof(versions) / sizeof(versions[0]); 149 | 150 | for (int i = 0; i < versionCount; i++) { 151 | u8* apiReqData = nullptr; 152 | u32 apiReqSize = 0; 153 | 154 | logPrintf("Downloading %s...\n", versions[i]); 155 | 156 | try { 157 | httpGet(versions[i], &apiReqData, &apiReqSize, true); 158 | } catch (const std::runtime_error& e) { 159 | logPrintf("Could not download, skipping..."); 160 | continue; 161 | } 162 | 163 | logPrintf("Downloaded %lu bytes\n", apiReqSize); 164 | gfxFlushBuffers(); 165 | 166 | std::string hourlyName = std::string((const char*)apiReqData, apiReqSize); 167 | trim(hourlyName); 168 | 169 | // Use stable's hourly id as "latest" since it gets updated more often 170 | if (i == 0) { 171 | hourly.name = hourlyName; 172 | } 173 | 174 | /*std::string url = verurls[i] + hourlyName + ".zip";*/ 175 | std::string url = verurls[i]; 176 | 177 | hourly.versions.push_back(ReleaseVer { hourlyName, "latest " + std::string(vertypes[i]) + " (" + hourlyName + ")", std::string(url), 0 }); 178 | hourly.commits[std::string(vertypes[i])] = hourlyName; 179 | 180 | std::free(apiReqData); 181 | } 182 | 183 | #endif 184 | 185 | return hourly; 186 | } 187 | 188 | bool releaseGetPayload(const PayloadType payloadType, const ReleaseVer& release, const bool isHourly, u8** payloadData, size_t* offset, size_t* payloadSize) { 189 | u8* fileData = nullptr; 190 | u32 fileSize = 0; 191 | HTTPResponseInfo info; 192 | 193 | try { 194 | #ifdef FAKEDL 195 | // Read predownloaded file 196 | std::ifstream predownloaded(release.filename + ".7z", std::ios::binary | std::ios::ate); 197 | fileSize = predownloaded.tellg(); 198 | predownloaded.seekg(0, std::ios::beg); 199 | fileData = (u8*)malloc(fileSize); 200 | predownloaded.read((char*)fileData, fileSize); 201 | info.etag = "\"0973d3d5fe62fccc30c8f663aec6918c\""; 202 | #else 203 | httpGet(release.url.c_str(), &fileData, &fileSize, true, &info); 204 | #endif 205 | } catch (const std::runtime_error& e) { 206 | logPrintf("%s\n", e.what()); 207 | return false; 208 | } 209 | logPrintf("Download complete! Size: %lu\n", fileSize); 210 | 211 | if (release.fileSize != 0) { 212 | logPrintf("Integrity check #1"); 213 | if (fileSize != release.fileSize) { 214 | logPrintf(" [ERR]\r\nReceived file is a different size than expected!\n"); 215 | gfxFlushBuffers(); 216 | return false; 217 | } 218 | logPrintf(" [OK]\r\n"); 219 | } else { 220 | logPrintf("Skipping integrity check #1 (unknown size)\n"); 221 | } 222 | 223 | if (!info.etag.empty()) { 224 | logPrintf("Integrity check #2"); 225 | if (!httpCheckETag(info.etag, fileData, fileSize)) { 226 | logPrintf(" [ERR]\r\nMD5 mismatch between server's and local file!\n"); 227 | gfxFlushBuffers(); 228 | return false; 229 | } 230 | logPrintf(" [OK]\r\n"); 231 | } else { 232 | logPrintf("Skipping integrity check #2 (no ETag found)\n"); 233 | } 234 | 235 | logPrintf("\nExtracting payload"); 236 | gfxFlushBuffers(); 237 | 238 | std::string payloadPath; 239 | switch (payloadType) { 240 | case PayloadType::SIGHAX: 241 | payloadPath = DEFAULT_SIGHAX_PATH; 242 | break; 243 | /*case PayloadType::Menuhax: 244 | payloadPath = DEFAULT_MHAX_PATH; 245 | break; 246 | case PayloadType::Homebrew: 247 | payloadPath = DEFAULT_3DSX_PATH; 248 | break;*/ 249 | } 250 | 251 | try { 252 | ZipArchive archive(fileData, fileSize); 253 | archive.extractFile(payloadPath, payloadData, payloadSize); 254 | offset = 0; 255 | } catch (const std::runtime_error& e) { 256 | logPrintf(" [ERR]\nFATAL: %s", e.what()); 257 | std::free(fileData); 258 | return false; 259 | } 260 | 261 | logPrintf(" [OK]\n"); 262 | std::free(fileData); 263 | return true; 264 | } 265 | --------------------------------------------------------------------------------