package main
+import "core:encoding/base64"
import "core:log"
import "core:math/rand"
import "core:os"
return .Invalid_Arguments
}
- room, ok := room_init(room_details[0], room_details[1])
+ room, ok := room_init_with_key_string(room_details[0], room_details[1])
if !ok {
app_set_info_bar(app, "Invalid room.")
return .Invalid_Arguments
}
- ok = app_add_room(app, room)
+ if app_room_key_exists(app, room.key) {
+ app_set_info_bar(app, "A room with this key already exists, are you sure you want to create another one? (yes/no)")
- if !ok {
- app_set_info_bar(app, "A room with this name already exists.")
- return .Command_Failed
+ answer := app_get_input(app, allocator = context.temp_allocator)
+
+ if answer != "yes" {
+ app_set_info_bar(app, "Opperation cancelled.")
+ return nil
+ }
}
+ app_add_room(app, room)
app_set_info_bar(app, "Room added.")
return nil
key: [ROOM_KEY_SIZE]u8
_ = rand.read(key[:])
- room, ok := room_init(room_name, string(key[:]))
+ room, ok := room_init(room_name, key)
if !ok {
app_set_info_bar(app, "Invalid name.")
return .Invalid_Arguments
}
- ok = app_add_room(app, room)
+ app_add_room(app, room)
+ app_set_info_bar(app, "Room generated.")
- if !ok {
- app_set_info_bar(app, "A room with this name already exists.")
- return .Command_Failed
+ return nil
+
+ case ":k", ":key":
+ selected_room := &app.profile.rooms[app.selected_room]
+
+ key_string_buffer: [44]u8
+ key_string_builder := strings.builder_from_bytes(key_string_buffer[:])
+ key_string_stream := strings.to_stream(&key_string_builder)
+
+ err := base64.encode_into(key_string_stream, selected_room.key[:])
+
+ if err != nil {
+ app_set_info_bar(app, "Failed to encode key")
+ return nil
}
- app_set_info_bar(app, "Room generated.")
+ key_string := strings.to_string(key_string_builder)
+
+ app_set_info_bar(app, "%v", key_string)
return nil
case ":rm", ":remove":
- if len(args) == 0 {
- app_set_info_bar(app, "No room name provided.")
- return .Invalid_Arguments
- }
-
- room_name := args[0]
+ app_set_info_bar(app, "Are you sure you want to remove this room? (yes/no)")
- ok := app_remove_room(app, room_name)
+ answer := app_get_input(app, allocator = context.temp_allocator)
- if !ok {
- app_set_info_bar(app, "No room with that name.")
- return .Command_Failed
+ if answer != "yes" {
+ app_set_info_bar(app, "Opperation cancelled.")
+ return nil
}
+ app_remove_room(app, app.selected_room)
app_set_info_bar(app, "Room removed.")
return nil
app.seed_phrase_checksum = entropy_hash[0] & 0b1111
}
-app_get_room_index :: proc(app: ^App, name: string) -> Maybe(int) {
- for &room, i in app.profile.rooms {
- if room_get_name(&room) != name {
- continue
- }
+app_room_key_exists :: proc(app: ^App, key: [ROOM_KEY_SIZE]u8) -> bool {
+ key := key
- return i
+ for &room in app.profile.rooms {
+ if slice.equal(room.key[:], key[:]) {
+ return true
+ }
}
- return nil
+ return false
}
-app_add_room :: proc(app: ^App, room: Room) -> bool {
+app_add_room :: proc(app: ^App, room: Room) {
room := room
- for &profile_room in app.profile.rooms {
- if room_get_name(&profile_room) == room_get_name(&room) {
- return false
- }
- }
-
append(&app.profile.rooms, room)
profile_update(app.profile, app)
app_update_room_list_window(app)
-
- return true
}
-app_remove_room :: proc(app: ^App, name: string) -> bool {
- room_index, ok := app_get_room_index(app, name).?
-
- if !ok {
- return false
- }
-
- ordered_remove(&app.profile.rooms, room_index)
+app_remove_room :: proc(app: ^App, index: int) {
+ ordered_remove(&app.profile.rooms, index)
profile_update(app.profile, app)
if app.selected_room >= len(app.profile.rooms) {
}
app_update_room_list_window(app)
-
- return true
}
handle_state :: proc(app: ^App) {
package main
+import "core:bytes"
import "core:container/small_array"
import "core:crypto/ed25519"
import "core:crypto/sha3"
+import "core:encoding/base64"
import "core:encoding/json"
import "core:log"
import "core:math/rand"
key: [ROOM_KEY_SIZE]u8,
}
-room_init :: proc(name: string, key: string) -> (Room, bool) {
+room_init :: proc(name: string, key: [ROOM_KEY_SIZE]u8) -> (Room, bool) {
_, name_len, _ := utf8.grapheme_count(name)
- if name_len > ROOM_NAME_MAX_LEN || len(key) != ROOM_KEY_SIZE {
+ if name_len > ROOM_NAME_MAX_LEN {
return {}, false
}
name_bytes := transmute([]u8)name
- key_bytes := transmute([]u8)key
room_name: Room_Name
small_array.append_elems(&room_name, ..name_bytes)
- room_key: [ROOM_KEY_SIZE]u8
- mem.copy_non_overlapping(raw_data(room_key[:]), raw_data(key_bytes), ROOM_KEY_SIZE)
-
return {
name = room_name,
- key = room_key,
+ key = key,
},
true
}
+room_init_with_key_string :: proc(name: string, key_string: string) -> (Room, bool) {
+ if len(key_string) != 44 {
+ return {}, false
+ }
+
+ key_bytes: [ROOM_KEY_SIZE]u8
+
+ key_bytes_buffer := bytes.Buffer{ buf = mem.buffer_from_slice(key_bytes[:]) }
+ key_bytes_stream := bytes.buffer_to_stream(&key_bytes_buffer)
+
+ err := base64.decode_into(key_bytes_stream, key_string)
+
+ if err != nil {
+ return {}, false
+ }
+
+ return room_init(name, key_bytes)
+}
+
room_get_name :: proc(room: ^Room) -> string {
bytes := small_array.slice(&room.name)
return string(bytes)
private_key_bytes: [sha3.DIGEST_SIZE_256]u8
sha3.final(&sha_context, private_key_bytes[:])
- {
- sync.mutex_lock(&app.mutex)
- defer sync.mutex_unlock(&app.mutex)
-
- if !ed25519.private_key_set_bytes(&profile.private_key, private_key_bytes[:]) {
- log.errorf("Failed to set private key bytes.")
- }
+ if !ed25519.private_key_set_bytes(&profile.private_key, private_key_bytes[:]) {
+ log.errorf("Failed to set private key bytes.")
}
return nil