func peerFrom(entry data.RosterEntry, c *config.Account) *roster.Peer { belongsTo := c.ID() var nickname string p, ok := c.GetPeer(entry.Jid) if ok { nickname = p.Nickname } return roster.PeerFrom(entry, belongsTo, nickname) }
func peerFrom(entry data.RosterEntry, c *config.Account) *roster.Peer { belongsTo := c.ID() var nickname string var groups []string if p, ok := c.GetPeer(entry.Jid); ok { nickname = p.Nickname groups = p.Groups } return roster.PeerFrom(entry, belongsTo, nickname, groups) }
func parseFromConfig(cu *config.Account) []otr3.PrivateKey { var result []otr3.PrivateKey allKeys := cu.AllPrivateKeys() log.Printf("Loading %d configured keys", len(allKeys)) for _, pp := range allKeys { _, ok, parsedKey := otr3.ParsePrivateKey(pp) if ok { result = append(result, parsedKey) log.Printf("Loaded key: %s", config.FormatFingerprint(parsedKey.PublicKey().Fingerprint())) } } return result }
// PeerFrom returns a new Peer that contains the same information as the RosterEntry given func PeerFrom(e xmpp.RosterEntry, conf *config.Account) *Peer { belongsTo := conf.ID() var nickname string p, ok := conf.GetPeer(e.Jid) if ok { nickname = p.Nickname } return &Peer{ Jid: xmpp.RemoveResourceFromJid(e.Jid), Subscription: e.Subscription, Name: e.Name, Nickname: nickname, Groups: toSet(e.Group...), BelongsTo: belongsTo, } }
func (r *roster) renameContactPopup(conf *config.Account, jid string) { builder := builderForDefinition("RenameContact") obj, _ := builder.GetObject("RenameContactPopup") popup := obj.(*gtk.Dialog) builder.ConnectSignals(map[string]interface{}{ "on_rename_signal": func() { obj, _ = builder.GetObject("rename") renameTxt := obj.(*gtk.Entry) newName, _ := renameTxt.GetText() conf.RenamePeer(jid, newName) r.ui.SaveConfig() r.redraw() popup.Destroy() }, }) popup.ShowAll() }
func (u *gtkUI) exportKeysFor(account *config.Account, file string) bool { var result []*otr3.Account allKeys := account.AllPrivateKeys() for _, pp := range allKeys { _, ok, parsedKey := otr3.ParsePrivateKey(pp) if ok { result = append(result, &otr3.Account{ Name: account.Account, Protocol: "prpl-jabber", Key: parsedKey, }) } } err := otr3.ExportKeysToFile(result, file) return err == nil }
func (u *gtkUI) importFingerprintsFor(account *config.Account, file string) (int, bool) { fprs, ok := importer.ImportFingerprintsFromPidginStyle(file, func(string) bool { return true }) if !ok { return 0, false } num := 0 for _, kfprs := range fprs { for _, kfpr := range kfprs { log.Printf("Importing fingerprint %X for %s", kfpr.Fingerprint, kfpr.UserID) fpr := account.EnsurePeer(kfpr.UserID).EnsureHasFingerprint(kfpr.Fingerprint) num = num + 1 if !kfpr.Untrusted { fpr.Trusted = true } } } return num, true }
func (u *gtkUI) importKeysFor(account *config.Account, file string) (int, bool) { keys, ok := importer.ImportKeysFromPidginStyle(file, func(string) bool { return true }) if !ok { return 0, false } switch len(keys) { case 0: return 0, true case 1: account.PrivateKeys = [][]byte{firstItem(keys)} return 1, true default: kk, ok := u.chooseKeyToImport(keys) if ok { account.PrivateKeys = [][]byte{kk} return 1, true } return 0, false } }
func (m *accountManager) removeAccount(conf *config.Account, k func()) { toRemove, exists := m.getAccountByID(conf.ID()) if !exists { return } m.Lock() defer m.Unlock() accs := make([]*account, 0, len(m.accounts)-1) for _, acc := range m.accounts { if acc == toRemove { delete(m.contacts, acc) continue } accs = append(accs, acc) } m.accounts = accs k() }
func (u *gtkUI) importKeysFor(account *config.Account, file string) (int, bool) { keys, ok := importer.ImportKeysFromPidginStyle(file, func(string) bool { return true }) if !ok { return 0, false } newKeys := [][]byte{} for _, kk := range keys { newKeys = append(newKeys, kk) } account.PrivateKeys = newKeys return len(newKeys), true }
func (u *gtkUI) askForServerDetails(conf *config.Account, connectFn func() error) { builder := builderForDefinition("ConnectionSettings") obj, _ := builder.GetObject("ConnectionSettingsDialog") dialog := obj.(*gtk.Dialog) obj, _ = builder.GetObject("server") serverEntry := obj.(*gtk.Entry) obj, _ = builder.GetObject("port") portEntry := obj.(*gtk.Entry) if conf.Port == 0 { conf.Port = 5222 } serverEntry.SetText(conf.Server) portEntry.SetText(strconv.Itoa(conf.Port)) builder.ConnectSignals(map[string]interface{}{ "reconnect": func() { defer dialog.Destroy() //TODO: validate conf.Server, _ = serverEntry.GetText() p, _ := portEntry.GetText() conf.Port, _ = strconv.Atoi(p) go func() { if connectFn() != nil { return } u.saveConfigOnly() }() }, }) dialog.SetTransientFor(u.window) dialog.ShowAll() }
func (c *cliUI) enroll(conf *config.ApplicationConfig, currentConf *config.Account) bool { var err error c.warn("Enrolling new config file") var domain string for { c.term.SetPrompt("Account (i.e. [email protected], enter to quit): ") if currentConf.Account, err = c.term.ReadLine(); err != nil || len(currentConf.Account) == 0 { return false } parts := strings.SplitN(currentConf.Account, "@", 2) if len(parts) != 2 { c.alert("invalid username (want user@domain): " + currentConf.Account) continue } domain = parts[1] break } c.term.SetPrompt("Enable debug logging to /tmp/xmpp-client-debug.log? ") if debugLog, err := c.term.ReadLine(); err != nil || !config.ParseYes(debugLog) { c.info("Not enabling debug logging...") } else { c.info("Debug logging enabled...") conf.RawLogFile = "/tmp/xmpp-client-debug.log" } c.term.SetPrompt("Use Tor?: ") if useTorQuery, err := c.term.ReadLine(); err != nil || len(useTorQuery) == 0 || !config.ParseYes(useTorQuery) { c.info("Not using Tor...") currentConf.Proxies = []string{} } else { c.info("Using Tor...") } c.term.SetPrompt("File to import libotr private key from (enter to generate): ") var pkeys []otr3.PrivateKey for { importFile, err := c.term.ReadLine() if err != nil { return false } if len(importFile) > 0 { privKeyBytes, err := ioutil.ReadFile(importFile) if err != nil { c.alert("Failed to open private key file: " + err.Error()) continue } var priv otr3.DSAPrivateKey if !priv.Import(privKeyBytes) { c.alert("Failed to parse libotr private key file (the parser is pretty simple I'm afraid)") continue } pkeys = append(pkeys, &priv) break } else { c.info("Generating private key...") pkeys, err = otr3.GenerateMissingKeys([][]byte{}) if err != nil { c.alert("Failed to generate private key - this implies something is really bad with your system, so we bail out now") return false } break } } currentConf.PrivateKeys = config.SerializedKeys(pkeys) currentConf.OTRAutoAppendTag = true currentConf.OTRAutoStartSession = true currentConf.OTRAutoTearDown = false // Force Tor for servers with well known Tor hidden services. if _, ok := servers.Get(domain); ok && currentConf.HasTorAuto() { const torProxyURL = "socks5://127.0.0.1:9050" c.info("It appears that you are using a well known server and we will use its Tor hidden service to connect.") currentConf.Proxies = []string{torProxyURL} c.term.SetPrompt("> ") return true } var proxyStr string proxyDefaultPrompt := ", enter for none" if currentConf.HasTorAuto() { proxyDefaultPrompt = ", which is the default" } c.term.SetPrompt("Proxy (i.e socks5://127.0.0.1:9050" + proxyDefaultPrompt + "): ") for { if proxyStr, err = c.term.ReadLine(); err != nil { return false } if len(proxyStr) == 0 { if !currentConf.HasTorAuto() { break } else { proxyStr = "socks5://127.0.0.1:9050" } } u, err := url.Parse(proxyStr) if err != nil { c.alert("Failed to parse " + proxyStr + " as a URL: " + err.Error()) continue } if _, err = proxy.FromURL(u, proxy.Direct); err != nil { c.alert("Failed to parse " + proxyStr + " as a proxy: " + err.Error()) continue } break } c.term.SetPrompt("> ") return true }
func (u *gtkUI) accountDialog(s access.Session, account *config.Account, saveFunction func()) { data := getBuilderAndAccountDialogDetails() data.otherSettings.SetActive(u.config.AdvancedOptions) data.acc.SetText(account.Account) data.server.SetText(account.Server) if account.Port == 0 { account.Port = 5222 } data.port.SetText(strconv.Itoa(account.Port)) for _, px := range account.Proxies { iter := data.proxies.Append() data.proxies.SetValue(iter, 0, net.ParseProxy(px).ForPresentation()) data.proxies.SetValue(iter, 1, px) } data.fingerprintsMessage.SetSelectable(true) m := i18n.Local("Your fingerprints for %s:\n%s") message := fmt.Sprintf(m, account.Account, formattedFingerprintsFor(s)) data.fingerprintsMessage.SetText(message) p2, _ := data.notebook.GetNthPage(1) p3, _ := data.notebook.GetNthPage(2) p4, _ := data.notebook.GetNthPage(3) failures := 0 editProxy := func(iter *gtk.TreeIter, onCancel func()) { val, _ := data.proxies.GetValue(iter, 1) realProxyData, _ := val.GetString() u.editProxy(realProxyData, data.dialog, func(p net.Proxy) { data.proxies.SetValue(iter, 0, p.ForPresentation()) data.proxies.SetValue(iter, 1, p.ForProcessing()) }, onCancel) } data.builder.ConnectSignals(map[string]interface{}{ "on_toggle_other_settings": func() { otherSettings := data.otherSettings.GetActive() u.setShowAdvancedSettings(otherSettings) data.notebook.SetShowTabs(otherSettings) if otherSettings { p2.Show() p3.Show() p4.Show() } else { p2.Hide() p3.Hide() p4.Hide() } }, "on_save_signal": func() { accTxt, _ := data.acc.GetText() passTxt, _ := data.pass.GetText() servTxt, _ := data.server.GetText() portTxt, _ := data.port.GetText() isJid, err := verifyXmppAddress(accTxt) if !isJid && failures > 0 { failures++ return } if !isJid { notification := buildBadUsernameNotification(err) data.notificationArea.Add(notification) notification.ShowAll() failures++ log.Printf(err) return } account.Account = accTxt account.Server = servTxt if passTxt != "" { account.Password = passTxt } convertedPort, e := strconv.Atoi(portTxt) if len(strings.TrimSpace(portTxt)) == 0 || e != nil { convertedPort = 5222 } account.Port = convertedPort newProxies := []string{} iter, ok := data.proxies.GetIterFirst() for ok { vv, _ := data.proxies.GetValue(iter, 1) newProxy, _ := vv.GetString() newProxies = append(newProxies, newProxy) ok = data.proxies.IterNext(iter) } account.Proxies = newProxies go saveFunction() data.dialog.Destroy() }, "on_edit_proxy_signal": func() { ts, _ := data.proxiesView.GetSelection() var iter gtk.TreeIter if ts.GetSelected(nil, &iter) { editProxy(&iter, func() {}) } }, "on_remove_proxy_signal": func() { ts, _ := data.proxiesView.GetSelection() var iter gtk.TreeIter if ts.GetSelected(nil, &iter) { data.proxies.Remove(&iter) } }, "on_add_proxy_signal": func() { iter := data.proxies.Append() data.proxies.SetValue(iter, 0, "tor-auto://") data.proxies.SetValue(iter, 1, "tor-auto://") ts, _ := data.proxiesView.GetSelection() ts.SelectIter(iter) editProxy(iter, func() { data.proxies.Remove(iter) }) }, "on_edit_activate_proxy_signal": func(_ *gtk.TreeView, path *gtk.TreePath) { iter, err := data.proxies.GetIter(path) if err == nil { editProxy(iter, func() {}) } }, "on_cancel_signal": func() { u.buildAccountsMenu() data.dialog.Destroy() }, "on_import_key_signal": func() { u.importKeysForDialog(account, data.dialog) }, "on_import_fpr_signal": func() { u.importFingerprintsForDialog(account, data.dialog) }, "on_export_key_signal": func() { u.exportKeysForDialog(account, data.dialog) }, "on_export_fpr_signal": func() { u.exportFingerprintsForDialog(account, data.dialog) }, }) data.dialog.SetTransientFor(u.window) data.dialog.ShowAll() data.notebook.SetCurrentPage(0) data.notebook.SetShowTabs(u.config.AdvancedOptions) if !u.config.AdvancedOptions { p2.Hide() p3.Hide() p4.Hide() } }
func (u *gtkUI) accountDialog(account *config.Account, saveFunction func()) { dialogID := "AccountDetails" builder := builderForDefinition(dialogID) obj, _ := builder.GetObject(dialogID) dialog := obj.(*gtk.Dialog) obj, _ = builder.GetObject("notebook1") notebook := obj.(*gtk.Notebook) obj, _ = builder.GetObject("otherSettings") otherSettingsToggle := obj.(*gtk.CheckButton) obj, _ = builder.GetObject("account") accEntry := obj.(*gtk.Entry) accEntry.SetText(account.Account) obj, _ = builder.GetObject("password") passEntry := obj.(*gtk.Entry) obj, _ = builder.GetObject("server") serverEntry := obj.(*gtk.Entry) serverEntry.SetText(account.Server) obj, _ = builder.GetObject("port") portEntry := obj.(*gtk.Entry) if account.Port == 0 { account.Port = 5222 } portEntry.SetText(strconv.Itoa(account.Port)) obj, _ = builder.GetObject("notification-area") notificationArea := obj.(*gtk.Box) p2, _ := notebook.GetNthPage(1) p3, _ := notebook.GetNthPage(2) failures := 0 builder.ConnectSignals(map[string]interface{}{ "on_toggle_other_settings": func() { otherSettings := otherSettingsToggle.GetActive() if otherSettings { p2.Show() p3.Show() } else { p2.Hide() p3.Hide() } }, "on_save_signal": func() { accTxt, _ := accEntry.GetText() passTxt, _ := passEntry.GetText() servTxt, _ := serverEntry.GetText() portTxt, _ := portEntry.GetText() isJid, err := verifyXmppAddress(accTxt) if !isJid && failures > 0 { failures++ return } if !isJid { notification := buildBadUsernameNotification(err) notificationArea.Add(notification) notification.ShowAll() failures++ log.Printf(err) return } account.Account = accTxt account.Server = servTxt if passTxt != "" { account.Password = passTxt } convertedPort, e := strconv.Atoi(portTxt) if len(strings.TrimSpace(portTxt)) == 0 || e != nil { convertedPort = 5222 } account.Port = convertedPort go saveFunction() dialog.Destroy() }, "on_cancel_signal": func() { u.buildAccountsMenu() dialog.Destroy() }, }) dialog.SetTransientFor(u.window) dialog.ShowAll() notebook.SetCurrentPage(0) p2.Hide() p3.Hide() }