summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules4
-rw-r--r--README.md1
-rw-r--r--bin15/mir_full.sln82
-rw-r--r--bin15/mir_icons.sln10
-rw-r--r--bin15/miranda32.sln20
-rw-r--r--docs/contributors.txt22
-rw-r--r--docs/mirandaboot.ini4
-rw-r--r--git_read.cmd1
-rw-r--r--include/delphi/m_api.pas1
-rw-r--r--include/delphi/testdll.dpr1
-rw-r--r--include/m_addcontact.h68
-rw-r--r--include/m_contacts.h9
-rw-r--r--include/m_core.h33
-rw-r--r--include/m_idle.h33
-rw-r--r--include/m_json.h25
-rw-r--r--include/m_langpack.h6
-rw-r--r--include/m_message.h5
-rw-r--r--include/m_protosvc.h30
-rw-r--r--include/m_system_cpp.h62
-rw-r--r--include/newpluginapi.h1
-rw-r--r--langpacks/belarusian/=CORE=.txt146
-rw-r--r--langpacks/belarusian/=HEAD=.txt2
-rw-r--r--langpacks/belarusian/Deprecated/AIM.txt (renamed from langpacks/belarusian/Plugins/AIM.txt)0
-rw-r--r--langpacks/belarusian/Plugins/AddContactPlus.txt2
-rw-r--r--langpacks/belarusian/Plugins/AsSingleWindow.txt20
-rw-r--r--langpacks/belarusian/Plugins/AssocMgr.txt4
-rw-r--r--langpacks/belarusian/Plugins/BASS_interface.txt20
-rw-r--r--langpacks/belarusian/Plugins/BasicHistory.txt92
-rw-r--r--langpacks/belarusian/Plugins/Clist_modern.txt2
-rw-r--r--langpacks/belarusian/Plugins/Clist_nicer.txt2
-rw-r--r--langpacks/belarusian/Plugins/CloudFile.txt2
-rw-r--r--langpacks/belarusian/Plugins/DbEditorPP.txt4
-rw-r--r--langpacks/belarusian/Plugins/Fingerprint.txt12
-rw-r--r--langpacks/belarusian/Plugins/GmailNotifier.txt12
-rw-r--r--langpacks/belarusian/Plugins/IEView.txt2
-rw-r--r--langpacks/belarusian/Plugins/MSN.txt2
-rw-r--r--langpacks/belarusian/Plugins/New_GPG.txt190
-rw-r--r--langpacks/belarusian/Plugins/SimpleStatusMsg.txt2
-rw-r--r--langpacks/belarusian/Plugins/SmileyAdd.txt8
-rw-r--r--langpacks/belarusian/Plugins/SplashScreen.txt2
-rw-r--r--langpacks/belarusian/Plugins/StatusManager.txt2
-rw-r--r--langpacks/belarusian/Plugins/Steam.txt2
-rw-r--r--langpacks/belarusian/Plugins/StopSpam.txt6
-rw-r--r--langpacks/belarusian/Plugins/StopSpamMod.txt6
-rw-r--r--langpacks/belarusian/Plugins/TabSRMM.txt2
-rw-r--r--langpacks/belarusian/Plugins/Tipper.txt2
-rw-r--r--langpacks/belarusian/Plugins/Tox.txt2
-rw-r--r--langpacks/belarusian/Plugins/mRadio.txt6
-rw-r--r--langpacks/bulgarian/=CORE=.txt146
-rw-r--r--langpacks/bulgarian/=HEAD=.txt2
-rw-r--r--langpacks/bulgarian/Deprecated/AIM.txt (renamed from langpacks/bulgarian/Plugins/AIM.txt)0
-rw-r--r--langpacks/bulgarian/Plugins/AddContactPlus.txt2
-rw-r--r--langpacks/bulgarian/Plugins/AssocMgr.txt4
-rw-r--r--langpacks/bulgarian/Plugins/BASS_interface.txt20
-rw-r--r--langpacks/bulgarian/Plugins/BasicHistory.txt80
-rw-r--r--langpacks/bulgarian/Plugins/Clist_modern.txt2
-rw-r--r--langpacks/bulgarian/Plugins/Clist_nicer.txt2
-rw-r--r--langpacks/bulgarian/Plugins/CloudFile.txt2
-rw-r--r--langpacks/bulgarian/Plugins/DbEditorPP.txt2
-rw-r--r--langpacks/bulgarian/Plugins/Fingerprint.txt12
-rw-r--r--langpacks/bulgarian/Plugins/GmailNotifier.txt4
-rw-r--r--langpacks/bulgarian/Plugins/MSN.txt2
-rw-r--r--langpacks/bulgarian/Plugins/New_GPG.txt32
-rw-r--r--langpacks/bulgarian/Plugins/SimpleStatusMsg.txt2
-rw-r--r--langpacks/bulgarian/Plugins/SmileyAdd.txt2
-rw-r--r--langpacks/bulgarian/Plugins/StatusManager.txt2
-rw-r--r--langpacks/bulgarian/Plugins/Steam.txt2
-rw-r--r--langpacks/bulgarian/Plugins/StopSpam.txt10
-rw-r--r--langpacks/bulgarian/Plugins/StopSpamMod.txt2
-rw-r--r--langpacks/bulgarian/Plugins/TabSRMM.txt2
-rw-r--r--langpacks/bulgarian/Plugins/Tox.txt2
-rw-r--r--langpacks/bulgarian/Plugins/mRadio.txt4
-rw-r--r--langpacks/bulgarian/Untranslated/AIM.txt58
-rw-r--r--langpacks/bulgarian/Untranslated/BasicHistory.txt24
-rw-r--r--langpacks/bulgarian/Untranslated/GmailNotifier.txt2
-rw-r--r--langpacks/bulgarian/Untranslated/IEView.txt1
-rw-r--r--langpacks/bulgarian/Untranslated/New_GPG.txt73
-rw-r--r--langpacks/bulgarian/Untranslated/SmileyAdd.txt1
-rw-r--r--langpacks/bulgarian/Untranslated/SplashScreen.txt1
-rw-r--r--langpacks/bulgarian/Untranslated/mRadio.txt1
-rw-r--r--langpacks/croatian/=CORE=.txt155
-rw-r--r--langpacks/croatian/=HEAD=.txt2
-rw-r--r--langpacks/croatian/Plugins/AIM.txt426
-rw-r--r--langpacks/croatian/Plugins/AddContactPlus.txt2
-rw-r--r--langpacks/croatian/Plugins/AssocMgr.txt2
-rw-r--r--langpacks/croatian/Plugins/BASS_interface.txt14
-rw-r--r--langpacks/croatian/Plugins/BasicHistory.txt88
-rw-r--r--langpacks/croatian/Plugins/Clist_modern.txt2
-rw-r--r--langpacks/croatian/Plugins/Clist_nicer.txt2
-rw-r--r--langpacks/croatian/Plugins/CloudFile.txt2
-rw-r--r--langpacks/croatian/Plugins/DbEditorPP.txt2
-rw-r--r--langpacks/croatian/Plugins/Fingerprint.txt12
-rw-r--r--langpacks/croatian/Plugins/GmailNotifier.txt12
-rw-r--r--langpacks/croatian/Plugins/IEView.txt2
-rw-r--r--langpacks/croatian/Plugins/MSN.txt2
-rw-r--r--langpacks/croatian/Plugins/New_GPG.txt186
-rw-r--r--langpacks/croatian/Plugins/SimpleStatusMsg.txt2
-rw-r--r--langpacks/croatian/Plugins/SmileyAdd.txt8
-rw-r--r--langpacks/croatian/Plugins/SplashScreen.txt2
-rw-r--r--langpacks/croatian/Plugins/StatusManager.txt2
-rw-r--r--langpacks/croatian/Plugins/Steam.txt2
-rw-r--r--langpacks/croatian/Plugins/StopSpam.txt10
-rw-r--r--langpacks/croatian/Plugins/StopSpamMod.txt2
-rw-r--r--langpacks/croatian/Plugins/TabSRMM.txt2
-rw-r--r--langpacks/croatian/Plugins/Tox.txt2
-rw-r--r--langpacks/croatian/Plugins/mRadio.txt4
-rw-r--r--langpacks/croatian/Untranslated/=CORE=.txt51
-rw-r--r--langpacks/croatian/Untranslated/AIM.txt200
-rw-r--r--langpacks/croatian/Untranslated/AssocMgr.txt2
-rw-r--r--langpacks/croatian/Untranslated/BASS_interface.txt11
-rw-r--r--langpacks/croatian/Untranslated/BasicHistory.txt88
-rw-r--r--langpacks/croatian/Untranslated/Clist_modern.txt1
-rw-r--r--langpacks/croatian/Untranslated/Clist_nicer.txt1
-rw-r--r--langpacks/croatian/Untranslated/Fingerprint.txt6
-rw-r--r--langpacks/croatian/Untranslated/GmailNotifier.txt5
-rw-r--r--langpacks/croatian/Untranslated/IEView.txt1
-rw-r--r--langpacks/croatian/Untranslated/New_GPG.txt91
-rw-r--r--langpacks/croatian/Untranslated/SmileyAdd.txt3
-rw-r--r--langpacks/croatian/Untranslated/SplashScreen.txt1
-rw-r--r--langpacks/croatian/Untranslated/StopSpam.txt2
-rw-r--r--langpacks/croatian/Untranslated/TabSRMM.txt1
-rw-r--r--langpacks/croatian/Untranslated/mRadio.txt3
-rw-r--r--langpacks/czech/=CORE=.txt155
-rw-r--r--langpacks/czech/=HEAD=.txt2
-rw-r--r--langpacks/czech/Deprecated/AIM.txt (renamed from langpacks/czech/Plugins/AIM.txt)0
-rw-r--r--langpacks/czech/Plugins/AddContactPlus.txt2
-rw-r--r--langpacks/czech/Plugins/AssocMgr.txt4
-rw-r--r--langpacks/czech/Plugins/BASS_interface.txt28
-rw-r--r--langpacks/czech/Plugins/BasicHistory.txt108
-rw-r--r--langpacks/czech/Plugins/Clist_modern.txt2
-rw-r--r--langpacks/czech/Plugins/Clist_nicer.txt2
-rw-r--r--langpacks/czech/Plugins/CloudFile.txt2
-rw-r--r--langpacks/czech/Plugins/DbEditorPP.txt2
-rw-r--r--langpacks/czech/Plugins/Fingerprint.txt12
-rw-r--r--langpacks/czech/Plugins/GmailNotifier.txt12
-rw-r--r--langpacks/czech/Plugins/IEView.txt2
-rw-r--r--langpacks/czech/Plugins/MSN.txt2
-rw-r--r--langpacks/czech/Plugins/New_GPG.txt188
-rw-r--r--langpacks/czech/Plugins/SimpleStatusMsg.txt2
-rw-r--r--langpacks/czech/Plugins/SmileyAdd.txt8
-rw-r--r--langpacks/czech/Plugins/SplashScreen.txt2
-rw-r--r--langpacks/czech/Plugins/StatusManager.txt2
-rw-r--r--langpacks/czech/Plugins/Steam.txt2
-rw-r--r--langpacks/czech/Plugins/StopSpam.txt10
-rw-r--r--langpacks/czech/Plugins/StopSpamMod.txt2
-rw-r--r--langpacks/czech/Plugins/TabSRMM.txt2
-rw-r--r--langpacks/czech/Plugins/Tox.txt2
-rw-r--r--langpacks/czech/Plugins/mRadio.txt6
-rw-r--r--langpacks/czech/Untranslated/Fingerprint.txt4
-rw-r--r--langpacks/czech/Untranslated/GmailNotifier.txt1
-rw-r--r--langpacks/czech/Untranslated/IEView.txt1
-rw-r--r--langpacks/czech/Untranslated/New_GPG.txt61
-rw-r--r--langpacks/czech/Untranslated/SplashScreen.txt1
-rw-r--r--langpacks/czech/Untranslated/mRadio.txt1
-rw-r--r--langpacks/english/=CORE=.txt84
-rw-r--r--langpacks/english/Plugins/AIM.txt222
-rw-r--r--langpacks/english/Plugins/AddContactPlus.txt2
-rw-r--r--langpacks/english/Plugins/AssocMgr.txt3
-rw-r--r--langpacks/english/Plugins/BASS_interface.txt13
-rw-r--r--langpacks/english/Plugins/BasicHistory.txt88
-rw-r--r--langpacks/english/Plugins/Clist_modern.txt1
-rw-r--r--langpacks/english/Plugins/Clist_nicer.txt1
-rw-r--r--langpacks/english/Plugins/CloudFile.txt2
-rw-r--r--langpacks/english/Plugins/DbEditorPP.txt2
-rw-r--r--langpacks/english/Plugins/Fingerprint.txt8
-rw-r--r--langpacks/english/Plugins/GmailNotifier.txt7
-rw-r--r--langpacks/english/Plugins/IEView.txt1
-rw-r--r--langpacks/english/Plugins/MSN.txt2
-rw-r--r--langpacks/english/Plugins/New_GPG.txt97
-rw-r--r--langpacks/english/Plugins/QuickSearch.txt2
-rw-r--r--langpacks/english/Plugins/Quotes.txt2
-rw-r--r--langpacks/english/Plugins/SimpleStatusMsg.txt2
-rw-r--r--langpacks/english/Plugins/SmileyAdd.txt5
-rw-r--r--langpacks/english/Plugins/SplashScreen.txt1
-rw-r--r--langpacks/english/Plugins/StatusManager.txt2
-rw-r--r--langpacks/english/Plugins/Steam.txt2
-rw-r--r--langpacks/english/Plugins/StopSpam.txt8
-rw-r--r--langpacks/english/Plugins/StopSpamMod.txt2
-rw-r--r--langpacks/english/Plugins/TabSRMM.txt1
-rw-r--r--langpacks/english/Plugins/Tox.txt51
-rw-r--r--langpacks/english/Plugins/VKontakte.txt5
-rw-r--r--langpacks/english/Plugins/YAMN.txt1
-rw-r--r--langpacks/english/Plugins/mRadio.txt3
-rw-r--r--langpacks/english/Weather/Intellicast.txt2
-rw-r--r--langpacks/english/Weather/weatherxml.txt2
-rw-r--r--langpacks/english/Weather/wundergrnd_intl.txt2
-rw-r--r--langpacks/english/Weather/yweather.txt2
-rw-r--r--langpacks/english_gb/=CORE=.txt32
-rw-r--r--langpacks/english_gb/=HEAD=.txt2
-rw-r--r--langpacks/english_gb/Plugins/AIM.txt13
-rw-r--r--langpacks/english_gb/Plugins/AddContactPlus.txt2
-rw-r--r--langpacks/english_gb/Plugins/AsSingleWindow.txt9
-rw-r--r--langpacks/english_gb/Plugins/DbEditorPP.txt2
-rw-r--r--langpacks/english_gb/Plugins/MSN.txt2
-rw-r--r--langpacks/english_gb/Plugins/Ping.txt7
-rw-r--r--langpacks/english_gb/Plugins/SimpleStatusMsg.txt2
-rw-r--r--langpacks/english_gb/Plugins/SmileyAdd.txt2
-rw-r--r--langpacks/english_gb/Plugins/StatusManager.txt2
-rw-r--r--langpacks/english_gb/Plugins/Steam.txt2
-rw-r--r--langpacks/english_gb/Plugins/StopSpamMod.txt2
-rw-r--r--langpacks/english_gb/Plugins/Tox.txt2
-rw-r--r--langpacks/french/=CORE=.txt155
-rw-r--r--langpacks/french/=HEAD=.txt2
-rw-r--r--langpacks/french/Deprecated/AIM.txt (renamed from langpacks/french/Plugins/AIM.txt)0
-rw-r--r--langpacks/french/Plugins/AddContactPlus.txt2
-rw-r--r--langpacks/french/Plugins/AssocMgr.txt4
-rw-r--r--langpacks/french/Plugins/BASS_interface.txt14
-rw-r--r--langpacks/french/Plugins/BasicHistory.txt88
-rw-r--r--langpacks/french/Plugins/Clist_modern.txt2
-rw-r--r--langpacks/french/Plugins/Clist_nicer.txt2
-rw-r--r--langpacks/french/Plugins/CloudFile.txt2
-rw-r--r--langpacks/french/Plugins/DbEditorPP.txt2
-rw-r--r--langpacks/french/Plugins/Fingerprint.txt12
-rw-r--r--langpacks/french/Plugins/GmailNotifier.txt12
-rw-r--r--langpacks/french/Plugins/IEView.txt2
-rw-r--r--langpacks/french/Plugins/MSN.txt2
-rw-r--r--langpacks/french/Plugins/New_GPG.txt188
-rw-r--r--langpacks/french/Plugins/SimpleStatusMsg.txt2
-rw-r--r--langpacks/french/Plugins/SmileyAdd.txt8
-rw-r--r--langpacks/french/Plugins/SplashScreen.txt2
-rw-r--r--langpacks/french/Plugins/StatusManager.txt2
-rw-r--r--langpacks/french/Plugins/Steam.txt2
-rw-r--r--langpacks/french/Plugins/StopSpam.txt10
-rw-r--r--langpacks/french/Plugins/StopSpamMod.txt2
-rw-r--r--langpacks/french/Plugins/TabSRMM.txt2
-rw-r--r--langpacks/french/Plugins/Tox.txt2
-rw-r--r--langpacks/french/Plugins/mRadio.txt4
-rw-r--r--langpacks/french/Untranslated/=CORE=.txt16
-rw-r--r--langpacks/french/Untranslated/AIM.txt118
-rw-r--r--langpacks/french/Untranslated/BASS_interface.txt11
-rw-r--r--langpacks/french/Untranslated/BasicHistory.txt68
-rw-r--r--langpacks/french/Untranslated/Clist_modern.txt1
-rw-r--r--langpacks/french/Untranslated/Clist_nicer.txt1
-rw-r--r--langpacks/french/Untranslated/Fingerprint.txt6
-rw-r--r--langpacks/french/Untranslated/GmailNotifier.txt5
-rw-r--r--langpacks/french/Untranslated/IEView.txt1
-rw-r--r--langpacks/french/Untranslated/New_GPG.txt71
-rw-r--r--langpacks/french/Untranslated/SplashScreen.txt1
-rw-r--r--langpacks/french/Untranslated/TabSRMM.txt1
-rw-r--r--langpacks/french/Untranslated/mRadio.txt3
-rw-r--r--langpacks/german/=CORE=.txt155
-rw-r--r--langpacks/german/=HEAD=.txt2
-rw-r--r--langpacks/german/Deprecated/AIM.txt (renamed from langpacks/german/Plugins/AIM.txt)0
-rw-r--r--langpacks/german/Plugins/AddContactPlus.txt2
-rw-r--r--langpacks/german/Plugins/AssocMgr.txt4
-rw-r--r--langpacks/german/Plugins/BASS_interface.txt28
-rw-r--r--langpacks/german/Plugins/BasicHistory.txt90
-rw-r--r--langpacks/german/Plugins/Clist_modern.txt2
-rw-r--r--langpacks/german/Plugins/Clist_nicer.txt2
-rw-r--r--langpacks/german/Plugins/CloudFile.txt2
-rw-r--r--langpacks/german/Plugins/DbEditorPP.txt2
-rw-r--r--langpacks/german/Plugins/Fingerprint.txt12
-rw-r--r--langpacks/german/Plugins/GmailNotifier.txt12
-rw-r--r--langpacks/german/Plugins/IEView.txt2
-rw-r--r--langpacks/german/Plugins/MSN.txt2
-rw-r--r--langpacks/german/Plugins/New_GPG.txt192
-rw-r--r--langpacks/german/Plugins/SimpleStatusMsg.txt2
-rw-r--r--langpacks/german/Plugins/SmileyAdd.txt8
-rw-r--r--langpacks/german/Plugins/SplashScreen.txt2
-rw-r--r--langpacks/german/Plugins/StatusManager.txt2
-rw-r--r--langpacks/german/Plugins/Steam.txt2
-rw-r--r--langpacks/german/Plugins/StopSpam.txt14
-rw-r--r--langpacks/german/Plugins/StopSpamMod.txt2
-rw-r--r--langpacks/german/Plugins/TabSRMM.txt2
-rw-r--r--langpacks/german/Plugins/Tox.txt2
-rw-r--r--langpacks/german/Plugins/mRadio.txt8
-rw-r--r--langpacks/german/Untranslated/GmailNotifier.txt1
-rw-r--r--langpacks/german/Untranslated/IEView.txt1
-rw-r--r--langpacks/german/Untranslated/New_GPG.txt1
-rw-r--r--langpacks/german/Untranslated/SplashScreen.txt1
-rw-r--r--langpacks/polish/=CORE=.txt155
-rw-r--r--langpacks/polish/=HEAD=.txt2
-rw-r--r--langpacks/polish/Deprecated/AIM.txt (renamed from langpacks/polish/Plugins/AIM.txt)0
-rw-r--r--langpacks/polish/Plugins/AddContactPlus.txt2
-rw-r--r--langpacks/polish/Plugins/AssocMgr.txt4
-rw-r--r--langpacks/polish/Plugins/BASS_interface.txt22
-rw-r--r--langpacks/polish/Plugins/BasicHistory.txt94
-rw-r--r--langpacks/polish/Plugins/Clist_modern.txt2
-rw-r--r--langpacks/polish/Plugins/Clist_nicer.txt2
-rw-r--r--langpacks/polish/Plugins/CloudFile.txt2
-rw-r--r--langpacks/polish/Plugins/DbEditorPP.txt2
-rw-r--r--langpacks/polish/Plugins/Fingerprint.txt12
-rw-r--r--langpacks/polish/Plugins/GmailNotifier.txt12
-rw-r--r--langpacks/polish/Plugins/IEView.txt2
-rw-r--r--langpacks/polish/Plugins/MSN.txt2
-rw-r--r--langpacks/polish/Plugins/New_GPG.txt192
-rw-r--r--langpacks/polish/Plugins/SimpleStatusMsg.txt2
-rw-r--r--langpacks/polish/Plugins/SmileyAdd.txt8
-rw-r--r--langpacks/polish/Plugins/SplashScreen.txt2
-rw-r--r--langpacks/polish/Plugins/StatusManager.txt2
-rw-r--r--langpacks/polish/Plugins/Steam.txt2
-rw-r--r--langpacks/polish/Plugins/StopSpam.txt14
-rw-r--r--langpacks/polish/Plugins/StopSpamMod.txt2
-rw-r--r--langpacks/polish/Plugins/TabSRMM.txt2
-rw-r--r--langpacks/polish/Plugins/Tox.txt2
-rw-r--r--langpacks/polish/Plugins/mRadio.txt6
-rw-r--r--langpacks/polish/Untranslated/GmailNotifier.txt1
-rw-r--r--langpacks/polish/Untranslated/IEView.txt1
-rw-r--r--langpacks/polish/Untranslated/New_GPG.txt1
-rw-r--r--langpacks/polish/Untranslated/SplashScreen.txt1
-rw-r--r--langpacks/polish/Untranslated/mRadio.txt1
-rw-r--r--langpacks/russian/=CORE=.txt146
-rw-r--r--langpacks/russian/=HEAD=.txt2
-rw-r--r--langpacks/russian/Deprecated/AIM.txt (renamed from langpacks/russian/Plugins/AIM.txt)0
-rw-r--r--langpacks/russian/Plugins/AddContactPlus.txt2
-rw-r--r--langpacks/russian/Plugins/AssocMgr.txt4
-rw-r--r--langpacks/russian/Plugins/BASS_interface.txt18
-rw-r--r--langpacks/russian/Plugins/BasicHistory.txt92
-rw-r--r--langpacks/russian/Plugins/Clist_modern.txt2
-rw-r--r--langpacks/russian/Plugins/Clist_nicer.txt2
-rw-r--r--langpacks/russian/Plugins/CloudFile.txt2
-rw-r--r--langpacks/russian/Plugins/DbEditorPP.txt2
-rw-r--r--langpacks/russian/Plugins/Fingerprint.txt12
-rw-r--r--langpacks/russian/Plugins/GmailNotifier.txt10
-rw-r--r--langpacks/russian/Plugins/IEView.txt2
-rw-r--r--langpacks/russian/Plugins/MSN.txt2
-rw-r--r--langpacks/russian/Plugins/New_GPG.txt184
-rw-r--r--langpacks/russian/Plugins/SimpleStatusMsg.txt2
-rw-r--r--langpacks/russian/Plugins/SmileyAdd.txt8
-rw-r--r--langpacks/russian/Plugins/SplashScreen.txt2
-rw-r--r--langpacks/russian/Plugins/StatusManager.txt2
-rw-r--r--langpacks/russian/Plugins/Steam.txt2
-rw-r--r--langpacks/russian/Plugins/StopSpam.txt6
-rw-r--r--langpacks/russian/Plugins/StopSpamMod.txt6
-rw-r--r--langpacks/russian/Plugins/TabSRMM.txt2
-rw-r--r--langpacks/russian/Plugins/Tox.txt2
-rw-r--r--langpacks/russian/Plugins/VKontakte.txt2
-rw-r--r--langpacks/russian/Plugins/mRadio.txt6
-rw-r--r--langpacks/russian/Untranslated/AIM.txt40
-rw-r--r--langpacks/russian/Untranslated/GmailNotifier.txt1
-rw-r--r--langpacks/russian/Untranslated/New_GPG.txt3
-rw-r--r--langpacks/serbian/=CORE=.txt155
-rw-r--r--langpacks/serbian/=HEAD=.txt2
-rw-r--r--langpacks/serbian/Plugins/AIM.txt426
-rw-r--r--langpacks/serbian/Plugins/AddContactPlus.txt2
-rw-r--r--langpacks/serbian/Plugins/AssocMgr.txt2
-rw-r--r--langpacks/serbian/Plugins/BASS_interface.txt14
-rw-r--r--langpacks/serbian/Plugins/BasicHistory.txt88
-rw-r--r--langpacks/serbian/Plugins/Clist_modern.txt2
-rw-r--r--langpacks/serbian/Plugins/Clist_nicer.txt2
-rw-r--r--langpacks/serbian/Plugins/CloudFile.txt2
-rw-r--r--langpacks/serbian/Plugins/DbEditorPP.txt2
-rw-r--r--langpacks/serbian/Plugins/Fingerprint.txt12
-rw-r--r--langpacks/serbian/Plugins/GmailNotifier.txt12
-rw-r--r--langpacks/serbian/Plugins/IEView.txt2
-rw-r--r--langpacks/serbian/Plugins/MSN.txt2
-rw-r--r--langpacks/serbian/Plugins/New_GPG.txt188
-rw-r--r--langpacks/serbian/Plugins/SimpleStatusMsg.txt2
-rw-r--r--langpacks/serbian/Plugins/SmileyAdd.txt8
-rw-r--r--langpacks/serbian/Plugins/SplashScreen.txt2
-rw-r--r--langpacks/serbian/Plugins/StatusManager.txt2
-rw-r--r--langpacks/serbian/Plugins/Steam.txt2
-rw-r--r--langpacks/serbian/Plugins/StopSpam.txt10
-rw-r--r--langpacks/serbian/Plugins/StopSpamMod.txt2
-rw-r--r--langpacks/serbian/Plugins/TabSRMM.txt2
-rw-r--r--langpacks/serbian/Plugins/Tox.txt2
-rw-r--r--langpacks/serbian/Plugins/mRadio.txt4
-rw-r--r--langpacks/serbian/Untranslated/=CORE=.txt1
-rw-r--r--langpacks/serbian/Untranslated/AIM.txt188
-rw-r--r--langpacks/serbian/Untranslated/AssocMgr.txt2
-rw-r--r--langpacks/serbian/Untranslated/BASS_interface.txt11
-rw-r--r--langpacks/serbian/Untranslated/BasicHistory.txt78
-rw-r--r--langpacks/serbian/Untranslated/Clist_modern.txt1
-rw-r--r--langpacks/serbian/Untranslated/Clist_nicer.txt1
-rw-r--r--langpacks/serbian/Untranslated/Fingerprint.txt6
-rw-r--r--langpacks/serbian/Untranslated/GmailNotifier.txt5
-rw-r--r--langpacks/serbian/Untranslated/IEView.txt1
-rw-r--r--langpacks/serbian/Untranslated/New_GPG.txt81
-rw-r--r--langpacks/serbian/Untranslated/SmileyAdd.txt3
-rw-r--r--langpacks/serbian/Untranslated/SplashScreen.txt1
-rw-r--r--langpacks/serbian/Untranslated/TabSRMM.txt1
-rw-r--r--langpacks/serbian/Untranslated/mRadio.txt3
-rw-r--r--langpacks/spanish/=CORE=.txt144
-rw-r--r--langpacks/spanish/=HEAD=.txt2
-rw-r--r--langpacks/spanish/Plugins/AIM.txt53
-rw-r--r--langpacks/spanish/Plugins/AddContactPlus.txt2
-rw-r--r--langpacks/spanish/Plugins/BASS_interface.txt26
-rw-r--r--langpacks/spanish/Plugins/BasicHistory.txt12
-rw-r--r--langpacks/spanish/Plugins/CloudFile.txt10
-rw-r--r--langpacks/spanish/Plugins/DbEditorPP.txt2
-rw-r--r--langpacks/spanish/Plugins/GmailNotifier.txt2
-rw-r--r--langpacks/spanish/Plugins/MRA.txt6
-rw-r--r--langpacks/spanish/Plugins/MSN.txt2
-rw-r--r--langpacks/spanish/Plugins/New_GPG.txt24
-rw-r--r--langpacks/spanish/Plugins/SimpleStatusMsg.txt2
-rw-r--r--langpacks/spanish/Plugins/SmileyAdd.txt2
-rw-r--r--langpacks/spanish/Plugins/StatusManager.txt2
-rw-r--r--langpacks/spanish/Plugins/Steam.txt2
-rw-r--r--langpacks/spanish/Plugins/StopSpam.txt2
-rw-r--r--langpacks/spanish/Plugins/StopSpamMod.txt2
-rw-r--r--langpacks/spanish/Plugins/Tox.txt2
-rw-r--r--langpacks/spanish/Untranslated/=CORE=.txt1
-rw-r--r--langpacks/spanish/Untranslated/AIM.txt181
-rw-r--r--langpacks/spanish/Untranslated/AssocMgr.txt2
-rw-r--r--langpacks/spanish/Untranslated/BasicHistory.txt76
-rw-r--r--langpacks/spanish/Untranslated/Clist_modern.txt1
-rw-r--r--langpacks/spanish/Untranslated/Clist_nicer.txt1
-rw-r--r--langpacks/spanish/Untranslated/CloudFile.txt4
-rw-r--r--langpacks/spanish/Untranslated/Fingerprint.txt6
-rw-r--r--langpacks/spanish/Untranslated/GmailNotifier.txt5
-rw-r--r--langpacks/spanish/Untranslated/IEView.txt1
-rw-r--r--langpacks/spanish/Untranslated/MRA.txt3
-rw-r--r--langpacks/spanish/Untranslated/New_GPG.txt73
-rw-r--r--langpacks/spanish/Untranslated/SmileyAdd.txt3
-rw-r--r--langpacks/spanish/Untranslated/SplashScreen.txt1
-rw-r--r--langpacks/spanish/Untranslated/TabSRMM.txt1
-rw-r--r--langpacks/spanish/Untranslated/mRadio.txt3
-rw-r--r--langpacks/ukrainian/=CORE=.txt146
-rw-r--r--langpacks/ukrainian/=HEAD=.txt2
-rw-r--r--langpacks/ukrainian/Deprecated/AIM.txt (renamed from langpacks/ukrainian/Plugins/AIM.txt)0
-rw-r--r--langpacks/ukrainian/Plugins/AddContactPlus.txt2
-rw-r--r--langpacks/ukrainian/Plugins/AssocMgr.txt4
-rw-r--r--langpacks/ukrainian/Plugins/BASS_interface.txt14
-rw-r--r--langpacks/ukrainian/Plugins/BasicHistory.txt88
-rw-r--r--langpacks/ukrainian/Plugins/Clist_modern.txt2
-rw-r--r--langpacks/ukrainian/Plugins/Clist_nicer.txt2
-rw-r--r--langpacks/ukrainian/Plugins/CloudFile.txt2
-rw-r--r--langpacks/ukrainian/Plugins/DbEditorPP.txt2
-rw-r--r--langpacks/ukrainian/Plugins/Fingerprint.txt12
-rw-r--r--langpacks/ukrainian/Plugins/GmailNotifier.txt10
-rw-r--r--langpacks/ukrainian/Plugins/MSN.txt2
-rw-r--r--langpacks/ukrainian/Plugins/New_GPG.txt136
-rw-r--r--langpacks/ukrainian/Plugins/QuickSearch.txt2
-rw-r--r--langpacks/ukrainian/Plugins/SimpleStatusMsg.txt2
-rw-r--r--langpacks/ukrainian/Plugins/SmileyAdd.txt8
-rw-r--r--langpacks/ukrainian/Plugins/StatusManager.txt2
-rw-r--r--langpacks/ukrainian/Plugins/Steam.txt2
-rw-r--r--langpacks/ukrainian/Plugins/StopSpam.txt6
-rw-r--r--langpacks/ukrainian/Plugins/StopSpamMod.txt2
-rw-r--r--langpacks/ukrainian/Plugins/TabSRMM.txt2
-rw-r--r--langpacks/ukrainian/Plugins/Tox.txt2
-rw-r--r--langpacks/ukrainian/Plugins/mRadio.txt4
-rw-r--r--langpacks/ukrainian/Untranslated/AIM.txt53
-rw-r--r--langpacks/ukrainian/Untranslated/GmailNotifier.txt1
-rw-r--r--langpacks/ukrainian/Untranslated/IEView.txt1
-rw-r--r--langpacks/ukrainian/Untranslated/New_GPG.txt27
-rw-r--r--langpacks/ukrainian/Untranslated/SplashScreen.txt1
-rw-r--r--langpacks/ukrainian/Untranslated/mRadio.txt1
-rw-r--r--langpacks/ukrainian/Weather/Intellicast.txt2
-rw-r--r--langpacks/ukrainian/Weather/weatherxml.txt2
-rw-r--r--langpacks/ukrainian/Weather/wundergrnd_intl.txt2
-rw-r--r--langpacks/ukrainian/Weather/yweather.txt2
-rw-r--r--libs/libjson/src/libjson.def7
-rw-r--r--libs/libjson/src/libjson64.def7
-rw-r--r--libs/libjson/src/stdafx.cxx48
-rw-r--r--libs/libsodium/docs/AUTHORS135
-rw-r--r--libs/libsodium/docs/ChangeLog505
-rw-r--r--libs/libsodium/docs/LICENSE18
-rw-r--r--libs/libsodium/docs/README.markdown46
-rw-r--r--libs/libsodium/docs/THANKS91
-rw-r--r--libs/libsodium/libsodium.vcxproj493
-rw-r--r--libs/libsodium/libsodium.vcxproj.filters (renamed from protocols/AimOscar/aim.vcxproj.filters)8
-rw-r--r--libs/libsodium/src/crypto_aead/aes256gcm/aesni/aead_aes256gcm_aesni.c1079
-rw-r--r--libs/libsodium/src/crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c399
-rw-r--r--libs/libsodium/src/crypto_aead/xchacha20poly1305/sodium/aead_xchacha20poly1305.c160
-rw-r--r--libs/libsodium/src/crypto_auth/crypto_auth.c41
-rw-r--r--libs/libsodium/src/crypto_auth/hmacsha256/auth_hmacsha256.c118
-rw-r--r--libs/libsodium/src/crypto_auth/hmacsha512/auth_hmacsha512.c118
-rw-r--r--libs/libsodium/src/crypto_auth/hmacsha512256/auth_hmacsha512256.c93
-rw-r--r--libs/libsodium/src/crypto_box/crypto_box.c114
-rw-r--r--libs/libsodium/src/crypto_box/crypto_box_easy.c115
-rw-r--r--libs/libsodium/src/crypto_box/crypto_box_seal.c68
-rw-r--r--libs/libsodium/src/crypto_box/curve25519xchacha20poly1305/box_curve25519xchacha20poly1305.c204
-rw-r--r--libs/libsodium/src/crypto_box/curve25519xchacha20poly1305/box_seal_curve25519xchacha20poly1305.c79
-rw-r--r--libs/libsodium/src/crypto_box/curve25519xsalsa20poly1305/box_curve25519xsalsa20poly1305.c156
-rw-r--r--libs/libsodium/src/crypto_core/ed25519/core_ed25519.c79
-rw-r--r--libs/libsodium/src/crypto_core/ed25519/ref10/ed25519_ref10.c2031
-rw-r--r--libs/libsodium/src/crypto_core/ed25519/ref10/fe_25_5/base.h1344
-rw-r--r--libs/libsodium/src/crypto_core/ed25519/ref10/fe_25_5/base2.h40
-rw-r--r--libs/libsodium/src/crypto_core/ed25519/ref10/fe_25_5/constants.h20
-rw-r--r--libs/libsodium/src/crypto_core/ed25519/ref10/fe_25_5/fe.h220
-rw-r--r--libs/libsodium/src/crypto_core/ed25519/ref10/fe_51/base.h1344
-rw-r--r--libs/libsodium/src/crypto_core/ed25519/ref10/fe_51/base2.h40
-rw-r--r--libs/libsodium/src/crypto_core/ed25519/ref10/fe_51/constants.h21
-rw-r--r--libs/libsodium/src/crypto_core/ed25519/ref10/fe_51/fe.h116
-rw-r--r--libs/libsodium/src/crypto_core/hchacha20/core_hchacha20.c93
-rw-r--r--libs/libsodium/src/crypto_core/hsalsa20/core_hsalsa20.c21
-rw-r--r--libs/libsodium/src/crypto_core/hsalsa20/ref2/core_hsalsa20_ref2.c95
-rw-r--r--libs/libsodium/src/crypto_core/salsa/ref/core_salsa_ref.c195
-rw-r--r--libs/libsodium/src/crypto_generichash/blake2b/generichash_blake2.c55
-rw-r--r--libs/libsodium/src/crypto_generichash/blake2b/ref/blake2.h109
-rw-r--r--libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-avx2.c49
-rw-r--r--libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-avx2.h140
-rw-r--r--libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-ref.c93
-rw-r--r--libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-sse41.c87
-rw-r--r--libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-sse41.h103
-rw-r--r--libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-ssse3.c90
-rw-r--r--libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-ssse3.h103
-rw-r--r--libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-load-avx2.h340
-rw-r--r--libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-load-sse2.h164
-rw-r--r--libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-load-sse41.h307
-rw-r--r--libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-ref.c436
-rw-r--r--libs/libsodium/src/crypto_generichash/blake2b/ref/generichash_blake2b.c111
-rw-r--r--libs/libsodium/src/crypto_generichash/crypto_generichash.c91
-rw-r--r--libs/libsodium/src/crypto_hash/crypto_hash.c20
-rw-r--r--libs/libsodium/src/crypto_hash/sha256/cp/hash_sha256_cp.c254
-rw-r--r--libs/libsodium/src/crypto_hash/sha256/hash_sha256.c13
-rw-r--r--libs/libsodium/src/crypto_hash/sha512/cp/hash_sha512_cp.c282
-rw-r--r--libs/libsodium/src/crypto_hash/sha512/hash_sha512.c13
-rw-r--r--libs/libsodium/src/crypto_kdf/blake2b/kdf_blake2b.c52
-rw-r--r--libs/libsodium/src/crypto_kdf/crypto_kdf.c49
-rw-r--r--libs/libsodium/src/crypto_kx/crypto_kx.c143
-rw-r--r--libs/libsodium/src/crypto_onetimeauth/crypto_onetimeauth.c71
-rw-r--r--libs/libsodium/src/crypto_onetimeauth/poly1305/donna/poly1305_donna.c124
-rw-r--r--libs/libsodium/src/crypto_onetimeauth/poly1305/donna/poly1305_donna.h12
-rw-r--r--libs/libsodium/src/crypto_onetimeauth/poly1305/donna/poly1305_donna32.h235
-rw-r--r--libs/libsodium/src/crypto_onetimeauth/poly1305/donna/poly1305_donna64.h220
-rw-r--r--libs/libsodium/src/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c90
-rw-r--r--libs/libsodium/src/crypto_onetimeauth/poly1305/onetimeauth_poly1305.h21
-rw-r--r--libs/libsodium/src/crypto_onetimeauth/poly1305/sse2/poly1305_sse2.c949
-rw-r--r--libs/libsodium/src/crypto_onetimeauth/poly1305/sse2/poly1305_sse2.h12
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2-core.c549
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2-core.h297
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2-encoding.c305
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2-encoding.h33
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-avx2.c239
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-avx512f.c244
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-ref.c233
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-ssse3.c238
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2.c277
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/argon2.h305
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/blake2b-long.c79
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/blake2b-long.h8
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/blamka-round-avx2.h150
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/blamka-round-avx512f.h145
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/blamka-round-ref.h40
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/blamka-round-ssse3.h120
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/pwhash_argon2i.c290
-rw-r--r--libs/libsodium/src/crypto_pwhash/argon2/pwhash_argon2id.c234
-rw-r--r--libs/libsodium/src/crypto_pwhash/crypto_pwhash.c211
-rw-r--r--libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt-common.c263
-rw-r--r--libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt.h98
-rw-r--r--libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c375
-rw-r--r--libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.c95
-rw-r--r--libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.h45
-rw-r--r--libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c285
-rw-r--r--libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/scrypt_platform.c108
-rw-r--r--libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c400
-rw-r--r--libs/libsodium/src/crypto_scalarmult/crypto_scalarmult.c33
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/ref10/x25519_ref10.c159
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/ref10/x25519_ref10.h10
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/consts.S25
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/consts_namespace.h20
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/curve25519_sandy2x.c114
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/curve25519_sandy2x.h9
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe.h26
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51.h35
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_invert.c58
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_mul.S197
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_namespace.h16
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_nsquare.S172
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_pack.S226
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe_frombytes_sandy2x.c78
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder.S1440
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder.h18
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder_base.S1295
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder_base.h18
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder_base_namespace.h8
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder_namespace.h8
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/sandy2x.S17
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/scalarmult_curve25519.c59
-rw-r--r--libs/libsodium/src/crypto_scalarmult/curve25519/scalarmult_curve25519.h11
-rw-r--r--libs/libsodium/src/crypto_scalarmult/ed25519/ref10/scalarmult_ed25519_ref10.c86
-rw-r--r--libs/libsodium/src/crypto_secretbox/crypto_secretbox.c67
-rw-r--r--libs/libsodium/src/crypto_secretbox/crypto_secretbox_easy.c144
-rw-r--r--libs/libsodium/src/crypto_secretbox/xchacha20poly1305/secretbox_xchacha20poly1305.c177
-rw-r--r--libs/libsodium/src/crypto_secretbox/xsalsa20poly1305/secretbox_xsalsa20poly1305.c89
-rw-r--r--libs/libsodium/src/crypto_secretstream/xchacha20poly1305/secretstream_xchacha20poly1305.c311
-rw-r--r--libs/libsodium/src/crypto_shorthash/crypto_shorthash.c34
-rw-r--r--libs/libsodium/src/crypto_shorthash/siphash24/ref/shorthash_siphash24_ref.c65
-rw-r--r--libs/libsodium/src/crypto_shorthash/siphash24/ref/shorthash_siphash_ref.h24
-rw-r--r--libs/libsodium/src/crypto_shorthash/siphash24/ref/shorthash_siphashx24_ref.c71
-rw-r--r--libs/libsodium/src/crypto_shorthash/siphash24/shorthash_siphash24.c11
-rw-r--r--libs/libsodium/src/crypto_shorthash/siphash24/shorthash_siphashx24.c11
-rw-r--r--libs/libsodium/src/crypto_sign/crypto_sign.c115
-rw-r--r--libs/libsodium/src/crypto_sign/ed25519/ref10/keypair.c91
-rw-r--r--libs/libsodium/src/crypto_sign/ed25519/ref10/obsolete.c116
-rw-r--r--libs/libsodium/src/crypto_sign/ed25519/ref10/open.c93
-rw-r--r--libs/libsodium/src/crypto_sign/ed25519/ref10/sign.c144
-rw-r--r--libs/libsodium/src/crypto_sign/ed25519/ref10/sign_ed25519_ref10.h18
-rw-r--r--libs/libsodium/src/crypto_sign/ed25519/sign_ed25519.c97
-rw-r--r--libs/libsodium/src/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-avx2.c180
-rw-r--r--libs/libsodium/src/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-avx2.h8
-rw-r--r--libs/libsodium/src/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-ssse3.c174
-rw-r--r--libs/libsodium/src/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-ssse3.h8
-rw-r--r--libs/libsodium/src/crypto_stream/chacha20/dolbeau/u0.h86
-rw-r--r--libs/libsodium/src/crypto_stream/chacha20/dolbeau/u1.h98
-rw-r--r--libs/libsodium/src/crypto_stream/chacha20/dolbeau/u4.h175
-rw-r--r--libs/libsodium/src/crypto_stream/chacha20/dolbeau/u8.h357
-rw-r--r--libs/libsodium/src/crypto_stream/chacha20/ref/chacha20_ref.c315
-rw-r--r--libs/libsodium/src/crypto_stream/chacha20/ref/chacha20_ref.h8
-rw-r--r--libs/libsodium/src/crypto_stream/chacha20/stream_chacha20.c130
-rw-r--r--libs/libsodium/src/crypto_stream/chacha20/stream_chacha20.h22
-rw-r--r--libs/libsodium/src/crypto_stream/crypto_stream.c49
-rw-r--r--libs/libsodium/src/crypto_stream/salsa20/ref/salsa20_ref.c120
-rw-r--r--libs/libsodium/src/crypto_stream/salsa20/ref/salsa20_ref.h8
-rw-r--r--libs/libsodium/src/crypto_stream/salsa20/stream_salsa20.c100
-rw-r--r--libs/libsodium/src/crypto_stream/salsa20/stream_salsa20.h16
-rw-r--r--libs/libsodium/src/crypto_stream/salsa20/xmm6/salsa20_xmm6-asm.S960
-rw-r--r--libs/libsodium/src/crypto_stream/salsa20/xmm6/salsa20_xmm6.c31
-rw-r--r--libs/libsodium/src/crypto_stream/salsa20/xmm6/salsa20_xmm6.h8
-rw-r--r--libs/libsodium/src/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-avx2.c131
-rw-r--r--libs/libsodium/src/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-avx2.h8
-rw-r--r--libs/libsodium/src/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-sse2.c122
-rw-r--r--libs/libsodium/src/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-sse2.h8
-rw-r--r--libs/libsodium/src/crypto_stream/salsa20/xmm6int/u0.h195
-rw-r--r--libs/libsodium/src/crypto_stream/salsa20/xmm6int/u1.h207
-rw-r--r--libs/libsodium/src/crypto_stream/salsa20/xmm6int/u4.h547
-rw-r--r--libs/libsodium/src/crypto_stream/salsa20/xmm6int/u8.h476
-rw-r--r--libs/libsodium/src/crypto_stream/salsa2012/ref/stream_salsa2012_ref.c106
-rw-r--r--libs/libsodium/src/crypto_stream/salsa2012/stream_salsa2012.c26
-rw-r--r--libs/libsodium/src/crypto_stream/salsa208/ref/stream_salsa208_ref.c106
-rw-r--r--libs/libsodium/src/crypto_stream/salsa208/stream_salsa208.c26
-rw-r--r--libs/libsodium/src/crypto_stream/xchacha20/stream_xchacha20.c69
-rw-r--r--libs/libsodium/src/crypto_stream/xsalsa20/stream_xsalsa20.c66
-rw-r--r--libs/libsodium/src/crypto_verify/sodium/verify.c98
-rw-r--r--libs/libsodium/src/include/Makefile.am75
-rw-r--r--libs/libsodium/src/include/sodium.h70
-rw-r--r--libs/libsodium/src/include/sodium/core.h28
-rw-r--r--libs/libsodium/src/include/sodium/crypto_aead_aes256gcm.h171
-rw-r--r--libs/libsodium/src/include/sodium/crypto_aead_chacha20poly1305.h174
-rw-r--r--libs/libsodium/src/include/sodium/crypto_aead_xchacha20poly1305.h97
-rw-r--r--libs/libsodium/src/include/sodium/crypto_auth.h44
-rw-r--r--libs/libsodium/src/include/sodium/crypto_auth_hmacsha256.h68
-rw-r--r--libs/libsodium/src/include/sodium/crypto_auth_hmacsha512.h67
-rw-r--r--libs/libsodium/src/include/sodium/crypto_auth_hmacsha512256.h62
-rw-r--r--libs/libsodium/src/include/sodium/crypto_box.h173
-rw-r--r--libs/libsodium/src/include/sodium/crypto_box_curve25519xchacha20poly1305.h159
-rw-r--r--libs/libsodium/src/include/sodium/crypto_box_curve25519xsalsa20poly1305.h109
-rw-r--r--libs/libsodium/src/include/sodium/crypto_core_ed25519.h37
-rw-r--r--libs/libsodium/src/include/sodium/crypto_core_hchacha20.h35
-rw-r--r--libs/libsodium/src/include/sodium/crypto_core_hsalsa20.h35
-rw-r--r--libs/libsodium/src/include/sodium/crypto_core_salsa20.h35
-rw-r--r--libs/libsodium/src/include/sodium/crypto_core_salsa2012.h35
-rw-r--r--libs/libsodium/src/include/sodium/crypto_core_salsa208.h39
-rw-r--r--libs/libsodium/src/include/sodium/crypto_generichash.h75
-rw-r--r--libs/libsodium/src/include/sodium/crypto_generichash_blake2b.h117
-rw-r--r--libs/libsodium/src/include/sodium/crypto_hash.h40
-rw-r--r--libs/libsodium/src/include/sodium/crypto_hash_sha256.h57
-rw-r--r--libs/libsodium/src/include/sodium/crypto_hash_sha512.h57
-rw-r--r--libs/libsodium/src/include/sodium/crypto_kdf.h51
-rw-r--r--libs/libsodium/src/include/sodium/crypto_kdf_blake2b.h42
-rw-r--r--libs/libsodium/src/include/sodium/crypto_kx.h64
-rw-r--r--libs/libsodium/src/include/sodium/crypto_onetimeauth.h62
-rw-r--r--libs/libsodium/src/include/sodium/crypto_onetimeauth_poly1305.h67
-rw-r--r--libs/libsodium/src/include/sodium/crypto_pwhash.h147
-rw-r--r--libs/libsodium/src/include/sodium/crypto_pwhash_argon2i.h122
-rw-r--r--libs/libsodium/src/include/sodium/crypto_pwhash_argon2id.h122
-rw-r--r--libs/libsodium/src/include/sodium/crypto_pwhash_scryptsalsa208sha256.h120
-rw-r--r--libs/libsodium/src/include/sodium/crypto_scalarmult.h45
-rw-r--r--libs/libsodium/src/include/sodium/crypto_scalarmult_curve25519.h40
-rw-r--r--libs/libsodium/src/include/sodium/crypto_scalarmult_ed25519.h41
-rw-r--r--libs/libsodium/src/include/sodium/crypto_secretbox.h91
-rw-r--r--libs/libsodium/src/include/sodium/crypto_secretbox_xchacha20poly1305.h68
-rw-r--r--libs/libsodium/src/include/sodium/crypto_secretbox_xsalsa20poly1305.h67
-rw-r--r--libs/libsodium/src/include/sodium/crypto_secretstream_xchacha20poly1305.h102
-rw-r--r--libs/libsodium/src/include/sodium/crypto_shorthash.h39
-rw-r--r--libs/libsodium/src/include/sodium/crypto_shorthash_siphash24.h48
-rw-r--r--libs/libsodium/src/include/sodium/crypto_sign.h103
-rw-r--r--libs/libsodium/src/include/sodium/crypto_sign_ed25519.h114
-rw-r--r--libs/libsodium/src/include/sodium/crypto_sign_edwards25519sha512batch.h55
-rw-r--r--libs/libsodium/src/include/sodium/crypto_stream.h56
-rw-r--r--libs/libsodium/src/include/sodium/crypto_stream_chacha20.h98
-rw-r--r--libs/libsodium/src/include/sodium/crypto_stream_salsa20.h57
-rw-r--r--libs/libsodium/src/include/sodium/crypto_stream_salsa2012.h50
-rw-r--r--libs/libsodium/src/include/sodium/crypto_stream_salsa208.h56
-rw-r--r--libs/libsodium/src/include/sodium/crypto_stream_xchacha20.h57
-rw-r--r--libs/libsodium/src/include/sodium/crypto_stream_xsalsa20.h57
-rw-r--r--libs/libsodium/src/include/sodium/crypto_verify_16.h23
-rw-r--r--libs/libsodium/src/include/sodium/crypto_verify_32.h23
-rw-r--r--libs/libsodium/src/include/sodium/crypto_verify_64.h23
-rw-r--r--libs/libsodium/src/include/sodium/export.h53
-rw-r--r--libs/libsodium/src/include/sodium/private/common.h246
-rw-r--r--libs/libsodium/src/include/sodium/private/ed25519_ref10.h125
-rw-r--r--libs/libsodium/src/include/sodium/private/ed25519_ref10_fe_25_5.h1050
-rw-r--r--libs/libsodium/src/include/sodium/private/ed25519_ref10_fe_51.h518
-rw-r--r--libs/libsodium/src/include/sodium/private/implementations.h11
-rw-r--r--libs/libsodium/src/include/sodium/private/mutex.h7
-rw-r--r--libs/libsodium/src/include/sodium/private/sse2_64_32.h50
-rw-r--r--libs/libsodium/src/include/sodium/randombytes.h68
-rw-r--r--libs/libsodium/src/include/sodium/randombytes_nativeclient.h23
-rw-r--r--libs/libsodium/src/include/sodium/randombytes_salsa20_random.h19
-rw-r--r--libs/libsodium/src/include/sodium/randombytes_sysrandom.h19
-rw-r--r--libs/libsodium/src/include/sodium/runtime.h52
-rw-r--r--libs/libsodium/src/include/sodium/utils.h170
-rw-r--r--libs/libsodium/src/include/sodium/version.h32
-rw-r--r--libs/libsodium/src/randombytes/nativeclient/randombytes_nativeclient.c61
-rw-r--r--libs/libsodium/src/randombytes/randombytes.c206
-rw-r--r--libs/libsodium/src/randombytes/salsa20/randombytes_salsa20_random.c564
-rw-r--r--libs/libsodium/src/randombytes/sysrandom/randombytes_sysrandom.c382
-rw-r--r--libs/libsodium/src/sodium/codecs.c333
-rw-r--r--libs/libsodium/src/sodium/core.c231
-rw-r--r--libs/libsodium/src/sodium/runtime.c286
-rw-r--r--libs/libsodium/src/sodium/utils.c737
-rw-r--r--libs/libsodium/src/sodium/version.c30
-rw-r--r--libs/libsodium/src/stdafx.cxx2
-rw-r--r--libs/libsodium/src/stdafx.h0
-rw-r--r--libs/pthreads/docs/ANNOUNCE483
-rw-r--r--libs/pthreads/docs/BUGS141
-rw-r--r--libs/pthreads/docs/Bmakefile268
-rw-r--r--libs/pthreads/docs/CONTRIBUTORS140
-rw-r--r--libs/pthreads/docs/COPYING150
-rw-r--r--libs/pthreads/docs/ChangeLog5211
-rw-r--r--libs/pthreads/docs/FAQ451
-rw-r--r--libs/pthreads/docs/GNUmakefile593
-rw-r--r--libs/pthreads/docs/MAINTAINERS4
-rw-r--r--libs/pthreads/docs/Makefile514
-rw-r--r--libs/pthreads/docs/NEWS1241
-rw-r--r--libs/pthreads/docs/Nmakefile24
-rw-r--r--libs/pthreads/docs/PROGRESS4
-rw-r--r--libs/pthreads/docs/README601
-rw-r--r--libs/pthreads/docs/TODO7
-rw-r--r--libs/pthreads/docs/WinCE-PORT222
-rw-r--r--libs/pthreads/pthreads.vcxproj93
-rw-r--r--libs/pthreads/pthreads.vcxproj.filters22
-rw-r--r--libs/pthreads/src/attr.c53
-rw-r--r--libs/pthreads/src/autostatic.c69
-rw-r--r--libs/pthreads/src/barrier.c47
-rw-r--r--libs/pthreads/src/cancel.c44
-rw-r--r--libs/pthreads/src/cleanup.c148
-rw-r--r--libs/pthreads/src/condvar.c50
-rw-r--r--libs/pthreads/src/config.h153
-rw-r--r--libs/pthreads/src/context.h74
-rw-r--r--libs/pthreads/src/create.c308
-rw-r--r--libs/pthreads/src/dll.c92
-rw-r--r--libs/pthreads/src/errno.c94
-rw-r--r--libs/pthreads/src/exit.c44
-rw-r--r--libs/pthreads/src/fork.c39
-rw-r--r--libs/pthreads/src/global.c107
-rw-r--r--libs/pthreads/src/implement.h943
-rw-r--r--libs/pthreads/src/misc.c50
-rw-r--r--libs/pthreads/src/mutex.c62
-rw-r--r--libs/pthreads/src/need_errno.h145
-rw-r--r--libs/pthreads/src/nonportable.c47
-rw-r--r--libs/pthreads/src/private.c54
-rw-r--r--libs/pthreads/src/pthread.c66
-rw-r--r--libs/pthreads/src/pthread.h1368
-rw-r--r--libs/pthreads/src/pthread_attr_destroy.c79
-rw-r--r--libs/pthreads/src/pthread_attr_getdetachstate.c86
-rw-r--r--libs/pthreads/src/pthread_attr_getinheritsched.c51
-rw-r--r--libs/pthreads/src/pthread_attr_getschedparam.c52
-rw-r--r--libs/pthreads/src/pthread_attr_getschedpolicy.c61
-rw-r--r--libs/pthreads/src/pthread_attr_getscope.c54
-rw-r--r--libs/pthreads/src/pthread_attr_getstackaddr.c97
-rw-r--r--libs/pthreads/src/pthread_attr_getstacksize.c100
-rw-r--r--libs/pthreads/src/pthread_attr_init.c117
-rw-r--r--libs/pthreads/src/pthread_attr_setdetachstate.c91
-rw-r--r--libs/pthreads/src/pthread_attr_setinheritsched.c57
-rw-r--r--libs/pthreads/src/pthread_attr_setschedparam.c63
-rw-r--r--libs/pthreads/src/pthread_attr_setschedpolicy.c55
-rw-r--r--libs/pthreads/src/pthread_attr_setscope.c62
-rw-r--r--libs/pthreads/src/pthread_attr_setstackaddr.c97
-rw-r--r--libs/pthreads/src/pthread_attr_setstacksize.c110
-rw-r--r--libs/pthreads/src/pthread_barrier_destroy.c103
-rw-r--r--libs/pthreads/src/pthread_barrier_init.c69
-rw-r--r--libs/pthreads/src/pthread_barrier_wait.c104
-rw-r--r--libs/pthreads/src/pthread_barrierattr_destroy.c83
-rw-r--r--libs/pthreads/src/pthread_barrierattr_getpshared.c95
-rw-r--r--libs/pthreads/src/pthread_barrierattr_init.c85
-rw-r--r--libs/pthreads/src/pthread_barrierattr_setpshared.c119
-rw-r--r--libs/pthreads/src/pthread_cancel.c189
-rw-r--r--libs/pthreads/src/pthread_cond_destroy.c253
-rw-r--r--libs/pthreads/src/pthread_cond_init.c167
-rw-r--r--libs/pthreads/src/pthread_cond_signal.c231
-rw-r--r--libs/pthreads/src/pthread_cond_wait.c567
-rw-r--r--libs/pthreads/src/pthread_condattr_destroy.c86
-rw-r--r--libs/pthreads/src/pthread_condattr_getpshared.c97
-rw-r--r--libs/pthreads/src/pthread_condattr_init.c87
-rw-r--r--libs/pthreads/src/pthread_condattr_setpshared.c117
-rw-r--r--libs/pthreads/src/pthread_delay_np.c172
-rw-r--r--libs/pthreads/src/pthread_detach.c136
-rw-r--r--libs/pthreads/src/pthread_equal.c76
-rw-r--r--libs/pthreads/src/pthread_exit.c106
-rw-r--r--libs/pthreads/src/pthread_getconcurrency.c45
-rw-r--r--libs/pthreads/src/pthread_getschedparam.c75
-rw-r--r--libs/pthreads/src/pthread_getspecific.c87
-rw-r--r--libs/pthreads/src/pthread_getunique_np.c47
-rw-r--r--libs/pthreads/src/pthread_getw32threadhandle_np.c65
-rw-r--r--libs/pthreads/src/pthread_join.c157
-rw-r--r--libs/pthreads/src/pthread_key_create.c108
-rw-r--r--libs/pthreads/src/pthread_key_delete.c125
-rw-r--r--libs/pthreads/src/pthread_kill.c105
-rw-r--r--libs/pthreads/src/pthread_mutex_consistent.c190
-rw-r--r--libs/pthreads/src/pthread_mutex_destroy.c148
-rw-r--r--libs/pthreads/src/pthread_mutex_init.c130
-rw-r--r--libs/pthreads/src/pthread_mutex_lock.c269
-rw-r--r--libs/pthreads/src/pthread_mutex_timedlock.c324
-rw-r--r--libs/pthreads/src/pthread_mutex_trylock.c158
-rw-r--r--libs/pthreads/src/pthread_mutex_unlock.c178
-rw-r--r--libs/pthreads/src/pthread_mutexattr_destroy.c83
-rw-r--r--libs/pthreads/src/pthread_mutexattr_getkind_np.c44
-rw-r--r--libs/pthreads/src/pthread_mutexattr_getpshared.c95
-rw-r--r--libs/pthreads/src/pthread_mutexattr_getrobust.c113
-rw-r--r--libs/pthreads/src/pthread_mutexattr_gettype.c56
-rw-r--r--libs/pthreads/src/pthread_mutexattr_init.c86
-rw-r--r--libs/pthreads/src/pthread_mutexattr_setkind_np.c44
-rw-r--r--libs/pthreads/src/pthread_mutexattr_setpshared.c119
-rw-r--r--libs/pthreads/src/pthread_mutexattr_setrobust.c119
-rw-r--r--libs/pthreads/src/pthread_mutexattr_settype.c143
-rw-r--r--libs/pthreads/src/pthread_num_processors_np.c56
-rw-r--r--libs/pthreads/src/pthread_once.c79
-rw-r--r--libs/pthreads/src/pthread_rwlock_destroy.c143
-rw-r--r--libs/pthreads/src/pthread_rwlock_init.c109
-rw-r--r--libs/pthreads/src/pthread_rwlock_rdlock.c102
-rw-r--r--libs/pthreads/src/pthread_rwlock_timedrdlock.c109
-rw-r--r--libs/pthreads/src/pthread_rwlock_timedwrlock.c139
-rw-r--r--libs/pthreads/src/pthread_rwlock_tryrdlock.c102
-rw-r--r--libs/pthreads/src/pthread_rwlock_trywrlock.c122
-rw-r--r--libs/pthreads/src/pthread_rwlock_unlock.c93
-rw-r--r--libs/pthreads/src/pthread_rwlock_wrlock.c133
-rw-r--r--libs/pthreads/src/pthread_rwlockattr_destroy.c84
-rw-r--r--libs/pthreads/src/pthread_rwlockattr_getpshared.c97
-rw-r--r--libs/pthreads/src/pthread_rwlockattr_init.c83
-rw-r--r--libs/pthreads/src/pthread_rwlockattr_setpshared.c120
-rw-r--r--libs/pthreads/src/pthread_self.c141
-rw-r--r--libs/pthreads/src/pthread_setcancelstate.c125
-rw-r--r--libs/pthreads/src/pthread_setcanceltype.c126
-rw-r--r--libs/pthreads/src/pthread_setconcurrency.c53
-rw-r--r--libs/pthreads/src/pthread_setschedparam.c123
-rw-r--r--libs/pthreads/src/pthread_setspecific.c167
-rw-r--r--libs/pthreads/src/pthread_spin_destroy.c111
-rw-r--r--libs/pthreads/src/pthread_spin_init.c123
-rw-r--r--libs/pthreads/src/pthread_spin_lock.c80
-rw-r--r--libs/pthreads/src/pthread_spin_trylock.c77
-rw-r--r--libs/pthreads/src/pthread_spin_unlock.c71
-rw-r--r--libs/pthreads/src/pthread_testcancel.c103
-rw-r--r--libs/pthreads/src/pthread_timechange_handler_np.c108
-rw-r--r--libs/pthreads/src/pthread_win32_attach_detach_np.c256
-rw-r--r--libs/pthreads/src/ptw32_MCS_lock.c278
-rw-r--r--libs/pthreads/src/ptw32_OLL_lock.c734
-rw-r--r--libs/pthreads/src/ptw32_callUserDestroyRoutines.c232
-rw-r--r--libs/pthreads/src/ptw32_calloc.c56
-rw-r--r--libs/pthreads/src/ptw32_cond_check_need_init.c78
-rw-r--r--libs/pthreads/src/ptw32_getprocessors.c91
-rw-r--r--libs/pthreads/src/ptw32_is_attr.c47
-rw-r--r--libs/pthreads/src/ptw32_mutex_check_need_init.c92
-rw-r--r--libs/pthreads/src/ptw32_new.c94
-rw-r--r--libs/pthreads/src/ptw32_processInitialize.c92
-rw-r--r--libs/pthreads/src/ptw32_processTerminate.c105
-rw-r--r--libs/pthreads/src/ptw32_relmillisecs.c132
-rw-r--r--libs/pthreads/src/ptw32_reuse.c151
-rw-r--r--libs/pthreads/src/ptw32_rwlock_cancelwrwait.c50
-rw-r--r--libs/pthreads/src/ptw32_rwlock_check_need_init.c77
-rw-r--r--libs/pthreads/src/ptw32_semwait.c135
-rw-r--r--libs/pthreads/src/ptw32_spinlock_check_need_init.c78
-rw-r--r--libs/pthreads/src/ptw32_threadDestroy.c79
-rw-r--r--libs/pthreads/src/ptw32_threadStart.c357
-rw-r--r--libs/pthreads/src/ptw32_throw.c189
-rw-r--r--libs/pthreads/src/ptw32_timespec.c83
-rw-r--r--libs/pthreads/src/ptw32_tkAssocCreate.c118
-rw-r--r--libs/pthreads/src/ptw32_tkAssocDestroy.c114
-rw-r--r--libs/pthreads/src/rwlock.c51
-rw-r--r--libs/pthreads/src/sched.c53
-rw-r--r--libs/pthreads/src/sched.h183
-rw-r--r--libs/pthreads/src/sched_get_priority_max.c134
-rw-r--r--libs/pthreads/src/sched_get_priority_min.c135
-rw-r--r--libs/pthreads/src/sched_getscheduler.c71
-rw-r--r--libs/pthreads/src/sched_setscheduler.c83
-rw-r--r--libs/pthreads/src/sched_yield.c71
-rw-r--r--libs/pthreads/src/sem_close.c58
-rw-r--r--libs/pthreads/src/sem_destroy.c144
-rw-r--r--libs/pthreads/src/sem_getvalue.c110
-rw-r--r--libs/pthreads/src/sem_init.c169
-rw-r--r--libs/pthreads/src/sem_open.c58
-rw-r--r--libs/pthreads/src/sem_post.c128
-rw-r--r--libs/pthreads/src/sem_post_multiple.c142
-rw-r--r--libs/pthreads/src/sem_timedwait.c238
-rw-r--r--libs/pthreads/src/sem_trywait.c117
-rw-r--r--libs/pthreads/src/sem_unlink.c58
-rw-r--r--libs/pthreads/src/sem_wait.c187
-rw-r--r--libs/pthreads/src/semaphore.c69
-rw-r--r--libs/pthreads/src/semaphore.h169
-rw-r--r--libs/pthreads/src/signal.c179
-rw-r--r--libs/pthreads/src/spin.c46
-rw-r--r--libs/pthreads/src/sync.c43
-rw-r--r--libs/pthreads/src/tsd.c44
-rw-r--r--libs/pthreads/src/w32_CancelableWait.c161
-rw-r--r--libs/win32/libjson.libbin63584 -> 65902 bytes
-rw-r--r--libs/win32/mir_app.libbin130706 -> 131618 bytes
-rw-r--r--libs/win32/mir_core.libbin318226 -> 318478 bytes
-rw-r--r--libs/win64/libjson.libbin64114 -> 66538 bytes
-rw-r--r--libs/win64/mir_app.libbin126274 -> 127106 bytes
-rw-r--r--libs/win64/mir_core.libbin319200 -> 319436 bytes
-rw-r--r--plugins/AVS/src/main.cpp1
-rw-r--r--plugins/AVS/src/version.h1
-rw-r--r--plugins/Actman/actman.dpr1
-rw-r--r--plugins/AddContactPlus/src/addcontact.cpp2
-rw-r--r--plugins/AddContactPlus/src/main.cpp1
-rw-r--r--plugins/AddContactPlus/src/stdafx.h2
-rw-r--r--plugins/AddContactPlus/src/version.h1
-rw-r--r--plugins/AdvaImg/src/main.cpp1
-rw-r--r--plugins/AdvaImg/src/version.h1
-rw-r--r--plugins/Alarms/src/alarms.cpp1
-rwxr-xr-xplugins/Alarms/src/version.h1
-rw-r--r--plugins/AsSingleWindow/src/AsSingleWindow.cpp1
-rw-r--r--plugins/AsSingleWindow/src/version.h1
-rw-r--r--plugins/AssocMgr/src/main.cpp1
-rw-r--r--plugins/AssocMgr/src/test.cpp140
-rw-r--r--plugins/AssocMgr/src/version.h3
-rw-r--r--plugins/AuthState/src/main.cpp1
-rw-r--r--plugins/AuthState/src/version.h1
-rw-r--r--plugins/AutoRun/src/main.cpp1
-rw-r--r--plugins/AutoRun/src/version.h1
-rw-r--r--plugins/AutoShutdown/src/main.cpp1
-rw-r--r--plugins/AutoShutdown/src/version.h1
-rw-r--r--plugins/AvatarHistory/src/AvatarHistory.cpp1
-rw-r--r--plugins/AvatarHistory/src/version.h1
-rw-r--r--plugins/BASS_interface/src/Main.cpp1
-rw-r--r--plugins/BASS_interface/src/version.h1
-rw-r--r--plugins/BasicHistory/res/BasicHistory.rc2
-rw-r--r--plugins/BasicHistory/src/BasicHistory.cpp1
-rw-r--r--plugins/BasicHistory/src/Options.cpp2
-rw-r--r--plugins/BasicHistory/src/version.h1
-rw-r--r--plugins/Boltun/src/boltun.cpp1
-rw-r--r--plugins/Boltun/src/version.h1
-rw-r--r--plugins/BossKeyPlus/src/BossKey.cpp1
-rw-r--r--plugins/BossKeyPlus/src/version.h1
-rw-r--r--plugins/BuddyExpectator/src/BuddyExpectator.cpp1
-rw-r--r--plugins/BuddyExpectator/src/version.h1
-rw-r--r--plugins/BuddyPounce/src/main.cpp1
-rw-r--r--plugins/BuddyPounce/src/version.h1
-rw-r--r--plugins/CSList/src/cslist.cpp47
-rw-r--r--plugins/CSList/src/version.h1
-rw-r--r--plugins/ChangeKeyboardLayout/src/main.cpp1
-rw-r--r--plugins/ChangeKeyboardLayout/src/version.h1
-rw-r--r--plugins/ClientChangeNotify/src/ClientChangeNotify.cpp1
-rw-r--r--plugins/ClientChangeNotify/src/version.h1
-rw-r--r--plugins/Clist_blind/src/init.cpp1
-rw-r--r--plugins/Clist_blind/src/version.h1
-rw-r--r--plugins/Clist_modern/src/init.cpp1
-rw-r--r--plugins/Clist_modern/src/version.h1
-rw-r--r--plugins/Clist_nicer/src/clistmenus.cpp9
-rw-r--r--plugins/Clist_nicer/src/init.cpp1
-rw-r--r--plugins/Clist_nicer/src/stdafx.h2
-rw-r--r--plugins/Clist_nicer/src/version.h1
-rw-r--r--plugins/Cln_skinedit/src/main.cpp1
-rw-r--r--plugins/Cln_skinedit/src/version.h1
-rw-r--r--plugins/CloudFile/src/http_request.h2
-rw-r--r--plugins/CloudFile/src/main.cpp1
-rw-r--r--plugins/CloudFile/src/version.h1
-rw-r--r--plugins/CmdLine/src/CmdLine.cpp1
-rw-r--r--plugins/CmdLine/src/version.h1
-rw-r--r--plugins/ConnectionNotify/src/ConnectionNotify.cpp1
-rw-r--r--plugins/ConnectionNotify/src/version.h1
-rw-r--r--plugins/Console/src/init.cpp1
-rw-r--r--plugins/Console/src/version.h1
-rw-r--r--plugins/ContactsPlus/src/main.cpp1
-rw-r--r--plugins/ContactsPlus/src/receive.cpp4
-rw-r--r--plugins/ContactsPlus/src/send.cpp2
-rw-r--r--plugins/ContactsPlus/src/stdafx.h2
-rw-r--r--plugins/ContactsPlus/src/utils.cpp9
-rw-r--r--plugins/ContactsPlus/src/utils.h2
-rw-r--r--plugins/ContactsPlus/src/version.h1
-rw-r--r--plugins/ContextHelp/src/main.cpp1
-rw-r--r--plugins/ContextHelp/src/stdafx.h2
-rw-r--r--plugins/ContextHelp/src/version.h21
-rw-r--r--plugins/CountryFlags/src/main.cpp1
-rw-r--r--plugins/CountryFlags/src/version.h1
-rw-r--r--plugins/CrashDumper/src/crshdmp.cpp1
-rw-r--r--plugins/CrashDumper/src/upload.cpp2
-rw-r--r--plugins/CrashDumper/src/version.h1
-rw-r--r--plugins/CryptoPP/src/base16.cpp6
-rw-r--r--plugins/CryptoPP/src/base16.h6
-rw-r--r--plugins/CryptoPP/src/base64.cpp6
-rw-r--r--plugins/CryptoPP/src/cpp_keys.cpp2
-rw-r--r--plugins/CryptoPP/src/cpp_svcs.cpp4
-rw-r--r--plugins/CryptoPP/src/main.cpp1
-rw-r--r--plugins/CryptoPP/src/version.h1
-rw-r--r--plugins/CyrTranslit/src/main.cpp1
-rw-r--r--plugins/CyrTranslit/src/version.h1
-rw-r--r--plugins/Db3x_mmap/src/init.cpp1
-rw-r--r--plugins/Db3x_mmap/src/version.h1
-rw-r--r--plugins/DbChecker/src/main.cpp1
-rw-r--r--plugins/DbChecker/src/version.h1
-rw-r--r--plugins/DbEditorPP/src/main.cpp1
-rw-r--r--plugins/DbEditorPP/src/version.h1
-rw-r--r--plugins/Db_autobackups/src/main.cpp1
-rw-r--r--plugins/Db_autobackups/src/version.h1
-rw-r--r--plugins/Dbx_mdb/dbx_lmdb.vcxproj10
-rw-r--r--plugins/Dbx_mdb/src/dbintf.cpp6
-rw-r--r--plugins/Dbx_mdb/src/init.cpp1
m---------plugins/Dbx_mdb/src/libmdbx0
-rw-r--r--plugins/Dbx_mdb/src/mdbx/bits.h1226
-rw-r--r--plugins/Dbx_mdb/src/mdbx/defs.h423
-rw-r--r--plugins/Dbx_mdb/src/mdbx/lck-windows.c452
-rw-r--r--plugins/Dbx_mdb/src/mdbx/mdbx.c11611
-rw-r--r--plugins/Dbx_mdb/src/mdbx/mdbx.h1825
-rw-r--r--plugins/Dbx_mdb/src/mdbx/osal.c1002
-rw-r--r--plugins/Dbx_mdb/src/mdbx/osal.h645
-rw-r--r--plugins/Dbx_mdb/src/mdbx/version.c34
-rw-r--r--plugins/Dbx_mdb/src/stdafx.h2
-rw-r--r--plugins/Dbx_mdb/src/version.h1
-rw-r--r--plugins/Exchange/src/exchange.cpp1
-rw-r--r--plugins/Exchange/src/version.h1
-rw-r--r--plugins/FTPFileYM/src/ftpfile.cpp1
-rw-r--r--plugins/FTPFileYM/src/version.h1
-rw-r--r--plugins/FavContacts/src/main.cpp1
-rw-r--r--plugins/FavContacts/src/version.h1
-rw-r--r--plugins/FileAsMessage/fileecho.vcxproj (renamed from protocols/AimOscar/proto_aim/Proto_AIM.vcxproj)59
-rw-r--r--plugins/FileAsMessage/fileecho.vcxproj.filters4
-rw-r--r--plugins/FileAsMessage/fileecho_15.vcxproj213
-rw-r--r--plugins/FileAsMessage/fileecho_15.vcxproj.filters56
-rw-r--r--plugins/FileAsMessage/src/crc32.cpp2
-rw-r--r--plugins/FileAsMessage/src/dialog.cpp857
-rw-r--r--plugins/FileAsMessage/src/main.cpp3
-rw-r--r--plugins/FileAsMessage/src/optionsdlg.cpp2
-rw-r--r--plugins/FileAsMessage/src/stdafx.cpp18
-rw-r--r--plugins/FileAsMessage/src/stdafx.cxx1
-rw-r--r--plugins/FileAsMessage/src/stdafx.h (renamed from plugins/FileAsMessage/src/main.h)101
-rw-r--r--plugins/FileAsMessage/src/version.h17
-rw-r--r--plugins/FingerprintNG/iconpacks/res/AIM/AIM_6.x.icobin1150 -> 0 bytes
-rw-r--r--plugins/FingerprintNG/iconpacks/res/AIM/AIM_7.x.icobin1150 -> 0 bytes
-rw-r--r--plugins/FingerprintNG/iconpacks/res/AIM/AIM_Mac.icobin1150 -> 0 bytes
-rw-r--r--plugins/FingerprintNG/iconpacks/res/AIM/AIM_Mobile.icobin1150 -> 0 bytes
-rw-r--r--plugins/FingerprintNG/iconpacks/res/AIM/AIM_Triton.icobin1150 -> 0 bytes
-rw-r--r--plugins/FingerprintNG/iconpacks/res/AIM/TerraIM.icobin1150 -> 0 bytes
-rw-r--r--plugins/FingerprintNG/iconpacks/res/AIM/miniaim.icobin1150 -> 0 bytes
-rw-r--r--plugins/FingerprintNG/iconpacks/res/AIM/naim.icobin1150 -> 0 bytes
-rw-r--r--plugins/FingerprintNG/iconpacks/res/Jabber/PyAIMt.icobin1150 -> 0 bytes
-rw-r--r--plugins/FingerprintNG/iconpacks/res/Overlays/overlay_proto_AIM.icobin1150 -> 0 bytes
-rw-r--r--plugins/FingerprintNG/iconpacks/res/fp_icons.rc9
-rw-r--r--plugins/FingerprintNG/res/resource.rc1
-rw-r--r--plugins/FingerprintNG/src/finger_groups.h5
-rw-r--r--plugins/FingerprintNG/src/main.cpp1
-rw-r--r--plugins/FingerprintNG/src/masks.cpp15
-rw-r--r--plugins/FingerprintNG/src/options.cpp1
-rw-r--r--plugins/FingerprintNG/src/resource.h10
-rw-r--r--plugins/FingerprintNG/src/stdafx.h1
-rw-r--r--plugins/FingerprintNG/src/version.h1
-rw-r--r--plugins/FloatingContacts/src/main.cpp1
-rw-r--r--plugins/FloatingContacts/src/version.h1
-rw-r--r--plugins/Folders/src/folders.cpp1
-rw-r--r--plugins/Folders/src/version.h1
-rw-r--r--plugins/GmailNotifier/src/check.cpp2
-rw-r--r--plugins/GmailNotifier/src/main.cpp1
-rw-r--r--plugins/GmailNotifier/src/version.h1
-rw-r--r--plugins/HTTPServer/src/main.cpp1
-rw-r--r--plugins/HTTPServer/src/version.h1
-rw-r--r--plugins/HistoryLinkListPlus/src/linklist.cpp1
-rw-r--r--plugins/HistoryLinkListPlus/src/version.h1
-rw-r--r--plugins/HistoryPlusPlus/historypp.dpr1
-rw-r--r--plugins/HistoryPlusPlus/hpp_global.pas1
-rw-r--r--plugins/HistoryStats/src/main.cpp1
-rw-r--r--plugins/HistoryStats/src/stdafx.h1
-rw-r--r--plugins/HistoryStats/src/version.h1
-rw-r--r--plugins/HistorySweeperLight/src/main.cpp1
-rw-r--r--plugins/HistorySweeperLight/src/version.h1
-rw-r--r--plugins/HwHotKeys/src/HwHotKeys_DllMain.cpp1
-rw-r--r--plugins/HwHotKeys/src/version.h1
-rw-r--r--plugins/IEHistory/src/IEHistory.cpp2
-rw-r--r--plugins/IEHistory/src/version.h1
-rw-r--r--plugins/IEView/src/ieview_main.cpp1
-rw-r--r--plugins/IEView/src/version.h1
-rw-r--r--plugins/IgnoreState/src/main.cpp1
-rw-r--r--plugins/IgnoreState/src/version.h1
-rw-r--r--plugins/Import/src/main.cpp1
-rw-r--r--plugins/Import/src/version.h1
-rw-r--r--plugins/ImportTXT/importtxt.dpr1
-rw-r--r--plugins/KeyboardNotify/src/main.cpp1
-rw-r--r--plugins/KeyboardNotify/src/version.h1
-rw-r--r--plugins/ListeningTo/src/main.cpp1
-rw-r--r--plugins/ListeningTo/src/version.h1
-rw-r--r--plugins/LotusNotify/src/LotusNotify.cpp1
-rw-r--r--plugins/LotusNotify/src/version.h1
-rw-r--r--plugins/MenuItemEx/src/main.cpp1
-rw-r--r--plugins/MenuItemEx/src/version.h1
-rw-r--r--plugins/MessageState/src/main.cpp1
-rw-r--r--plugins/MessageState/src/version.h1
-rw-r--r--plugins/MimCmd/src/version.h1
-rw-r--r--plugins/MirFox/src/MirandaInterface.cpp1
-rw-r--r--plugins/MirFox/src/version.h1
-rw-r--r--plugins/MirLua/src/main.cpp1
-rw-r--r--plugins/MirLua/src/version.h1
-rw-r--r--plugins/MirOTR/src/dllmain.cpp1
-rw-r--r--plugins/MirOTR/src/version.h1
-rw-r--r--plugins/MirandaG15/src/Miranda.cpp1
-rw-r--r--plugins/MirandaG15/src/version.h1
-rw-r--r--plugins/MobileState/src/main.cpp1
-rw-r--r--plugins/MobileState/src/version.h1
-rw-r--r--plugins/MsgPopup/src/main.cpp1
-rw-r--r--plugins/MsgPopup/src/version.h1
-rwxr-xr-xplugins/Msg_Export/src/main.cpp1
-rw-r--r--plugins/Msg_Export/src/version.h1
-rw-r--r--plugins/MyDetails/src/mydetails.cpp1
-rw-r--r--plugins/MyDetails/src/version.h1
-rw-r--r--plugins/NewAwaySysMod/src/AwaySys.cpp1
-rw-r--r--plugins/NewAwaySysMod/src/version.h1
-rw-r--r--plugins/NewEventNotify/src/main.cpp1
-rw-r--r--plugins/NewEventNotify/src/version.h1
-rw-r--r--plugins/NewXstatusNotify/src/main.cpp1
-rw-r--r--plugins/NewXstatusNotify/src/version.h1
-rwxr-xr-xplugins/New_GPG/src/init.cpp1
-rwxr-xr-xplugins/New_GPG/src/version.h1
-rw-r--r--plugins/NewsAggregator/Src/Authentication.cpp2
-rw-r--r--plugins/NewsAggregator/Src/NewsAggregator.cpp1
-rw-r--r--plugins/NewsAggregator/Src/version.h1
-rw-r--r--plugins/NoHistory/src/dllmain.cpp1
-rw-r--r--plugins/NoHistory/src/version.h1
-rw-r--r--plugins/Non-IM Contact/src/main.cpp1
-rw-r--r--plugins/Non-IM Contact/src/version.h1
-rw-r--r--plugins/NotesAndReminders/src/main.cpp1
-rw-r--r--plugins/NotesAndReminders/src/version.h1
-rw-r--r--plugins/NotifyAnything/src/main.cpp1
-rw-r--r--plugins/NotifyAnything/src/version.h1
-rw-r--r--plugins/Nudge/src/main.cpp1
-rw-r--r--plugins/Nudge/src/version.h1
-rw-r--r--plugins/OpenFolder/src/openFolder.cpp1
-rw-r--r--plugins/OpenFolder/src/version.h1
-rw-r--r--plugins/OpenSSL/src/main.cpp1
-rw-r--r--plugins/OpenSSL/src/version.h3
-rw-r--r--plugins/PackUpdater/Src/PackUpdater.cpp1
-rw-r--r--plugins/PackUpdater/Src/version.h1
-rw-r--r--plugins/PasteIt/src/PasteIt.cpp1
-rw-r--r--plugins/PasteIt/src/version.h1
-rw-r--r--plugins/Ping/src/ping.cpp1
-rw-r--r--plugins/Ping/src/version.h1
-rw-r--r--plugins/PluginUpdater/src/DlgUpdate.cpp1
-rw-r--r--plugins/PluginUpdater/src/PluginUpdater.cpp1
-rw-r--r--plugins/PluginUpdater/src/version.h3
-rw-r--r--plugins/Popup/src/config.cpp1
-rw-r--r--plugins/Popup/src/popup_wnd2.cpp28
-rw-r--r--plugins/Popup/src/skin.cpp10
-rw-r--r--plugins/Popup/src/stdafx.h2
-rw-r--r--plugins/Popup/src/version.h1
-rw-r--r--plugins/ProfileManager/src/pmanagerEx.cpp1
-rw-r--r--plugins/ProfileManager/src/version.h1
-rw-r--r--plugins/QuickContacts/src/quickcontacts.cpp1
-rw-r--r--plugins/QuickContacts/src/version.h1
-rw-r--r--plugins/QuickMessages/src/main.cpp1
-rw-r--r--plugins/QuickMessages/src/version.h1
-rw-r--r--plugins/QuickReplies/src/quickreplies.cpp1
-rw-r--r--plugins/QuickReplies/src/version.h1
-rw-r--r--plugins/QuickSearch/quicksearch.dpr1
-rw-r--r--plugins/Quotes/docs/Utility/google.xml448
-rw-r--r--plugins/Quotes/src/Forex.cpp1
-rw-r--r--plugins/Quotes/src/ImportExport.cpp2
-rw-r--r--plugins/Quotes/src/QuotesProviderGoogle.cpp2
-rw-r--r--plugins/Quotes/src/version.h1
-rw-r--r--plugins/Rate/src/main.cpp1
-rw-r--r--plugins/Rate/src/version.h1
-rw-r--r--plugins/RecentContacts/src/RecentContacts.cpp1
-rw-r--r--plugins/RecentContacts/src/version.h1
-rw-r--r--plugins/RemovePersonalSettings/src/rps.cpp1
-rw-r--r--plugins/RemovePersonalSettings/src/version.h1
-rw-r--r--plugins/Restart/src/restart.cpp1
-rw-r--r--plugins/Restart/src/version.h1
-rw-r--r--plugins/SMS/src/main.cpp1
-rw-r--r--plugins/SMS/src/version.h1
-rw-r--r--plugins/Scriver/src/cmdlist.h2
-rw-r--r--plugins/Scriver/src/msgdialog.cpp5
-rw-r--r--plugins/Scriver/src/srmm.cpp1
-rw-r--r--plugins/Scriver/src/stdafx.h1
-rw-r--r--plugins/Scriver/src/version.h1
-rw-r--r--plugins/SecureIM/src/main.cpp1
-rw-r--r--plugins/SecureIM/src/version.h1
-rw-r--r--plugins/SeenPlugin/src/main.cpp1
-rw-r--r--plugins/SeenPlugin/src/version.h1
-rw-r--r--plugins/SendScreenshotPlus/src/Main.cpp2
-rw-r--r--plugins/SendScreenshotPlus/src/version.h1
-rw-r--r--plugins/Sessions/Src/Main.cpp1
-rw-r--r--plugins/Sessions/Src/version.h1
-rw-r--r--plugins/ShellExt/src/main.cpp1
-rw-r--r--plugins/ShellExt/src/version.h1
-rw-r--r--plugins/SimpleAR/src/Main.cpp1
-rw-r--r--plugins/SimpleAR/src/version.h1
-rw-r--r--plugins/SimpleStatusMsg/src/main.cpp17
-rw-r--r--plugins/SimpleStatusMsg/src/version.h1
-rw-r--r--plugins/SkypeStatusChange/src/main.cpp1
-rw-r--r--plugins/SkypeStatusChange/src/version.h1
-rw-r--r--plugins/SmileyAdd/smileys/nova/AIM.mslbin2898 -> 0 bytes
-rw-r--r--plugins/SmileyAdd/src/customsmiley.cpp2
-rw-r--r--plugins/SmileyAdd/src/main.cpp1
-rw-r--r--plugins/SmileyAdd/src/version.h1
-rw-r--r--plugins/Spamotron/src/spamotron.cpp1
-rw-r--r--plugins/Spamotron/src/version.h1
-rw-r--r--plugins/SpellChecker/src/spellchecker.cpp1
-rw-r--r--plugins/SpellChecker/src/version.h1
-rw-r--r--plugins/SplashScreen/src/main.cpp1
-rw-r--r--plugins/SplashScreen/src/version.h1
-rw-r--r--plugins/StartPosition/src/main.cpp1
-rw-r--r--plugins/StartPosition/src/version.h1
-rw-r--r--plugins/StartupSilence/src/main.cpp1
-rw-r--r--plugins/StartupSilence/src/version.h1
-rw-r--r--plugins/StatusChange/src/main.cpp1
-rw-r--r--plugins/StatusChange/src/version.h1
-rw-r--r--plugins/StatusManager/src/StartupStatus/ss_options.cpp34
-rw-r--r--plugins/StatusManager/src/main.cpp1
-rw-r--r--plugins/StatusManager/src/version.h1
-rwxr-xr-xplugins/StopSpamMod/src/init.cpp4
-rwxr-xr-xplugins/StopSpamMod/src/stdafx.h8
-rwxr-xr-xplugins/StopSpamMod/src/utilities.cpp68
-rwxr-xr-xplugins/StopSpamMod/src/version.h1
-rw-r--r--plugins/StopSpamPlus/src/options.cpp10
-rw-r--r--plugins/StopSpamPlus/src/stopspam.cpp1
-rw-r--r--plugins/StopSpamPlus/src/version.h1
-rw-r--r--plugins/TabSRMM/res/chat.rc4
-rw-r--r--plugins/TabSRMM/res/msgwindow.rc5
-rw-r--r--plugins/TabSRMM/res/resource.rc28
-rw-r--r--plugins/TabSRMM/src/generic_msghandlers.cpp2
-rw-r--r--plugins/TabSRMM/src/globals.cpp8
-rw-r--r--plugins/TabSRMM/src/hotkeyhandler.cpp2
-rw-r--r--plugins/TabSRMM/src/infopanel.cpp2
-rw-r--r--plugins/TabSRMM/src/msgdialog.cpp50
-rw-r--r--plugins/TabSRMM/src/msgdlgutils.cpp59
-rw-r--r--plugins/TabSRMM/src/msgs.h5
-rw-r--r--plugins/TabSRMM/src/resource.h21
-rw-r--r--plugins/TabSRMM/src/sendlater.cpp2
-rw-r--r--plugins/TabSRMM/src/sendqueue.h1
-rw-r--r--plugins/TabSRMM/src/srmm.cpp1
-rw-r--r--plugins/TabSRMM/src/stdafx.h1
-rw-r--r--plugins/TabSRMM/src/utils.cpp41
-rw-r--r--plugins/TabSRMM/src/utils.h11
-rw-r--r--plugins/TabSRMM/src/version.h3
-rw-r--r--plugins/TipperYM/src/tipper.cpp1
-rw-r--r--plugins/TipperYM/src/version.h1
-rw-r--r--plugins/Toaster/src/main.cpp1
-rw-r--r--plugins/Toaster/src/version.h1
-rw-r--r--plugins/TooltipNotify/src/main.cpp1
-rw-r--r--plugins/TooltipNotify/src/version.h1
-rw-r--r--plugins/TopToolBar/src/main.cpp1
-rw-r--r--plugins/TopToolBar/src/version.h1
-rw-r--r--plugins/TrafficCounter/src/TrafficCounter.cpp1
-rw-r--r--plugins/TrafficCounter/src/resource.h1
-rw-r--r--plugins/TrafficCounter/src/version.h1
-rw-r--r--plugins/TranslitSwitcher/src/TranslitSwitcher.cpp1
-rw-r--r--plugins/TranslitSwitcher/src/version.h1
-rw-r--r--plugins/UserGuide/src/main.cpp1
-rw-r--r--plugins/UserGuide/src/version.h1
-rw-r--r--plugins/UserInfoEx/src/ex_import/classExImContactXML.cpp8
-rw-r--r--plugins/UserInfoEx/src/init.cpp1
-rw-r--r--plugins/UserInfoEx/src/version.h1
-rw-r--r--plugins/Variables/src/main.cpp1
-rw-r--r--plugins/Variables/src/version.h1
-rw-r--r--plugins/Watrack/docs/sampledll.dpr1
-rw-r--r--plugins/Watrack/player.ini7
-rw-r--r--plugins/Watrack/watrack.dpr1
-rwxr-xr-xplugins/Watrack_MPD/src/init.cpp1
-rw-r--r--plugins/Watrack_MPD/src/version.h1
-rw-r--r--plugins/Weather/src/version.h1
-rw-r--r--plugins/Weather/src/weather.cpp1
-rw-r--r--plugins/WebView/src/main.cpp1
-rw-r--r--plugins/WebView/src/version.h1
-rw-r--r--plugins/WhenWasIt/src/WhenWasIt.cpp1
-rw-r--r--plugins/WhenWasIt/src/version.h1
-rw-r--r--plugins/WhoUsesMyFiles/src/version.h1
-rw-r--r--plugins/WhoUsesMyFiles/src/wumfplug.cpp1
-rw-r--r--plugins/WinterSpeak/src/main.cpp1
-rw-r--r--plugins/WinterSpeak/src/version.h1
-rw-r--r--plugins/XSoundNotify/src/version.h1
-rw-r--r--plugins/XSoundNotify/src/xsn_main.cpp1
-rw-r--r--plugins/YAMN/res/YAMN.rc2
-rw-r--r--plugins/YAMN/src/main.cpp1
-rw-r--r--plugins/YAMN/src/proto/pop3/pop3comm.cpp1
-rw-r--r--plugins/YAMN/src/proto/pop3/pop3opt.cpp2
-rw-r--r--plugins/YAMN/src/resource.h1
-rw-r--r--plugins/YAMN/src/version.h1
-rw-r--r--plugins/YAPP/src/version.h1
-rw-r--r--plugins/YAPP/src/yapp.cpp1
-rw-r--r--plugins/YARelay/src/main.cpp1
-rw-r--r--plugins/YARelay/src/version.h1
-rw-r--r--plugins/ZeroNotification/src/main.cpp1
-rw-r--r--plugins/ZeroNotification/src/version.h1
-rw-r--r--plugins/ZeroSwitch/src/ZeroSwitch.cpp1
-rw-r--r--plugins/ZeroSwitch/src/version.h1
-rw-r--r--plugins/helpers/commonheaders.h1
-rw-r--r--plugins/mRadio/mradio.dpr1
-rw-r--r--plugins/mRadio/rbass.pas18
-rw-r--r--plugins/mTextControl/src/main.cpp1
-rw-r--r--plugins/mTextControl/src/version.h1
-rw-r--r--plugins/wbOSD/src/main.cpp1
-rw-r--r--plugins/wbOSD/src/version.h1
-rw-r--r--protocols/AimOscar/CMakeLists.txt4
-rw-r--r--protocols/AimOscar/docs/changelog.txt455
-rw-r--r--protocols/AimOscar/docs/readme.txt104
-rw-r--r--protocols/AimOscar/proto_aim/CMakeLists.txt2
-rw-r--r--protocols/AimOscar/proto_aim/res/Away.icobin5430 -> 0 bytes
-rw-r--r--protocols/AimOscar/proto_aim/res/Invisible.icobin5430 -> 0 bytes
-rw-r--r--protocols/AimOscar/proto_aim/res/Offline.icobin5430 -> 0 bytes
-rw-r--r--protocols/AimOscar/proto_aim/res/Online.icobin5430 -> 0 bytes
-rw-r--r--protocols/AimOscar/proto_aim/res/Phone.icobin5430 -> 0 bytes
-rw-r--r--protocols/AimOscar/proto_aim/res/Proto_AIM.rc73
-rw-r--r--protocols/AimOscar/proto_aim/src/resource.h20
-rw-r--r--protocols/AimOscar/res/add.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/admin.icobin1150 -> 0 bytes
-rwxr-xr-xprotocols/AimOscar/res/aim.rc403
-rw-r--r--protocols/AimOscar/res/aol.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/away.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/backgroundcolor.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/block.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/bold.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/bot.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/confirmed.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/foregroundcolor.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/hiptop.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/icq.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/idle.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/inbox.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/italic.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/nbold.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/nitalic.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/nnormalscript.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/normalscript.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/nsubscript.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/nsuperscript.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/nunderline.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/oscar.icobin5430 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/profile.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/subscript.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/superscript.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/unconfirmed.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/underline.icobin1150 -> 0 bytes
-rw-r--r--protocols/AimOscar/res/version.rc55
-rw-r--r--protocols/AimOscar/src/aim.cpp128
-rw-r--r--protocols/AimOscar/src/avatars.cpp221
-rw-r--r--protocols/AimOscar/src/avatars.h52
-rw-r--r--protocols/AimOscar/src/away.cpp120
-rw-r--r--protocols/AimOscar/src/chat.cpp265
-rw-r--r--protocols/AimOscar/src/chat.h57
-rwxr-xr-xprotocols/AimOscar/src/client.cpp985
-rwxr-xr-xprotocols/AimOscar/src/connection.cpp784
-rw-r--r--protocols/AimOscar/src/conv.cpp758
-rw-r--r--protocols/AimOscar/src/conv.h56
-rw-r--r--protocols/AimOscar/src/defines.h353
-rw-r--r--protocols/AimOscar/src/direct_connect.cpp80
-rw-r--r--protocols/AimOscar/src/direct_connect.h24
-rw-r--r--protocols/AimOscar/src/error.cpp287
-rw-r--r--protocols/AimOscar/src/file.cpp546
-rw-r--r--protocols/AimOscar/src/file.h81
-rw-r--r--protocols/AimOscar/src/flap.cpp53
-rw-r--r--protocols/AimOscar/src/flap.h37
-rw-r--r--protocols/AimOscar/src/links.cpp171
-rw-r--r--protocols/AimOscar/src/links.h23
-rw-r--r--protocols/AimOscar/src/packets.cpp121
-rw-r--r--protocols/AimOscar/src/packets.h66
-rw-r--r--protocols/AimOscar/src/popup.cpp114
-rw-r--r--protocols/AimOscar/src/proto.cpp685
-rwxr-xr-xprotocols/AimOscar/src/proto.h432
-rw-r--r--protocols/AimOscar/src/proxy.cpp172
-rw-r--r--protocols/AimOscar/src/proxy.h24
-rwxr-xr-xprotocols/AimOscar/src/resource.h125
-rw-r--r--protocols/AimOscar/src/server.cpp1994
-rw-r--r--protocols/AimOscar/src/services.cpp478
-rw-r--r--protocols/AimOscar/src/snac.cpp63
-rw-r--r--protocols/AimOscar/src/snac.h49
-rw-r--r--protocols/AimOscar/src/stdafx.cxx18
-rwxr-xr-xprotocols/AimOscar/src/stdafx.h326
-rw-r--r--protocols/AimOscar/src/theme.cpp270
-rw-r--r--protocols/AimOscar/src/theme.h36
-rw-r--r--protocols/AimOscar/src/thread.cpp84
-rw-r--r--protocols/AimOscar/src/tlv.cpp102
-rw-r--r--protocols/AimOscar/src/tlv.h50
-rwxr-xr-xprotocols/AimOscar/src/ui.cpp1457
-rw-r--r--protocols/AimOscar/src/ui.h61
-rwxr-xr-xprotocols/AimOscar/src/utility.cpp663
-rwxr-xr-xprotocols/AimOscar/src/utility.h64
-rw-r--r--protocols/AimOscar/src/version.h14
-rw-r--r--protocols/Discord/src/avatars.cpp2
-rw-r--r--protocols/Discord/src/gateway.cpp2
-rw-r--r--protocols/Discord/src/main.cpp1
-rw-r--r--protocols/Discord/src/proto.h53
-rw-r--r--protocols/Discord/src/utils.cpp34
-rw-r--r--protocols/Discord/src/version.h1
-rw-r--r--protocols/Dummy/src/main.cpp1
-rw-r--r--protocols/Dummy/src/version.h1
-rw-r--r--protocols/EmLanProto/amdproto_15.vcxproj216
-rw-r--r--protocols/EmLanProto/amdproto_15.vcxproj.filters62
-rw-r--r--protocols/EmLanProto/emlanproto.vcxproj (renamed from protocols/AimOscar/aim.vcxproj)59
-rw-r--r--protocols/EmLanProto/emlanproto.vcxproj.filters4
-rw-r--r--protocols/EmLanProto/src/amdproto.cpp24
-rw-r--r--protocols/EmLanProto/src/get_time.cpp19
-rw-r--r--protocols/EmLanProto/src/lan.cpp2
-rw-r--r--protocols/EmLanProto/src/lan.h6
-rw-r--r--protocols/EmLanProto/src/mlan.cpp164
-rw-r--r--protocols/EmLanProto/src/mlan.h14
-rw-r--r--protocols/EmLanProto/src/stdafx.cxx (renamed from protocols/EmLanProto/src/stdafx.cpp)16
-rw-r--r--protocols/EmLanProto/src/stdafx.h1
-rw-r--r--protocols/EmLanProto/src/version.h3
-rw-r--r--protocols/FacebookRM/src/client.h2
-rw-r--r--protocols/FacebookRM/src/json.cpp45
-rw-r--r--protocols/FacebookRM/src/json.h60
-rw-r--r--protocols/FacebookRM/src/main.cpp1
-rw-r--r--protocols/FacebookRM/src/messages.cpp2
-rw-r--r--protocols/FacebookRM/src/proto.cpp4
-rw-r--r--protocols/FacebookRM/src/requests/contacts.h8
-rw-r--r--protocols/FacebookRM/src/requests/history.h70
-rw-r--r--protocols/FacebookRM/src/version.h1
-rw-r--r--protocols/Gadu-Gadu/src/avatar.cpp2
-rw-r--r--protocols/Gadu-Gadu/src/gg.cpp1
-rw-r--r--protocols/Gadu-Gadu/src/version.h1
-rw-r--r--protocols/ICQCorp/src/corp.cpp1
-rw-r--r--protocols/ICQCorp/src/version.h1
-rw-r--r--protocols/IRCG/res/IRC.rc29
-rw-r--r--protocols/IRCG/src/commandmonitor.cpp137
-rw-r--r--protocols/IRCG/src/irc_dlg.h5
-rw-r--r--protocols/IRCG/src/irclib.cpp8
-rw-r--r--protocols/IRCG/src/ircproto.cpp6
-rw-r--r--protocols/IRCG/src/main.cpp1
-rw-r--r--protocols/IRCG/src/options.cpp14
-rw-r--r--protocols/IRCG/src/resource.h7
-rw-r--r--protocols/IRCG/src/services.cpp9
-rw-r--r--protocols/IRCG/src/stdafx.h7
-rw-r--r--protocols/IRCG/src/version.h3
-rw-r--r--protocols/IcqOscarJ/src/init.cpp1
-rw-r--r--protocols/IcqOscarJ/src/version.h1
-rwxr-xr-xprotocols/JabberG/src/jabber.cpp1
-rwxr-xr-xprotocols/JabberG/src/jabber_caps.cpp2
-rw-r--r--protocols/JabberG/src/jabber_captcha.cpp2
-rw-r--r--protocols/JabberG/src/jabber_chat.cpp7
-rw-r--r--protocols/JabberG/src/jabber_events.cpp4
-rw-r--r--protocols/JabberG/src/jabber_ft.cpp2
-rw-r--r--protocols/JabberG/src/jabber_ibb.cpp2
-rw-r--r--protocols/JabberG/src/jabber_iq_handlers.cpp2
-rwxr-xr-xprotocols/JabberG/src/jabber_iqid.cpp4
-rwxr-xr-xprotocols/JabberG/src/jabber_misc.cpp2
-rwxr-xr-xprotocols/JabberG/src/jabber_omemo.cpp50
-rw-r--r--protocols/JabberG/src/jabber_secur.cpp20
-rw-r--r--protocols/JabberG/src/jabber_svc.cpp8
-rw-r--r--protocols/JabberG/src/jabber_vcard.cpp2
-rw-r--r--protocols/JabberG/src/stdafx.h1
-rw-r--r--protocols/JabberG/src/version.h1
-rw-r--r--protocols/MRA/src/Mra.cpp1
-rw-r--r--protocols/MRA/src/MraOfflineMsg.cpp2
-rw-r--r--protocols/MRA/src/MraSendCommand.cpp8
-rw-r--r--protocols/MRA/src/Mra_functions.cpp2
-rw-r--r--protocols/MRA/src/Mra_proto.cpp4
-rw-r--r--protocols/MRA/src/version.h1
-rw-r--r--protocols/MSN/src/msn.cpp1
-rw-r--r--protocols/MSN/src/msn_auth.cpp2
-rw-r--r--protocols/MSN/src/msn_links.cpp9
-rw-r--r--protocols/MSN/src/msn_misc.cpp6
-rw-r--r--protocols/MSN/src/msn_soapab.cpp4
-rw-r--r--protocols/MSN/src/msn_srv.cpp2
-rw-r--r--protocols/MSN/src/version.h1
-rw-r--r--protocols/MinecraftDynmap/src/main.cpp1
-rw-r--r--protocols/MinecraftDynmap/src/version.h1
-rw-r--r--protocols/Omegle/src/main.cpp1
-rw-r--r--protocols/Omegle/src/version.h1
-rw-r--r--protocols/Sametime/src/StdAfx.h2
-rw-r--r--protocols/Sametime/src/sametime.cpp1
-rw-r--r--protocols/Sametime/src/version.h1
-rw-r--r--protocols/SkypeWeb/src/main.cpp1
-rw-r--r--protocols/SkypeWeb/src/skype_utils.cpp8
-rw-r--r--protocols/SkypeWeb/src/stdafx.h2
-rw-r--r--protocols/SkypeWeb/src/version.h1
-rw-r--r--protocols/Steam/src/main.cpp1
-rw-r--r--protocols/Steam/src/steam_events.cpp4
-rw-r--r--protocols/Steam/src/version.h1
-rw-r--r--protocols/Tox/Tox.vcxproj12
-rw-r--r--protocols/Tox/bin/x64/libtox.dllbin3016025 -> 0 bytes
-rw-r--r--protocols/Tox/bin/x86/libtox.dllbin2753946 -> 0 bytes
-rw-r--r--protocols/Tox/copydll.cmd7
-rw-r--r--protocols/Tox/include/toxav.h763
-rw-r--r--protocols/Tox/include/vpx/vp8.h153
-rw-r--r--protocols/Tox/include/vpx/vp8cx.h850
-rw-r--r--protocols/Tox/include/vpx/vp8dx.h180
-rw-r--r--protocols/Tox/include/vpx/vpx_codec.h463
-rw-r--r--protocols/Tox/include/vpx/vpx_decoder.h365
-rw-r--r--protocols/Tox/include/vpx/vpx_encoder.h980
-rw-r--r--protocols/Tox/include/vpx/vpx_frame_buffer.h83
-rw-r--r--protocols/Tox/include/vpx/vpx_image.h224
-rw-r--r--protocols/Tox/include/vpx/vpx_integer.h63
-rw-r--r--protocols/Tox/libtox/docs/CHANGELOG.md450
-rw-r--r--protocols/Tox/libtox/docs/COPYING674
-rw-r--r--protocols/Tox/libtox/docs/DONATORS7
-rw-r--r--protocols/Tox/libtox/docs/README.md174
-rw-r--r--protocols/Tox/libtox/libtox.vcxproj60
-rw-r--r--protocols/Tox/libtox/libtox.vcxproj.filters (renamed from protocols/AimOscar/proto_aim/Proto_AIM.vcxproj.filters)8
-rw-r--r--protocols/Tox/libtox/src/libtox.def155
-rw-r--r--protocols/Tox/libtox/src/stdafx.cxx2
-rw-r--r--protocols/Tox/libtox/src/stdafx.h0
-rw-r--r--protocols/Tox/libtox/src/toxcore/DHT.c2853
-rw-r--r--protocols/Tox/libtox/src/toxcore/DHT.h448
-rw-r--r--protocols/Tox/libtox/src/toxcore/LAN_discovery.c410
-rw-r--r--protocols/Tox/libtox/src/toxcore/LAN_discovery.h52
-rw-r--r--protocols/Tox/libtox/src/toxcore/Messenger.c3157
-rw-r--r--protocols/Tox/libtox/src/toxcore/Messenger.h777
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_client.c991
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_client.h167
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_connection.c1491
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_connection.h223
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_server.c1417
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_server.h167
-rw-r--r--protocols/Tox/libtox/src/toxcore/ccompat.h43
-rw-r--r--protocols/Tox/libtox/src/toxcore/crypto_core.api.h246
-rw-r--r--protocols/Tox/libtox/src/toxcore/crypto_core.c287
-rw-r--r--protocols/Tox/libtox/src/toxcore/crypto_core.h234
-rw-r--r--protocols/Tox/libtox/src/toxcore/crypto_core_mem.c87
-rw-r--r--protocols/Tox/libtox/src/toxcore/friend_connection.c937
-rw-r--r--protocols/Tox/libtox/src/toxcore/friend_connection.h210
-rw-r--r--protocols/Tox/libtox/src/toxcore/friend_requests.c152
-rw-r--r--protocols/Tox/libtox/src/toxcore/friend_requests.h76
-rw-r--r--protocols/Tox/libtox/src/toxcore/group.c2544
-rw-r--r--protocols/Tox/libtox/src/toxcore/group.h395
-rw-r--r--protocols/Tox/libtox/src/toxcore/list.c266
-rw-r--r--protocols/Tox/libtox/src/toxcore/list.h85
-rw-r--r--protocols/Tox/libtox/src/toxcore/logger.c77
-rw-r--r--protocols/Tox/libtox/src/toxcore/logger.h80
-rw-r--r--protocols/Tox/libtox/src/toxcore/net_crypto.c2908
-rw-r--r--protocols/Tox/libtox/src/toxcore/net_crypto.h428
-rw-r--r--protocols/Tox/libtox/src/toxcore/network.c1446
-rw-r--r--protocols/Tox/libtox/src/toxcore/network.h424
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion.c679
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion.h165
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion_announce.c497
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion_announce.h140
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion_client.c1771
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion_client.h302
-rw-r--r--protocols/Tox/libtox/src/toxcore/ping.c381
-rw-r--r--protocols/Tox/libtox/src/toxcore/ping.h54
-rw-r--r--protocols/Tox/libtox/src/toxcore/ping_array.c172
-rw-r--r--protocols/Tox/libtox/src/toxcore/ping_array.h76
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox.api.h2583
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox.c1551
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox.h (renamed from protocols/Tox/include/tox.h)2
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_api.c97
-rw-r--r--protocols/Tox/libtox/src/toxcore/util.c195
-rw-r--r--protocols/Tox/libtox/src/toxcore/util.h64
-rw-r--r--protocols/Tox/libtox/src/toxdns/toxdns.c243
-rw-r--r--protocols/Tox/libtox/src/toxdns/toxdns.h (renamed from protocols/Tox/include/toxdns.h)0
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h92
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt-common.c257
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt.h93
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/export.h38
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c309
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/note_to_maintainers.txt14
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.c97
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.h52
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c211
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.c140
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.h33
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/scrypt_platform.c107
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c398
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sysendian.h153
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.c78
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.h40
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/defines.h2
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.api.h327
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c338
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h (renamed from protocols/Tox/include/toxencryptsave.h)2
-rw-r--r--protocols/Tox/res/Icons/audio_call.icobin5430 -> 0 bytes
-rw-r--r--protocols/Tox/res/Icons/audio_end.icobin5430 -> 0 bytes
-rw-r--r--protocols/Tox/res/Icons/audio_ring.icobin5430 -> 0 bytes
-rw-r--r--protocols/Tox/res/Icons/audio_start.icobin5430 -> 0 bytes
-rw-r--r--protocols/Tox/res/resource.rc204
-rw-r--r--protocols/Tox/src/api_av.cpp98
-rw-r--r--protocols/Tox/src/api_avatars.cpp43
-rw-r--r--protocols/Tox/src/api_connection.cpp28
-rw-r--r--protocols/Tox/src/api_dns.cpp23
-rw-r--r--protocols/Tox/src/api_encryption.cpp18
-rw-r--r--protocols/Tox/src/api_friends.cpp135
-rw-r--r--protocols/Tox/src/api_groupchats.cpp96
-rw-r--r--protocols/Tox/src/api_main.cpp131
-rw-r--r--protocols/Tox/src/api_transfer.cpp63
-rw-r--r--protocols/Tox/src/main.cpp34
-rw-r--r--protocols/Tox/src/resource.h46
-rw-r--r--protocols/Tox/src/stdafx.h33
-rw-r--r--protocols/Tox/src/tox_accounts.cpp7
-rw-r--r--protocols/Tox/src/tox_avatars.cpp4
-rw-r--r--protocols/Tox/src/tox_bootstrap.cpp4
-rw-r--r--protocols/Tox/src/tox_chatrooms.cpp326
-rw-r--r--protocols/Tox/src/tox_chatrooms.h10
-rw-r--r--protocols/Tox/src/tox_connection.cpp6
-rw-r--r--protocols/Tox/src/tox_contacts.cpp35
-rw-r--r--protocols/Tox/src/tox_core.cpp19
-rw-r--r--protocols/Tox/src/tox_events.cpp32
-rw-r--r--protocols/Tox/src/tox_icons.cpp4
-rw-r--r--protocols/Tox/src/tox_menus.cpp69
-rw-r--r--protocols/Tox/src/tox_menus.h6
-rw-r--r--protocols/Tox/src/tox_messages.cpp19
-rw-r--r--protocols/Tox/src/tox_multimedia.cpp626
-rw-r--r--protocols/Tox/src/tox_multimedia.h84
-rw-r--r--protocols/Tox/src/tox_options.cpp177
-rw-r--r--protocols/Tox/src/tox_options.h36
-rw-r--r--protocols/Tox/src/tox_profile.cpp229
-rw-r--r--protocols/Tox/src/tox_profile.h57
-rw-r--r--protocols/Tox/src/tox_proto.cpp47
-rw-r--r--protocols/Tox/src/tox_proto.h87
-rw-r--r--protocols/Tox/src/tox_search.cpp7
-rw-r--r--protocols/Tox/src/tox_services.cpp2
-rw-r--r--protocols/Tox/src/tox_thread.h13
-rw-r--r--protocols/Tox/src/tox_transfer.cpp34
-rw-r--r--protocols/Tox/src/tox_utils.cpp7
-rw-r--r--protocols/Tox/src/version.h5
-rw-r--r--protocols/Tox/tools/CHANGES266
-rw-r--r--protocols/Tox/tools/FEATURES33
-rw-r--r--protocols/Tox/tools/INSTALL71
-rw-r--r--protocols/Tox/tools/LICENSE201
-rw-r--r--protocols/Tox/tools/README139
-rw-r--r--protocols/Tox/tools/TODO28
-rw-r--r--protocols/Tox/tools/VERSION1
-rw-r--r--protocols/Tox/tools/cv2pdb.exebin243712 -> 0 bytes
-rw-r--r--protocols/Twitter/src/main.cpp1
-rw-r--r--protocols/Twitter/src/utility.cpp2
-rw-r--r--protocols/Twitter/src/version.h1
-rw-r--r--protocols/VKontakte/src/main.cpp1
-rw-r--r--protocols/VKontakte/src/misc.cpp38
-rw-r--r--protocols/VKontakte/src/version.h3
-rw-r--r--protocols/VKontakte/src/vk.h5
-rw-r--r--protocols/VKontakte/src/vk_messages.cpp17
-rw-r--r--protocols/VKontakte/src/vk_pollserver.cpp11
-rw-r--r--protocols/VKontakte/src/vk_proto.cpp1
-rw-r--r--protocols/VKontakte/src/vk_proto.h2
-rw-r--r--protocols/VKontakte/src/vk_struct.h30
-rw-r--r--src/core/stdautoaway/src/autoaway.cpp4
-rw-r--r--src/core/stdautoaway/src/main.cpp1
-rw-r--r--src/core/stdautoaway/src/version.h1
-rw-r--r--src/core/stdaway/src/main.cpp1
-rw-r--r--src/core/stdaway/src/sendmsg.cpp80
-rw-r--r--src/core/stdaway/src/version.h1
-rw-r--r--src/core/stdclist/src/init.cpp1
-rw-r--r--src/core/stdclist/src/version.h1
-rw-r--r--src/core/stdcrypt/src/main.cpp1
-rw-r--r--src/core/stdcrypt/src/version.h1
-rw-r--r--src/core/stdemail/src/main.cpp1
-rw-r--r--src/core/stdemail/src/version.h1
-rw-r--r--src/core/stdfile/src/filerecvdlg.cpp13
-rw-r--r--src/core/stdfile/src/main.cpp1
-rw-r--r--src/core/stdfile/src/stdafx.h1
-rw-r--r--src/core/stdfile/src/version.h1
-rw-r--r--src/core/stdidle/res/resource.rc4
-rw-r--r--src/core/stdidle/src/idle.cpp327
-rw-r--r--src/core/stdidle/src/main.cpp1
-rw-r--r--src/core/stdidle/src/options.cpp134
-rw-r--r--src/core/stdidle/src/stdafx.h33
-rw-r--r--src/core/stdidle/src/version.h1
-rw-r--r--src/core/stdmsg/src/msgdialog.cpp9
-rw-r--r--src/core/stdmsg/src/srmm.cpp1
-rw-r--r--src/core/stdmsg/src/stdafx.h1
-rw-r--r--src/core/stdmsg/src/version.h1
-rw-r--r--src/core/stdssl/src/main.cpp1
-rw-r--r--src/core/stdssl/src/version.h1
-rw-r--r--src/core/stduihist/src/main.cpp1
-rw-r--r--src/core/stduihist/src/version.h1
-rw-r--r--src/core/stduserinfo/src/main.cpp1
-rw-r--r--src/core/stduserinfo/src/version.h1
-rw-r--r--src/core/stduseronline/src/main.cpp1
-rw-r--r--src/core/stduseronline/src/version.h1
-rw-r--r--src/mir_app/res/resource.rc6
-rw-r--r--src/mir_app/src/MDatabaseCommon.cpp2
-rw-r--r--src/mir_app/src/addcontact.cpp184
-rw-r--r--src/mir_app/src/auth.cpp276
-rw-r--r--src/mir_app/src/authdialogs.cpp286
-rw-r--r--src/mir_app/src/clui.cpp6
-rw-r--r--src/mir_app/src/colorchooser.cpp40
-rw-r--r--src/mir_app/src/db_ini.cpp2
-rw-r--r--src/mir_app/src/findadd.cpp48
-rw-r--r--src/mir_app/src/mir_app.def4
-rw-r--r--src/mir_app/src/mir_app64.def4
-rw-r--r--src/mir_app/src/modules.cpp2
-rw-r--r--src/mir_app/src/netlibsecurity.cpp6
-rw-r--r--src/mir_app/src/newplugins.cpp44
-rw-r--r--src/mir_app/src/options.cpp8
-rw-r--r--src/mir_app/src/pluginopts.cpp17
-rw-r--r--src/mir_app/src/resource.h1
-rw-r--r--src/mir_app/src/searchresults.cpp9
-rw-r--r--src/mir_app/src/srmm_base.cpp43
-rw-r--r--src/mir_app/src/stdafx.h1
-rwxr-xr-xsrc/mir_core/src/http.cpp13
-rw-r--r--src/mir_core/src/mir_core.def1
-rw-r--r--src/mir_core/src/mir_core64.def1
-rw-r--r--src/mir_core/src/stdafx.h1
-rw-r--r--src/mir_core/src/utf.cpp2
-rw-r--r--src/mir_core/src/winver.cpp15
-rw-r--r--tools/WinSCP/WinSCP.combin284496 -> 284496 bytes
-rw-r--r--tools/WinSCP/WinSCP.exebin19146960 -> 19149008 bytes
-rw-r--r--tools/boost/build_boost.bat6
-rw-r--r--tools/build_scripts/bin15/z2_PackPluginUpdater_x32.txt2
-rw-r--r--tools/build_scripts/bin15/z2_PackPluginUpdater_x64.txt2
-rw-r--r--tools/build_scripts/z2_PackPluginUpdater.bat3
-rw-r--r--tools/installer_ng/Common/Files/Settings/mirandaboot_default.ini4
-rw-r--r--tools/installer_ng/Common/Files/Settings/mirandaboot_portable.ini4
-rw-r--r--tools/installer_ng_stable/Common/Files/Settings/mirandaboot_default.ini4
-rw-r--r--tools/installer_ng_stable/Common/Files/Settings/mirandaboot_portable.ini4
-rw-r--r--tools/lpgen/lpgen.js4
1674 files changed, 114438 insertions, 47322 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000000..fff2a59f2a
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,4 @@
+[submodule "plugins/Dbx_mdb/src/libmdbx"]
+ path = plugins/Dbx_mdb/src/libmdbx
+ url = https://github.com/leo-yuriev/libmdbx.git
+ branch = master
diff --git a/README.md b/README.md
index 0b11e925f6..b56287467a 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,6 @@ fast.
## Protocol Support ##
-- AIM (AOL Instant Messenger)
- Discord
- Em-LAN
- Facebook
diff --git a/bin15/mir_full.sln b/bin15/mir_full.sln
index 95af5dbacf..1470f0cb55 100644
--- a/bin15/mir_full.sln
+++ b/bin15/mir_full.sln
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.27004.2010
+VisualStudioVersion = 15.0.27130.2010
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Miranda", "..\src\miranda32\miranda32.vcxproj", "{F9916510-9055-4C9F-997A-3755DEC1511B}"
ProjectSection(ProjectDependencies) = postProject
@@ -28,8 +28,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Scriver", "..\plugins\Scriv
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TabSRMM", "..\plugins\TabSRMM\tabsrmm.vcxproj", "{99D26CA1-BFD4-4E77-9A1E-919E54CF33F7}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AIM", "..\protocols\AimOscar\aim.vcxproj", "{736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}"
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GG", "..\protocols\Gadu-Gadu\Gadu-Gadu_15.vcxproj", "{6DA1396F-2A44-4D5C-8442-012F71006217}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IRC", "..\protocols\IRCG\IRC.vcxproj", "{3A12F777-56A8-42EC-BD17-8F325524241E}"
@@ -164,8 +162,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MirOTR", "..\plugins\MirOTR
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NewEventNotify", "..\plugins\NewEventNotify\neweventnotify.vcxproj", "{2E0A2793-94C3-82E7-2AB0-FD421816CFBF}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileAsMessage", "..\plugins\FileAsMessage\fileecho_15.vcxproj", "{D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}"
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WhoUsesMyFiles", "..\plugins\WhoUsesMyFiles\wumf.vcxproj", "{F29CCB9B-79CF-4341-AA05-3626A036D3E3}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CryptoPP", "..\plugins\CryptoPP\cryptopp_15.vcxproj", "{4AC1E062-0236-4E49-AA04-F732043D2DCF}"
@@ -278,8 +274,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NoHistory", "..\plugins\NoH
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NotesReminders", "..\plugins\NotesAndReminders\NotesReminders_15.vcxproj", "{EEB57129-946C-4B98-8856-FDA501AE2A5E}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EmLanProto", "..\protocols\EmLanProto\amdproto_15.vcxproj", "{2115FEBC-1EC4-4F95-A058-A523ED5295A4}"
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "YAMN", "..\plugins\YAMN\YAMN.vcxproj", "{C5A87409-F08C-4A07-A8F9-1F5D52BA6D72}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NewsAggregator", "..\plugins\NewsAggregator\NewsAggregator.vcxproj", "{6DE11A47-2268-4B08-8DE5-15A1705FCE28}"
@@ -426,6 +420,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AsSingleWindow", "..\plugin
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sqlite3", "..\libs\sqlite3\sqlite3.vcxproj", "{0C02E395-E73F-47E3-8B95-B7924C0C7A6A}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libsodium", "..\libs\libsodium\libsodium.vcxproj", "{A185B162-6CB6-4502-B03F-B56F7699A8D9}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pthreads", "..\libs\pthreads\pthreads.vcxproj", "{E0EBB8A5-B577-414C-A5F9-9B4E2A0A66E9}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtox", "..\protocols\Tox\libtox\libtox.vcxproj", "{A21C50CD-28A6-481A-A12B-47189FE66641}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileAsMessage", "..\plugins\FileAsMessage\fileecho.vcxproj", "{D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EmLanProto", "..\protocols\EmLanProto\emlanproto.vcxproj", "{2115FEBC-1EC4-4F95-A058-A523ED5295A4}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -522,14 +526,6 @@ Global
{99D26CA1-BFD4-4E77-9A1E-919E54CF33F7}.Release|Win32.Build.0 = Release|Win32
{99D26CA1-BFD4-4E77-9A1E-919E54CF33F7}.Release|x64.ActiveCfg = Release|x64
{99D26CA1-BFD4-4E77-9A1E-919E54CF33F7}.Release|x64.Build.0 = Release|x64
- {736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}.Debug|Win32.ActiveCfg = Debug|Win32
- {736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}.Debug|Win32.Build.0 = Debug|Win32
- {736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}.Debug|x64.ActiveCfg = Debug|x64
- {736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}.Debug|x64.Build.0 = Debug|x64
- {736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}.Release|Win32.ActiveCfg = Release|Win32
- {736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}.Release|Win32.Build.0 = Release|Win32
- {736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}.Release|x64.ActiveCfg = Release|x64
- {736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}.Release|x64.Build.0 = Release|x64
{6DA1396F-2A44-4D5C-8442-012F71006217}.Debug|Win32.ActiveCfg = Debug|Win32
{6DA1396F-2A44-4D5C-8442-012F71006217}.Debug|Win32.Build.0 = Debug|Win32
{6DA1396F-2A44-4D5C-8442-012F71006217}.Debug|x64.ActiveCfg = Debug|x64
@@ -1066,14 +1062,6 @@ Global
{2E0A2793-94C3-82E7-2AB0-FD421816CFBF}.Release|Win32.Build.0 = Release|Win32
{2E0A2793-94C3-82E7-2AB0-FD421816CFBF}.Release|x64.ActiveCfg = Release|x64
{2E0A2793-94C3-82E7-2AB0-FD421816CFBF}.Release|x64.Build.0 = Release|x64
- {D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}.Debug|Win32.ActiveCfg = Debug|Win32
- {D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}.Debug|Win32.Build.0 = Debug|Win32
- {D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}.Debug|x64.ActiveCfg = Debug|x64
- {D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}.Debug|x64.Build.0 = Debug|x64
- {D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}.Release|Win32.ActiveCfg = Release|Win32
- {D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}.Release|Win32.Build.0 = Release|Win32
- {D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}.Release|x64.ActiveCfg = Release|x64
- {D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}.Release|x64.Build.0 = Release|x64
{F29CCB9B-79CF-4341-AA05-3626A036D3E3}.Debug|Win32.ActiveCfg = Debug|Win32
{F29CCB9B-79CF-4341-AA05-3626A036D3E3}.Debug|Win32.Build.0 = Debug|Win32
{F29CCB9B-79CF-4341-AA05-3626A036D3E3}.Debug|x64.ActiveCfg = Debug|x64
@@ -1378,14 +1366,6 @@ Global
{EEB57129-946C-4B98-8856-FDA501AE2A5E}.Release|Win32.Build.0 = Release|Win32
{EEB57129-946C-4B98-8856-FDA501AE2A5E}.Release|x64.ActiveCfg = Release|x64
{EEB57129-946C-4B98-8856-FDA501AE2A5E}.Release|x64.Build.0 = Release|x64
- {2115FEBC-1EC4-4F95-A058-A523ED5295A4}.Debug|Win32.ActiveCfg = Debug|Win32
- {2115FEBC-1EC4-4F95-A058-A523ED5295A4}.Debug|Win32.Build.0 = Debug|Win32
- {2115FEBC-1EC4-4F95-A058-A523ED5295A4}.Debug|x64.ActiveCfg = Debug|x64
- {2115FEBC-1EC4-4F95-A058-A523ED5295A4}.Debug|x64.Build.0 = Debug|x64
- {2115FEBC-1EC4-4F95-A058-A523ED5295A4}.Release|Win32.ActiveCfg = Release|Win32
- {2115FEBC-1EC4-4F95-A058-A523ED5295A4}.Release|Win32.Build.0 = Release|Win32
- {2115FEBC-1EC4-4F95-A058-A523ED5295A4}.Release|x64.ActiveCfg = Release|x64
- {2115FEBC-1EC4-4F95-A058-A523ED5295A4}.Release|x64.Build.0 = Release|x64
{C5A87409-F08C-4A07-A8F9-1F5D52BA6D72}.Debug|Win32.ActiveCfg = Debug|Win32
{C5A87409-F08C-4A07-A8F9-1F5D52BA6D72}.Debug|Win32.Build.0 = Debug|Win32
{C5A87409-F08C-4A07-A8F9-1F5D52BA6D72}.Debug|x64.ActiveCfg = Debug|x64
@@ -1968,6 +1948,46 @@ Global
{0C02E395-E73F-47E3-8B95-B7924C0C7A6A}.Release|Win32.Build.0 = Release|Win32
{0C02E395-E73F-47E3-8B95-B7924C0C7A6A}.Release|x64.ActiveCfg = Release|x64
{0C02E395-E73F-47E3-8B95-B7924C0C7A6A}.Release|x64.Build.0 = Release|x64
+ {A185B162-6CB6-4502-B03F-B56F7699A8D9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A185B162-6CB6-4502-B03F-B56F7699A8D9}.Debug|Win32.Build.0 = Debug|Win32
+ {A185B162-6CB6-4502-B03F-B56F7699A8D9}.Debug|x64.ActiveCfg = Debug|x64
+ {A185B162-6CB6-4502-B03F-B56F7699A8D9}.Debug|x64.Build.0 = Debug|x64
+ {A185B162-6CB6-4502-B03F-B56F7699A8D9}.Release|Win32.ActiveCfg = Release|Win32
+ {A185B162-6CB6-4502-B03F-B56F7699A8D9}.Release|Win32.Build.0 = Release|Win32
+ {A185B162-6CB6-4502-B03F-B56F7699A8D9}.Release|x64.ActiveCfg = Release|x64
+ {A185B162-6CB6-4502-B03F-B56F7699A8D9}.Release|x64.Build.0 = Release|x64
+ {E0EBB8A5-B577-414C-A5F9-9B4E2A0A66E9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E0EBB8A5-B577-414C-A5F9-9B4E2A0A66E9}.Debug|Win32.Build.0 = Debug|Win32
+ {E0EBB8A5-B577-414C-A5F9-9B4E2A0A66E9}.Debug|x64.ActiveCfg = Debug|x64
+ {E0EBB8A5-B577-414C-A5F9-9B4E2A0A66E9}.Debug|x64.Build.0 = Debug|x64
+ {E0EBB8A5-B577-414C-A5F9-9B4E2A0A66E9}.Release|Win32.ActiveCfg = Release|Win32
+ {E0EBB8A5-B577-414C-A5F9-9B4E2A0A66E9}.Release|Win32.Build.0 = Release|Win32
+ {E0EBB8A5-B577-414C-A5F9-9B4E2A0A66E9}.Release|x64.ActiveCfg = Release|x64
+ {E0EBB8A5-B577-414C-A5F9-9B4E2A0A66E9}.Release|x64.Build.0 = Release|x64
+ {A21C50CD-28A6-481A-A12B-47189FE66641}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A21C50CD-28A6-481A-A12B-47189FE66641}.Debug|Win32.Build.0 = Debug|Win32
+ {A21C50CD-28A6-481A-A12B-47189FE66641}.Debug|x64.ActiveCfg = Debug|x64
+ {A21C50CD-28A6-481A-A12B-47189FE66641}.Debug|x64.Build.0 = Debug|x64
+ {A21C50CD-28A6-481A-A12B-47189FE66641}.Release|Win32.ActiveCfg = Release|Win32
+ {A21C50CD-28A6-481A-A12B-47189FE66641}.Release|Win32.Build.0 = Release|Win32
+ {A21C50CD-28A6-481A-A12B-47189FE66641}.Release|x64.ActiveCfg = Release|x64
+ {A21C50CD-28A6-481A-A12B-47189FE66641}.Release|x64.Build.0 = Release|x64
+ {D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}.Debug|Win32.Build.0 = Debug|Win32
+ {D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}.Debug|x64.ActiveCfg = Debug|x64
+ {D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}.Debug|x64.Build.0 = Debug|x64
+ {D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}.Release|Win32.ActiveCfg = Release|Win32
+ {D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}.Release|Win32.Build.0 = Release|Win32
+ {D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}.Release|x64.ActiveCfg = Release|x64
+ {D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}.Release|x64.Build.0 = Release|x64
+ {2115FEBC-1EC4-4F95-A058-A523ED5295A4}.Debug|Win32.ActiveCfg = Debug|Win32
+ {2115FEBC-1EC4-4F95-A058-A523ED5295A4}.Debug|Win32.Build.0 = Debug|Win32
+ {2115FEBC-1EC4-4F95-A058-A523ED5295A4}.Debug|x64.ActiveCfg = Debug|x64
+ {2115FEBC-1EC4-4F95-A058-A523ED5295A4}.Debug|x64.Build.0 = Debug|x64
+ {2115FEBC-1EC4-4F95-A058-A523ED5295A4}.Release|Win32.ActiveCfg = Release|Win32
+ {2115FEBC-1EC4-4F95-A058-A523ED5295A4}.Release|Win32.Build.0 = Release|Win32
+ {2115FEBC-1EC4-4F95-A058-A523ED5295A4}.Release|x64.ActiveCfg = Release|x64
+ {2115FEBC-1EC4-4F95-A058-A523ED5295A4}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/bin15/mir_icons.sln b/bin15/mir_icons.sln
index 42b81d8914..9dd43101c8 100644
--- a/bin15/mir_icons.sln
+++ b/bin15/mir_icons.sln
@@ -16,8 +16,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UInfoEx_icons_ice_Z1", "..\
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UInfoEx_icons_ice_Z2", "..\plugins\UserInfoEx\IconPacks\ice\icons_ice_15_z2.vcxproj", "{E787B42A-6489-4078-90CD-B78B751A1284}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Proto_AIM", "..\protocols\AimOscar\proto_aim\Proto_AIM.vcxproj", "{975505EA-F0C7-4DAC-A95E-75249615F30C}"
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Proto_Facebook", "..\protocols\FacebookRM\proto_facebook\Proto_Facebook.vcxproj", "{44298314-7DD4-4EF7-B576-30E503257223}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Proto_ICQ", "..\protocols\IcqOscarJ\proto_icq\Proto_ICQ.vcxproj", "{DB3B0449-E576-4BBB-8B08-AB9E914D39CA}"
@@ -142,14 +140,6 @@ Global
{E787B42A-6489-4078-90CD-B78B751A1284}.Release|Win32.Build.0 = Release|Win32
{E787B42A-6489-4078-90CD-B78B751A1284}.Release|x64.ActiveCfg = Release|x64
{E787B42A-6489-4078-90CD-B78B751A1284}.Release|x64.Build.0 = Release|x64
- {975505EA-F0C7-4DAC-A95E-75249615F30C}.Debug|Win32.ActiveCfg = Debug|Win32
- {975505EA-F0C7-4DAC-A95E-75249615F30C}.Debug|Win32.Build.0 = Debug|Win32
- {975505EA-F0C7-4DAC-A95E-75249615F30C}.Debug|x64.ActiveCfg = Debug|x64
- {975505EA-F0C7-4DAC-A95E-75249615F30C}.Debug|x64.Build.0 = Debug|x64
- {975505EA-F0C7-4DAC-A95E-75249615F30C}.Release|Win32.ActiveCfg = Release|Win32
- {975505EA-F0C7-4DAC-A95E-75249615F30C}.Release|Win32.Build.0 = Release|Win32
- {975505EA-F0C7-4DAC-A95E-75249615F30C}.Release|x64.ActiveCfg = Release|x64
- {975505EA-F0C7-4DAC-A95E-75249615F30C}.Release|x64.Build.0 = Release|x64
{44298314-7DD4-4EF7-B576-30E503257223}.Debug|Win32.ActiveCfg = Debug|Win32
{44298314-7DD4-4EF7-B576-30E503257223}.Debug|Win32.Build.0 = Debug|Win32
{44298314-7DD4-4EF7-B576-30E503257223}.Debug|x64.ActiveCfg = Debug|x64
diff --git a/bin15/miranda32.sln b/bin15/miranda32.sln
index 963b290121..3db4994b8f 100644
--- a/bin15/miranda32.sln
+++ b/bin15/miranda32.sln
@@ -28,8 +28,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AdvaImg", "..\plugins\AdvaI
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TabSRMM", "..\plugins\TabSRMM\tabsrmm.vcxproj", "{99D26CA1-BFD4-4E77-9A1E-919E54CF33F7}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AIM", "..\protocols\AimOscar\aim.vcxproj", "{736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}"
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GG", "..\protocols\Gadu-Gadu\Gadu-Gadu_15.vcxproj", "{6DA1396F-2A44-4D5C-8442-012F71006217}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IRC", "..\protocols\IRCG\IRC.vcxproj", "{3A12F777-56A8-42EC-BD17-8F325524241E}"
@@ -48,8 +46,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xStatus_Jabber", "..\protoc
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Cln_skinedit", "..\plugins\Cln_skinedit\skinedit.vcxproj", "{987F026D-EB1F-4013-ADA8-2406ACCDA526}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Proto_AIM", "..\protocols\AimOscar\proto_aim\Proto_AIM.vcxproj", "{975505EA-F0C7-4DAC-A95E-75249615F30C}"
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Proto_GG", "..\protocols\Gadu-Gadu\proto_gg\Proto_GG.vcxproj", "{33912E32-3B68-4E2C-82AE-64C06EE987A7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Proto_ICQ", "..\protocols\IcqOscarJ\proto_icq\Proto_ICQ.vcxproj", "{DB3B0449-E576-4BBB-8B08-AB9E914D39CA}"
@@ -234,14 +230,6 @@ Global
{99D26CA1-BFD4-4E77-9A1E-919E54CF33F7}.Release|Win32.Build.0 = Release|Win32
{99D26CA1-BFD4-4E77-9A1E-919E54CF33F7}.Release|x64.ActiveCfg = Release|x64
{99D26CA1-BFD4-4E77-9A1E-919E54CF33F7}.Release|x64.Build.0 = Release|x64
- {736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}.Debug|Win32.ActiveCfg = Debug|Win32
- {736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}.Debug|Win32.Build.0 = Debug|Win32
- {736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}.Debug|x64.ActiveCfg = Debug|x64
- {736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}.Debug|x64.Build.0 = Debug|x64
- {736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}.Release|Win32.ActiveCfg = Release|Win32
- {736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}.Release|Win32.Build.0 = Release|Win32
- {736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}.Release|x64.ActiveCfg = Release|x64
- {736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}.Release|x64.Build.0 = Release|x64
{6DA1396F-2A44-4D5C-8442-012F71006217}.Debug|Win32.ActiveCfg = Debug|Win32
{6DA1396F-2A44-4D5C-8442-012F71006217}.Debug|Win32.Build.0 = Debug|Win32
{6DA1396F-2A44-4D5C-8442-012F71006217}.Debug|x64.ActiveCfg = Debug|x64
@@ -314,14 +302,6 @@ Global
{987F026D-EB1F-4013-ADA8-2406ACCDA526}.Release|Win32.Build.0 = Release|Win32
{987F026D-EB1F-4013-ADA8-2406ACCDA526}.Release|x64.ActiveCfg = Release|x64
{987F026D-EB1F-4013-ADA8-2406ACCDA526}.Release|x64.Build.0 = Release|x64
- {975505EA-F0C7-4DAC-A95E-75249615F30C}.Debug|Win32.ActiveCfg = Debug|Win32
- {975505EA-F0C7-4DAC-A95E-75249615F30C}.Debug|Win32.Build.0 = Debug|Win32
- {975505EA-F0C7-4DAC-A95E-75249615F30C}.Debug|x64.ActiveCfg = Debug|x64
- {975505EA-F0C7-4DAC-A95E-75249615F30C}.Debug|x64.Build.0 = Debug|x64
- {975505EA-F0C7-4DAC-A95E-75249615F30C}.Release|Win32.ActiveCfg = Release|Win32
- {975505EA-F0C7-4DAC-A95E-75249615F30C}.Release|Win32.Build.0 = Release|Win32
- {975505EA-F0C7-4DAC-A95E-75249615F30C}.Release|x64.ActiveCfg = Release|x64
- {975505EA-F0C7-4DAC-A95E-75249615F30C}.Release|x64.Build.0 = Release|x64
{33912E32-3B68-4E2C-82AE-64C06EE987A7}.Debug|Win32.ActiveCfg = Debug|Win32
{33912E32-3B68-4E2C-82AE-64C06EE987A7}.Debug|Win32.Build.0 = Debug|Win32
{33912E32-3B68-4E2C-82AE-64C06EE987A7}.Debug|x64.ActiveCfg = Debug|x64
diff --git a/docs/contributors.txt b/docs/contributors.txt
index 443def803a..4ebfe29fc3 100644
--- a/docs/contributors.txt
+++ b/docs/contributors.txt
@@ -1,31 +1,31 @@
Miranda NG is designed, written & supported by:
-Bartosz Białek aka Dezeath
Sergey Bolkhovskoy aka Elzor
Alexander Gluzsky aka sss
Vladislav Grishenko aka theMIROn
Ekaterina Gritsenko aka Tuarisa
George Hazan aka ghazan
-Alexey Koulakov aka Awkward
-Michael Kunz aka Protogenes
-Dmitry Kuzkin aka Bio
Alexander Lantsev aka Unsane
-Eugene Lishnevsky aka elishnevsky
-Vlad Mironov aka mironych
-Victor Pavlychko aka nullbie
-Robert Pösel aka Robyer
-Konstantin Romanov aka Kildor
Nikolai Romanovich aka MikalaiR
Ivan Rozhuk aka rozhuk
Alexander Shorin aka Kxepal
-Artem Shpynov aka FYR
Kirill Volinsky aka Mataes
Tobias Weimer aka Wishmaster
Sound pack is developed by Andre Louis aka onj
-People that previously used to develop Miranda IM Project:
+People that previously used to develop Miranda IM/NG Project:
+Robert Pösel aka Robyer
+Alexey Koulakov aka Awkward
+Bartosz Białek aka Dezeath
+Michael Kunz aka Protogenes
+Dmitry Kuzkin aka Bio
+Eugene Lishnevsky aka elishnevsky
+Vlad Mironov aka mironych
+Victor Pavlychko aka nullbie
+Konstantin Romanov aka Kildor
+Artem Shpynov aka FYR
Alexey Oblezov aka faith_healer
Ulrich Hecht aka fishbone
Vitaly Igonin aka persei
diff --git a/docs/mirandaboot.ini b/docs/mirandaboot.ini
index f42e8ef5e3..bf45aa91ee 100644
--- a/docs/mirandaboot.ini
+++ b/docs/mirandaboot.ini
@@ -70,8 +70,8 @@ Safe=CLC Icons CLUI CList SkinSounds
;Unsafe
;A space-separated list of database module names that could be altered for
;malicious purposes (e.g., by faking a login server to steal passwords).
-;Default: AIM Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
-Unsafe=AIM Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
+;Default: Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
+Unsafe=Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
;OverrideSecurityFilename
;System administrators may find it desirable to install settings without prompting
diff --git a/git_read.cmd b/git_read.cmd
index ad40fb1e75..74a4899310 100644
--- a/git_read.cmd
+++ b/git_read.cmd
@@ -1,5 +1,6 @@
@echo off
git pull --rebase=true --progress -v 2>&1 > "%temp%\report.txt"
+git submodule update --recursive --rebase
call .\build\make_ver.bat
start "" "%temp%\report.txt"
goto :eof
diff --git a/include/delphi/m_api.pas b/include/delphi/m_api.pas
index 2abea6900c..252d3fef6e 100644
--- a/include/delphi/m_api.pas
+++ b/include/delphi/m_api.pas
@@ -132,7 +132,6 @@ type
version :dword;
description:PAnsiChar;
author :PAnsiChar;
- authorEmail:PAnsiChar;
copyright :PAnsiChar;
homepage :PAnsiChar;
flags :byte; // right now the only flag, UNICODE_AWARE, is recognized here
diff --git a/include/delphi/testdll.dpr b/include/delphi/testdll.dpr
index f19fd9ea40..135ceeb0a0 100644
--- a/include/delphi/testdll.dpr
+++ b/include/delphi/testdll.dpr
@@ -14,7 +14,6 @@ begin
PluginInfo.version :=$00000001;
PluginInfo.description:='The long description of your plugin, to go in the plugin options dialog';
PluginInfo.author :='J. Random Hacker';
- PluginInfo.authorEmail:='noreply@sourceforge.net';
PluginInfo.copyright :='(c) 2003 J. Random Hacker';
PluginInfo.homepage :='http://miranda-icq.sourceforge.net/';
PluginInfo.flags :=UNICODE_AWARE;
diff --git a/include/m_addcontact.h b/include/m_addcontact.h
deleted file mode 100644
index c4ee042ef6..0000000000
--- a/include/m_addcontact.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (c) 2012-17 Miranda NG project (https://miranda-ng.org)
-Copyright (c) 2000-08 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef M_ADDCONTACT_H__
-#define M_ADDCONTACT_H__ 1
-
-typedef struct{
- int handleType; // one of the HANDLE_ constants
- union {
- MEVENT hDbEvent; // hDbEvent if acs.handleType == HANDLE_EVENT
- MCONTACT hContact; // hContact if acs.handleType == HANDLE_CONTACT
- // ignored if acs.handleType == HANDLE_SEARCHRESULT
- };
- const char *szProto; // ignored if acs.handleType != HANDLE_SEARCHRESULT
- PROTOSEARCHRESULT *psr; // ignored if acs.handleType != HANDLE_SEARCHRESULT
-}ADDCONTACTSTRUCT;
-
-/*
- Description: Open the add contact dialog, see notes
-
- wParam = [ (WPARAM)hWndParent ]
- lParam = (LPARAM)(ADDCONTACTSTRUCT*)&acs
-
- Notes:
-
- During 0.3.0.0 development (circa 2003/06/08)
-
- An entire copy of the ADDCONTACTSTRUCT structure is made,
- the PROTOSEARCHRESULT is also copied at psr->cbSize, all default
- strings are copied (even if they're not needed/used)
- if you pass a structure that is bigger than PROTOSEARCHRESULT
- then do not use pointers in the newly defined area because
- they will not be copied.
-
- passing wParam == NULL will result in a dialog that is created modeless
-
- Before the circa, a modal dialog was *always* created and
- strings within PROTOSEARCHRESULT were not copied.
-
-*/
-
-#define HANDLE_SEARCHRESULT 0
-#define HANDLE_EVENT 1
-#define HANDLE_CONTACT 2
-#define MS_ADDCONTACT_SHOW "AddContact/Show"
-
-#endif // M_ADDCONTACT_H__
diff --git a/include/m_contacts.h b/include/m_contacts.h
index 9295074932..17811981b3 100644
--- a/include/m_contacts.h
+++ b/include/m_contacts.h
@@ -79,4 +79,13 @@ EXTERN_C MIR_APP_DLL(wchar_t*) Contact_GetInfo(
MCONTACT hContact, // contact id or NULL for the global data
const char *szProto = NULL); // protocol for global data. if skipped, grabbed from hContact
+/////////////////////////////////////////////////////////////////////////////////////////
+// Add contact's dialog
+
+// passing hWnd == NULL will result in a dialog that is created modeless
+
+EXTERN_C MIR_APP_DLL(void) Contact_Add(MCONTACT hContact, HWND hwndParent = nullptr);
+EXTERN_C MIR_APP_DLL(void) Contact_AddByEvent(MEVENT hEvent, HWND hwndParent = nullptr);
+EXTERN_C MIR_APP_DLL(void) Contact_AddBySearch(const char *m_szProto, struct PROTOSEARCHRESULT *m_psr, HWND hwndParent = nullptr);
+
#endif // M_CONTACTS_H__
diff --git a/include/m_core.h b/include/m_core.h
index 6438116551..ff2e754157 100644
--- a/include/m_core.h
+++ b/include/m_core.h
@@ -397,11 +397,11 @@ MIR_CORE_DLL(void) mir_hmac_sha256(BYTE hashout[MIR_SHA256_HASH_SIZE], const BYT
///////////////////////////////////////////////////////////////////////////////
// strings
-MIR_CORE_DLL(void*) mir_base64_decode(const char *input, unsigned *outputLen);
-MIR_CORE_DLL(char*) mir_base64_encode(const BYTE *input, unsigned inputLen);
-MIR_CORE_DLL(char*) mir_base64_encodebuf(const BYTE *input, unsigned inputLen, char *output, unsigned outLen);
+MIR_CORE_DLL(void*) mir_base64_decode(const char *input, size_t *outputLen);
+MIR_CORE_DLL(char*) mir_base64_encode(const void *input, size_t inputLen);
+MIR_CORE_DLL(char*) mir_base64_encodebuf(const void *input, size_t inputLen, char *output, size_t outLen);
-__forceinline unsigned mir_base64_encode_bufsize(unsigned inputLen)
+__forceinline size_t mir_base64_encode_bufsize(size_t inputLen)
{
return 4 * ((inputLen + 2) / 3) + 1;
}
@@ -533,23 +533,18 @@ MIR_CORE_DLL(void) KillModuleSubclassing(HMODULE hInst);
///////////////////////////////////////////////////////////////////////////////
// Windows utilities
-MIR_CORE_DLL(BOOL) IsWinVerVistaPlus();
-MIR_CORE_DLL(BOOL) IsWinVer7Plus();
-MIR_CORE_DLL(BOOL) IsWinVer8Plus();
-MIR_CORE_DLL(BOOL) IsWinVer81Plus();
-MIR_CORE_DLL(BOOL) IsWinVer10Plus();
+MIR_CORE_DLL(BOOL) IsWinVerVistaPlus();
+MIR_CORE_DLL(BOOL) IsWinVer7Plus();
+MIR_CORE_DLL(BOOL) IsWinVer8Plus();
+MIR_CORE_DLL(BOOL) IsWinVer81Plus();
+MIR_CORE_DLL(BOOL) IsWinVer10Plus();
-MIR_CORE_DLL(BOOL) IsFullScreen();
-MIR_CORE_DLL(BOOL) IsWorkstationLocked();
-MIR_CORE_DLL(BOOL) IsScreenSaverRunning();
+MIR_CORE_DLL(BOOL) IsFullScreen();
+MIR_CORE_DLL(BOOL) IsWorkstationLocked();
+MIR_CORE_DLL(BOOL) IsScreenSaverRunning();
+MIR_CORE_DLL(BOOL) IsTerminalDisconnected();
-MIR_CORE_DLL(BOOL) GetOSDisplayString(wchar_t *buf, size_t bufSize);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// retrieves the hLangpack of a plugin by its HINSTANCE
-// returns hLangpack if found, or 0 if error occurred
-
-MIR_APP_DLL(int) GetPluginLangByInstance(HINSTANCE);
+MIR_CORE_DLL(BOOL) GetOSDisplayString(wchar_t *buf, size_t bufSize);
///////////////////////////////////////////////////////////////////////////////
diff --git a/include/m_idle.h b/include/m_idle.h
index 58d786ac8a..635fb7a643 100644
--- a/include/m_idle.h
+++ b/include/m_idle.h
@@ -31,9 +31,6 @@ for "long" idle. Thie module will generate long/short events based on these user
and other information too. If you are unsure which idle mode to report for, report it
for short idle.*/
-#define IDF_ISIDLE 0x1 // idle has become active (if not set, inactive)
-#define IDF_PRIVACY 0x8 // if set, the information provided shouldn't be given to third parties.
-
/*
wParam: 0
lParam: IDF_* (or'd field)
@@ -47,18 +44,11 @@ for short idle.*/
set.
Version: 0.3.4a+ (2004/09/16)
*/
-#define ME_IDLE_CHANGED "Miranda/Idle/Changed"
-typedef struct {
- int cbSize; // sizeof()
- int idleTime; // idle in mins, if zero then disabled
- int privacy; // user doesnt want other people seeing anything more than they are idle
- int aaStatus; // status to go to when user is auto away
- int aaLock; // the status shouldn't be unset if its set
- int idleType;
- int idlesoundsoff;
-}
- MIRANDA_IDLE_INFO;
+#define IDF_ISIDLE 0x1 // idle has become active (if not set, inactive)
+#define IDF_PRIVACY 0x8 // if set, the information provided shouldn't be given to third parties.
+
+#define ME_IDLE_CHANGED "Miranda/Idle/Changed"
/*
wParam; 0
@@ -69,6 +59,21 @@ typedef struct {
Version: 0.3.4 (2004/09/16)
*/
+struct MIRANDA_IDLE_INFO
+{
+ int idleTime; // idle in mins, if zero then disabled
+ int privacy; // user doesnt want other people seeing anything more than they are idle
+ int aaStatus; // status to go to when user is auto away
+ int aaLock; // the status shouldn't be unset if its set
+ int idleType;
+ int idlesoundsoff;
+};
+
#define MS_IDLE_GETIDLEINFO "Miranda/Idle/GetInfo"
+__forceinline int Idle_GetInfo(MIRANDA_IDLE_INFO &pInfo)
+{
+ return CallService(MS_IDLE_GETIDLEINFO, 0, (LPARAM)&pInfo);
+}
+
#endif // M_IDLE_H__
diff --git a/include/m_json.h b/include/m_json.h
index d63c6184e4..9211e408fb 100644
--- a/include/m_json.h
+++ b/include/m_json.h
@@ -126,6 +126,8 @@ LIBJSON_DLL(JSONNode*) json_pop_back(JSONNode *node, const char *name);
//comparison
LIBJSON_DLL(int) json_equal(JSONNode *node, JSONNode *node2);
+}
+
#ifdef __cplusplus
class JSONROOT
@@ -142,7 +144,28 @@ public:
__forceinline JSONNode* Parse(LPCSTR text) { return (m_node = json_parse(text)); }
};
-}
+struct NULL_PARAM : public PARAM
+{
+ __forceinline NULL_PARAM(LPCSTR _name) : PARAM(_name)
+ {}
+ ;
+};
+
+struct JSON_PARAM : public PARAM
+{
+ JSONNode node;
+ __forceinline JSON_PARAM(LPCSTR _name, JSONNode _node) :
+ PARAM(_name), node(_node)
+ {}
+};
+
+LIBJSON_DLL(JSONNode&) operator<<(JSONNode &json, const INT_PARAM &param);
+LIBJSON_DLL(JSONNode&) operator<<(JSONNode &json, const INT64_PARAM &param);
+LIBJSON_DLL(JSONNode&) operator<<(JSONNode &json, const BOOL_PARAM &param);
+LIBJSON_DLL(JSONNode&) operator<<(JSONNode &json, const CHAR_PARAM &param);
+LIBJSON_DLL(JSONNode&) operator<<(JSONNode &json, const WCHAR_PARAM &param);
+LIBJSON_DLL(JSONNode&) operator<<(JSONNode &json, const NULL_PARAM &param);
+LIBJSON_DLL(JSONNode&) operator<<(JSONNode &json, const JSON_PARAM &param);
#endif // __cplusplus
diff --git a/include/m_langpack.h b/include/m_langpack.h
index 7d97d36499..45e408a499 100644
--- a/include/m_langpack.h
+++ b/include/m_langpack.h
@@ -92,6 +92,12 @@ EXTERN_C MIR_CORE_DLL(int) Langpack_GetDefaultLocale(void);
EXTERN_C MIR_CORE_DLL(wchar_t*) Langpack_PcharToTchar(const char *pszStr);
/////////////////////////////////////////////////////////////////////////////////////////
+// retrieves the hLangpack of a plugin by its HINSTANCE
+// returns hLangpack if found, or 0 if error occurred
+
+EXTERN_C MIR_APP_DLL(int) GetPluginLangByInstance(HINSTANCE);
+
+/////////////////////////////////////////////////////////////////////////////////////////
// reloads langpack
// wParam = 0 (ignored)
// lParam = (LPARAM)(wchar_t*)langpack file name or NULL to reload the current one
diff --git a/include/m_message.h b/include/m_message.h
index ece398ca66..8e96220ac5 100644
--- a/include/m_message.h
+++ b/include/m_message.h
@@ -299,4 +299,9 @@ struct CustomButtonClickData
DWORD flags; // BBCF_ flags
};
+/////////////////////////////////////////////////////////////////////////////////////////
+// color table for embedded color chooser
+
+EXTERN_C MIR_APP_DLL(COLORREF*) Srmm_GetColorTable(int *pTableSize = nullptr);
+
#endif // M_MESSAGE_H__
diff --git a/include/m_protosvc.h b/include/m_protosvc.h
index cc6c6ccc13..4c1064e6e4 100644
--- a/include/m_protosvc.h
+++ b/include/m_protosvc.h
@@ -338,7 +338,8 @@ static __inline unsigned long Proto_Status2Flag(int status)
#define PSR_UNICODE 0x0001 // all strings go in UTF16-LE
#define PSR_UTF8 0x0002 // all strings go in UTF8
-typedef struct {
+struct PROTOSEARCHRESULT
+{
int cbSize;
MAllStrings nick;
MAllStrings firstName;
@@ -346,7 +347,7 @@ typedef struct {
MAllStrings email;
MAllStrings id;
int flags;
-} PROTOSEARCHRESULT;
+};
#define PS_BASICSEARCH "/BasicSearch"
@@ -371,11 +372,12 @@ typedef struct {
// Results are returned as for PS_BASICSEARCH.
// This function is only available if the PF1_SEARCHBYNAME capability is set
-typedef struct {
+struct PROTOSEARCHBYNAME
+{
wchar_t *pszNick;
wchar_t *pszFirstName;
wchar_t *pszLastName;
-} PROTOSEARCHBYNAME;
+};
#define PS_SEARCHBYNAME "/SearchByName"
@@ -405,12 +407,13 @@ typedef struct {
#define PS_SEARCHBYADVANCED "/SearchByAdvanced"
-typedef struct {
+struct CUSTOMSEARCHRESULTS
+{
size_t nSize;
int nFieldCount;
wchar_t **pszFields;
PROTOSEARCHRESULT psr;
-} CUSTOMSEARCHRESULTS;
+};
///////////////////////////////////////////////////////////////////////////////
// Adds a search result to the contact list
@@ -465,10 +468,11 @@ typedef struct {
#define FILERESUME_RENAME 3
#define FILERESUME_SKIP 4
-typedef struct {
+struct PROTOFILERESUME
+{
int action; // a FILERESUME_ flag
const wchar_t *szFilename; // full path. Only valid if action == FILERESUME_RENAME
-} PROTOFILERESUME;
+};
#define PS_FILERESUME "/FileResume"
@@ -743,14 +747,15 @@ typedef struct {
// DB event: EVENTTYPE_MESSAGE, blob contains szMessage without 0 terminator
// Return 0 - success, other failure
-typedef struct {
+struct PROTORECVEVENT
+{
DWORD flags;
DWORD timestamp; // unix time
char *szMessage; // message body in utf8
LPARAM lParam; // extra space for the network level protocol module
void *pCustomData;
DWORD cbCustomDataSize;
-} PROTORECVEVENT;
+};
#define PREF_CREATEREAD 1 // create the database event with the 'read' flag set
#define PREF_RTL 4 // 0.5+ addition: support for right-to-left messages
@@ -801,14 +806,15 @@ __forceinline INT_PTR Proto_AuthRecv(const char *szProtoName, PROTORECVEVENT *pc
#define PRFF_UNICODE 1
-typedef struct {
+struct PROTORECVFILET
+{
DWORD dwFlags; // PRFF_*
DWORD timestamp; // unix time
MAllStrings descr; // file description
int fileCount; // number of files being transferred
MAllStringArray files; // array of file names
LPARAM lParam; // extra space for the network level protocol module
-} PROTORECVFILET;
+};
#define PSR_FILE "/RecvFile"
diff --git a/include/m_system_cpp.h b/include/m_system_cpp.h
index be7c6ff84f..11ccbfc0b2 100644
--- a/include/m_system_cpp.h
+++ b/include/m_system_cpp.h
@@ -92,9 +92,8 @@ public:
__inline explicit pass_ptrA(char *_p) : mir_ptr(_p) {}
__inline ~pass_ptrA() { zero(); }
__inline char* operator = (char *_p){ zero(); return mir_ptr::operator=(_p); }
- __inline void zero()
- {
- if (data) SecureZeroMemory(data, mir_strlen(data));
+ __inline void zero() {
+ if (data) SecureZeroMemory(data, mir_strlen(data));
}
};
@@ -105,14 +104,11 @@ public:
__inline explicit pass_ptrW(wchar_t *_p) : mir_ptr(_p) {}
__inline ~pass_ptrW() { zero(); }
__inline wchar_t* operator = (wchar_t *_p){ zero(); return mir_ptr::operator=(_p); }
- __inline void zero()
- {
- if (data) SecureZeroMemory(data, mir_wstrlen(data)*sizeof(wchar_t));
+ __inline void zero() {
+ if (data) SecureZeroMemory(data, mir_wstrlen(data)*sizeof(wchar_t));
}
};
-typedef pass_ptrW pass_ptrT;
-
///////////////////////////////////////////////////////////////////////////////
// mir_cslockfull - controllable locker for the critical sections
@@ -319,6 +315,56 @@ public:
void remove(size_t sz);
};
+///////////////////////////////////////////////////////////////////////////////
+// parameter classes for XML, JSON & HTTP requests
+
+struct PARAM
+{
+ const char *szName;
+ __forceinline PARAM(const char *_name) : szName(_name)
+ {}
+};
+
+struct BOOL_PARAM : public PARAM
+{
+ bool bValue;
+ __forceinline BOOL_PARAM(const char *_name, bool _value) :
+ PARAM(_name), bValue(_value)
+ {}
+};
+
+struct INT_PARAM : public PARAM
+{
+ int32_t iValue;
+ __forceinline INT_PARAM(const char *_name, int32_t _value) :
+ PARAM(_name), iValue(_value)
+ {}
+};
+
+struct INT64_PARAM : public PARAM
+{
+ int64_t iValue;
+ __forceinline INT64_PARAM(const char *_name, int64_t _value) :
+ PARAM(_name), iValue(_value)
+ {}
+};
+
+struct CHAR_PARAM : public PARAM
+{
+ const char *szValue;
+ __forceinline CHAR_PARAM(const char *_name, const char *_value) :
+ PARAM(_name), szValue(_value)
+ {}
+};
+
+struct WCHAR_PARAM : public PARAM
+{
+ const wchar_t *wszValue;
+ __forceinline WCHAR_PARAM(const char *_name, const wchar_t *_value) :
+ PARAM(_name), wszValue(_value)
+ {}
+};
+
#endif
#endif // M_SYSTEM_CPP_H
diff --git a/include/newpluginapi.h b/include/newpluginapi.h
index 35c11c0d9b..c35502a157 100644
--- a/include/newpluginapi.h
+++ b/include/newpluginapi.h
@@ -113,7 +113,6 @@ struct PLUGININFOEX
DWORD version;
char *description;
char *author;
- char *authorEmail;
char *copyright;
char *homepage;
BYTE flags; // right now the only flag, UNICODE_AWARE, is recognized here
diff --git a/langpacks/belarusian/=CORE=.txt b/langpacks/belarusian/=CORE=.txt
index 8065aee8cc..52e4b03a6e 100644
--- a/langpacks/belarusian/=CORE=.txt
+++ b/langpacks/belarusian/=CORE=.txt
@@ -3,28 +3,6 @@
; Module: Miranda Core
; Version: 0.95.8
;============================================================
-[Authorization request]
-Запыт аўтарызацыі
-[&Authorize]
-Дазволіць
-[&Deny]
-Забараніць
-[Decide &later]
-Вырашыць &пазней
-[User &details]
-&ІнфармацыÑ
-[Reason:]
-Чыннік:
-[Denial reason:]
-Чыннік адмовы:
-[Add to contact list if authorized]
-Дадаваць у ÑÐ¿Ñ–Ñ ÐºÐ°Ð½Ñ‚Ð°ÐºÑ‚Ð°Ñž паÑÐ»Ñ Ð°ÑžÑ‚Ð°Ñ€Ñ‹Ð·Ð°Ñ†Ñ‹Ñ–
-[You were added]
-Ð’Ð°Ñ Ð´Ð°Ð´Ð°Ð»Ñ–
-[&Close]
-Зачыніць
-[&Add]
-Дадаць
[%s message for %s]
%s (%s)
[&Cancel]
@@ -287,6 +265,8 @@
ÐпіÑанне:
[&User menu]
Меню кантакта
+[User &details]
+&ІнфармацыÑ
[&History]
ГіÑторыÑ
[Incoming file transfer]
@@ -303,6 +283,8 @@
Файлы:
[Save to:]
Захоўваць у:
+[&Add]
+Дадаць
[&Open...]
Ðдкрыць...
[Open &folder]
@@ -391,10 +373,6 @@
ДапіÑаць "(1)" Ñ– г. д.
[You will always be asked about files from people not on your contact list]
Запыт заўÑёды будзе паказаны, калі чалавек не Ñž ÑпіÑе
-[About Miranda NG]
-Ðб праграме
-[Credits >]
-Ðўтары >
[Become idle if the following is left unattended:]
ПерайÑці Ñž Ñ€Ñжым чаканнÑ, калі неактыўныÑ:
[Become idle if the screen saver is active]
@@ -713,6 +691,8 @@
Зададзенае імÑ:
[Group:]
Гурт:
+[Authorization request]
+Запыт аўтарызацыі
[&Yes]
&Так
[&No]
@@ -989,6 +969,8 @@
[Insert separator]
УÑтавіць падзельнік
+[Module:]
+Модуль:
[Service:]
Cлужба:
[Default]
@@ -1123,6 +1105,26 @@ UIN, E-mail і г.д.
Прамежак кнопак:
[Hide if there isn't enough space]
Хаваць, калі недаÑтаткова меÑцы
+[&Authorize]
+Дазволіць
+[&Deny]
+Забараніць
+[Decide &later]
+Вырашыць &пазней
+[Reason:]
+Чыннік:
+[Denial reason:]
+Чыннік адмовы:
+[Add to contact list if authorized]
+Дадаваць у ÑÐ¿Ñ–Ñ ÐºÐ°Ð½Ñ‚Ð°ÐºÑ‚Ð°Ñž паÑÐ»Ñ Ð°ÑžÑ‚Ð°Ñ€Ñ‹Ð·Ð°Ñ†Ñ‹Ñ–
+[You were added]
+Ð’Ð°Ñ Ð´Ð°Ð´Ð°Ð»Ñ–
+[&Close]
+Зачыніць
+[About Miranda NG]
+Ðб праграме
+[Credits >]
+Ðўтары >
[Tray]
ТрÑй
[&Hide/Show]
@@ -1183,40 +1185,6 @@ UIN, E-mail і г.д.
[Google Translate]
-[%s requests authorization]
-%s запытаў аўтарызацыю
-[%u requests authorization]
-%u запытаў аўтарызацыю
-[%s added you to their contact list]
-%s дадаў(ла) Ð²Ð°Ñ Ñƒ Ñвой ÑпіÑ
-[%u added you to their contact list]
-%u дадаў(ла) Ð²Ð°Ñ Ñƒ Ñвой ÑпіÑ
-[Alerts]
-ÐбвеÑткі
-[Added event]
-ÐŸÐ°Ð´Ð·ÐµÑ Ð´Ð°Ð´Ð°Ð½Ð½Ñ
-[View user's details]
-Пра кантакт
-[Add contact permanently to list]
-Дадаць у ÑпіÑ
-[<Unknown>]
-ÐевÑдома
-[%s added you to the contact list\n%u (%s) on %s]
-%s дададзены(а) у Ваш ÑÐ¿Ñ–Ñ ÐºÐ°Ð½Ñ‚Ð°ÐºÑ‚Ð°Ñž\n%u (%s) у %s
-[%s added you to the contact list\n%u on %s]
-%s дададзены(а) у Ваш ÑÐ¿Ñ–Ñ ÐºÐ°Ð½Ñ‚Ð°ÐºÑ‚Ð°Ñž\n%u у %s
-[%s added you to the contact list\n%s on %s]
-%s дададзены(а) у Ваш ÑÐ¿Ñ–Ñ ÐºÐ°Ð½Ñ‚Ð°ÐºÑ‚Ð°Ñž\n%s у %s
-[(Unknown)]
-(невÑдомы)
-[%s requested authorization\n%u (%s) on %s]
-%s запытаў(ла) аўтарызацыю\n%u (%s) у %s
-[%s requested authorization\n%u on %s]
-%s запытаў(ла) аўтарызацыю\n%u у %s
-[%s requested authorization\n%s on %s]
-%s запытаў(ла) аўтарызацыю\n%s у %s
-[Feature is not supported by protocol]
-Ðе падтрымліваецца пратаколам
[Re&ad %s message]
&Прачытаць паведамленне "%s"
[Re&ad status message]
@@ -1327,6 +1295,10 @@ UIN, E-mail і г.д.
Ðбраць Ñ‚Ñчку
[My received files]
Мае Ð°Ñ‚Ñ€Ñ‹Ð¼Ð°Ð½Ñ‹Ñ Ñ„Ð°Ð¹Ð»Ñ‹
+[Add contact permanently to list]
+Дадаць у ÑпіÑ
+[View user's details]
+Пра кантакт
[View user's history]
ГіÑÑ‚Ð¾Ñ€Ñ‹Ñ Ð¿Ð°Ð²ÐµÐ´Ð°Ð¼Ð»ÐµÐ½Ð½ÑÑž
[User menu]
@@ -1391,18 +1363,6 @@ UIN, E-mail і г.д.
Перадача Ñ– праверка на віруÑÑ‹ завершаны
[Outgoing]
ВыходныÑ
-[< Copyright]
-< Правы
-[&Help]
-Даведка
-[&About...]
-&Пра праграму
-[&Support]
-&Падтрымка
-[&Miranda NG homepage]
-Ð&фіцыйны Ñайт Miranda NG
-[&Report bug]
-Паведаміць пра памылку
[Idle]
Чаканне
[Chat module]
@@ -1861,10 +1821,40 @@ Miranda не здолела загрузіць убудаваную ÑÑ–ÑÑ‚Ñм
ÐÑабіÑÑ‚Ñ‹Ñ Ð´Ð°Ð´Ð·ÐµÐ½Ñ‹Ñ
[%s is online]
%s далучаны
+[Alerts]
+ÐбвеÑткі
[Add %s]
Дадаць %s
[Please authorize my request and add me to your contact list.]
Калі лаÑка, дазвольце дадаць Ð’Ð°Ñ Ñƒ мой ÑÐ¿Ñ–Ñ ÐºÐ°Ð½Ñ‚Ð°ÐºÑ‚Ð°Ñž.
+[%s requests authorization]
+%s запытаў аўтарызацыю
+[%u requests authorization]
+%u запытаў аўтарызацыю
+[%s added you to their contact list]
+%s дадаў(ла) Ð²Ð°Ñ Ñƒ Ñвой ÑпіÑ
+[%u added you to their contact list]
+%u дадаў(ла) Ð²Ð°Ñ Ñƒ Ñвой ÑпіÑ
+[Added event]
+ÐŸÐ°Ð´Ð·ÐµÑ Ð´Ð°Ð´Ð°Ð½Ð½Ñ
+[<Unknown>]
+ÐевÑдома
+[%s added you to the contact list\n%u (%s) on %s]
+%s дададзены(а) у Ваш ÑÐ¿Ñ–Ñ ÐºÐ°Ð½Ñ‚Ð°ÐºÑ‚Ð°Ñž\n%u (%s) у %s
+[%s added you to the contact list\n%u on %s]
+%s дададзены(а) у Ваш ÑÐ¿Ñ–Ñ ÐºÐ°Ð½Ñ‚Ð°ÐºÑ‚Ð°Ñž\n%u у %s
+[%s added you to the contact list\n%s on %s]
+%s дададзены(а) у Ваш ÑÐ¿Ñ–Ñ ÐºÐ°Ð½Ñ‚Ð°ÐºÑ‚Ð°Ñž\n%s у %s
+[(Unknown)]
+(невÑдомы)
+[%s requested authorization\n%u (%s) on %s]
+%s запытаў(ла) аўтарызацыю\n%u (%s) у %s
+[%s requested authorization\n%u on %s]
+%s запытаў(ла) аўтарызацыю\n%u у %s
+[%s requested authorization\n%s on %s]
+%s запытаў(ла) аўтарызацыю\n%s у %s
+[Feature is not supported by protocol]
+Ðе падтрымліваецца пратаколам
[&Join chat]
ЗайÑці
[&Open chat window]
@@ -2133,6 +2123,18 @@ Ctrl+Шукаць дадае карыÑтальніка
ÐÑноўны Ñ‚ÑкÑÑ‚
[Small text]
Дадатковы Ñ‚ÑкÑÑ‚
+[< Copyright]
+< Правы
+[&Help]
+Даведка
+[&About...]
+&Пра праграму
+[&Support]
+&Падтрымка
+[&Miranda NG homepage]
+Ð&фіцыйны Ñайт Miranda NG
+[&Report bug]
+Паведаміць пра памылку
[Browser: Back]
[Browser: Forward]
diff --git a/langpacks/belarusian/=HEAD=.txt b/langpacks/belarusian/=HEAD=.txt
index 99e010ca2f..e4ac2fe3d0 100644
--- a/langpacks/belarusian/=HEAD=.txt
+++ b/langpacks/belarusian/=HEAD=.txt
@@ -1,6 +1,6 @@
Miranda Language Pack Version 1
Language: Belarusian (BY)
Locale: 0423
-Last-Modified-Using: 0.95.7
+Last-Modified-Using: 0.95.8
Authors: Jerbifor, Inha
Author-email: jerbifor@gmail.com \ No newline at end of file
diff --git a/langpacks/belarusian/Plugins/AIM.txt b/langpacks/belarusian/Deprecated/AIM.txt
index 62e7ae1dd1..62e7ae1dd1 100644
--- a/langpacks/belarusian/Plugins/AIM.txt
+++ b/langpacks/belarusian/Deprecated/AIM.txt
diff --git a/langpacks/belarusian/Plugins/AddContactPlus.txt b/langpacks/belarusian/Plugins/AddContactPlus.txt
index 226fdf1b77..b9af4c41a1 100644
--- a/langpacks/belarusian/Plugins/AddContactPlus.txt
+++ b/langpacks/belarusian/Plugins/AddContactPlus.txt
@@ -3,7 +3,7 @@
; File: AddContactPlus.dll
; Plugin: Add contact+
; Version: 0.9.9.2
-; Authors: Bartosz 'Dezeath' Bialek
+; Authors: Bartosz 'Dezeath' Białek
;============================================================
[Provides the ability to quickly add new contacts.]
Дае магчымаÑць хутка дадаваць Ð½Ð¾Ð²Ñ‹Ñ ÐºÐ°Ð½Ñ‚Ð°ÐºÑ‚Ñ‹.
diff --git a/langpacks/belarusian/Plugins/AsSingleWindow.txt b/langpacks/belarusian/Plugins/AsSingleWindow.txt
index 9932a80489..22f5a5e90d 100644
--- a/langpacks/belarusian/Plugins/AsSingleWindow.txt
+++ b/langpacks/belarusian/Plugins/AsSingleWindow.txt
@@ -6,24 +6,24 @@
; Authors: Aleksey Smyrnov aka Soar
;============================================================
[Allows you to move, minimize and activate Miranda's windows as if it were a single window.]
-
+ПалÑгчае маніпулÑцыі з вокнамі, Ñк быццам гÑта адно акно.
[Windows moving]
-
+ПерамÑшчÑнне вокнаў
[Contact list on the left]
-
+Ð¡Ð¿Ñ–Ñ ÐºÐ°Ð½Ñ‚Ð°ÐºÑ‚Ð°Ñž злева
[Contact list on the right]
-
+Ð¡Ð¿Ñ–Ñ ÐºÐ°Ð½Ñ‚Ð°ÐºÑ‚Ð°Ñž Ñправа
[Don't merge windows]
-
+Ðе "Ñклейваць" вокны
[At opening one more message window]
-
+Пры адкрыцці больш аднаго вакна
[Merge windows in opening order]
-
+"ПрылÑплÑць" вокны Ñž парадку адкрыццÑ
[Merge only first window]
-
+"ПрылÑплÑць" толькі першае акно
[Don't merge windows until closing]
-
+Ðдключыць "злепванне" да зачыненнÑ
[AsSingleWindow]
-
+Як_адно_вакно
[Customize]
Ð¢Ð¾Ð½ÐºÐ°Ñ Ð½Ð°Ð»Ð°Ð´Ð°
diff --git a/langpacks/belarusian/Plugins/AssocMgr.txt b/langpacks/belarusian/Plugins/AssocMgr.txt
index 5fe4d03c5d..2ebd67f98b 100644
--- a/langpacks/belarusian/Plugins/AssocMgr.txt
+++ b/langpacks/belarusian/Plugins/AssocMgr.txt
@@ -5,8 +5,8 @@
; Version: 0.2.1.0
; Authors: H. Herkenrath
;============================================================
-[Handles file type associations and URLs like aim, gg, mirpu, tlen, wpmsg, xmpp, ymsgr.]
-СупаÑтаўленне пашырÑннÑÑž файлаў Ñ– ÑпаÑылак з пратаколамі: AIM, Gadu-Gadu, Jabber, MSN, PluginUpdater, Tlen, Yahoo.
+[Handles file type associations and URLs like aim, gg, mirpu, wpmsg, xmpp, ymsgr.]
+СупаÑтаўленне пашырÑннÑÑž файлаў Ñ– ÑпаÑылак з пратаколамі: AIM, Gadu-Gadu, Jabber, MSN, PluginUpdater, Yahoo.
[Registered associations for Miranda NG:]
ЗарÑгіÑÑ‚Ñ€Ð°Ð²Ð°Ð½Ñ‹Ñ ÑупаÑтаўленні Ð´Ð»Ñ Miranda NG:
[Miscellaneous]
diff --git a/langpacks/belarusian/Plugins/BASS_interface.txt b/langpacks/belarusian/Plugins/BASS_interface.txt
index 134b524d9b..9d266947a7 100644
--- a/langpacks/belarusian/Plugins/BASS_interface.txt
+++ b/langpacks/belarusian/Plugins/BASS_interface.txt
@@ -1,19 +1,19 @@
#muuid {2f07ea05-05b5-4ff0-875d-c590da2ddac1}
;============================================================
; File: BASS_interface.dll
-; Plugin: BASS interface
+; Plugin: BASS Interface
; Version: 0.0.0.14
; Authors: tico-tico
;============================================================
-[un4seen's BASS interface Miranda NG plugin.]
-Падтрымка бібліÑÑ‚Ñкі bass.
-[un4seen's bass interface]
+[Un4seen's BASS interface Miranda NG plugin.]
+Падтрымка бібліÑÑ‚Ñкі BASS.
+[Un4seen's BASS interface]
Падтрымка бібліÑÑ‚Ñкі BASS
[bass.dll loading error]
Памылка загрузкі бібліÑÑ‚Ñкі bass.dll
[Current bass.dll path:]
БÑгучы шлÑÑ… да bass.dll:
-[Maximum number of bass internal channels:]
+[Maximum number of BASS internal channels:]
МакÑÑ–Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ ÐºÐ¾Ð»ÑŒÐºÐ°Ñць каналаў:
[Output device:]
Прылада выÑновы:
@@ -21,8 +21,8 @@
Узровень гучнаÑці:
[Quiet time:]
Ð¦Ñ–Ñ…Ð°Ñ Ð³Ð°Ð´Ð·Ñ–Ð½Ð°:
-[download bass library]
-загрузіць бібліÑÑ‚Ñку bass
+[download BASS library]
+загрузіць бібліÑÑ‚Ñку BASS
[Play only if]
Граць, калі
[Offline]
@@ -47,7 +47,7 @@
Ðбедаю
[Preview]
ПраглÑд
-[un4seen's bass version: %d.%d.%d.%d]
+[Un4seen's BASS version: %d.%d.%d.%d]
ВерÑÑ–Ñ Ð±Ñ–Ð±Ð»Ñ–ÑÑ‚Ñкі BASS: %d.%d.%d.%d
[--default device--]
--прылада па змаўчанні--
@@ -59,10 +59,12 @@
Уключыць гукі
[Frame background]
Колер фону
+[BASS Interface]
+БібліÑÑ‚Ñка BASS
[Bass Interface]
БібліÑÑ‚Ñка BASS
[Bass library]
-БібліÑÑ‚Ñка Bass
+БібліÑÑ‚Ñка BASS
[Sounds enabled]
Гукі ўключаны
[Sounds disabled]
diff --git a/langpacks/belarusian/Plugins/BasicHistory.txt b/langpacks/belarusian/Plugins/BasicHistory.txt
index 186e3716e2..c2c82a7308 100644
--- a/langpacks/belarusian/Plugins/BasicHistory.txt
+++ b/langpacks/belarusian/Plugins/BasicHistory.txt
@@ -7,7 +7,7 @@
;============================================================
[History viewer for Miranda NG.]
ПраглÑдчык гіÑторыі Ð´Ð»Ñ Miranda NG.
-[Message History]
+[Message history]
ГіÑÑ‚Ð¾Ñ€Ñ‹Ñ Ð¿Ð°Ð²ÐµÐ´Ð°Ð¼Ð»ÐµÐ½Ð½ÑÑž
[Settings]
Ðалады
@@ -15,9 +15,9 @@
ЗаўÑёды паказваць ÑÐ¿Ñ–Ñ ÐºÐ°Ð½Ñ‚Ð°ÐºÑ‚Ð°Ñž
[Show groups in contact list]
Паказваць гурты Ñž ÑпіÑе кантактаў
-[Do not show Find control border]
+[Do not show find control border]
Ðе малÑваць рамку Ð´Ð»Ñ Ñ€Ð°Ð´ÐºÐ° пошуку
-[Default Event Filter]
+[Default event filter]
Фільтр падзей
[Custom filters]
Свае фільтры
@@ -55,31 +55,31 @@
Паказваць дату
[Show seconds in timestamps]
Паказваць Ñекунды
-[Enable Smileys]
+[Enable smileys]
Уключыць Ñмайлы
[Search forward in list group]
Шукаць далей у гурце
[Search forward in message window]
Шукаць далей у вакне гутаркі
-[Match Case]
+[Match case]
Улічваць Ñ€ÑгіÑтр
-[Match Whole Word]
+[Match whole word]
Слова цалкам
-[Only Incoming Messages]
+[Only incoming messages]
Толькі ÑžÐ²Ð°Ñ…Ð¾Ð´Ð½Ñ‹Ñ Ð¿Ð°Ð²ÐµÐ´Ð°Ð¼Ð»ÐµÐ½Ð½Ñ–
-[Only Outgoing Messages]
+[Only outgoing messages]
Толькі Ð²Ñ‹Ñ…Ð¾Ð´Ð½Ñ‹Ñ Ð¿Ð°Ð²ÐµÐ´Ð°Ð¼Ð»ÐµÐ½Ð½Ñ–
-[Only Selected Group]
+[Only selected group]
Толькі абраны гурт
-[All Contacts]
+[All contacts]
УÑе кантакты
-[Export To Txt]
+[Export to txt]
ЭкÑпарт у Ñ‚ÑкÑÑ‚
[File encoding*]
Кадоўка файла*
-[Export To Plain Html]
+[Export to plain HTML]
ЭкÑпарт у чыÑты HTML
-[Export To Rich Html]
+[Export to rich HTML]
ЭкÑпарт у паўнавартаÑны HTML
[External CSS file]
Знешні CSS файл
@@ -139,9 +139,9 @@
СкаÑаваць
[Open History]
Ðдчыніць гіÑторыю
-[View &History]
+[View &history]
&ГіÑторыÑ
-[Delete All User History]
+[Delete all user history]
Выдаліць уÑÑŽ гіÑторыю кантакта
[Execute history task]
Выканаць задачу гіÑторыі
@@ -151,13 +151,13 @@
Зыходнае
[Status change]
Змена ÑтатуÑу
-[Show Contacts]
+[Show contacts]
Паказаць кантакты
-[Hide Contacts]
+[Hide contacts]
Схаваць кантакты
-[Find Next]
+[Find next]
ЗнайÑці далей
-[Find Previous]
+[Find previous]
ЗнайÑці раней
[Plus in export]
ÐŸÐ»ÑŽÑ Ñƒ ÑкÑпарце
@@ -175,9 +175,9 @@
СіÑÑ‚Ñма
[Me]
Я
-[Invalid Message]
+[Invalid message]
Паведамленне пашкоджана
-[%s Files (*.%s)]
+[%s files (*.%s)]
%s файлы (*.%s)
[Import]
Імпартаваць
@@ -189,7 +189,7 @@
Файл Ñпорчаны
[This operation will PERMANENTLY REMOVE all history for this contact.\nAre you sure you want to do this?]
ГÑта Ð°Ð¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ñ†Ð°Ð»ÐºÐ°Ð¼ выдаліць гіÑторыю гÑтага кантакту.\nÐ’Ñ‹ ўпÑўнены?
-[Are You sure?]
+[Are you sure?]
Ð’Ñ‹ ўпÑўнены?
[Do you want to delete all imported messages for this contact?\nNote that next scheduler task import this messages again.]
Ð’Ñ‹ хочаце выдаліць уÑе Ñ–Ð¼Ð¿Ð°Ñ€Ñ‚Ð°Ð²Ð°Ð½Ñ‹Ñ Ð¿Ð°Ð²ÐµÐ´Ð°Ð¼Ð»ÐµÐ½Ð½Ñ– гÑтага кантакту?\nПамÑтаеце, што наÑÑ‚ÑƒÐ¿Ð½Ð°Ñ Ð·Ð°Ð¿Ð»Ð°Ð½Ð°Ð²Ð°Ð½Ð°Ñ Ð·Ð°Ð´Ð°Ñ‡Ð° будзе зноў імпартуе гÑÑ‚Ñ‹Ñ Ð¿Ð°Ð²ÐµÐ´Ð°Ð¼Ð»ÐµÐ½Ð½Ñ–.
@@ -203,11 +203,11 @@
КапіÑваць
[Delete]
Выдаліць
-[Send Message]
+[Send message]
Ðдправіць
-[Reply &Quoted]
+[Reply &quoted]
Ðдказаць з &цытатай
-[Delete Group]
+[Delete group]
Выдаленне гурту
[Options]
Ðалады
@@ -219,9 +219,9 @@
Ðбразкі
[Hotkeys]
Ð“Ð°Ñ€Ð°Ñ‡Ñ‹Ñ ÐºÐ»Ð°Ð²Ñ–ÑˆÑ‹
-[Rich Html]
+[Rich HTML]
ПаўнавартаÑны HTML
-[Plain Html]
+[Plain HTML]
ЧыÑты HTML
[Txt]
Txt
@@ -295,28 +295,28 @@ Dat (мКантакты)
Ð“Ð»Ð°Ð±Ð°Ð»ÑŒÐ½Ð°Ñ Ð³Ñ–ÑторыÑ
[Find]
ЗнайÑці
-[Switch Match Case]
+[Switch match case]
Улічваць Ñ€ÑгіÑтр
-[Switch Match Whole Word]
+[Switch match whole word]
Слова цалкам
-[Show/Hide Contacts]
+[Show/hide contacts]
Паказаць/Ñхаваць кантакты
-[Switch Only Incoming Messages]
+[Switch only incoming messages]
Толькі ÑžÐ²Ð°Ñ…Ð¾Ð´Ð½Ñ‹Ñ Ð¿Ð°Ð²ÐµÐ´Ð°Ð¼Ð»ÐµÐ½Ð½Ñ–
-[Switch Only Outgoing Messages]
+[Switch only outgoing messages]
Толькі Ð²Ñ‹Ñ…Ð¾Ð´Ð½Ñ‹Ñ Ð¿Ð°Ð²ÐµÐ´Ð°Ð¼Ð»ÐµÐ½Ð½Ñ–
-[Switch Only Selected Group]
+[Switch only selected group]
Толькі Ð°Ð±Ñ€Ð°Ð½Ñ‹Ñ Ð³ÑƒÑ€Ñ‚Ñ‹
-[Switch All Contacts]
+[Switch all contacts]
УÑе кантакты
-[Export To Binary]
+[Export to binary]
ЭкÑпарт у двайковы файл
-[Import From Binary]
+[Import from binary]
Імпарт з двайковага файла
-[Export To Dat (mContacts)]
-ЭкÑпарт у Dat (мКантакты)
-[Import From Dat (mContacts)]
-Імпарт з Dat (мКантакты)
+[Export to dat (mContacts)]
+ЭкÑпарт у dat (мКантакты)
+[Import from dat (mContacts)]
+Імпарт з dat (мКантакты)
[Invalid event number]
Ðепрымальны нумар падзеі
[Incoming events]
@@ -327,7 +327,7 @@ Dat (мКантакты)
Файл адÑутнічае. УвÑдзі дакладны шлÑÑ… да файла.
[Invalid file]
ÐÑÑлушны файл
-[All Files (*.*)]
+[All files (*.*)]
УÑе файлы (*.*)
[Enter filter name]
УвÑдзіце Ñ–Ð¼Ñ Ñ„Ñ–Ð»ÑŒÑ‚Ñ€Ð°
@@ -345,17 +345,17 @@ Dat (мКантакты)
ÐÑÑÐ»ÑƒÑˆÐ½Ð°Ñ ÐºÐ¾Ð´Ð°Ð²Ð°Ñ Ñтаронка
[Browse CSS file]
Паказаць CSS файл
-[Export and Delete]
+[Export and delete]
ЭкÑпартаваць Ñ– выдаліць
-[Import and Merge]
+[Import and merge]
Імпарт і зьліцьцё
[Minute]
Хвілін
[Hour]
Гадзін
-[At Start]
+[At start]
Пры запуÑку
-[At Finish]
+[At finish]
Пры выйÑці
[Daily]
Дзён
@@ -399,7 +399,7 @@ Dat (мКантакты)
Імпарт з:
[** Use <date> to insert date, <ext> to insert extension, <contact> to insert contact name]
** <date> - уÑтаўлÑе дату, <ext> - пашырÑнне, <contact> - Ñ–Ð¼Ñ ÐºÐ°Ð½Ñ‚Ð°ÐºÑ‚Ñƒ
-[History Log]
+[History log]
ПраглÑд гіÑторыі
[Filter:]
Фільтр:
diff --git a/langpacks/belarusian/Plugins/Clist_modern.txt b/langpacks/belarusian/Plugins/Clist_modern.txt
index a26349c4a5..25e7eabe65 100644
--- a/langpacks/belarusian/Plugins/Clist_modern.txt
+++ b/langpacks/belarusian/Plugins/Clist_modern.txt
@@ -49,6 +49,8 @@
* Ð”Ð»Ñ Ð·Ð¼ÑненнÑÑž патрÑбны перазапуÑк
[Skin folder]
+[Download more skins]
+Запампаваць Ñкіны
[Available view modes]
ДаÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ñ€Ñжымы выглÑду
[Include protocols]
diff --git a/langpacks/belarusian/Plugins/Clist_nicer.txt b/langpacks/belarusian/Plugins/Clist_nicer.txt
index 487c0862ea..0c579a5af1 100644
--- a/langpacks/belarusian/Plugins/Clist_nicer.txt
+++ b/langpacks/belarusian/Plugins/Clist_nicer.txt
@@ -379,6 +379,8 @@
Ð’Ñ‹ÑˆÑ‹Ð½Ñ Ð½Ð°Ð·Ð²Ñ‹ фрÑйма
[Ignore selection for groups]
Ігнараваць вылучÑнне Ð´Ð»Ñ Ð³ÑƒÑ€Ñ‚Ð¾Ñž
+[Download more skins]
+Запампаваць Ñкіны
[Load from skin file]
Загрузіць з файла
[Export to skin file]
diff --git a/langpacks/belarusian/Plugins/CloudFile.txt b/langpacks/belarusian/Plugins/CloudFile.txt
index 20be4b1ce4..4531f5c90d 100644
--- a/langpacks/belarusian/Plugins/CloudFile.txt
+++ b/langpacks/belarusian/Plugins/CloudFile.txt
@@ -2,7 +2,7 @@
;============================================================
; File: CloudFile.dll
; Plugin: CloudFile
-; Version: 0.11.0.2
+; Version: 0.11.0.3
; Authors: Miranda NG Team
;============================================================
[Allows you to transfer files via cloud services.]
diff --git a/langpacks/belarusian/Plugins/DbEditorPP.txt b/langpacks/belarusian/Plugins/DbEditorPP.txt
index d2001359a2..949330fa36 100644
--- a/langpacks/belarusian/Plugins/DbEditorPP.txt
+++ b/langpacks/belarusian/Plugins/DbEditorPP.txt
@@ -2,7 +2,7 @@
;============================================================
; File: DbEditorPP.dll
; Plugin: Database editor++
-; Version: 4.0.1.1
+; Version: 4.0.1.2
; Authors: Bio, Jonathan Gordon
;============================================================
[Advanced Database Editor.]
@@ -326,4 +326,4 @@ INI файлы
[*** resident ***]
[Database Setting Changed: \nModule: "%s", Setting: "%s"\nNew Value (%s): "%s"]
-Зменена налада базы: \nПлагін: "%s", налада: "%s"\nÐовае значÑнне (%s): "%s"
+Зменена налада базы: \nМодуль: "%s", налада: "%s"\nÐовае значÑнне (%s): "%s"
diff --git a/langpacks/belarusian/Plugins/Fingerprint.txt b/langpacks/belarusian/Plugins/Fingerprint.txt
index 9f836bc8b1..52767dc2be 100644
--- a/langpacks/belarusian/Plugins/Fingerprint.txt
+++ b/langpacks/belarusian/Plugins/Fingerprint.txt
@@ -45,8 +45,6 @@ Fingerprint NG адлюÑтроўвае абразкі кліентаў, выкÐ
Кліенты QQ
[RSS clients]
Кліенты RSS
-[Tlen clients]
-Кліенты Tlen
[Weather clients]
Кліенты надвор'Ñ
[Yahoo clients]
@@ -103,8 +101,6 @@ Mail.Ru (невÑдомы)
TM 2008 Ñ– вышÑй
[Gadu-Gadu client]
Gadu-Gadu
-[Tlen.pl client]
-Tlen.pl
[Python-based clients]
Кліенты на Python
[Jabber client]
@@ -135,8 +131,6 @@ Jabber
MSN
[QQ overlay]
QQ
-[Tlen.pl overlay]
-Tlen.pl
[Yahoo overlay]
Yahoo
[Mail.Ru Agent overlay]
@@ -171,12 +165,6 @@ Mail.Ru Agent
[Gadu-Gadu v8 client]
-[Tlen 7.x overlay]
-
-[Tlen 6.x overlay]
-
-[Tlen 5.x overlay]
-
[TM/QQ 2012 overlay]
[TM/QQ 2011 overlay]
diff --git a/langpacks/belarusian/Plugins/GmailNotifier.txt b/langpacks/belarusian/Plugins/GmailNotifier.txt
index efa84a07ce..3c9835c567 100644
--- a/langpacks/belarusian/Plugins/GmailNotifier.txt
+++ b/langpacks/belarusian/Plugins/GmailNotifier.txt
@@ -2,7 +2,7 @@
;============================================================
; File: GmailNotifier.dll
; Plugin: Gmail Multiple Notifier
-; Version: 0.3.1.1
+; Version: 1.0.1.1
; Authors: Mixwind
;============================================================
[Check your Gmail inboxes locally.]
@@ -55,20 +55,18 @@
[Checking...]
-[Can't open Internet!]
-
-[Can't reach server!]
-
[Can't send account data!]
-[Can't get RSS feed!]
-
[Wrong name or password!]
+[Can't get RSS feed!]
+
[Other]
Іншае
[Gmail: New thread(s)]
+[Gmail Notifier connection]
+
[&Check all Gmail inboxes]
[&Check Gmail inbox]
diff --git a/langpacks/belarusian/Plugins/IEView.txt b/langpacks/belarusian/Plugins/IEView.txt
index 248b3a2928..a09ad679e6 100644
--- a/langpacks/belarusian/Plugins/IEView.txt
+++ b/langpacks/belarusian/Plugins/IEView.txt
@@ -65,6 +65,8 @@
Літарны фармат даты
[Use relative timestamp]
ÐдноÑны чаÑ
+[Download more templates]
+
[Outgoing File Transfer]
Ð’Ñ‹Ñ…Ð¾Ð´Ð½Ñ‹Ñ Ð¿ÐµÑ€Ð°Ð´Ð°Ñ‡Ñ‹ файлаў
[Incoming File Transfer]
diff --git a/langpacks/belarusian/Plugins/MSN.txt b/langpacks/belarusian/Plugins/MSN.txt
index 2309f570d9..29f82f2163 100644
--- a/langpacks/belarusian/Plugins/MSN.txt
+++ b/langpacks/belarusian/Plugins/MSN.txt
@@ -2,7 +2,7 @@
;============================================================
; File: MSN.dll
; Plugin: MSN protocol
-; Version: 0.14.0.1
+; Version: 0.14.0.2
; Authors: Boris Krasnovskiy, George Hazan, Richard Hughes, leecher
;============================================================
[Microsoft Network (MSN) protocol support for Miranda NG.]
diff --git a/langpacks/belarusian/Plugins/New_GPG.txt b/langpacks/belarusian/Plugins/New_GPG.txt
index c1b8a418a8..bc3bdcb647 100644
--- a/langpacks/belarusian/Plugins/New_GPG.txt
+++ b/langpacks/belarusian/Plugins/New_GPG.txt
@@ -173,86 +173,6 @@ ID ключа:
[GPG encryption status]
Ð¡Ñ‚Ð°Ñ‚ÑƒÑ ÑˆÑ‹Ñ„Ñ€Ð°Ð²Ð°Ð½Ð½Ñ GPG
-[Email]
-Пошта
-[Name]
-ІмÑ
-[Creation date]
-Дата ÑтварÑннÑ
-[Expire date]
-
-[Key length]
-Ð”Ð¾ÑžÐ³Ð°Ñ ÐºÐ»ÑŽÑ‡Ð°
-[Accounts]
-Конты
-[Default]
-Змаўчанні
-[key ID]
-Ключ
-[not set]
-не наладжана
-[Default private key ID]
-ÐÑноўны прыватны ключ
-[Failed to open file]
-
-[Error]
-Памылка
-[Generating new random key, please wait]
-
-[Failed to allocate memory]
-
-[Failed to lock memory with error %d]
-
-[Failed write to clipboard with error %d]
-
-[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
-
-[Warning]
-Заўвага
-[Wrong GPG binary location found in system.\nPlease choose another location]
-
-[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-Ðбраны вамі exe не GnuPG!\nРÑкамÑндуецца выкарыÑтоўваць GnuPG v1.xx з гÑтым плагінам.
-[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-Ваша верÑÑ–Ñ GnuPG не падтрымліваецца Ñ– можа працаваць не правільна!\nРÑкамÑндуецца выкарыÑтоўваць GnuPG v1.xx з гÑтым плагінам.
-["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
-
-[Info]
-Інфа
-[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
-Ваша верÑÑ–Ñ GPG падтрымліваецца. ÐœÐ¾ÑžÐ½Ñ‹Ñ Ñ„Ð°Ð¹Ð»Ñ‹ знойдзеныÑ.\nGPG Павінен працаваць нармальна.\nÐаціÑьніце ОК.
-[GPG binary does not exist.\nPlease choose another location]
-
-[Please choose GPG binary location]
-Вылучыце дырÑкторыю з GnuPG
-[Please set keyring's home directory]
-Вылучыце дырÑкторыю з ключамі GnuPG
-[There is existing key for contact, would you like to replace it with new key?]
-Ðтрыманы ключ, але Ñž кантакта ўжо Ñ‘Ñць ключ. Ð’Ñ‹ жадаеце Ñго замÑніць новым?
-[New public key was received, do you want to import it?]
-Ðтрыманы новы адкрыты ключ. Ð’Ñ‹ хочаце прынÑць Ñго?
-[Replace]
-ЗамÑніць
-[Accept]
-ПрынÑць
-[Received key from %s]
-
-[You must set encryption algorithm first]
-
-[Key length must be of length from 1024 to 4096 bits]
-
-[Invalid date]
-
-[Name must contain at least 5 characters]
-
-[Name cannot contain '(' or ')']
-
-[Invalid Email]
-
-[Generating new key, please wait...]
-
-[Failed to export public key.]
-
[GPG binary is set and valid (this is good).\n]
[GPG binary unset or invalid (plugin will not work).\n]
@@ -289,28 +209,28 @@ ID ключа:
[We received encrypted message from contact with encryption turned off.\nDo you want to turn on encryption for this contact?]
+[Warning]
+Заўвага
[Do you want to try to decrypt encrypted message?]
[We're trying to encrypt with untrusted key. Do you want to trust this key permanently?]
[Something is wrong, GPG does not understand us, aborting encryption.]
-[Services]
-Службы
-[Main]
-Галоўны
-[GnuPG Variables]
-ШлÑÑ…Ñ– да GPG
-[Messages]
-Паведамленні
-[Advanced]
-Дадаткова
[Contact]
Кантакт
[Key ID]
Ключ
+[Name]
+ІмÑ
+[Email]
+Пошта
[Protocol]
Пратакол
+[Default private key ID]
+ÐÑноўны прыватны ключ
+[not set]
+не наладжана
[This key is not used by any contact. Do you want to remove it from public keyring?]
[Key info]
@@ -327,6 +247,14 @@ ID ключа:
[.asc pubkey file]
+[Failed to allocate memory]
+
+[Error]
+Памылка
+[Failed to lock memory with error %d]
+
+[Failed write to clipboard with error %d]
+
[Failed to open clipboard with error %d]
[Set log file]
@@ -335,6 +263,8 @@ ID ключа:
Файлы лога
[Choose gpg.exe]
ЗнайÑці gpg.exe
+[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+Ðбраны вамі exe не GnuPG!\nРÑкамÑндуецца выкарыÑтоўваць GnuPG v1.xx з гÑтым плагінам.
[Set home directory]
[Load Public GPG Key for ]
@@ -351,12 +281,82 @@ ID ключа:
[Key already in secret keyring.]
+[Info]
+Інфа
[Set file containing GPG public key]
[GPG public key file]
+[Failed to open file]
+
[There is no public or private key.]
+[Services]
+Службы
+[Main]
+Галоўны
+[GnuPG Variables]
+ШлÑÑ…Ñ– да GPG
+[Messages]
+Паведамленні
+[Advanced]
+Дадаткова
+[New passwords do not match]
+ÐÐ¾Ð²Ñ‹Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ– не Ñупадаюць
+[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+Стары пароль не Ñупадае, вы можаце працÑгваць, але GPG адхіліць нÑÑлушны пароль.\nХочаце прадоўжыць?
+[Creation date]
+Дата ÑтварÑннÑ
+[Expire date]
+
+[Key length]
+Ð”Ð¾ÑžÐ³Ð°Ñ ÐºÐ»ÑŽÑ‡Ð°
+[Accounts]
+Конты
+[Default]
+Змаўчанні
+[key ID]
+Ключ
+[Generating new random key, please wait]
+
+[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
+
+[Wrong GPG binary location found in system.\nPlease choose another location]
+
+[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+Ваша верÑÑ–Ñ GnuPG не падтрымліваецца Ñ– можа працаваць не правільна!\nРÑкамÑндуецца выкарыÑтоўваць GnuPG v1.xx з гÑтым плагінам.
+["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
+
+[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
+Ваша верÑÑ–Ñ GPG падтрымліваецца. ÐœÐ¾ÑžÐ½Ñ‹Ñ Ñ„Ð°Ð¹Ð»Ñ‹ знойдзеныÑ.\nGPG Павінен працаваць нармальна.\nÐаціÑьніце ОК.
+[There is existing key for contact, would you like to replace it with new key?]
+Ðтрыманы ключ, але Ñž кантакта ўжо Ñ‘Ñць ключ. Ð’Ñ‹ жадаеце Ñго замÑніць новым?
+[New public key was received, do you want to import it?]
+Ðтрыманы новы адкрыты ключ. Ð’Ñ‹ хочаце прынÑць Ñго?
+[Replace]
+ЗамÑніць
+[Accept]
+ПрынÑць
+[Received key from %s]
+
+[You must set encryption algorithm first]
+
+[Key length must be of length from 1024 to 4096 bits]
+
+[Invalid date]
+
+[Name must contain at least 5 characters]
+
+[Name cannot contain '(' or ')']
+
+[Invalid Email]
+
+[Generating new key, please wait...]
+
+[Expiration date]
+
+[Failed to export public key.]
+
[Do you want to toggle encryption for all subcontacts?]
[Turn off GPG encryption]
@@ -387,7 +387,9 @@ ID ключа:
[Keys import result]
-[New passwords do not match]
-ÐÐ¾Ð²Ñ‹Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ– не Ñупадаюць
-[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
-Стары пароль не Ñупадае, вы можаце працÑгваць, але GPG адхіліць нÑÑлушны пароль.\nХочаце прадоўжыць?
+[GPG binary does not exist.\nPlease choose another location]
+
+[Please choose GPG binary location]
+Вылучыце дырÑкторыю з GnuPG
+[Please set keyring's home directory]
+Вылучыце дырÑкторыю з ключамі GnuPG
diff --git a/langpacks/belarusian/Plugins/SimpleStatusMsg.txt b/langpacks/belarusian/Plugins/SimpleStatusMsg.txt
index cfffd5a360..fc3a7fedc2 100644
--- a/langpacks/belarusian/Plugins/SimpleStatusMsg.txt
+++ b/langpacks/belarusian/Plugins/SimpleStatusMsg.txt
@@ -3,7 +3,7 @@
; File: SimpleStatusMsg.dll
; Plugin: Simple status message
; Version: 1.9.0.6
-; Authors: Bartosz 'Dezeath' Bialek, Harven
+; Authors: Bartosz 'Dezeath' Białek, Harven
;============================================================
[Provides a simple way to set status and away messages.]
Ð¥ÑƒÑ‚ÐºÐ°Ñ Ð·ÑŒÐ¼ÐµÐ½Ð° ÑтатуÑаў Ñ– ÑтатуÑных паведамленьнÑÑž.
diff --git a/langpacks/belarusian/Plugins/SmileyAdd.txt b/langpacks/belarusian/Plugins/SmileyAdd.txt
index 365276b8e6..31f902521c 100644
--- a/langpacks/belarusian/Plugins/SmileyAdd.txt
+++ b/langpacks/belarusian/Plugins/SmileyAdd.txt
@@ -2,7 +2,7 @@
;============================================================
; File: SmileyAdd.dll
; Plugin: SmileyAdd
-; Version: 0.2.4.2
+; Version: 0.3.0.1
; Authors: Peacow, nightwish, bid, borkra
;============================================================
[Smiley support for Miranda NG.]
@@ -91,16 +91,14 @@ HTTP далучÑнне SmileyAdd
У адпаведнаÑці з пратаколам
[Smiley pack %s for category "%s" not found.\nSelect correct smiley pack in the Options -> Customize -> Smileys.]
-[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
-Праблемы з загрузкай набору Ñмайлаў (неабходна выправіць).\nÐ”Ð»Ñ Ð¿Ð°Ð´Ñ€Ð°Ð±ÑзнаÑцÑÑž гледзіце Ñеткавы дзённік.
[Smiley #%u in file %s for smiley pack %s not found.]
Смайл #%u у файле %s Ð´Ð»Ñ Ð½Ð°Ð±Ð¾Ñ€Ñƒ Ñмайлікаў %s не знойдзены.
+[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
+Праблемы з загрузкай набору Ñмайлаў (неабходна выправіць).\nÐ”Ð»Ñ Ð¿Ð°Ð´Ñ€Ð°Ð±ÑзнаÑцÑÑž гледзіце Ñеткавы дзённік.
[%s global smiley pack]
[Standard]
СтандартныÑ
-[Regular expression "%s" in smiley pack "%s" could produce "empty matches".]
-РÑгулÑрны выраз "%s" у наборы Ñмайлаў "%s" не можа выводзіць "пуÑÑ‚Ñ‹Ñ Ð·Ð½Ð°Ñ‡Ñнні".
[Regular expression "%s" in smiley pack "%s" malformed.]
РÑгулÑрны выраз "%s" у наборы Ñмайлаў "%s" пашкоджана.
[d'Oh!]
diff --git a/langpacks/belarusian/Plugins/SplashScreen.txt b/langpacks/belarusian/Plugins/SplashScreen.txt
index 4b1cc8f808..b55488c4b1 100644
--- a/langpacks/belarusian/Plugins/SplashScreen.txt
+++ b/langpacks/belarusian/Plugins/SplashScreen.txt
@@ -37,6 +37,8 @@
AdvaImg плагін не знойдзены. Калі лаÑка, уключыце Ñго, каб мець магчымаÑць выкарыÑтоўваць выÑвы.
[Preview...]
ПраглÑд...
+[Download more splash screens]
+
[Graphic files]
Ð“Ñ€Ð°Ñ„Ñ–Ñ‡Ð½Ñ‹Ñ Ñ„Ð°Ð¹Ð»Ñ‹
[Sound Files]
diff --git a/langpacks/belarusian/Plugins/StatusManager.txt b/langpacks/belarusian/Plugins/StatusManager.txt
index 1b3763dcaa..b75bdcaa95 100644
--- a/langpacks/belarusian/Plugins/StatusManager.txt
+++ b/langpacks/belarusian/Plugins/StatusManager.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StatusManager.dll
; Plugin: Status manager
-; Version: 0.11.2.3
+; Version: 1.0.1.1
; Authors: P Boon
;============================================================
[A connection checker and auto away module. Also allows you to define the status Miranda should set on startup, configurable per protocol.]
diff --git a/langpacks/belarusian/Plugins/Steam.txt b/langpacks/belarusian/Plugins/Steam.txt
index 239d5e8684..cb318e979e 100644
--- a/langpacks/belarusian/Plugins/Steam.txt
+++ b/langpacks/belarusian/Plugins/Steam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Steam.dll
; Plugin: Steam protocol
-; Version: 0.11.6.1
+; Version: 0.11.6.3
; Authors: Miranda NG Team, Robert Pösel
;============================================================
[Steam protocol support for Miranda NG.]
diff --git a/langpacks/belarusian/Plugins/StopSpam.txt b/langpacks/belarusian/Plugins/StopSpam.txt
index 1eb8340151..a8555df2c4 100644
--- a/langpacks/belarusian/Plugins/StopSpam.txt
+++ b/langpacks/belarusian/Plugins/StopSpam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpam.dll
; Plugin: StopSpam+
-; Version: 0.0.1.5
+; Version: 0.1.0.1
; Authors: Roman Miklashevsky, A. Petkevich, Kosh&chka, persei
;============================================================
[Anti-spam plugin for Miranda NG.]
@@ -41,6 +41,8 @@
ЗапіÑваць у ÑÑ–ÑÑ‚Ñмную гіÑторыю
[StopSpam automatic message:\r\n]
Паведамленне антыÑпама:\r\n
+[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
+ÐÑма больш Ñпаму! Робаты адпачываюць!\r\n\r\nГÑты плагін працуе проÑта:\r\nУ той Ñ‡Ð°Ñ Ñк паведамленні ад кантактаў у Вашым ÑпіÑе прыходзÑць без праверкі на Ñпам, паведамленні ад невÑдомых кантактаў вам не даÑтаўлÑюцца. Ðле Ñны не ігнаруюцца, плагін адказвае проÑтым пытаннем, Ñ– калі кантакт дае правільны адказ, плагін дадае Ñго Ñž ÑпіÑ, Ð´Ð»Ñ Ñ‚Ð°Ð³Ð¾ каб ён мог звÑзацца з Вамі.
[Message sessions]
Гутаркі
[General]
@@ -49,8 +51,6 @@
Паведамленні
[Accounts]
Конты
-[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
-ÐÑма больш Ñпаму! Робаты адпачываюць!\r\n\r\nГÑты плагін працуе проÑта:\r\nУ той Ñ‡Ð°Ñ Ñк паведамленні ад кантактаў у Вашым ÑпіÑе прыходзÑць без праверкі на Ñпам, паведамленні ад невÑдомых кантактаў вам не даÑтаўлÑюцца. Ðле Ñны не ігнаруюцца, плагін адказвае проÑтым пытаннем, Ñ– калі кантакт дае правільны адказ, плагін дадае Ñго Ñž ÑпіÑ, Ð´Ð»Ñ Ñ‚Ð°Ð³Ð¾ каб ён мог звÑзацца з Вамі.
[Not In List]
Ðе Ñž ÑпіÑе
[Complete]
diff --git a/langpacks/belarusian/Plugins/StopSpamMod.txt b/langpacks/belarusian/Plugins/StopSpamMod.txt
index 2dfdb81db6..43000d2517 100644
--- a/langpacks/belarusian/Plugins/StopSpamMod.txt
+++ b/langpacks/belarusian/Plugins/StopSpamMod.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpamMod.dll
; Plugin: StopSpam mod
-; Version: 0.0.2.1
+; Version: 0.0.2.2
; Authors: Roman Miklashevsky, sss, Elzor
;============================================================
[Anti-spam plugin for Miranda NG.]
@@ -79,10 +79,10 @@
ÐÑма больш Ñпаму! Робаты адпачываюць!\r\n\r\nГÑты плагін працуе проÑта:\r\nУ той Ñ‡Ð°Ñ Ñк паведамленні ад кантактаў у Вашым ÑпіÑе прыходзÑць без праверкі на Ñпам, паведамленні ад невÑдомых кантактаў вам не даÑтаўлÑюцца. Ðле Ñны не ігнаруюцца, плагін адказвае проÑтым пытаннем, Ñ– калі кантакт дае правільны адказ, плагін дадае Ñго Ñž ÑпіÑ, Ð´Ð»Ñ Ñ‚Ð°Ð³Ð¾ каб ён мог звÑзацца з Вамі.
[Spammers made me to install small anti-spam system you are now speaking with. Please reply "nospam" without quotes and spaces if you want to contact me.]
Прывітанне! Ð’Ñ‹ гавораце з Ñ Ð°Ð½Ñ‚Ñ‹-Ñпам ботам. Клі лаÑка, напішыце "nospam" без двукоÑÑÑÑž, каб прайÑці праверку.\r\nSpammers made me to install small anti-spam system you are now speaking with. Please reply "nospam" without quotes and spaces if you want to contact me.
-[StopSpam: send a message and reply to an anti-spam bot question.]
-StopSpam: адпраўце паведамленне Ñ– адкажыце на проÑтае пытанне анты-Ñпам бота.\r\nStopSpam: send a message and reply to an anti-spam bot question.
[Congratulations! You just passed human/robot test. Now you can write me a message.]
Віншуем! Ð’Ñ‹ прайшлі Ñ‚ÑÑÑ‚, зараз можаце адпраўлÑць паведамленні канаткту.\r\nCongratulations! You just passed human/robot test. Now you can write me a message.
+[StopSpam: send a message and reply to an anti-spam bot question.]
+StopSpam: адпраўце паведамленне Ñ– адкажыце на проÑтае пытанне анты-Ñпам бота.\r\nStopSpam: send a message and reply to an anti-spam bot question.
[If math expression is turned on, you can use following expression in message text:\nXX+XX-X/X*X\neach X will be replaced by one random number and answer will be expression result.\nMessage must contain only one expression without spaces.]
Калі адключаны матÑÐ¼Ð°Ñ‚Ñ‹Ñ‡Ð½Ñ‹Ñ Ð²Ñ‹Ñ€Ð°Ð·Ñ‹, Ñ–Ñ… магчыма выкарыÑтоўваць у Ñ‚ÑкÑце пытаннÑ:\nXX+XX-X/X*X\nкожны X будзе заменены выпадковай лічбай, адказам будзе рашÑнне.\nПытанне можа ўключаць толькі адзін выраз, запіÑаны без прабелаў.
[Info]
diff --git a/langpacks/belarusian/Plugins/TabSRMM.txt b/langpacks/belarusian/Plugins/TabSRMM.txt
index e5b5363c5d..c41033ad52 100644
--- a/langpacks/belarusian/Plugins/TabSRMM.txt
+++ b/langpacks/belarusian/Plugins/TabSRMM.txt
@@ -513,6 +513,8 @@ CтатуÑÑ‹ Ð´Ð»Ñ Ð°ÑžÑ‚Ð°Ð¼Ð°Ñ‚Ñ‹Ñ‡Ð½Ð°Ð³Ð° ÑтварÑÐ½Ð½Ñ ÑžÐºÐ»Ð°Ð´Ð°Ð
ЭкÑпартаваць...
[Import from a file...]
Імпартаваць...
+[Download more skins]
+Запампаваць Ñкіны
[Icons]
Ðбразкі
[Event type icons in the message log]
diff --git a/langpacks/belarusian/Plugins/Tipper.txt b/langpacks/belarusian/Plugins/Tipper.txt
index 1796efcedb..553e41c573 100644
--- a/langpacks/belarusian/Plugins/Tipper.txt
+++ b/langpacks/belarusian/Plugins/Tipper.txt
@@ -64,7 +64,7 @@
[Label:]
Пазнака:
[Module:]
-Плагін:
+Модуль:
[Contact protocol module]
Плагін пратаколу кантакту
[Setting or prefix:]
diff --git a/langpacks/belarusian/Plugins/Tox.txt b/langpacks/belarusian/Plugins/Tox.txt
index 472b4eca07..b2837d0f52 100644
--- a/langpacks/belarusian/Plugins/Tox.txt
+++ b/langpacks/belarusian/Plugins/Tox.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Tox.dll
; Plugin: Tox protocol
-; Version: 0.11.1.25
+; Version: 0.11.1.26
; Authors: Miranda NG Team
;============================================================
[Tox protocol support for Miranda NG.]
diff --git a/langpacks/belarusian/Plugins/mRadio.txt b/langpacks/belarusian/Plugins/mRadio.txt
index f2e94b4ffe..4156eea60c 100644
--- a/langpacks/belarusian/Plugins/mRadio.txt
+++ b/langpacks/belarusian/Plugins/mRadio.txt
@@ -101,8 +101,8 @@ PreBuf, % (75%)
Кар'ер
[Sorry!]
Выбачыце!
-[BASS.DLL not found!]
-BASS.DLL не знойдзены!
+[bass.dll not found!]
+bass.dll не знойдзены!
[Station]
СтанцыÑ
[Custom INI file]
@@ -199,3 +199,5 @@ URL Ñтанцыі/плÑйліÑта
Стварыць
[Quick Open]
+[bass.dll not found! Choose bass.dll path manually]
+
diff --git a/langpacks/bulgarian/=CORE=.txt b/langpacks/bulgarian/=CORE=.txt
index 1b01ef59c6..113284cf7a 100644
--- a/langpacks/bulgarian/=CORE=.txt
+++ b/langpacks/bulgarian/=CORE=.txt
@@ -3,28 +3,6 @@
; Module: Miranda Core
; Version: 0.95.8
;============================================================
-[Authorization request]
-Молба за упълномощаване
-[&Authorize]
-Приемане
-[&Deny]
-ОтхвърлÑне
-[Decide &later]
-Попитай по-къÑно
-[User &details]
-ПодробноÑти за потребителÑ
-[Reason:]
-Причина:
-[Denial reason:]
-Причина за отказ:
-[Add to contact list if authorized]
-ДобавÑне в ÑпиÑъка Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¸ при приемане
-[You were added]
-Вие бÑхте добавен
-[&Close]
-ЗатварÑне
-[&Add]
-ДобавÑне
[%s message for %s]
ТекÑÑ‚ "%s" на %s
[&Cancel]
@@ -285,6 +263,8 @@
ОпиÑание:
[&User menu]
ПотребителÑко меню
+[User &details]
+ПодробноÑти за потребителÑ
[&History]
ИÑториÑ
[Incoming file transfer]
@@ -301,6 +281,8 @@
Файлове:
[Save to:]
Ð—Ð°Ð¿Ð¸Ñ Ð²:
+[&Add]
+ДобавÑне
[&Open...]
ОтварÑне...
[Open &folder]
@@ -389,10 +371,6 @@
Преименуване (наÑтавка (1),(2)...)
[You will always be asked about files from people not on your contact list]
Винаги ще бъдете питани за файлове, пратени от хора извън ÑпиÑъка ви Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¸
-[About Miranda NG]
-ОтноÑно Miranda NG
-[Credits >]
-ЗаÑлуги >
[Become idle if the following is left unattended:]
БездейÑтващ при липÑа на активноÑÑ‚ в:
[Become idle if the screen saver is active]
@@ -703,6 +681,8 @@ Popup за приÑтавката Chat
Избор на име:
[Group:]
Група:
+[Authorization request]
+Молба за упълномощаване
[&Yes]
Да
[&No]
@@ -961,6 +941,8 @@ Copyright:
Внимание!\r\nТова меню не поддържа дефиниране на елементи от потребителÑ.
[Insert separator]
Вмъкване на разделител
+[Module:]
+Модул:
[Service:]
УÑлуга:
[Default]
@@ -1085,6 +1067,26 @@ Miranda NG Ñе реÑтартира.\nМолÑ, изчакайте...
Пролука м/у бутоните:
[Hide if there isn't enough space]
Скриване, ако нÑма доÑтатъчно мÑÑто
+[&Authorize]
+Приемане
+[&Deny]
+ОтхвърлÑне
+[Decide &later]
+Попитай по-къÑно
+[Reason:]
+Причина:
+[Denial reason:]
+Причина за отказ:
+[Add to contact list if authorized]
+ДобавÑне в ÑпиÑъка Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¸ при приемане
+[You were added]
+Вие бÑхте добавен
+[&Close]
+ЗатварÑне
+[About Miranda NG]
+ОтноÑно Miranda NG
+[Credits >]
+ЗаÑлуги >
[Tray]
Трей
[&Hide/Show]
@@ -1143,40 +1145,6 @@ Wikipedia (en)
Google Maps
[Google Translate]
Google Translate
-[%s requests authorization]
-%s желае да бъде упълномощен
-[%u requests authorization]
-%u желае да бъде упълномощен
-[%s added you to their contact list]
-%s ви добави в ÑпиÑъка Ñи Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¸
-[%u added you to their contact list]
-%u ви добави в ÑпиÑъка Ñи Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¸
-[Alerts]
-УведомÑваниÑ
-[Added event]
-ДобавÑне на Ñъбитие
-[View user's details]
-ПодробноÑти за потребителÑ
-[Add contact permanently to list]
-ДобавÑне на контакта за поÑтоÑнно в ÑпиÑъка
-[<Unknown>]
-<ÐеизвеÑтно>
-[%s added you to the contact list\n%u (%s) on %s]
-%s ви добави в ÑпиÑъка Ñи Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¸\n%u (%s) (Ðкаунт: %s)
-[%s added you to the contact list\n%u on %s]
-%s ви добави в ÑпиÑъка Ñи Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¸\n%u (Ðкаунт: %s)
-[%s added you to the contact list\n%s on %s]
-%s ви добави в ÑпиÑъка Ñи Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¸\n%s (Ðкаунт: %s)
-[(Unknown)]
-(ÐеизвеÑтен)
-[%s requested authorization\n%u (%s) on %s]
-%s изпрати молба за упълномощаване\n%u (%s) (Ðкаунт: %s)
-[%s requested authorization\n%u on %s]
-%s изпрати молба за упълномощаване\n%u (Ðкаунт: %s)
-[%s requested authorization\n%s on %s]
-%s изпрати молба за упълномощаване\n%s (Ðкаунт: %s)
-[Feature is not supported by protocol]
-Ðе Ñе поддържа от протокола
[Re&ad %s message]
Показване на текÑта "%s"
[Re&ad status message]
@@ -1287,6 +1255,10 @@ Google Translate
Избор на папка
[My received files]
Получени файлове
+[Add contact permanently to list]
+ДобавÑне на контакта за поÑтоÑнно в ÑпиÑъка
+[View user's details]
+ПодробноÑти за потребителÑ
[View user's history]
ИÑÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ð° ÑъобщениÑта
[User menu]
@@ -1351,18 +1323,6 @@ Google Translate
ПрехвърлÑнето и Ñканирането за вируÑи завърши.
[Outgoing]
ИзходÑщи
-[< Copyright]
-< Copyright
-[&Help]
-Помощ
-[&About...]
-ОтноÑно...
-[&Support]
-Поддръжка
-[&Miranda NG homepage]
-Страницата на Miranda NG
-[&Report bug]
-Съобщи за програмна грешка
[Idle]
БездейÑтвие
[Chat module]
@@ -1807,10 +1767,40 @@ Popups за изобразÑване
Преглед/ПромÑна на личните данни
[%s is online]
%s е на линиÑ
+[Alerts]
+УведомÑваниÑ
[Add %s]
ДобавÑне на %s
[Please authorize my request and add me to your contact list.]
МолÑ, приемете моÑта молба за упълномощаване и ме добавете в ÑпиÑъка Ñи Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¸.
+[%s requests authorization]
+%s желае да бъде упълномощен
+[%u requests authorization]
+%u желае да бъде упълномощен
+[%s added you to their contact list]
+%s ви добави в ÑпиÑъка Ñи Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¸
+[%u added you to their contact list]
+%u ви добави в ÑпиÑъка Ñи Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¸
+[Added event]
+ДобавÑне на Ñъбитие
+[<Unknown>]
+<ÐеизвеÑтно>
+[%s added you to the contact list\n%u (%s) on %s]
+%s ви добави в ÑпиÑъка Ñи Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¸\n%u (%s) (Ðкаунт: %s)
+[%s added you to the contact list\n%u on %s]
+%s ви добави в ÑпиÑъка Ñи Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¸\n%u (Ðкаунт: %s)
+[%s added you to the contact list\n%s on %s]
+%s ви добави в ÑпиÑъка Ñи Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¸\n%s (Ðкаунт: %s)
+[(Unknown)]
+(ÐеизвеÑтен)
+[%s requested authorization\n%u (%s) on %s]
+%s изпрати молба за упълномощаване\n%u (%s) (Ðкаунт: %s)
+[%s requested authorization\n%u on %s]
+%s изпрати молба за упълномощаване\n%u (Ðкаунт: %s)
+[%s requested authorization\n%s on %s]
+%s изпрати молба за упълномощаване\n%s (Ðкаунт: %s)
+[Feature is not supported by protocol]
+Ðе Ñе поддържа от протокола
[&Join chat]
Влизане
[&Open chat window]
@@ -2057,6 +2047,18 @@ Popups за изобразÑване
ОÑновен текÑÑ‚
[Small text]
Малък текÑÑ‚
+[< Copyright]
+< Copyright
+[&Help]
+Помощ
+[&About...]
+ОтноÑно...
+[&Support]
+Поддръжка
+[&Miranda NG homepage]
+Страницата на Miranda NG
+[&Report bug]
+Съобщи за програмна грешка
[Browser: Back]
Браузър: Ðазад
[Browser: Forward]
diff --git a/langpacks/bulgarian/=HEAD=.txt b/langpacks/bulgarian/=HEAD=.txt
index 49d3a2060c..38be7ab0ad 100644
--- a/langpacks/bulgarian/=HEAD=.txt
+++ b/langpacks/bulgarian/=HEAD=.txt
@@ -1,6 +1,6 @@
Miranda Language Pack Version 1
Language: Bulgarian
Locale: 0402
-Last-Modified-Using: Miranda NG 0.95.7
+Last-Modified-Using: Miranda NG 0.95.8
Authors: NEOhidra, Castel
Author-email: neohidra@gmail.com \ No newline at end of file
diff --git a/langpacks/bulgarian/Plugins/AIM.txt b/langpacks/bulgarian/Deprecated/AIM.txt
index 147be1fcf9..147be1fcf9 100644
--- a/langpacks/bulgarian/Plugins/AIM.txt
+++ b/langpacks/bulgarian/Deprecated/AIM.txt
diff --git a/langpacks/bulgarian/Plugins/AddContactPlus.txt b/langpacks/bulgarian/Plugins/AddContactPlus.txt
index 7ea6903a0a..599d2c4f42 100644
--- a/langpacks/bulgarian/Plugins/AddContactPlus.txt
+++ b/langpacks/bulgarian/Plugins/AddContactPlus.txt
@@ -3,7 +3,7 @@
; File: AddContactPlus.dll
; Plugin: Add contact+
; Version: 0.9.9.2
-; Authors: Bartosz 'Dezeath' Bialek
+; Authors: Bartosz 'Dezeath' Białek
;============================================================
[Provides the ability to quickly add new contacts.]
ОÑигурÑва бързо добавÑне на контакти.
diff --git a/langpacks/bulgarian/Plugins/AssocMgr.txt b/langpacks/bulgarian/Plugins/AssocMgr.txt
index 4c4c2137e0..ec932845d2 100644
--- a/langpacks/bulgarian/Plugins/AssocMgr.txt
+++ b/langpacks/bulgarian/Plugins/AssocMgr.txt
@@ -5,8 +5,8 @@
; Version: 0.2.1.0
; Authors: H. Herkenrath
;============================================================
-[Handles file type associations and URLs like aim, gg, mirpu, tlen, wpmsg, xmpp, ymsgr.]
-ОÑигурÑва възможноÑÑ‚ за аÑоцииране на нÑкои типове файлове и на URL-адреÑи водещи към aim, gg, mirpu, tlen, wpmsg, xmpp, ymsgr.
+[Handles file type associations and URLs like aim, gg, mirpu, wpmsg, xmpp, ymsgr.]
+ОÑигурÑва възможноÑÑ‚ за аÑоцииране на нÑкои типове файлове и на URL-адреÑи водещи към aim, gg, mirpu, wpmsg, xmpp, ymsgr.
[Registered associations for Miranda NG:]
РегиÑтрирани аÑоциации Ñ Miranda NG:
[Miscellaneous]
diff --git a/langpacks/bulgarian/Plugins/BASS_interface.txt b/langpacks/bulgarian/Plugins/BASS_interface.txt
index bea00b1eb6..98439993ea 100644
--- a/langpacks/bulgarian/Plugins/BASS_interface.txt
+++ b/langpacks/bulgarian/Plugins/BASS_interface.txt
@@ -1,19 +1,19 @@
#muuid {2f07ea05-05b5-4ff0-875d-c590da2ddac1}
;============================================================
; File: BASS_interface.dll
-; Plugin: BASS interface
+; Plugin: BASS Interface
; Version: 0.0.0.14
; Authors: tico-tico
;============================================================
-[un4seen's BASS interface Miranda NG plugin.]
-ПриÑтавката е Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð·Ð° библиотеката BASS на un4seen
-[un4seen's bass interface]
-Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð·Ð° библиотеката BASS на un4seen
+[Un4seen's BASS interface Miranda NG plugin.]
+ПриÑтавката е Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð·Ð° библиотеката BASS на Un4seen
+[Un4seen's BASS interface]
+Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð·Ð° библиотеката BASS на Un4seen
[bass.dll loading error]
Грешка при зареждането на bass.dll
[Current bass.dll path:]
Път до bass.dll:
-[Maximum number of bass internal channels:]
+[Maximum number of BASS internal channels:]
МакÑимален брой вътрешни канали
[Output device:]
Изходни уÑтройÑтва:
@@ -21,7 +21,7 @@
Сила на звука:
[Quiet time:]
Тишина:
-[download bass library]
+[download BASS library]
ÑвалÑне на библиотеката BASS
[Play only if]
При ÑÑŠÑтоÑние
@@ -47,7 +47,7 @@
Ðа обÑд
[Preview]
Образец
-[un4seen's bass version: %d.%d.%d.%d]
+[Un4seen's BASS version: %d.%d.%d.%d]
ВерÑÐ¸Ñ Ð½Ð° библиотеката BASS: %d.%d.%d.%d
[--default device--]
--Ñтандартно уÑтройÑтво--
@@ -59,10 +59,12 @@
Включване на звука
[Frame background]
Фон на рамката
+[BASS Interface]
+BASS интерфейÑ
[Bass Interface]
BASS интерфейÑ
[Bass library]
-Библиотеката Bass
+Библиотеката BASS
[Sounds enabled]
Звукът е включен
[Sounds disabled]
diff --git a/langpacks/bulgarian/Plugins/BasicHistory.txt b/langpacks/bulgarian/Plugins/BasicHistory.txt
index 0f521b6a16..6f8acbc547 100644
--- a/langpacks/bulgarian/Plugins/BasicHistory.txt
+++ b/langpacks/bulgarian/Plugins/BasicHistory.txt
@@ -7,7 +7,7 @@
;============================================================
[History viewer for Miranda NG.]
Прегледайте иÑториÑта на разговорите в Miranda NG.
-[Message History]
+[Message history]
ИÑÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ð° ÑъобщениÑта
[Settings]
ÐаÑтройки
@@ -49,24 +49,24 @@
Дата във времевата марка
[Show seconds in timestamps]
Показване на Ñекунди във времевата марка
-[Enable Smileys]
+[Enable smileys]
Включване на уÑмивките
-[Only Incoming Messages]
+[Only incoming messages]
Само входÑщи ÑъобщениÑ
-[Only Outgoing Messages]
+[Only outgoing messages]
Само изходÑщи ÑъобщениÑ
-[Only Selected Group]
+[Only selected group]
Само ибраните групи
-[All Contacts]
+[All contacts]
Ð’Ñички контакти
-[Export To Txt]
+[Export to txt]
Ð˜Ð·Ð½Ð¾Ñ Ð² текÑтови файл
[File encoding*]
Кодиране на файла*
-[Export To Plain Html]
-Ð˜Ð·Ð½Ð¾Ñ Ð² Plain Html
-[Export To Rich Html]
-Ð˜Ð·Ð½Ð¾Ñ Ð² Rich Html
+[Export to plain HTML]
+Ð˜Ð·Ð½Ð¾Ñ Ð² plain HTML
+[Export to rich HTML]
+Ð˜Ð·Ð½Ð¾Ñ Ð² rich HTML
[External CSS file]
Външен CSS файл
[Add task]
@@ -113,9 +113,9 @@
Отказ
[Open History]
ÐžÑ‚Ð²Ð°Ñ€Ñ Ð¸ÑториÑта
-[View &History]
+[View &history]
Преглед на иÑториÑта
-[Delete All User History]
+[Delete all user history]
Изтриване на иÑториÑта на вÑички потребители
[Incoming message]
ВходÑщо Ñъобщение
@@ -123,9 +123,9 @@
ИзходÑщо Ñъобщение
[Status change]
ПромÑна на ÑÑŠÑтоÑние
-[Show Contacts]
+[Show contacts]
Показване на контакти
-[Hide Contacts]
+[Hide contacts]
Скриване на контакти
[History]
ИÑториÑ
@@ -139,9 +139,9 @@
СиÑтема
[Me]
Ðз
-[Invalid Message]
+[Invalid message]
Ðевалидно Ñъобщение
-[%s Files (*.%s)]
+[%s files (*.%s)]
%s файла (*.%s)
[Import]
ВноÑ
@@ -149,7 +149,7 @@
ИзноÑ
[File is corrupted]
Файлът е повреден
-[Are You sure?]
+[Are you sure?]
Сигурни ли Ñте?
[Open in &new window]
ОтварÑне в нов прозорец
@@ -161,11 +161,11 @@
Копиране
[Delete]
Изтриване
-[Send Message]
+[Send message]
Изпращане на Ñъобщение
-[Reply &Quoted]
+[Reply &quoted]
Цитиране
-[Delete Group]
+[Delete group]
Изтриване на групата
[Options]
ÐаÑтройки
@@ -177,10 +177,10 @@
Икони
[Hotkeys]
Клавишни комбинации
-[Rich Html]
-Rich Html
-[Plain Html]
-Plain Html
+[Rich HTML]
+Rich HTML
+[Plain HTML]
+Plain HTML
[Txt]
ТекÑÑ‚
[Binary]
@@ -233,16 +233,16 @@ SMS Ñъобщение
Фон на ÑпиÑъка Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¸
[Find]
Ðамери
-[Show/Hide Contacts]
+[Show/hide contacts]
Показване/Скриване на контактите
-[Export To Binary]
-Ð˜Ð·Ð½Ð¾Ñ Ð² Binary
-[Import From Binary]
-Ð’Ð½Ð¾Ñ Ð¾Ñ‚ Binary
-[Export To Dat (mContacts)]
-Ð˜Ð·Ð½Ð¾Ñ Ð² Dat (mContacts)
-[Import From Dat (mContacts)]
-Ð’Ð½Ð¾Ñ Ð¾Ñ‚ Dat (mContacts)
+[Export to binary]
+Ð˜Ð·Ð½Ð¾Ñ Ð² binary
+[Import from binary]
+Ð’Ð½Ð¾Ñ Ð¾Ñ‚ binary
+[Export to dat (mContacts)]
+Ð˜Ð·Ð½Ð¾Ñ Ð² dat (mContacts)
+[Import from dat (mContacts)]
+Ð’Ð½Ð¾Ñ Ð¾Ñ‚ dat (mContacts)
[Invalid event number]
Ðевалиден брой ÑъбитиÑ
[Incoming events]
@@ -253,7 +253,7 @@ SMS Ñъобщение
Файлът не ÑъщеÑтвува. Въведете правилен път до файла.
[Invalid file]
Ðевалиден файл
-[All Files (*.*)]
+[All files (*.*)]
Ð’Ñички файлове (*.*)
[Event already exists]
Събитието вече ÑъщеÑтвува
@@ -261,17 +261,17 @@ SMS Ñъобщение
Въвели Ñте невалидна кодова Ñтраница. Изберете от падащото меню или въведете правилно чиÑло.
[Invalid codepage]
Ðевалидна кодова Ñтраница
-[Export and Delete]
+[Export and delete]
Ð˜Ð·Ð½Ð¾Ñ Ð¸ изтриване
-[Import and Merge]
+[Import and merge]
Ð’Ð½Ð¾Ñ Ð¸ обединÑване
[Minute]
минута
[Hour]
чаÑ
-[At Start]
+[At start]
При Ñтартиране
-[At Finish]
+[At finish]
При приключване
[Daily]
Дневно
@@ -301,7 +301,7 @@ SMS Ñъобщение
СвалÑне от FTP Ñървър (WinSCP requred)
[Import from]
Ð’Ð½Ð¾Ñ Ð¾Ñ‚
-[History Log]
+[History log]
Дневник на иÑториÑта
[Filter:]
Филтър:
diff --git a/langpacks/bulgarian/Plugins/Clist_modern.txt b/langpacks/bulgarian/Plugins/Clist_modern.txt
index ac3cfb07c0..e29eee048f 100644
--- a/langpacks/bulgarian/Plugins/Clist_modern.txt
+++ b/langpacks/bulgarian/Plugins/Clist_modern.txt
@@ -45,6 +45,8 @@
Ð’ÐИМÐÐИЕ: \tВъзможно е облика да промени Ñ‚ÐµÐºÑƒÑ‰Ð¸Ñ Ð¿Ñ€Ð¾Ñ„Ð¸Ð». Промените Ñа необратими. \n\t\tМолÑ, направете резервно копие на базата от данни преди прилагането на облика.
[* Restart may be required for all changes to take effect]
*ИзиÑква реÑтарт за оÑъщеÑтвÑването на нÑкои промени
+[Download more skins]
+СвалÑне на още облици
[Available view modes]
Ðалични режими за преглед
[Include protocols]
diff --git a/langpacks/bulgarian/Plugins/Clist_nicer.txt b/langpacks/bulgarian/Plugins/Clist_nicer.txt
index d6faba8e8b..4e2efaeec5 100644
--- a/langpacks/bulgarian/Plugins/Clist_nicer.txt
+++ b/langpacks/bulgarian/Plugins/Clist_nicer.txt
@@ -345,6 +345,8 @@ ms
ÐаÑтройки на облика
[Frame title bar height]
ВиÑочина на имената на рамките
+[Download more skins]
+СвалÑне на още облици
[Load from skin file]
Зареждане от файл
[Export to skin file]
diff --git a/langpacks/bulgarian/Plugins/CloudFile.txt b/langpacks/bulgarian/Plugins/CloudFile.txt
index dd0e04fbbc..cd1ebe5aca 100644
--- a/langpacks/bulgarian/Plugins/CloudFile.txt
+++ b/langpacks/bulgarian/Plugins/CloudFile.txt
@@ -2,7 +2,7 @@
;============================================================
; File: CloudFile.dll
; Plugin: CloudFile
-; Version: 0.11.0.2
+; Version: 0.11.0.3
; Authors: Miranda NG Team
;============================================================
[General]
diff --git a/langpacks/bulgarian/Plugins/DbEditorPP.txt b/langpacks/bulgarian/Plugins/DbEditorPP.txt
index fe30641f9f..e50f73c2f3 100644
--- a/langpacks/bulgarian/Plugins/DbEditorPP.txt
+++ b/langpacks/bulgarian/Plugins/DbEditorPP.txt
@@ -2,7 +2,7 @@
;============================================================
; File: DbEditorPP.dll
; Plugin: Database editor++
-; Version: 4.0.1.1
+; Version: 4.0.1.2
; Authors: Bio, Jonathan Gordon
;============================================================
[Advanced Database Editor.]
diff --git a/langpacks/bulgarian/Plugins/Fingerprint.txt b/langpacks/bulgarian/Plugins/Fingerprint.txt
index cc778f3050..cbeb61e586 100644
--- a/langpacks/bulgarian/Plugins/Fingerprint.txt
+++ b/langpacks/bulgarian/Plugins/Fingerprint.txt
@@ -45,8 +45,6 @@ MSN клиенти
QQ клиенти
[RSS clients]
RSS клиенти
-[Tlen clients]
-Tlen клиенти
[Weather clients]
Weather клиенти
[Yahoo clients]
@@ -103,8 +101,6 @@ Mail.Ru (непознат клиент)
TM 2008 и по-нов
[Gadu-Gadu client]
Gadu-Gadu клиент
-[Tlen.pl client]
-Tlen.pl клиент
[Python-based clients]
Python базиран клиент
[Jabber client]
@@ -135,8 +131,6 @@ Jabber
MSN
[QQ overlay]
QQ
-[Tlen.pl overlay]
-Tlen.pl
[Yahoo overlay]
Yahoo
[Mail.Ru Agent overlay]
@@ -171,12 +165,6 @@ Gadu-Gadu v10 клиент
Gadu-Gadu v9 клиент
[Gadu-Gadu v8 client]
Gadu-Gadu v8 клиент
-[Tlen 7.x overlay]
-Tlen 7.x
-[Tlen 6.x overlay]
-Tlen 6.x
-[Tlen 5.x overlay]
-Tlen 5.x
[TM/QQ 2012 overlay]
TM/QQ 2012
[TM/QQ 2011 overlay]
diff --git a/langpacks/bulgarian/Plugins/GmailNotifier.txt b/langpacks/bulgarian/Plugins/GmailNotifier.txt
index a2f79ab37c..3866bcd9aa 100644
--- a/langpacks/bulgarian/Plugins/GmailNotifier.txt
+++ b/langpacks/bulgarian/Plugins/GmailNotifier.txt
@@ -2,7 +2,7 @@
;============================================================
; File: GmailNotifier.dll
; Plugin: Gmail Multiple Notifier
-; Version: 0.3.1.1
+; Version: 1.0.1.1
; Authors: Mixwind
;============================================================
[Check your Gmail inboxes locally.]
@@ -39,8 +39,6 @@ Gmail акаунт
Popup приÑтавка
[Checking...]
ПроверÑване...
-[Can't reach server!]
-Сървърът не е доÑтъпен!
[Wrong name or password!]
Грешно име или парола!
[Other]
diff --git a/langpacks/bulgarian/Plugins/MSN.txt b/langpacks/bulgarian/Plugins/MSN.txt
index 7983dfc166..30b6ba857e 100644
--- a/langpacks/bulgarian/Plugins/MSN.txt
+++ b/langpacks/bulgarian/Plugins/MSN.txt
@@ -2,7 +2,7 @@
;============================================================
; File: MSN.dll
; Plugin: MSN protocol
-; Version: 0.14.0.1
+; Version: 0.14.0.2
; Authors: Boris Krasnovskiy, George Hazan, Richard Hughes, leecher
;============================================================
[Microsoft Network (MSN) protocol support for Miranda NG.]
diff --git a/langpacks/bulgarian/Plugins/New_GPG.txt b/langpacks/bulgarian/Plugins/New_GPG.txt
index 3a46c473cb..e3c273bce0 100644
--- a/langpacks/bulgarian/Plugins/New_GPG.txt
+++ b/langpacks/bulgarian/Plugins/New_GPG.txt
@@ -29,18 +29,22 @@
ВноÑ
[Current password:]
Текуща парола:
-[Email]
-Имейл
+[Warning]
+Предупреждение
+[Contact]
+Контакт
[Name]
Име
-[Accounts]
-Ðкаунти
-[Default]
-Стандарт
+[Email]
+Имейл
+[Protocol]
+Протокол
+[info]
+ИнформациÑ
[Error]
Грешка
-[Warning]
-Предупреждение
+[LOG files]
+Дневници (файлове)
[Info]
ИнформациÑ
[Services]
@@ -51,11 +55,7 @@
СъобщениÑ
[Advanced]
Разширени
-[Contact]
-Контакт
-[Protocol]
-Протокол
-[info]
-ИнформациÑ
-[LOG files]
-Дневници (файлове)
+[Accounts]
+Ðкаунти
+[Default]
+Стандарт
diff --git a/langpacks/bulgarian/Plugins/SimpleStatusMsg.txt b/langpacks/bulgarian/Plugins/SimpleStatusMsg.txt
index d34737b1ff..d9de9d7031 100644
--- a/langpacks/bulgarian/Plugins/SimpleStatusMsg.txt
+++ b/langpacks/bulgarian/Plugins/SimpleStatusMsg.txt
@@ -3,7 +3,7 @@
; File: SimpleStatusMsg.dll
; Plugin: Simple status message
; Version: 1.9.0.6
-; Authors: Bartosz 'Dezeath' Bialek, Harven
+; Authors: Bartosz 'Dezeath' Białek, Harven
;============================================================
[%s message for %s]
ТекÑÑ‚ "%s" на %s
diff --git a/langpacks/bulgarian/Plugins/SmileyAdd.txt b/langpacks/bulgarian/Plugins/SmileyAdd.txt
index 3c75f3342c..4bab7e6b87 100644
--- a/langpacks/bulgarian/Plugins/SmileyAdd.txt
+++ b/langpacks/bulgarian/Plugins/SmileyAdd.txt
@@ -2,7 +2,7 @@
;============================================================
; File: SmileyAdd.dll
; Plugin: SmileyAdd
-; Version: 0.2.4.2
+; Version: 0.3.0.1
; Authors: Peacow, nightwish, bid, borkra
;============================================================
[Smiley support for Miranda NG.]
diff --git a/langpacks/bulgarian/Plugins/StatusManager.txt b/langpacks/bulgarian/Plugins/StatusManager.txt
index 9308bc97f0..c8b119fc6f 100644
--- a/langpacks/bulgarian/Plugins/StatusManager.txt
+++ b/langpacks/bulgarian/Plugins/StatusManager.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StatusManager.dll
; Plugin: Status manager
-; Version: 0.11.2.3
+; Version: 1.0.1.1
; Authors: P Boon
;============================================================
[Startup status]
diff --git a/langpacks/bulgarian/Plugins/Steam.txt b/langpacks/bulgarian/Plugins/Steam.txt
index 364cd6713f..b40de7e4d4 100644
--- a/langpacks/bulgarian/Plugins/Steam.txt
+++ b/langpacks/bulgarian/Plugins/Steam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Steam.dll
; Plugin: Steam protocol
-; Version: 0.11.6.1
+; Version: 0.11.6.3
; Authors: Miranda NG Team, Robert Pösel
;============================================================
[Username:]
diff --git a/langpacks/bulgarian/Plugins/StopSpam.txt b/langpacks/bulgarian/Plugins/StopSpam.txt
index 7d6c8d1f0b..40f4900996 100644
--- a/langpacks/bulgarian/Plugins/StopSpam.txt
+++ b/langpacks/bulgarian/Plugins/StopSpam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpam.dll
; Plugin: StopSpam+
-; Version: 0.0.1.5
+; Version: 0.1.0.1
; Authors: Roman Miklashevsky, A. Petkevich, Kosh&chka, persei
;============================================================
[Anti-spam plugin for Miranda NG.]
@@ -41,6 +41,8 @@
ВпиÑване на Ñпамърите в ÑиÑтемната иÑториÑ
[StopSpam automatic message:\r\n]
Ðвтоматично Ñъобщение от StopSpam:\r\n
+[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
+Без повече Ñпам! Добре дошли Ñа Ñамо изпратените от хора ÑъобщениÑ!\r\n\r\nКомуникациÑта ви Ñ Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»Ð¸ от ÑпиÑъка Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¸ нÑма да бъде възпрепÑÑ‚Ñтвана от приÑтавката, но първите ÑъобщениÑта от непознати потребители нÑма да ви бъдат предоÑтавÑни, но нÑма и да бъдат игнорирани. Вие ще получите даденото Ñъобщение при уÑловие, че потребителÑÑ‚ даде (еднократно) правилен отговор на въпроÑ, предварително определен от ваÑ.
[Message sessions]
Разговори
[General]
@@ -49,18 +51,16 @@
СъобщениÑ
[Accounts]
Ðкаунти
-[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
-Без повече Ñпам! Добре дошли Ñа Ñамо изпратените от хора ÑъобщениÑ!\r\n\r\nКомуникациÑта ви Ñ Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»Ð¸ от ÑпиÑъка Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¸ нÑма да бъде възпрепÑÑ‚Ñтвана от приÑтавката, но първите ÑъобщениÑта от непознати потребители нÑма да ви бъдат предоÑтавÑни, но нÑма и да бъдат игнорирани. Вие ще получите даденото Ñъобщение при уÑловие, че потребителÑÑ‚ даде (еднократно) правилен отговор на въпроÑ, предварително определен от ваÑ.
[Not In List]
Ðе е в ÑпиÑъка
[Complete]
Завършен
[Spammers made me to install small anti-spam system you are now speaking with. Please reply "nospam" without quotes and spaces if you want to contact me.]
Заради Ñпамъри Ñъм инÑталирал приÑтавка за борба Ñ Ð½ÐµÐ¶ÐµÐ»Ð°Ð½Ð¸ ÑъобщениÑ. Ðко желаете да Ñе Ñвържете Ñ Ð¼ÐµÐ½, Ð¼Ð¾Ð»Ñ Ð¾Ñ‚Ð³Ð¾Ð²ÐµÑ€ÐµÑ‚Ðµ ÑÑŠÑ ÑÐ»ÐµÐ´Ð½Ð¸Ñ Ñ‚ÐµÐºÑÑ‚: nospam.\r\nSpammers made me to install small anti-spam system you are now speaking with. Please reply "nospam" without quotes and spaces if you want to contact me.
-[Congratulations! You just passed human/robot test. Now you can write me a message.]
-ПоздравлениÑ! Преминахте теÑта. Вече можете да изпратите Ñъобщението Ñи.\r\nCongratulations! You just passed human/robot test. Now you can write me a message.
[StopSpam: send a message and reply to an anti-spam bot question.]
StopSpam: изпратете Ñъобщение и отговорете на въпроÑа.\r\nStopSpam: send a message and reply to an anti-spam bot question.
+[Congratulations! You just passed human/robot test. Now you can write me a message.]
+ПоздравлениÑ! Преминахте теÑта. Вече можете да изпратите Ñъобщението Ñи.\r\nCongratulations! You just passed human/robot test. Now you can write me a message.
[StopSpam]
StopSpam
[Remove Temporary Contacts]
diff --git a/langpacks/bulgarian/Plugins/StopSpamMod.txt b/langpacks/bulgarian/Plugins/StopSpamMod.txt
index 1b2f97152c..8501dde0b2 100644
--- a/langpacks/bulgarian/Plugins/StopSpamMod.txt
+++ b/langpacks/bulgarian/Plugins/StopSpamMod.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpamMod.dll
; Plugin: StopSpam mod
-; Version: 0.0.2.1
+; Version: 0.0.2.2
; Authors: Roman Miklashevsky, sss, Elzor
;============================================================
[Anti-spam plugin for Miranda NG.]
diff --git a/langpacks/bulgarian/Plugins/TabSRMM.txt b/langpacks/bulgarian/Plugins/TabSRMM.txt
index 57009292de..103a755818 100644
--- a/langpacks/bulgarian/Plugins/TabSRMM.txt
+++ b/langpacks/bulgarian/Plugins/TabSRMM.txt
@@ -491,6 +491,8 @@ Windows Aero - наÑтройки
Ð˜Ð·Ð½Ð¾Ñ Ð²ÑŠÐ² файл...
[Import from a file...]
Ð’Ð½Ð¾Ñ Ð¾Ñ‚ файл...
+[Download more skins]
+СвалÑне на още облици
[Icons]
Икони
[Event type icons in the message log]
diff --git a/langpacks/bulgarian/Plugins/Tox.txt b/langpacks/bulgarian/Plugins/Tox.txt
index 1d2483d4d9..378ab04986 100644
--- a/langpacks/bulgarian/Plugins/Tox.txt
+++ b/langpacks/bulgarian/Plugins/Tox.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Tox.dll
; Plugin: Tox protocol
-; Version: 0.11.1.25
+; Version: 0.11.1.26
; Authors: Miranda NG Team
;============================================================
[Tox protocol support for Miranda NG.]
diff --git a/langpacks/bulgarian/Plugins/mRadio.txt b/langpacks/bulgarian/Plugins/mRadio.txt
index f4e4e3a4e5..712e6a0062 100644
--- a/langpacks/bulgarian/Plugins/mRadio.txt
+++ b/langpacks/bulgarian/Plugins/mRadio.txt
@@ -95,8 +95,8 @@ mRadio Mod
Кариера
[Sorry!]
Извинете!
-[BASS.DLL not found!]
-BASS.DLL не може да бъде намерен!
+[bass.dll not found!]
+bass.dll не може да бъде намерен!
[Station]
СтанциÑ
[Custom INI file]
diff --git a/langpacks/bulgarian/Untranslated/AIM.txt b/langpacks/bulgarian/Untranslated/AIM.txt
deleted file mode 100644
index 58e676997b..0000000000
--- a/langpacks/bulgarian/Untranslated/AIM.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-[Screen name:]
-[Display name:]
-[Masquerade as a Sidekick/Hiptop user]
-[Force single client]
-[Use "clientlogin" (recommended)]
-[AIM instant idler]
-[This allows access to user defined chat rooms. To access predefined chat rooms use web links]
-[Screen name]
-[Invalid screen name or password.]
-[Mismatched screen name or password.]
-[Invalid SNAC header.]
-[Server rate limit exceeded.]
-[Client rate limit exceeded]
-[Recipient is not logged in.]
-[Requested service is unavailable.]
-[Requested service is not defined.]
-[You sent obsolete SNAC.]
-[Response lost.]
-[Incorrect SNAC format.]
-[Recipient blocked.]
-[Sender too evil.]
-[Receiver too evil.]
-[Request ambiguous.]
-[Server queue full.]
-[Not while on AOL.]
-[Check your screen name.]
-[Field change temporarily unavailable.]
-[Invalid screen name.]
-[Invalid registration preference.]
-[Invalid screen name Length.]
-[Deleted account.]
-[Bad database status.]
-[Migration cancel.]
-[There is already a pending request for this screen name.]
-[Not DT status.]
-[Outstanding confirmation.]
-[Email host fail.]
-[DNS fail.]
-[Contact tried to open an audio/video conference (not currently supported)]
-[Failed to add buddy to list: Item already exist.]
-[Error adding buddy (invalid ID or already in list?)]
-[Cannot add buddy. Limit for this type of item exceeded.]
-[Error? Attempting to add ICQ contact to an AIM list.]
-[Cannot add this buddy because it requires authorization.]
-[Unknown error when adding buddy to list. Error code %#x]
-[Unknown error when attempting to modify a group. Error code %#x]
-[Error uploading avatar. (Too small)]
-[Error uploading avatar. (Too big)]
-[Error uploading avatar. (Wrong type)]
-[Error uploading avatar. (Is banned)]
-[Error uploading avatar. (Unknown error)]
-[Unable to confirm at this time. Please try again later.]
-[Hiptop]
-[Foreground color]
-[Not normal script]
-[Instant idle]
-[Join me in this buddy chat!]
-[Failed to open file: %s %s]
diff --git a/langpacks/bulgarian/Untranslated/BasicHistory.txt b/langpacks/bulgarian/Untranslated/BasicHistory.txt
index 18291c02c9..0769f5063a 100644
--- a/langpacks/bulgarian/Untranslated/BasicHistory.txt
+++ b/langpacks/bulgarian/Untranslated/BasicHistory.txt
@@ -1,10 +1,10 @@
-[Do not show Find control border]
-[Default Event Filter]
+[Do not show find control border]
+[Default event filter]
[Delta time to group messages:]
[Search forward in list group]
[Search forward in message window]
-[Match Case]
-[Match Whole Word]
+[Match case]
+[Match whole word]
[* Choose encoding from combo box or enter code page number and name separated by semicolon, name is used in Content-Type header.]
[Triger type]
[Delta time]
@@ -12,8 +12,8 @@
[* Use negative values to filter younger events]
[Execute task for specified contacts]
[Execute history task]
-[Find Next]
-[Find Previous]
+[Find next]
+[Find previous]
[Plus in export]
[Minus in export]
[File does not contain selected contact]
@@ -29,12 +29,12 @@
[Find window background]
[Window background]
[Open global history]
-[Switch Match Case]
-[Switch Match Whole Word]
-[Switch Only Incoming Messages]
-[Switch Only Outgoing Messages]
-[Switch Only Selected Group]
-[Switch All Contacts]
+[Switch match case]
+[Switch match whole word]
+[Switch only incoming messages]
+[Switch only outgoing messages]
+[Switch only selected group]
+[Switch all contacts]
[Enter filter name]
[Filter name exists]
[Browse WinSCP file]
diff --git a/langpacks/bulgarian/Untranslated/GmailNotifier.txt b/langpacks/bulgarian/Untranslated/GmailNotifier.txt
index ff53279217..26687aa0d5 100644
--- a/langpacks/bulgarian/Untranslated/GmailNotifier.txt
+++ b/langpacks/bulgarian/Untranslated/GmailNotifier.txt
@@ -6,7 +6,7 @@
[Enable icon selection and icon in status bar (restart)]
[This is a shared computer so disable auto login]
[Log unread threads into database (enable history)]
-[Can't open Internet!]
[Can't send account data!]
[Can't get RSS feed!]
+[Gmail Notifier connection]
[GmailNotifier]
diff --git a/langpacks/bulgarian/Untranslated/IEView.txt b/langpacks/bulgarian/Untranslated/IEView.txt
index be04618036..eff235982d 100644
--- a/langpacks/bulgarian/Untranslated/IEView.txt
+++ b/langpacks/bulgarian/Untranslated/IEView.txt
@@ -1,5 +1,6 @@
[IE Based Chat Log.]
[Embed YouTube videos]
+[Download more templates]
[IID_IOleObject failed.]
[IID_IOleInPlaceObject failed.]
[Failed to Advise]
diff --git a/langpacks/bulgarian/Untranslated/New_GPG.txt b/langpacks/bulgarian/Untranslated/New_GPG.txt
index e5444da9ab..288705fea2 100644
--- a/langpacks/bulgarian/Untranslated/New_GPG.txt
+++ b/langpacks/bulgarian/Untranslated/New_GPG.txt
@@ -70,39 +70,6 @@
[Export GPG Public keys]
[Import GPG Public keys]
[GPG encryption status]
-[Creation date]
-[Expire date]
-[Key length]
-[key ID]
-[not set]
-[Default private key ID]
-[Failed to open file]
-[Generating new random key, please wait]
-[Failed to allocate memory]
-[Failed to lock memory with error %d]
-[Failed write to clipboard with error %d]
-[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
-[Wrong GPG binary location found in system.\nPlease choose another location]
-[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
-[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
-[GPG binary does not exist.\nPlease choose another location]
-[Please choose GPG binary location]
-[Please set keyring's home directory]
-[There is existing key for contact, would you like to replace it with new key?]
-[New public key was received, do you want to import it?]
-[Replace]
-[Accept]
-[Received key from %s]
-[You must set encryption algorithm first]
-[Key length must be of length from 1024 to 4096 bits]
-[Invalid date]
-[Name must contain at least 5 characters]
-[Name cannot contain '(' or ')']
-[Invalid Email]
-[Generating new key, please wait...]
-[Failed to export public key.]
[GPG binary is set and valid (this is good).\n]
[GPG binary unset or invalid (plugin will not work).\n]
[Home dir write access granted (this is good).\n]
@@ -124,8 +91,9 @@
[Do you want to try to decrypt encrypted message?]
[We're trying to encrypt with untrusted key. Do you want to trust this key permanently?]
[Something is wrong, GPG does not understand us, aborting encryption.]
-[GnuPG Variables]
[Key ID]
+[Default private key ID]
+[not set]
[This key is not used by any contact. Do you want to remove it from public keyring?]
[Key info]
[we have secret key for this public key, do not removing from GPG keyring]
@@ -133,9 +101,13 @@
[Do you want to remove key from entire metacontact (all subcontacts)?]
[Export public key]
[.asc pubkey file]
+[Failed to allocate memory]
+[Failed to lock memory with error %d]
+[Failed write to clipboard with error %d]
[Failed to open clipboard with error %d]
[Set log file]
[Choose gpg.exe]
+[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
[Set home directory]
[Load Public GPG Key for ]
[Turn off encryption]
@@ -146,7 +118,35 @@
[Key already in secret keyring.]
[Set file containing GPG public key]
[GPG public key file]
+[Failed to open file]
[There is no public or private key.]
+[GnuPG Variables]
+[New passwords do not match]
+[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[Creation date]
+[Expire date]
+[Key length]
+[key ID]
+[Generating new random key, please wait]
+[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
+[Wrong GPG binary location found in system.\nPlease choose another location]
+[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
+[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
+[There is existing key for contact, would you like to replace it with new key?]
+[New public key was received, do you want to import it?]
+[Replace]
+[Accept]
+[Received key from %s]
+[You must set encryption algorithm first]
+[Key length must be of length from 1024 to 4096 bits]
+[Invalid date]
+[Name must contain at least 5 characters]
+[Name cannot contain '(' or ')']
+[Invalid Email]
+[Generating new key, please wait...]
+[Expiration date]
+[Failed to export public key.]
[Do you want to toggle encryption for all subcontacts?]
[Turn off GPG encryption]
[Turn on GPG encryption]
@@ -162,5 +162,6 @@
[We have successfully processed %d public keys and some private keys.]
[We have successfully processed %d public keys.]
[Keys import result]
-[New passwords do not match]
-[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[GPG binary does not exist.\nPlease choose another location]
+[Please choose GPG binary location]
+[Please set keyring's home directory]
diff --git a/langpacks/bulgarian/Untranslated/SmileyAdd.txt b/langpacks/bulgarian/Untranslated/SmileyAdd.txt
index baae529a55..b7f040344f 100644
--- a/langpacks/bulgarian/Untranslated/SmileyAdd.txt
+++ b/langpacks/bulgarian/Untranslated/SmileyAdd.txt
@@ -7,6 +7,5 @@
[Smiley pack %s for category "%s" not found.\nSelect correct smiley pack in the Options -> Customize -> Smileys.]
[Smiley #%u in file %s for smiley pack %s not found.]
[%s global smiley pack]
-[Regular expression "%s" in smiley pack "%s" could produce "empty matches".]
[Regular expression "%s" in smiley pack "%s" malformed.]
[d'Oh!]
diff --git a/langpacks/bulgarian/Untranslated/SplashScreen.txt b/langpacks/bulgarian/Untranslated/SplashScreen.txt
index 3f1856394d..cc57fde2db 100644
--- a/langpacks/bulgarian/Untranslated/SplashScreen.txt
+++ b/langpacks/bulgarian/Untranslated/SplashScreen.txt
@@ -2,5 +2,6 @@
[Splash Options]
[Show splash]
[AdvaImg plugin not found. Please get it from https://miranda-ng.org/p/AdvaImg/ to be able to use images.]
+[Download more splash screens]
[Graphic files]
[Splash Screen]
diff --git a/langpacks/bulgarian/Untranslated/mRadio.txt b/langpacks/bulgarian/Untranslated/mRadio.txt
index a1071dc511..570bb0cc61 100644
--- a/langpacks/bulgarian/Untranslated/mRadio.txt
+++ b/langpacks/bulgarian/Untranslated/mRadio.txt
@@ -2,3 +2,4 @@
[Psychotic]
[Protocol depending status]
[Quick Open]
+[bass.dll not found! Choose bass.dll path manually]
diff --git a/langpacks/croatian/=CORE=.txt b/langpacks/croatian/=CORE=.txt
index 8f45386cd6..ef23f9edf8 100644
--- a/langpacks/croatian/=CORE=.txt
+++ b/langpacks/croatian/=CORE=.txt
@@ -3,29 +3,6 @@
; Module: Miranda Core
; Version: 0.95.8
;============================================================
-;file \src\core\stdauth\res\resource.rc
-[Authorization request]
-Zahtjev za prihvaćanje
-[&Authorize]
-&Prihvati
-[&Deny]
-&Odbij
-[Decide &later]
-OdluÄit ću &Kasnije
-[User &details]
-Detalji o &Korisniku
-[Reason:]
-Razlog:
-[Denial reason:]
-Razlog za odbijanje:
-[Add to contact list if authorized]
-Dodaj u listu kontakata ako je autoriziran
-[You were added]
-Dodani ste.
-[&Close]
-&Zatvori
-[&Add]
-&Dodaj
;file \src\core\stdaway\res\resource.rc
[%s message for %s]
%s poruka za %s
@@ -291,6 +268,8 @@ prikaži razdjelnik između kontakata na mreži i izvan mreže
[&User menu]
+[User &details]
+Detalji o &Korisniku
[&History]
p&ovijest
[Incoming file transfer]
@@ -307,6 +286,8 @@ p&ovijest
[Save to:]
+[&Add]
+&Dodaj
[&Open...]
[Open &folder]
@@ -395,11 +376,6 @@ p&ovijest
[You will always be asked about files from people not on your contact list]
-;file \src\core\stdhelp\res\resource.rc
-[About Miranda NG]
-
-[Credits >]
-
;file \src\core\stdidle\res\resource.rc
[Become idle if the following is left unattended:]
@@ -723,6 +699,8 @@ Otvori na o&voj poziciji
[Group:]
+[Authorization request]
+Zahtjev za prihvaćanje
[&Yes]
[&No]
@@ -999,6 +977,8 @@ Otvori na o&voj poziciji
[Insert separator]
+[Module:]
+
[Service:]
[Default]
@@ -1133,6 +1113,26 @@ Otvori na o&voj poziciji
[Hide if there isn't enough space]
+[&Authorize]
+&Prihvati
+[&Deny]
+&Odbij
+[Decide &later]
+OdluÄit ću &Kasnije
+[Reason:]
+Razlog:
+[Denial reason:]
+Razlog za odbijanje:
+[Add to contact list if authorized]
+Dodaj u listu kontakata ako je autoriziran
+[You were added]
+Dodani ste.
+[&Close]
+&Zatvori
+[About Miranda NG]
+
+[Credits >]
+
[Tray]
[&Hide/Show]
@@ -1193,42 +1193,6 @@ popis
[Google Translate]
-;file \src\core\stdauth\src\auth.cpp
-[%s requests authorization]
-
-[%u requests authorization]
-
-[%s added you to their contact list]
-
-[%u added you to their contact list]
-
-[Alerts]
-
-[Added event]
-
-;file \src\core\stdauth\src\authdialogs.cpp
-[View user's details]
-
-[Add contact permanently to list]
-
-[<Unknown>]
-
-[%s added you to the contact list\n%u (%s) on %s]
-
-[%s added you to the contact list\n%u on %s]
-
-[%s added you to the contact list\n%s on %s]
-
-[(Unknown)]
-
-[%s requested authorization\n%u (%s) on %s]
-
-[%s requested authorization\n%u on %s]
-
-[%s requested authorization\n%s on %s]
-
-[Feature is not supported by protocol]
-
;file \src\core\stdaway\src\awaymsg.cpp
[Re&ad %s message]
@@ -1351,6 +1315,10 @@ sve datoteke
[My received files]
+[Add contact permanently to list]
+
+[View user's details]
+
[View user's history]
[User menu]
@@ -1418,20 +1386,6 @@ sve datoteke
;file \src\core\stdfile\src\ftmanager.cpp
[Outgoing]
-;file \src\core\stdhelp\src\about.cpp
-[< Copyright]
-
-;file \src\core\stdhelp\src\help.cpp
-[&Help]
-
-[&About...]
-
-[&Support]
-
-[&Miranda NG homepage]
-
-[&Report bug]
-
;file \src\core\stdidle\src\idle.cpp
[Idle]
@@ -1907,11 +1861,43 @@ Prika&ži/sakrij popis nadimaka
;file \src\core\stduseronline\src\useronline.cpp
[%s is online]
+[Alerts]
+
;file \src\mir_app\src\addcontact.cpp
[Add %s]
[Please authorize my request and add me to your contact list.]
+;file \src\mir_app\src\auth.cpp
+[%s requests authorization]
+
+[%u requests authorization]
+
+[%s added you to their contact list]
+
+[%u added you to their contact list]
+
+[Added event]
+
+;file \src\mir_app\src\authdialogs.cpp
+[<Unknown>]
+
+[%s added you to the contact list\n%u (%s) on %s]
+
+[%s added you to the contact list\n%u on %s]
+
+[%s added you to the contact list\n%s on %s]
+
+[(Unknown)]
+
+[%s requested authorization\n%u (%s) on %s]
+
+[%s requested authorization\n%u on %s]
+
+[%s requested authorization\n%s on %s]
+
+[Feature is not supported by protocol]
+
;file \src\mir_app\src\chat_clist.cpp
[&Join chat]
@@ -2200,6 +2186,19 @@ Prika&ži/sakrij popis nadimaka
[Small text]
+;file \src\mir_app\src\help.cpp
+[< Copyright]
+
+[&Help]
+
+[&About...]
+
+[&Support]
+
+[&Miranda NG homepage]
+
+[&Report bug]
+
;file \src\mir_app\src\hotkey_opts.cpp
[Browser: Back]
diff --git a/langpacks/croatian/=HEAD=.txt b/langpacks/croatian/=HEAD=.txt
index e22c20f697..62d92e7dbb 100644
--- a/langpacks/croatian/=HEAD=.txt
+++ b/langpacks/croatian/=HEAD=.txt
@@ -3,4 +3,4 @@ Language: Croatian (HR)
Locale: 041A
Author: Zvonimir Stanecic (Zvonimirek222)
Author-email: zvonimirek222@yandex.com
-Last-Modified-Using: 0.95.7 \ No newline at end of file
+Last-Modified-Using: 0.95.8 \ No newline at end of file
diff --git a/langpacks/croatian/Plugins/AIM.txt b/langpacks/croatian/Plugins/AIM.txt
deleted file mode 100644
index 156e4817d1..0000000000
--- a/langpacks/croatian/Plugins/AIM.txt
+++ /dev/null
@@ -1,426 +0,0 @@
-#muuid {3750a5a3-bf0d-490e-b65d-41ac4d29aeb3}
-;============================================================
-; File: AIM.dll
-; Plugin: AIM protocol
-; Version: 0.11.0.1
-; Authors: Boris Krasnovskiy, Aaron Myles Landwehr
-;============================================================
-[AOL Instant Messenger (AIM) protocol support for Miranda NG.]
-
-;file \protocols\AimOscar\res\aim.rc
-[AIM user details]
-
-[Screen name:]
-
-[Display name:]
-
-[Password:]
-
-[AIM options]
-
-[Message delivery confirmation]
-
-[Do not autoreply when away]
-
-[Convert incoming messages to BBCode]
-
-[Convert outgoing messages to HTML]
-
-[Disable avatars]
-
-[Disable account type icons]
-
-[Disable extended status icons]
-
-[Notify about new mail]
-
-[Manage server groups]
-
-[Advanced options]
-
-[Instant idle on login]
-
-[Force proxy file transfers]
-
-[Masquerade as a Sidekick/Hiptop user]
-
-[Connection]
-
-[Login server:]
-
-[Port:]
-
-[Reset]
-
-[Disable SSL]
-
-[Force single client]
-
-[Use "clientlogin" (recommended)]
-
-[* Some changes will take effect the next time you connect to the AIM network]
-
-[Save profile]
-
-[Create a new AIM account]
-
-[AIM instant idler]
-
-[Number of hours:]
-
-[Number of minutes:]
-
-[Set idle]
-
-[Unset idle]
-
-[Users who can contact me:]
-
-[Allow all users]
-
-[Allow only users on contact list]
-
-[Allow only users below]
-
-[Block all users]
-
-[Block only users below]
-
-[Add]
-
-[Remove]
-
-[Idle]
-
-[Allow contacts to be notified of:]
-
-[Join chat room]
-
-[Chat room]
-
-[&Join]
-
-[&Cancel]
-&Odustani
-[This allows access to user defined chat rooms. To access predefined chat rooms use web links]
-
-[Change password]
-
-[Original]
-
-[New]
-
-[Repeat]
-
-[*Passwords don't match.]
-
-[Screen name]
-
-[E-mail]
-
-[Confirm account]
-
-[*Applied upon reconnect]
-
-[Save changes]
-
-[Invite buddy to chat room]
-
-[&Invite]
-
-[Invitation reason]
-
-[Chat room invitation request]
-
-[&Deny]
-&Odbij
-[Message]
-Poruka
-[Room]
-
-;file \protocols\AimOscar\src\chat.cpp
-[Me]
-
-[Others]
-
-[&Invite user...]
-
-[&Leave chat session]
-
-[User &details]
-Detalji o &Korisniku
-[User &history]
-
-;file \protocols\AimOscar\src\error.cpp
-[Invalid screen name or password.]
-
-[Mismatched screen name or password.]
-
-[You are connecting too frequently. Try waiting 10 minutes to reconnect.]
-
-[Unknown error occurred when attempting to connect.]
-
-[Invalid SNAC header.]
-
-[Server rate limit exceeded.]
-
-[Client rate limit exceeded]
-
-[Recipient is not logged in.]
-
-[Requested service is unavailable.]
-
-[Requested service is not defined.]
-
-[You sent obsolete SNAC.]
-
-[Not supported by server.]
-
-[Not supported by the client.]
-
-[Refused by client.]
-
-[Reply too big.]
-
-[Response lost.]
-
-[Request denied.]
-
-[Incorrect SNAC format.]
-
-[Insufficient rights.]
-
-[Recipient blocked.]
-
-[Sender too evil.]
-
-[Receiver too evil.]
-
-[User temporarily unavailable.]
-
-[No match.]
-
-[List overflow.]
-
-[Request ambiguous.]
-
-[Server queue full.]
-
-[Not while on AOL.]
-
-[Check your screen name.]
-
-[Check your password.]
-
-[Check your email address.]
-
-[Service temporarily unavailable.]
-
-[Field change temporarily unavailable.]
-
-[Invalid screen name.]
-
-[Invalid password.]
-
-[Invalid email.]
-
-[Invalid registration preference.]
-
-[Invalid old password.]
-
-[Invalid screen name Length.]
-
-[Invalid password length.]
-
-[Invalid email length.]
-
-[Invalid old password length.]
-
-[Need old password.]
-
-[Read only field.]
-
-[Write only field.]
-
-[Unsupported type.]
-
-[An error has occurred.]
-
-[Invalid account.]
-
-[Deleted account.]
-
-[Expired account.]
-
-[No database access.]
-
-[Invalid database fields.]
-
-[Bad database status.]
-
-[Migration cancel.]
-
-[Internal error.]
-
-[There is already a pending request for this screen name.]
-
-[Not DT status.]
-
-[Outstanding confirmation.]
-
-[No email address.]
-
-[Over limit.]
-
-[Email host fail.]
-
-[DNS fail.]
-
-;file \protocols\AimOscar\src\file.cpp
-[Failed to open file: %s : %s]
-
-;file \protocols\AimOscar\src\links.cpp
-[AIM link protocol]
-
-;file \protocols\AimOscar\src\popup.cpp
-[%s protocol]
-
-[Open mail account?]
-
-;file \protocols\AimOscar\src\proto.cpp
-[%s server connection]
-
-[%s client-to-client connections]
-
-;file \protocols\AimOscar\src\server.cpp
-[[Auto-response]:]
-
-[Contact tried to open an audio/video conference (not currently supported)]
-
-[No information has been provided by the server.]
-
-[Item you want to delete not found in list.]
-
-[Failed to add buddy to list: Item already exist.]
-
-[Error adding buddy (invalid ID or already in list?)]
-
-[Cannot add buddy. Limit for this type of item exceeded.]
-
-[Error? Attempting to add ICQ contact to an AIM list.]
-
-[Cannot add this buddy because it requires authorization.]
-
-[Unknown error when adding buddy to list. Error code %#x]
-
-[Item you want to modify not found in list.]
-
-[Unknown error when attempting to modify a group. Error code %#x]
-
-[You've got mail! Checked at]
-
-[Error uploading avatar. (Too small)]
-
-[Error uploading avatar. (Too big)]
-
-[Error uploading avatar. (Wrong type)]
-
-[Error uploading avatar. (Is banned)]
-
-[Error uploading avatar. (Unknown error)]
-
-[A confirmation message has been sent to the new email address. Please follow its instructions.]
-
-[A confirmation message has been sent to your email address. Please follow its instructions.]
-
-[Unable to confirm at this time. Please try again later.]
-
-[Your account has already been confirmed.]
-
-[Can't start the confirmation procedure.]
-
-;file \protocols\AimOscar\src\theme.cpp
-[Block]
-
-[Profile]
-
-[AOL mail]
-
-[AIM icon]
-
-[Hiptop]
-
-[AOL bot]
-
-[Admin]
-
-[Confirmed]
-
-[Not confirmed]
-
-[Blocked list]
-
-[Foreground color]
-
-[Background color]
-
-[Bold]
-
-[Not bold]
-
-[Italic]
-
-[Not italic]
-
-[Underline]
-
-[Not underline]
-
-[Subscript]
-
-[Not subscript]
-
-[Superscript]
-
-[Not superscript]
-
-[Normal script]
-
-[Not normal script]
-
-[Profile editor]
-
-[AIM account type]
-
-[AIM extended status]
-
-[&Block]
-
-[&Unblock]
-
-[Manage account]
-
-[Instant idle]
-
-[Read &HTML away message]
-
-[Read profile]
-
-[Add to server list]
-
-;file \protocols\AimOscar\src\ui.cpp
-[Network]
-
-[Basic]
-
-[Privacy]
-
-[Join me in this buddy chat!]
-
-;file \protocols\AimOscar\src\utility.cpp
-[Please, enter a user name in the options dialog.]
-
-[Please, enter a password in the options dialog.]
-
-[Failed to open file: %s %s]
-
diff --git a/langpacks/croatian/Plugins/AddContactPlus.txt b/langpacks/croatian/Plugins/AddContactPlus.txt
index 9444700739..a488a5589f 100644
--- a/langpacks/croatian/Plugins/AddContactPlus.txt
+++ b/langpacks/croatian/Plugins/AddContactPlus.txt
@@ -3,7 +3,7 @@
; File: AddContactPlus.dll
; Plugin: Add contact+
; Version: 0.9.9.2
-; Authors: Bartosz 'Dezeath' Bialek
+; Authors: Bartosz 'Dezeath' Białek
;============================================================
[Provides the ability to quickly add new contacts.]
diff --git a/langpacks/croatian/Plugins/AssocMgr.txt b/langpacks/croatian/Plugins/AssocMgr.txt
index 6fd486778b..141734f5cc 100644
--- a/langpacks/croatian/Plugins/AssocMgr.txt
+++ b/langpacks/croatian/Plugins/AssocMgr.txt
@@ -5,7 +5,7 @@
; Version: 0.2.1.0
; Authors: H. Herkenrath
;============================================================
-[Handles file type associations and URLs like aim, gg, mirpu, tlen, wpmsg, xmpp, ymsgr.]
+[Handles file type associations and URLs like aim, gg, mirpu, wpmsg, xmpp, ymsgr.]
;file \plugins\AssocMgr\res\resource.rc
[Registered associations for Miranda NG:]
diff --git a/langpacks/croatian/Plugins/BASS_interface.txt b/langpacks/croatian/Plugins/BASS_interface.txt
index af8fcd5dc0..a352a150fc 100644
--- a/langpacks/croatian/Plugins/BASS_interface.txt
+++ b/langpacks/croatian/Plugins/BASS_interface.txt
@@ -1,20 +1,20 @@
#muuid {2f07ea05-05b5-4ff0-875d-c590da2ddac1}
;============================================================
; File: BASS_interface.dll
-; Plugin: BASS interface
+; Plugin: BASS Interface
; Version: 0.0.0.14
; Authors: tico-tico
;============================================================
-[un4seen's BASS interface Miranda NG plugin.]
+[Un4seen's BASS interface Miranda NG plugin.]
;file \plugins\BASS_interface\res\Bass.rc
-[un4seen's bass interface]
+[Un4seen's BASS interface]
[bass.dll loading error]
[Current bass.dll path:]
-[Maximum number of bass internal channels:]
+[Maximum number of BASS internal channels:]
[Output device:]
@@ -22,7 +22,7 @@
[Quiet time:]
-[download bass library]
+[download BASS library]
[Play only if]
@@ -49,7 +49,7 @@
[Preview]
;file \plugins\BASS_interface\src\Main.cpp
-[un4seen's bass version: %d.%d.%d.%d]
+[Un4seen's BASS version: %d.%d.%d.%d]
[--default device--]
@@ -61,6 +61,8 @@
[Frame background]
+[BASS Interface]
+
[Bass Interface]
[Bass library]
diff --git a/langpacks/croatian/Plugins/BasicHistory.txt b/langpacks/croatian/Plugins/BasicHistory.txt
index 399570b16a..3ff59834b2 100644
--- a/langpacks/croatian/Plugins/BasicHistory.txt
+++ b/langpacks/croatian/Plugins/BasicHistory.txt
@@ -8,7 +8,7 @@
[History viewer for Miranda NG.]
;file \plugins\BasicHistory\res\BasicHistory.rc
-[Message History]
+[Message history]
[Settings]
@@ -16,9 +16,9 @@
[Show groups in contact list]
-[Do not show Find control border]
+[Do not show find control border]
-[Default Event Filter]
+[Default event filter]
[Custom filters]
@@ -56,31 +56,31 @@
[Show seconds in timestamps]
-[Enable Smileys]
+[Enable smileys]
[Search forward in list group]
[Search forward in message window]
-[Match Case]
+[Match case]
-[Match Whole Word]
+[Match whole word]
-[Only Incoming Messages]
+[Only incoming messages]
-[Only Outgoing Messages]
+[Only outgoing messages]
-[Only Selected Group]
+[Only selected group]
-[All Contacts]
+[All contacts]
-[Export To Txt]
+[Export to txt]
[File encoding*]
-[Export To Plain Html]
+[Export to plain HTML]
-[Export To Rich Html]
+[Export to rich HTML]
[External CSS file]
@@ -141,9 +141,9 @@
;file \plugins\BasicHistory\src\BasicHistory.cpp
[Open History]
-[View &History]
+[View &history]
-[Delete All User History]
+[Delete all user history]
[Execute history task]
@@ -153,13 +153,13 @@
[Status change]
-[Show Contacts]
+[Show contacts]
-[Hide Contacts]
+[Hide contacts]
-[Find Next]
+[Find next]
-[Find Previous]
+[Find previous]
[Plus in export]
@@ -178,10 +178,10 @@ Povijest
[Me]
-[Invalid Message]
+[Invalid message]
;file \plugins\BasicHistory\src\ExportManager.cpp
-[%s Files (*.%s)]
+[%s files (*.%s)]
[Import]
@@ -194,7 +194,7 @@ Povijest
;file \plugins\BasicHistory\src\HistoryWindow.cpp
[This operation will PERMANENTLY REMOVE all history for this contact.\nAre you sure you want to do this?]
-[Are You sure?]
+[Are you sure?]
[Do you want to delete all imported messages for this contact?\nNote that next scheduler task import this messages again.]
@@ -208,11 +208,11 @@ Povijest
kopiraj
[Delete]
-[Send Message]
+[Send message]
-[Reply &Quoted]
+[Reply &quoted]
-[Delete Group]
+[Delete group]
[Options]
opcije
@@ -224,9 +224,9 @@ opcije
[Hotkeys]
-[Rich Html]
+[Rich HTML]
-[Plain Html]
+[Plain HTML]
[Txt]
@@ -301,27 +301,27 @@ poruke
[Find]
-[Switch Match Case]
+[Switch match case]
-[Switch Match Whole Word]
+[Switch match whole word]
-[Show/Hide Contacts]
+[Show/hide contacts]
-[Switch Only Incoming Messages]
+[Switch only incoming messages]
-[Switch Only Outgoing Messages]
+[Switch only outgoing messages]
-[Switch Only Selected Group]
+[Switch only selected group]
-[Switch All Contacts]
+[Switch all contacts]
-[Export To Binary]
+[Export to binary]
-[Import From Binary]
+[Import from binary]
-[Export To Dat (mContacts)]
+[Export to dat (mContacts)]
-[Import From Dat (mContacts)]
+[Import from dat (mContacts)]
[Invalid event number]
@@ -333,7 +333,7 @@ poruke
[Invalid file]
-[All Files (*.*)]
+[All files (*.*)]
[Enter filter name]
@@ -351,17 +351,17 @@ poruke
[Browse CSS file]
-[Export and Delete]
+[Export and delete]
-[Import and Merge]
+[Import and merge]
[Minute]
[Hour]
-[At Start]
+[At start]
-[At Finish]
+[At finish]
[Daily]
@@ -407,7 +407,7 @@ poruke
;file \plugins\BasicHistory\src\Options.h
;file \plugins\BasicHistory\src\PlainHtmlExport.cpp
-[History Log]
+[History log]
[Filter:]
diff --git a/langpacks/croatian/Plugins/Clist_modern.txt b/langpacks/croatian/Plugins/Clist_modern.txt
index 85c96cc280..b55b7c4247 100644
--- a/langpacks/croatian/Plugins/Clist_modern.txt
+++ b/langpacks/croatian/Plugins/Clist_modern.txt
@@ -50,6 +50,8 @@
[Skin folder]
+[Download more skins]
+
[Available view modes]
[Include protocols]
diff --git a/langpacks/croatian/Plugins/Clist_nicer.txt b/langpacks/croatian/Plugins/Clist_nicer.txt
index 229bbb585d..3f86c1f706 100644
--- a/langpacks/croatian/Plugins/Clist_nicer.txt
+++ b/langpacks/croatian/Plugins/Clist_nicer.txt
@@ -380,6 +380,8 @@ prikaži razdjelnik između kontakata na mreži i izvan mreže
[Ignore selection for groups]
+[Download more skins]
+
[Load from skin file]
[Export to skin file]
diff --git a/langpacks/croatian/Plugins/CloudFile.txt b/langpacks/croatian/Plugins/CloudFile.txt
index 6fadd49339..5d4f7bff4e 100644
--- a/langpacks/croatian/Plugins/CloudFile.txt
+++ b/langpacks/croatian/Plugins/CloudFile.txt
@@ -2,7 +2,7 @@
;============================================================
; File: CloudFile.dll
; Plugin: CloudFile
-; Version: 0.11.0.2
+; Version: 0.11.0.3
; Authors: Miranda NG Team
;============================================================
[Allows you to transfer files via cloud services.]
diff --git a/langpacks/croatian/Plugins/DbEditorPP.txt b/langpacks/croatian/Plugins/DbEditorPP.txt
index 3ba14148cc..f2ec517058 100644
--- a/langpacks/croatian/Plugins/DbEditorPP.txt
+++ b/langpacks/croatian/Plugins/DbEditorPP.txt
@@ -2,7 +2,7 @@
;============================================================
; File: DbEditorPP.dll
; Plugin: Database editor++
-; Version: 4.0.1.1
+; Version: 4.0.1.2
; Authors: Bio, Jonathan Gordon
;============================================================
[Advanced Database Editor.]
diff --git a/langpacks/croatian/Plugins/Fingerprint.txt b/langpacks/croatian/Plugins/Fingerprint.txt
index ea68d9b69a..629cff89ac 100644
--- a/langpacks/croatian/Plugins/Fingerprint.txt
+++ b/langpacks/croatian/Plugins/Fingerprint.txt
@@ -46,8 +46,6 @@
[RSS clients]
-[Tlen clients]
-
[Weather clients]
[Yahoo clients]
@@ -107,8 +105,6 @@
[Gadu-Gadu client]
-[Tlen.pl client]
-
[Python-based clients]
[Jabber client]
@@ -139,8 +135,6 @@
[QQ overlay]
-[Tlen.pl overlay]
-
[Yahoo overlay]
[Mail.Ru Agent overlay]
@@ -175,12 +169,6 @@
[Gadu-Gadu v8 client]
-[Tlen 7.x overlay]
-
-[Tlen 6.x overlay]
-
-[Tlen 5.x overlay]
-
[TM/QQ 2012 overlay]
[TM/QQ 2011 overlay]
diff --git a/langpacks/croatian/Plugins/GmailNotifier.txt b/langpacks/croatian/Plugins/GmailNotifier.txt
index 32c26e1c00..69cff62fff 100644
--- a/langpacks/croatian/Plugins/GmailNotifier.txt
+++ b/langpacks/croatian/Plugins/GmailNotifier.txt
@@ -2,7 +2,7 @@
;============================================================
; File: GmailNotifier.dll
; Plugin: Gmail Multiple Notifier
-; Version: 0.3.1.1
+; Version: 1.0.1.1
; Authors: Mixwind
;============================================================
[Check your Gmail inboxes locally.]
@@ -57,21 +57,19 @@ sekundi
;file \plugins\GmailNotifier\src\check.cpp
[Checking...]
-[Can't open Internet!]
-
-[Can't reach server!]
-
[Can't send account data!]
-[Can't get RSS feed!]
-
[Wrong name or password!]
+[Can't get RSS feed!]
+
;file \plugins\GmailNotifier\src\main.cpp
[Other]
drugo
[Gmail: New thread(s)]
+[Gmail Notifier connection]
+
[&Check all Gmail inboxes]
[&Check Gmail inbox]
diff --git a/langpacks/croatian/Plugins/IEView.txt b/langpacks/croatian/Plugins/IEView.txt
index 9326795f34..11dca313b5 100644
--- a/langpacks/croatian/Plugins/IEView.txt
+++ b/langpacks/croatian/Plugins/IEView.txt
@@ -66,6 +66,8 @@ opcije
[Use relative timestamp]
+[Download more templates]
+
;file \plugins\IEView\src\HistoryHTMLBuilder.cpp
[Outgoing File Transfer]
diff --git a/langpacks/croatian/Plugins/MSN.txt b/langpacks/croatian/Plugins/MSN.txt
index 0a2c65cead..87461939d9 100644
--- a/langpacks/croatian/Plugins/MSN.txt
+++ b/langpacks/croatian/Plugins/MSN.txt
@@ -2,7 +2,7 @@
;============================================================
; File: MSN.dll
; Plugin: MSN protocol
-; Version: 0.14.0.1
+; Version: 0.14.0.2
; Authors: Boris Krasnovskiy, George Hazan, Richard Hughes, leecher
;============================================================
[Microsoft Network (MSN) protocol support for Miranda NG.]
diff --git a/langpacks/croatian/Plugins/New_GPG.txt b/langpacks/croatian/Plugins/New_GPG.txt
index b910829b5d..edc0e27a4f 100644
--- a/langpacks/croatian/Plugins/New_GPG.txt
+++ b/langpacks/croatian/Plugins/New_GPG.txt
@@ -176,86 +176,6 @@
[GPG encryption status]
;file \plugins\New_GPG\src\main.cpp
-[Email]
-
-[Name]
-
-[Creation date]
-
-[Expire date]
-
-[Key length]
-
-[Accounts]
-
-[Default]
-
-[key ID]
-
-[not set]
-
-[Default private key ID]
-
-[Failed to open file]
-
-[Error]
-
-[Generating new random key, please wait]
-
-[Failed to allocate memory]
-
-[Failed to lock memory with error %d]
-
-[Failed write to clipboard with error %d]
-
-[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
-
-[Warning]
-Upozorenje
-[Wrong GPG binary location found in system.\nPlease choose another location]
-
-[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-
-[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-
-["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
-
-[Info]
-
-[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
-
-[GPG binary does not exist.\nPlease choose another location]
-
-[Please choose GPG binary location]
-
-[Please set keyring's home directory]
-
-[There is existing key for contact, would you like to replace it with new key?]
-
-[New public key was received, do you want to import it?]
-
-[Replace]
-
-[Accept]
-
-[Received key from %s]
-
-[You must set encryption algorithm first]
-
-[Key length must be of length from 1024 to 4096 bits]
-
-[Invalid date]
-
-[Name must contain at least 5 characters]
-
-[Name cannot contain '(' or ')']
-
-[Invalid Email]
-
-[Generating new key, please wait...]
-
-[Failed to export public key.]
-
[GPG binary is set and valid (this is good).\n]
[GPG binary unset or invalid (plugin will not work).\n]
@@ -293,6 +213,8 @@ Upozorenje
;file \plugins\New_GPG\src\messages.cpp
[We received encrypted message from contact with encryption turned off.\nDo you want to turn on encryption for this contact?]
+[Warning]
+Upozorenje
[Do you want to try to decrypt encrypted message?]
[We're trying to encrypt with untrusted key. Do you want to trust this key permanently?]
@@ -300,21 +222,19 @@ Upozorenje
[Something is wrong, GPG does not understand us, aborting encryption.]
;file \plugins\New_GPG\src\options.cpp
-[Services]
+[Contact]
-[Main]
+[Key ID]
-[GnuPG Variables]
+[Name]
-[Messages]
-poruke
-[Advanced]
+[Email]
-[Contact]
+[Protocol]
-[Key ID]
+[Default private key ID]
-[Protocol]
+[not set]
[This key is not used by any contact. Do you want to remove it from public keyring?]
@@ -332,6 +252,14 @@ poruke
[.asc pubkey file]
+[Failed to allocate memory]
+
+[Error]
+
+[Failed to lock memory with error %d]
+
+[Failed write to clipboard with error %d]
+
[Failed to open clipboard with error %d]
[Set log file]
@@ -340,6 +268,8 @@ poruke
[Choose gpg.exe]
+[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+
[Set home directory]
[Load Public GPG Key for ]
@@ -356,12 +286,83 @@ poruke
[Key already in secret keyring.]
+[Info]
+
[Set file containing GPG public key]
[GPG public key file]
+[Failed to open file]
+
[There is no public or private key.]
+[Services]
+
+[Main]
+
+[GnuPG Variables]
+
+[Messages]
+poruke
+[Advanced]
+
+;file \plugins\New_GPG\src\ui.cpp
+[New passwords do not match]
+
+[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+
+[Creation date]
+
+[Expire date]
+
+[Key length]
+
+[Accounts]
+
+[Default]
+
+[key ID]
+
+[Generating new random key, please wait]
+
+[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
+
+[Wrong GPG binary location found in system.\nPlease choose another location]
+
+[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+
+["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
+
+[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
+
+[There is existing key for contact, would you like to replace it with new key?]
+
+[New public key was received, do you want to import it?]
+
+[Replace]
+
+[Accept]
+
+[Received key from %s]
+
+[You must set encryption algorithm first]
+
+[Key length must be of length from 1024 to 4096 bits]
+
+[Invalid date]
+
+[Name must contain at least 5 characters]
+
+[Name cannot contain '(' or ')']
+
+[Invalid Email]
+
+[Generating new key, please wait...]
+
+[Expiration date]
+
+[Failed to export public key.]
+
;file \plugins\New_GPG\src\utilities.cpp
[Do you want to toggle encryption for all subcontacts?]
@@ -393,7 +394,10 @@ poruke
[Keys import result]
-[New passwords do not match]
+[GPG binary does not exist.\nPlease choose another location]
-[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[Please choose GPG binary location]
+
+[Please set keyring's home directory]
+;file \plugins\New_GPG\src\utilities.h
diff --git a/langpacks/croatian/Plugins/SimpleStatusMsg.txt b/langpacks/croatian/Plugins/SimpleStatusMsg.txt
index 9e05a18daa..7573f00548 100644
--- a/langpacks/croatian/Plugins/SimpleStatusMsg.txt
+++ b/langpacks/croatian/Plugins/SimpleStatusMsg.txt
@@ -3,7 +3,7 @@
; File: SimpleStatusMsg.dll
; Plugin: Simple status message
; Version: 1.9.0.6
-; Authors: Bartosz 'Dezeath' Bialek, Harven
+; Authors: Bartosz 'Dezeath' Białek, Harven
;============================================================
[Provides a simple way to set status and away messages.]
diff --git a/langpacks/croatian/Plugins/SmileyAdd.txt b/langpacks/croatian/Plugins/SmileyAdd.txt
index ce8b111640..470dd82ffe 100644
--- a/langpacks/croatian/Plugins/SmileyAdd.txt
+++ b/langpacks/croatian/Plugins/SmileyAdd.txt
@@ -2,7 +2,7 @@
;============================================================
; File: SmileyAdd.dll
; Plugin: SmileyAdd
-; Version: 0.2.4.2
+; Version: 0.3.0.1
; Authors: Peacow, nightwish, bid, borkra
;============================================================
[Smiley support for Miranda NG.]
@@ -98,16 +98,14 @@ sve datoteke
;file \plugins\SmileyAdd\src\smileys.cpp
[Smiley pack %s for category "%s" not found.\nSelect correct smiley pack in the Options -> Customize -> Smileys.]
-[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
-
[Smiley #%u in file %s for smiley pack %s not found.]
+[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
+
[%s global smiley pack]
[Standard]
-[Regular expression "%s" in smiley pack "%s" could produce "empty matches".]
-
[Regular expression "%s" in smiley pack "%s" malformed.]
;file \plugins\SmileyAdd\src\smltool.cpp
diff --git a/langpacks/croatian/Plugins/SplashScreen.txt b/langpacks/croatian/Plugins/SplashScreen.txt
index afd3f83f99..9968537cdf 100644
--- a/langpacks/croatian/Plugins/SplashScreen.txt
+++ b/langpacks/croatian/Plugins/SplashScreen.txt
@@ -38,6 +38,8 @@
[Preview...]
+[Download more splash screens]
+
;file \plugins\SplashScreen\src\options.cpp
[Graphic files]
diff --git a/langpacks/croatian/Plugins/StatusManager.txt b/langpacks/croatian/Plugins/StatusManager.txt
index 5be515ab28..cf40e7a413 100644
--- a/langpacks/croatian/Plugins/StatusManager.txt
+++ b/langpacks/croatian/Plugins/StatusManager.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StatusManager.dll
; Plugin: Status manager
-; Version: 0.11.2.3
+; Version: 1.0.1.1
; Authors: P Boon
;============================================================
[A connection checker and auto away module. Also allows you to define the status Miranda should set on startup, configurable per protocol.]
diff --git a/langpacks/croatian/Plugins/Steam.txt b/langpacks/croatian/Plugins/Steam.txt
index 05666f02b5..b73ce92a41 100644
--- a/langpacks/croatian/Plugins/Steam.txt
+++ b/langpacks/croatian/Plugins/Steam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Steam.dll
; Plugin: Steam protocol
-; Version: 0.11.6.1
+; Version: 0.11.6.3
; Authors: Miranda NG Team, Robert Pösel
;============================================================
[Steam protocol support for Miranda NG.]
diff --git a/langpacks/croatian/Plugins/StopSpam.txt b/langpacks/croatian/Plugins/StopSpam.txt
index 5dd243382f..f47e19c69e 100644
--- a/langpacks/croatian/Plugins/StopSpam.txt
+++ b/langpacks/croatian/Plugins/StopSpam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpam.dll
; Plugin: StopSpam+
-; Version: 0.0.1.5
+; Version: 0.1.0.1
; Authors: Roman Miklashevsky, A. Petkevich, Kosh&chka, persei
;============================================================
[Anti-spam plugin for Miranda NG.]
@@ -43,6 +43,9 @@
;file \plugins\StopSpamPlus\src\events.cpp
[StopSpam automatic message:\r\n]
+;file \plugins\StopSpamPlus\src\options.cpp
+[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
+
[Message sessions]
[General]
@@ -51,15 +54,12 @@
poruke
[Accounts]
-;file \plugins\StopSpamPlus\src\options.cpp
-[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
-
;file \plugins\StopSpamPlus\src\services.cpp
[Not In List]
[Complete]
-;file \plugins\StopSpamPlus\src\settings.h
+;file \plugins\StopSpamPlus\src\settings.cpp
[Spammers made me to install small anti-spam system you are now speaking with. Please reply "nospam" without quotes and spaces if you want to contact me.]
[StopSpam: send a message and reply to an anti-spam bot question.]
diff --git a/langpacks/croatian/Plugins/StopSpamMod.txt b/langpacks/croatian/Plugins/StopSpamMod.txt
index 7a135d4d97..52c4ae170d 100644
--- a/langpacks/croatian/Plugins/StopSpamMod.txt
+++ b/langpacks/croatian/Plugins/StopSpamMod.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpamMod.dll
; Plugin: StopSpam mod
-; Version: 0.0.2.1
+; Version: 0.0.2.2
; Authors: Roman Miklashevsky, sss, Elzor
;============================================================
[Anti-spam plugin for Miranda NG.]
diff --git a/langpacks/croatian/Plugins/TabSRMM.txt b/langpacks/croatian/Plugins/TabSRMM.txt
index 20546766b5..6a0cb069a0 100644
--- a/langpacks/croatian/Plugins/TabSRMM.txt
+++ b/langpacks/croatian/Plugins/TabSRMM.txt
@@ -516,6 +516,8 @@ Poruka
[Import from a file...]
+[Download more skins]
+
[Icons]
[Event type icons in the message log]
diff --git a/langpacks/croatian/Plugins/Tox.txt b/langpacks/croatian/Plugins/Tox.txt
index 9e4f35236e..527c7fb0b3 100644
--- a/langpacks/croatian/Plugins/Tox.txt
+++ b/langpacks/croatian/Plugins/Tox.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Tox.dll
; Plugin: Tox protocol
-; Version: 0.11.1.25
+; Version: 0.11.1.26
; Authors: Miranda NG Team
;============================================================
[Tox protocol support for Miranda NG.]
diff --git a/langpacks/croatian/Plugins/mRadio.txt b/langpacks/croatian/Plugins/mRadio.txt
index b6c155618e..916fe60a74 100644
--- a/langpacks/croatian/Plugins/mRadio.txt
+++ b/langpacks/croatian/Plugins/mRadio.txt
@@ -101,7 +101,7 @@
[Sorry!]
-[BASS.DLL not found!]
+[bass.dll not found!]
[Station]
@@ -199,3 +199,5 @@ iskljuÄen
[Quick Open]
+[bass.dll not found! Choose bass.dll path manually]
+
diff --git a/langpacks/croatian/Untranslated/=CORE=.txt b/langpacks/croatian/Untranslated/=CORE=.txt
index 805caf07b6..1cddb237d7 100644
--- a/langpacks/croatian/Untranslated/=CORE=.txt
+++ b/langpacks/croatian/Untranslated/=CORE=.txt
@@ -115,8 +115,6 @@
[Ask me]
[Rename (append " (1)", etc.)]
[You will always be asked about files from people not on your contact list]
-[About Miranda NG]
-[Credits >]
[Become idle if the following is left unattended:]
[Become idle if the screen saver is active]
[Become idle if the computer is locked]
@@ -365,6 +363,7 @@
[Warning!\r\nThis menu object not support user defined options.]
[Insert submenu]
[Insert separator]
+[Module:]
[Service:]
[Default]
[Set]
@@ -432,6 +431,8 @@
[Show in chat rooms]
[Gap between buttons:]
[Hide if there isn't enough space]
+[About Miranda NG]
+[Credits >]
[Tray]
[&Hide/Show]
[Nowhere]
@@ -457,23 +458,6 @@
[Wikipedia (en)]
[Google Maps]
[Google Translate]
-[%s requests authorization]
-[%u requests authorization]
-[%s added you to their contact list]
-[%u added you to their contact list]
-[Alerts]
-[Added event]
-[View user's details]
-[Add contact permanently to list]
-[<Unknown>]
-[%s added you to the contact list\n%u (%s) on %s]
-[%s added you to the contact list\n%u on %s]
-[%s added you to the contact list\n%s on %s]
-[(Unknown)]
-[%s requested authorization\n%u (%s) on %s]
-[%s requested authorization\n%u on %s]
-[%s requested authorization\n%s on %s]
-[Feature is not supported by protocol]
[Re&ad %s message]
[Re&ad status message]
[I've been away since %time%.]
@@ -528,6 +512,8 @@
[Events]
[Select folder]
[My received files]
+[Add contact permanently to list]
+[View user's details]
[View user's history]
[User menu]
[Canceled]
@@ -560,12 +546,6 @@
[Scanning for viruses...]
[Transfer and virus scan complete]
[Outgoing]
-[< Copyright]
-[&Help]
-[&About...]
-[&Support]
-[&Miranda NG homepage]
-[&Report bug]
[Idle]
[Chat module]
[Group chat log background]
@@ -787,8 +767,23 @@
[Owner]
[View/change my &details...]
[%s is online]
+[Alerts]
[Add %s]
[Please authorize my request and add me to your contact list.]
+[%s requests authorization]
+[%u requests authorization]
+[%s added you to their contact list]
+[%u added you to their contact list]
+[Added event]
+[<Unknown>]
+[%s added you to the contact list\n%u (%s) on %s]
+[%s added you to the contact list\n%u on %s]
+[%s added you to the contact list\n%s on %s]
+[(Unknown)]
+[%s requested authorization\n%u (%s) on %s]
+[%s requested authorization\n%u on %s]
+[%s requested authorization\n%s on %s]
+[Feature is not supported by protocol]
[&Join chat]
[&Open chat window]
[%s has joined]
@@ -923,6 +918,12 @@
[Headers]
[Generic text]
[Small text]
+[< Copyright]
+[&Help]
+[&About...]
+[&Support]
+[&Miranda NG homepage]
+[&Report bug]
[Browser: Back]
[Browser: Forward]
[Browser: Refresh]
diff --git a/langpacks/croatian/Untranslated/AIM.txt b/langpacks/croatian/Untranslated/AIM.txt
deleted file mode 100644
index 114f0325fa..0000000000
--- a/langpacks/croatian/Untranslated/AIM.txt
+++ /dev/null
@@ -1,200 +0,0 @@
-[AOL Instant Messenger (AIM) protocol support for Miranda NG.]
-[AIM user details]
-[Screen name:]
-[Display name:]
-[Password:]
-[AIM options]
-[Message delivery confirmation]
-[Do not autoreply when away]
-[Convert incoming messages to BBCode]
-[Convert outgoing messages to HTML]
-[Disable avatars]
-[Disable account type icons]
-[Disable extended status icons]
-[Notify about new mail]
-[Manage server groups]
-[Advanced options]
-[Instant idle on login]
-[Force proxy file transfers]
-[Masquerade as a Sidekick/Hiptop user]
-[Connection]
-[Login server:]
-[Port:]
-[Reset]
-[Disable SSL]
-[Force single client]
-[Use "clientlogin" (recommended)]
-[* Some changes will take effect the next time you connect to the AIM network]
-[Save profile]
-[Create a new AIM account]
-[AIM instant idler]
-[Number of hours:]
-[Number of minutes:]
-[Set idle]
-[Unset idle]
-[Users who can contact me:]
-[Allow all users]
-[Allow only users on contact list]
-[Allow only users below]
-[Block all users]
-[Block only users below]
-[Add]
-[Remove]
-[Idle]
-[Allow contacts to be notified of:]
-[Join chat room]
-[Chat room]
-[&Join]
-[This allows access to user defined chat rooms. To access predefined chat rooms use web links]
-[Change password]
-[Original]
-[New]
-[Repeat]
-[*Passwords don't match.]
-[Screen name]
-[E-mail]
-[Confirm account]
-[*Applied upon reconnect]
-[Save changes]
-[Invite buddy to chat room]
-[&Invite]
-[Invitation reason]
-[Chat room invitation request]
-[Room]
-[Me]
-[Others]
-[&Invite user...]
-[&Leave chat session]
-[User &history]
-[Invalid screen name or password.]
-[Mismatched screen name or password.]
-[You are connecting too frequently. Try waiting 10 minutes to reconnect.]
-[Unknown error occurred when attempting to connect.]
-[Invalid SNAC header.]
-[Server rate limit exceeded.]
-[Client rate limit exceeded]
-[Recipient is not logged in.]
-[Requested service is unavailable.]
-[Requested service is not defined.]
-[You sent obsolete SNAC.]
-[Not supported by server.]
-[Not supported by the client.]
-[Refused by client.]
-[Reply too big.]
-[Response lost.]
-[Request denied.]
-[Incorrect SNAC format.]
-[Insufficient rights.]
-[Recipient blocked.]
-[Sender too evil.]
-[Receiver too evil.]
-[User temporarily unavailable.]
-[No match.]
-[List overflow.]
-[Request ambiguous.]
-[Server queue full.]
-[Not while on AOL.]
-[Check your screen name.]
-[Check your password.]
-[Check your email address.]
-[Service temporarily unavailable.]
-[Field change temporarily unavailable.]
-[Invalid screen name.]
-[Invalid password.]
-[Invalid email.]
-[Invalid registration preference.]
-[Invalid old password.]
-[Invalid screen name Length.]
-[Invalid password length.]
-[Invalid email length.]
-[Invalid old password length.]
-[Need old password.]
-[Read only field.]
-[Write only field.]
-[Unsupported type.]
-[An error has occurred.]
-[Invalid account.]
-[Deleted account.]
-[Expired account.]
-[No database access.]
-[Invalid database fields.]
-[Bad database status.]
-[Migration cancel.]
-[Internal error.]
-[There is already a pending request for this screen name.]
-[Not DT status.]
-[Outstanding confirmation.]
-[No email address.]
-[Over limit.]
-[Email host fail.]
-[DNS fail.]
-[Failed to open file: %s : %s]
-[AIM link protocol]
-[%s protocol]
-[Open mail account?]
-[%s server connection]
-[%s client-to-client connections]
-[[Auto-response]:]
-[Contact tried to open an audio/video conference (not currently supported)]
-[No information has been provided by the server.]
-[Item you want to delete not found in list.]
-[Failed to add buddy to list: Item already exist.]
-[Error adding buddy (invalid ID or already in list?)]
-[Cannot add buddy. Limit for this type of item exceeded.]
-[Error? Attempting to add ICQ contact to an AIM list.]
-[Cannot add this buddy because it requires authorization.]
-[Unknown error when adding buddy to list. Error code %#x]
-[Item you want to modify not found in list.]
-[Unknown error when attempting to modify a group. Error code %#x]
-[You've got mail! Checked at]
-[Error uploading avatar. (Too small)]
-[Error uploading avatar. (Too big)]
-[Error uploading avatar. (Wrong type)]
-[Error uploading avatar. (Is banned)]
-[Error uploading avatar. (Unknown error)]
-[A confirmation message has been sent to the new email address. Please follow its instructions.]
-[A confirmation message has been sent to your email address. Please follow its instructions.]
-[Unable to confirm at this time. Please try again later.]
-[Your account has already been confirmed.]
-[Can't start the confirmation procedure.]
-[Block]
-[Profile]
-[AOL mail]
-[AIM icon]
-[Hiptop]
-[AOL bot]
-[Admin]
-[Confirmed]
-[Not confirmed]
-[Blocked list]
-[Foreground color]
-[Background color]
-[Bold]
-[Not bold]
-[Italic]
-[Not italic]
-[Underline]
-[Not underline]
-[Subscript]
-[Not subscript]
-[Superscript]
-[Not superscript]
-[Normal script]
-[Not normal script]
-[Profile editor]
-[AIM account type]
-[AIM extended status]
-[&Block]
-[&Unblock]
-[Manage account]
-[Instant idle]
-[Read &HTML away message]
-[Read profile]
-[Add to server list]
-[Network]
-[Basic]
-[Privacy]
-[Join me in this buddy chat!]
-[Please, enter a user name in the options dialog.]
-[Please, enter a password in the options dialog.]
-[Failed to open file: %s %s]
diff --git a/langpacks/croatian/Untranslated/AssocMgr.txt b/langpacks/croatian/Untranslated/AssocMgr.txt
index 5e3df913b7..a35c85cb0e 100644
--- a/langpacks/croatian/Untranslated/AssocMgr.txt
+++ b/langpacks/croatian/Untranslated/AssocMgr.txt
@@ -1,4 +1,4 @@
-[Handles file type associations and URLs like aim, gg, mirpu, tlen, wpmsg, xmpp, ymsgr.]
+[Handles file type associations and URLs like aim, gg, mirpu, wpmsg, xmpp, ymsgr.]
[Registered associations for Miranda NG:]
[Miscellaneous]
[&Start Miranda NG automatically when the computer starts (using current profile)]
diff --git a/langpacks/croatian/Untranslated/BASS_interface.txt b/langpacks/croatian/Untranslated/BASS_interface.txt
index eba9a5d207..89b0d72907 100644
--- a/langpacks/croatian/Untranslated/BASS_interface.txt
+++ b/langpacks/croatian/Untranslated/BASS_interface.txt
@@ -1,12 +1,12 @@
-[un4seen's BASS interface Miranda NG plugin.]
-[un4seen's bass interface]
+[Un4seen's BASS interface Miranda NG plugin.]
+[Un4seen's BASS interface]
[bass.dll loading error]
[Current bass.dll path:]
-[Maximum number of bass internal channels:]
+[Maximum number of BASS internal channels:]
[Output device:]
[Volume:]
[Quiet time:]
-[download bass library]
+[download BASS library]
[Play only if]
[Offline]
[Online]
@@ -19,12 +19,13 @@
[On the phone]
[Out to lunch]
[Preview]
-[un4seen's bass version: %d.%d.%d.%d]
+[Un4seen's BASS version: %d.%d.%d.%d]
[--default device--]
[Sounds]
[Disable sounds]
[Enable sounds]
[Frame background]
+[BASS Interface]
[Bass Interface]
[Bass library]
[Sounds enabled]
diff --git a/langpacks/croatian/Untranslated/BasicHistory.txt b/langpacks/croatian/Untranslated/BasicHistory.txt
index 7a674b06a0..1ee85b835e 100644
--- a/langpacks/croatian/Untranslated/BasicHistory.txt
+++ b/langpacks/croatian/Untranslated/BasicHistory.txt
@@ -1,10 +1,10 @@
[History viewer for Miranda NG.]
-[Message History]
+[Message history]
[Settings]
[Always show contact list]
[Show groups in contact list]
-[Do not show Find control border]
-[Default Event Filter]
+[Do not show find control border]
+[Default event filter]
[Custom filters]
[Add filter]
[Delete filter]
@@ -23,19 +23,19 @@
[Limit messages to:]
[Show date in timestamps]
[Show seconds in timestamps]
-[Enable Smileys]
+[Enable smileys]
[Search forward in list group]
[Search forward in message window]
-[Match Case]
-[Match Whole Word]
-[Only Incoming Messages]
-[Only Outgoing Messages]
-[Only Selected Group]
-[All Contacts]
-[Export To Txt]
+[Match case]
+[Match whole word]
+[Only incoming messages]
+[Only outgoing messages]
+[Only selected group]
+[All contacts]
+[Export to txt]
[File encoding*]
-[Export To Plain Html]
-[Export To Rich Html]
+[Export to plain HTML]
+[Export to rich HTML]
[External CSS file]
[* Choose encoding from combo box or enter code page number and name separated by semicolon, name is used in Content-Type header.]
[Add task]
@@ -65,16 +65,16 @@
[Execute task for specified contacts]
[Cancel]
[Open History]
-[View &History]
-[Delete All User History]
+[View &history]
+[Delete all user history]
[Execute history task]
[Incoming message]
[Outgoing message]
[Status change]
-[Show Contacts]
-[Hide Contacts]
-[Find Next]
-[Find Previous]
+[Show contacts]
+[Hide contacts]
+[Find next]
+[Find previous]
[Plus in export]
[Minus in export]
[All events]
@@ -82,27 +82,27 @@
[History for %s]
[System]
[Me]
-[Invalid Message]
-[%s Files (*.%s)]
+[Invalid message]
+[%s files (*.%s)]
[Import]
[Export]
[File does not contain selected contact]
[File is corrupted]
[This operation will PERMANENTLY REMOVE all history for this contact.\nAre you sure you want to do this?]
-[Are You sure?]
+[Are you sure?]
[Do you want to delete all imported messages for this contact?\nNote that next scheduler task import this messages again.]
[Open in &new window]
[&Open in existing window]
[Delete]
-[Send Message]
-[Reply &Quoted]
-[Delete Group]
+[Send message]
+[Reply &quoted]
+[Delete group]
[Filters]
[Fonts and colors]
[Icons]
[Hotkeys]
-[Rich Html]
-[Plain Html]
+[Rich HTML]
+[Plain HTML]
[Txt]
[Binary]
[Dat (mContacts)]
@@ -134,23 +134,23 @@
[Contact list background]
[Open global history]
[Find]
-[Switch Match Case]
-[Switch Match Whole Word]
-[Show/Hide Contacts]
-[Switch Only Incoming Messages]
-[Switch Only Outgoing Messages]
-[Switch Only Selected Group]
-[Switch All Contacts]
-[Export To Binary]
-[Import From Binary]
-[Export To Dat (mContacts)]
-[Import From Dat (mContacts)]
+[Switch match case]
+[Switch match whole word]
+[Show/hide contacts]
+[Switch only incoming messages]
+[Switch only outgoing messages]
+[Switch only selected group]
+[Switch all contacts]
+[Export to binary]
+[Import from binary]
+[Export to dat (mContacts)]
+[Import from dat (mContacts)]
[Invalid event number]
[Incoming events]
[Outgoing events]
[File does not exist. Enter correct file path.]
[Invalid file]
-[All Files (*.*)]
+[All files (*.*)]
[Enter filter name]
[Filter name exists]
[Event already exists]
@@ -159,12 +159,12 @@
[You've entered invalid codepage. Select codepage from combo box or enter correct number.]
[Invalid codepage]
[Browse CSS file]
-[Export and Delete]
-[Import and Merge]
+[Export and delete]
+[Import and merge]
[Minute]
[Hour]
-[At Start]
-[At Finish]
+[At start]
+[At finish]
[Daily]
[Weekly]
[Monthly]
@@ -186,7 +186,7 @@
[Download from FTP (WinSCP requred)]
[Import from]
[** Use <date> to insert date, <ext> to insert extension, <contact> to insert contact name]
-[History Log]
+[History log]
[Filter:]
[Conversation started at %s]
[Menu]
diff --git a/langpacks/croatian/Untranslated/Clist_modern.txt b/langpacks/croatian/Untranslated/Clist_modern.txt
index db312acacd..f1341d6310 100644
--- a/langpacks/croatian/Untranslated/Clist_modern.txt
+++ b/langpacks/croatian/Untranslated/Clist_modern.txt
@@ -20,6 +20,7 @@
[WARNING: \tSkins can modify your current profile. Rollback is not possible. \n\t\tPlease BACKUP your database before applying skin.]
[* Restart may be required for all changes to take effect]
[Skin folder]
+[Download more skins]
[Available view modes]
[Include protocols]
[New]
diff --git a/langpacks/croatian/Untranslated/Clist_nicer.txt b/langpacks/croatian/Untranslated/Clist_nicer.txt
index dcab611ac0..2f134c0729 100644
--- a/langpacks/croatian/Untranslated/Clist_nicer.txt
+++ b/langpacks/croatian/Untranslated/Clist_nicer.txt
@@ -140,6 +140,7 @@
[Group top padding]
[Frame title bar height]
[Ignore selection for groups]
+[Download more skins]
[Load from skin file]
[Export to skin file]
[Dialog]
diff --git a/langpacks/croatian/Untranslated/Fingerprint.txt b/langpacks/croatian/Untranslated/Fingerprint.txt
index 58e33cf6c7..80ece18d95 100644
--- a/langpacks/croatian/Untranslated/Fingerprint.txt
+++ b/langpacks/croatian/Untranslated/Fingerprint.txt
@@ -18,7 +18,6 @@
[MSN clients]
[QQ clients]
[RSS clients]
-[Tlen clients]
[Weather clients]
[Yahoo clients]
[Facebook clients]
@@ -47,7 +46,6 @@
[Mail.Ru (unknown client)]
[TM 2008 and >]
[Gadu-Gadu client]
-[Tlen.pl client]
[Python-based clients]
[Jabber client]
[XMPP client]
@@ -63,7 +61,6 @@
[Jabber overlay]
[MSN overlay]
[QQ overlay]
-[Tlen.pl overlay]
[Yahoo overlay]
[Mail.Ru Agent overlay]
[VK overlay]
@@ -81,9 +78,6 @@
[Gadu-Gadu v10 client]
[Gadu-Gadu v9 client]
[Gadu-Gadu v8 client]
-[Tlen 7.x overlay]
-[Tlen 6.x overlay]
-[Tlen 5.x overlay]
[TM/QQ 2012 overlay]
[TM/QQ 2011 overlay]
[TM/QQ 2010 overlay]
diff --git a/langpacks/croatian/Untranslated/GmailNotifier.txt b/langpacks/croatian/Untranslated/GmailNotifier.txt
index f3de080320..7defcaefdd 100644
--- a/langpacks/croatian/Untranslated/GmailNotifier.txt
+++ b/langpacks/croatian/Untranslated/GmailNotifier.txt
@@ -22,12 +22,11 @@
[This is a shared computer so disable auto login]
[Log unread threads into database (enable history)]
[Checking...]
-[Can't open Internet!]
-[Can't reach server!]
[Can't send account data!]
-[Can't get RSS feed!]
[Wrong name or password!]
+[Can't get RSS feed!]
[Gmail: New thread(s)]
+[Gmail Notifier connection]
[&Check all Gmail inboxes]
[&Check Gmail inbox]
[GmailNotifier]
diff --git a/langpacks/croatian/Untranslated/IEView.txt b/langpacks/croatian/Untranslated/IEView.txt
index 15f85c0dfd..eaa687968a 100644
--- a/langpacks/croatian/Untranslated/IEView.txt
+++ b/langpacks/croatian/Untranslated/IEView.txt
@@ -25,6 +25,7 @@
[Show date]
[Use long date format]
[Use relative timestamp]
+[Download more templates]
[Outgoing File Transfer]
[Incoming File Transfer]
[URL sent]
diff --git a/langpacks/croatian/Untranslated/New_GPG.txt b/langpacks/croatian/Untranslated/New_GPG.txt
index ab35828ac4..9d6850c131 100644
--- a/langpacks/croatian/Untranslated/New_GPG.txt
+++ b/langpacks/croatian/Untranslated/New_GPG.txt
@@ -82,45 +82,6 @@
[Export GPG Public keys]
[Import GPG Public keys]
[GPG encryption status]
-[Email]
-[Name]
-[Creation date]
-[Expire date]
-[Key length]
-[Accounts]
-[Default]
-[key ID]
-[not set]
-[Default private key ID]
-[Failed to open file]
-[Error]
-[Generating new random key, please wait]
-[Failed to allocate memory]
-[Failed to lock memory with error %d]
-[Failed write to clipboard with error %d]
-[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
-[Wrong GPG binary location found in system.\nPlease choose another location]
-[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
-[Info]
-[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
-[GPG binary does not exist.\nPlease choose another location]
-[Please choose GPG binary location]
-[Please set keyring's home directory]
-[There is existing key for contact, would you like to replace it with new key?]
-[New public key was received, do you want to import it?]
-[Replace]
-[Accept]
-[Received key from %s]
-[You must set encryption algorithm first]
-[Key length must be of length from 1024 to 4096 bits]
-[Invalid date]
-[Name must contain at least 5 characters]
-[Name cannot contain '(' or ')']
-[Invalid Email]
-[Generating new key, please wait...]
-[Failed to export public key.]
[GPG binary is set and valid (this is good).\n]
[GPG binary unset or invalid (plugin will not work).\n]
[Home dir write access granted (this is good).\n]
@@ -142,13 +103,13 @@
[Do you want to try to decrypt encrypted message?]
[We're trying to encrypt with untrusted key. Do you want to trust this key permanently?]
[Something is wrong, GPG does not understand us, aborting encryption.]
-[Services]
-[Main]
-[GnuPG Variables]
-[Advanced]
[Contact]
[Key ID]
+[Name]
+[Email]
[Protocol]
+[Default private key ID]
+[not set]
[This key is not used by any contact. Do you want to remove it from public keyring?]
[Key info]
[we have secret key for this public key, do not removing from GPG keyring]
@@ -157,10 +118,15 @@
[Do you want to remove key from entire metacontact (all subcontacts)?]
[Export public key]
[.asc pubkey file]
+[Failed to allocate memory]
+[Error]
+[Failed to lock memory with error %d]
+[Failed write to clipboard with error %d]
[Failed to open clipboard with error %d]
[Set log file]
[LOG files]
[Choose gpg.exe]
+[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
[Set home directory]
[Load Public GPG Key for ]
[Turn off encryption]
@@ -169,9 +135,43 @@
[ found in presence.)]
[This is not public or private key]
[Key already in secret keyring.]
+[Info]
[Set file containing GPG public key]
[GPG public key file]
+[Failed to open file]
[There is no public or private key.]
+[Services]
+[Main]
+[GnuPG Variables]
+[Advanced]
+[New passwords do not match]
+[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[Creation date]
+[Expire date]
+[Key length]
+[Accounts]
+[Default]
+[key ID]
+[Generating new random key, please wait]
+[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
+[Wrong GPG binary location found in system.\nPlease choose another location]
+[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
+[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
+[There is existing key for contact, would you like to replace it with new key?]
+[New public key was received, do you want to import it?]
+[Replace]
+[Accept]
+[Received key from %s]
+[You must set encryption algorithm first]
+[Key length must be of length from 1024 to 4096 bits]
+[Invalid date]
+[Name must contain at least 5 characters]
+[Name cannot contain '(' or ')']
+[Invalid Email]
+[Generating new key, please wait...]
+[Expiration date]
+[Failed to export public key.]
[Do you want to toggle encryption for all subcontacts?]
[Turn off GPG encryption]
[Turn on GPG encryption]
@@ -187,5 +187,6 @@
[We have successfully processed %d public keys and some private keys.]
[We have successfully processed %d public keys.]
[Keys import result]
-[New passwords do not match]
-[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[GPG binary does not exist.\nPlease choose another location]
+[Please choose GPG binary location]
+[Please set keyring's home directory]
diff --git a/langpacks/croatian/Untranslated/SmileyAdd.txt b/langpacks/croatian/Untranslated/SmileyAdd.txt
index 09a69eab54..e3f0ef0723 100644
--- a/langpacks/croatian/Untranslated/SmileyAdd.txt
+++ b/langpacks/croatian/Untranslated/SmileyAdd.txt
@@ -39,10 +39,9 @@
[Customize]
[Protocol specific]
[Smiley pack %s for category "%s" not found.\nSelect correct smiley pack in the Options -> Customize -> Smileys.]
-[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
[Smiley #%u in file %s for smiley pack %s not found.]
+[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
[%s global smiley pack]
[Standard]
-[Regular expression "%s" in smiley pack "%s" could produce "empty matches".]
[Regular expression "%s" in smiley pack "%s" malformed.]
[d'Oh!]
diff --git a/langpacks/croatian/Untranslated/SplashScreen.txt b/langpacks/croatian/Untranslated/SplashScreen.txt
index 58cb20735e..7d3dc195ab 100644
--- a/langpacks/croatian/Untranslated/SplashScreen.txt
+++ b/langpacks/croatian/Untranslated/SplashScreen.txt
@@ -14,6 +14,7 @@
[Fade out:]
[AdvaImg plugin not found. Please get it from https://miranda-ng.org/p/AdvaImg/ to be able to use images.]
[Preview...]
+[Download more splash screens]
[Graphic files]
[Skins]
[Splash Screen]
diff --git a/langpacks/croatian/Untranslated/StopSpam.txt b/langpacks/croatian/Untranslated/StopSpam.txt
index dbf39d020d..e03e18a5b3 100644
--- a/langpacks/croatian/Untranslated/StopSpam.txt
+++ b/langpacks/croatian/Untranslated/StopSpam.txt
@@ -16,10 +16,10 @@
[Remove all temporary contacts after restart]
[Log Spammers to system history]
[StopSpam automatic message:\r\n]
+[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
[Message sessions]
[General]
[Accounts]
-[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
[Not In List]
[Complete]
[Spammers made me to install small anti-spam system you are now speaking with. Please reply "nospam" without quotes and spaces if you want to contact me.]
diff --git a/langpacks/croatian/Untranslated/TabSRMM.txt b/langpacks/croatian/Untranslated/TabSRMM.txt
index da298f3708..3bf78e2f44 100644
--- a/langpacks/croatian/Untranslated/TabSRMM.txt
+++ b/langpacks/croatian/Untranslated/TabSRMM.txt
@@ -228,6 +228,7 @@
[You can export and import all your color and font settings here. This allows you to create a Theme file which can be shared between different profiles or with your buddies.]
[Export to a file...]
[Import from a file...]
+[Download more skins]
[Icons]
[Event type icons in the message log]
[Text symbols as event markers]
diff --git a/langpacks/croatian/Untranslated/mRadio.txt b/langpacks/croatian/Untranslated/mRadio.txt
index 146b55221c..5c03d99975 100644
--- a/langpacks/croatian/Untranslated/mRadio.txt
+++ b/langpacks/croatian/Untranslated/mRadio.txt
@@ -46,7 +46,7 @@
[Continuous record]
[Quarry]
[Sorry!]
-[BASS.DLL not found!]
+[bass.dll not found!]
[Station]
[Custom INI file]
[Radio station URL]
@@ -94,3 +94,4 @@
[Equalizer]
[New]
[Quick Open]
+[bass.dll not found! Choose bass.dll path manually]
diff --git a/langpacks/czech/=CORE=.txt b/langpacks/czech/=CORE=.txt
index 45291ac4e3..ec2826b2e0 100644
--- a/langpacks/czech/=CORE=.txt
+++ b/langpacks/czech/=CORE=.txt
@@ -3,29 +3,6 @@
; Module: Miranda Core
; Version: 0.95.8
;============================================================
-;file \src\core\stdauth\res\resource.rc
-[Authorization request]
-Žádost o autorizaci
-[&Authorize]
-&Autorizovat
-[&Deny]
-O&dmítnout
-[Decide &later]
-&Později
-[User &details]
-&Detaily uživatele
-[Reason:]
-Důvod:
-[Denial reason:]
-Důvod odmítnutí:
-[Add to contact list if authorized]
-Je-li autorizován, přidat mezi kontakty
-[You were added]
-Zpráva o zařazení mezi kontakty
-[&Close]
-&Zavřít
-[&Add]
-Přid&at
;file \src\core\stdaway\res\resource.rc
[%s message for %s]
Stav: '%s', uživatel: %s
@@ -291,6 +268,8 @@ Celková velikost:
Popis:
[&User menu]
Nabídka &uživatele
+[User &details]
+&Detaily uživatele
[&History]
&Historie
[Incoming file transfer]
@@ -307,6 +286,8 @@ Datum:
Soubory:
[Save to:]
Uložit do:
+[&Add]
+Přid&at
[&Open...]
&Otevřít...
[Open &folder]
@@ -395,11 +376,6 @@ Zeptat se
Přejmenovat (přidá " (1)" atd.)
[You will always be asked about files from people not on your contact list]
Příjem souborů od lidí, kteří nejsou mezi kontakty, podléhá vždy dotazu.
-;file \src\core\stdhelp\res\resource.rc
-[About Miranda NG]
-O programu Miranda NG
-[Credits >]
-Poděkování >
;file \src\core\stdidle\res\resource.rc
[Become idle if the following is left unattended:]
PÅ™ejít do stavu neÄinnosti pokud se nic nedÄ›je v:
@@ -723,6 +699,8 @@ Otevřít komunikaÄní okno
Vlastní jméno:
[Group:]
Skupina:
+[Authorization request]
+Žádost o autorizaci
[&Yes]
&Ano
[&No]
@@ -999,6 +977,8 @@ Upozornění!\r\nTato nabídka nepodporuje změnu nastavení.
Vložit podnabídku
[Insert separator]
Vložit oddÄ›lovaÄ
+[Module:]
+Modul:
[Service:]
Služba:
[Default]
@@ -1133,6 +1113,26 @@ Zobrazit v chatovacích místnostech
Mezera mezi tlaÄítky:
[Hide if there isn't enough space]
Skrýt pokud není dost místa
+[&Authorize]
+&Autorizovat
+[&Deny]
+O&dmítnout
+[Decide &later]
+&Později
+[Reason:]
+Důvod:
+[Denial reason:]
+Důvod odmítnutí:
+[Add to contact list if authorized]
+Je-li autorizován, přidat mezi kontakty
+[You were added]
+Zpráva o zařazení mezi kontakty
+[&Close]
+&Zavřít
+[About Miranda NG]
+O programu Miranda NG
+[Credits >]
+Poděkování >
[Tray]
Oznamovací oblast
[&Hide/Show]
@@ -1193,42 +1193,6 @@ Wikipedia (en)
Mapy Google
[Google Translate]
PÅ™ekladaÄ Google
-;file \src\core\stdauth\src\auth.cpp
-[%s requests authorization]
-%s žádá o autorizaci
-[%u requests authorization]
-%u žádá o autorizaci
-[%s added you to their contact list]
-%s si vás přidal mezi své kontakty
-[%u added you to their contact list]
-%u si vás přidal mezi své kontakty
-[Alerts]
-Upozornění
-[Added event]
-Nová událost
-;file \src\core\stdauth\src\authdialogs.cpp
-[View user's details]
-Zobrazit osobní údaje
-[Add contact permanently to list]
-Přidat do seznamu natrvalo
-[<Unknown>]
-<neznámý>
-[%s added you to the contact list\n%u (%s) on %s]
-%s si vás přidal mezi své kontakty\n%u (%s) v síti %s
-[%s added you to the contact list\n%u on %s]
-%s si vás přidal mezi své kontakty\n%u v síti %s
-[%s added you to the contact list\n%s on %s]
-%s si vás přidal mezi své kontakty\n%s v síti %s
-[(Unknown)]
-(neznámý)
-[%s requested authorization\n%u (%s) on %s]
-%s žádá o autorizaci\n%u (%s) v síti %s
-[%s requested authorization\n%u on %s]
-%s žádá o autorizaci\n%u v síti %s
-[%s requested authorization\n%s on %s]
-%s žádá o autorizaci\n%s v síti %s
-[Feature is not supported by protocol]
-Funkce není protokolem podporována
;file \src\core\stdaway\src\awaymsg.cpp
[Re&ad %s message]
PÅ™eÄíst &automatickou odpovÄ›Ä
@@ -1351,6 +1315,10 @@ Události
Vyberte požadovanou složku
[My received files]
Moje přijaté soubory
+[Add contact permanently to list]
+Přidat do seznamu natrvalo
+[View user's details]
+Zobrazit osobní údaje
[View user's history]
Zobrazit historii
[User menu]
@@ -1418,20 +1386,6 @@ PÅ™enos a kontrola antivirem dokonÄena
;file \src\core\stdfile\src\ftmanager.cpp
[Outgoing]
Odchozí
-;file \src\core\stdhelp\src\about.cpp
-[< Copyright]
-< Copyright
-;file \src\core\stdhelp\src\help.cpp
-[&Help]
-&Nápověda
-[&About...]
-O progr&amu...
-[&Support]
-&Podpora
-[&Miranda NG homepage]
-Do&movská stránka
-[&Report bug]
-&Nahlásit chybu
;file \src\core\stdidle\src\idle.cpp
[Idle]
NeÄinnost
@@ -1907,11 +1861,43 @@ In&formace o sobÄ›...
;file \src\core\stduseronline\src\useronline.cpp
[%s is online]
%s je online
+[Alerts]
+Upozornění
;file \src\mir_app\src\addcontact.cpp
[Add %s]
Mezi kontakty přidat: %s
[Please authorize my request and add me to your contact list.]
Autorizujte prosím můj požadavek a přidejte si mě do vašeho seznamu.
+;file \src\mir_app\src\auth.cpp
+[%s requests authorization]
+%s žádá o autorizaci
+[%u requests authorization]
+%u žádá o autorizaci
+[%s added you to their contact list]
+%s si vás přidal mezi své kontakty
+[%u added you to their contact list]
+%u si vás přidal mezi své kontakty
+[Added event]
+Nová událost
+;file \src\mir_app\src\authdialogs.cpp
+[<Unknown>]
+<neznámý>
+[%s added you to the contact list\n%u (%s) on %s]
+%s si vás přidal mezi své kontakty\n%u (%s) v síti %s
+[%s added you to the contact list\n%u on %s]
+%s si vás přidal mezi své kontakty\n%u v síti %s
+[%s added you to the contact list\n%s on %s]
+%s si vás přidal mezi své kontakty\n%s v síti %s
+[(Unknown)]
+(neznámý)
+[%s requested authorization\n%u (%s) on %s]
+%s žádá o autorizaci\n%u (%s) v síti %s
+[%s requested authorization\n%u on %s]
+%s žádá o autorizaci\n%u v síti %s
+[%s requested authorization\n%s on %s]
+%s žádá o autorizaci\n%s v síti %s
+[Feature is not supported by protocol]
+Funkce není protokolem podporována
;file \src\mir_app\src\chat_clist.cpp
[&Join chat]
&Přidat se do diskuse
@@ -2200,6 +2186,19 @@ Záhlaví
Běžný text
[Small text]
Poznámky
+;file \src\mir_app\src\help.cpp
+[< Copyright]
+< Copyright
+[&Help]
+&Nápověda
+[&About...]
+O progr&amu...
+[&Support]
+&Podpora
+[&Miranda NG homepage]
+Do&movská stránka
+[&Report bug]
+&Nahlásit chybu
;file \src\mir_app\src\hotkey_opts.cpp
[Browser: Back]
ProhlížeÄ: ZpÄ›t
diff --git a/langpacks/czech/=HEAD=.txt b/langpacks/czech/=HEAD=.txt
index 56dd3a155d..7ff66d92f7 100644
--- a/langpacks/czech/=HEAD=.txt
+++ b/langpacks/czech/=HEAD=.txt
@@ -3,7 +3,7 @@ Language: Czech (CZ)
Locale: 0405
Authors: Robert Pösel (Robyer) (viz http://www.robyer.cz)
Author-email: robyer@seznam.cz
-Last-Modified-Using: Miranda NG 0.95.3
+Last-Modified-Using: Miranda NG 0.95.8
; Based on translation for Miranda IM (viz http://miranda.kvalitne.cz):
; Authors: Vít Å indlář, sir-qwerty, Martin KoníÄek, AleÅ¡ Studený, madmojo, Dave-Dave, Tur McDonnel, waclaw, Lev, Pavel Svátek, Mareman, Richard Nižnik, Laslo Gogolak, Petr HanuÅ¡, churchyard, tapin, Soustruh, Libor PolÄák, Jiří Kocman, MiSHAK, Robyer, Fille, Jake
diff --git a/langpacks/czech/Plugins/AIM.txt b/langpacks/czech/Deprecated/AIM.txt
index 6ab16d3a60..6ab16d3a60 100644
--- a/langpacks/czech/Plugins/AIM.txt
+++ b/langpacks/czech/Deprecated/AIM.txt
diff --git a/langpacks/czech/Plugins/AddContactPlus.txt b/langpacks/czech/Plugins/AddContactPlus.txt
index 3650623e4f..1d7df06efb 100644
--- a/langpacks/czech/Plugins/AddContactPlus.txt
+++ b/langpacks/czech/Plugins/AddContactPlus.txt
@@ -3,7 +3,7 @@
; File: AddContactPlus.dll
; Plugin: Add contact+
; Version: 0.9.9.2
-; Authors: Bartosz 'Dezeath' Bialek
+; Authors: Bartosz 'Dezeath' Białek
;============================================================
[Provides the ability to quickly add new contacts.]
Umožňuje rychle přidávat nové kontakty.
diff --git a/langpacks/czech/Plugins/AssocMgr.txt b/langpacks/czech/Plugins/AssocMgr.txt
index 8de0c28429..252c5569f9 100644
--- a/langpacks/czech/Plugins/AssocMgr.txt
+++ b/langpacks/czech/Plugins/AssocMgr.txt
@@ -5,8 +5,8 @@
; Version: 0.2.1.0
; Authors: H. Herkenrath
;============================================================
-[Handles file type associations and URLs like aim, gg, mirpu, tlen, wpmsg, xmpp, ymsgr.]
-Spravuje asociace souborů a URL jako jsou aim, gg, mirpu, tlen, wpmsg, xmpp, ymsgr.
+[Handles file type associations and URLs like aim, gg, mirpu, wpmsg, xmpp, ymsgr.]
+Spravuje asociace souborů a URL jako jsou aim, gg, mirpu, wpmsg, xmpp, ymsgr.
;file \plugins\AssocMgr\res\resource.rc
[Registered associations for Miranda NG:]
Asociace registrované pro Mirandu NG:
diff --git a/langpacks/czech/Plugins/BASS_interface.txt b/langpacks/czech/Plugins/BASS_interface.txt
index c9b707679f..d310431443 100644
--- a/langpacks/czech/Plugins/BASS_interface.txt
+++ b/langpacks/czech/Plugins/BASS_interface.txt
@@ -1,29 +1,29 @@
#muuid {2f07ea05-05b5-4ff0-875d-c590da2ddac1}
;============================================================
; File: BASS_interface.dll
-; Plugin: BASS interface
+; Plugin: BASS Interface
; Version: 0.0.0.14
; Authors: tico-tico
;============================================================
-[un4seen's BASS interface Miranda NG plugin.]
-Doplněk pro rozhraní un4seen's BASS pro Mirandu NG.
+[Un4seen's BASS interface Miranda NG plugin.]
+Doplněk pro rozhraní Un4seen's BASS pro Mirandu NG.
;file \plugins\BASS_interface\res\Bass.rc
-[un4seen's bass interface]
-Rozhraní un4seen's bass
+[Un4seen's BASS interface]
+Rozhraní Un4seen's BASS
[bass.dll loading error]
Chyba naÄítání bass.dll
[Current bass.dll path:]
Aktuální cesta k bass.dll:
-[Maximum number of bass internal channels:]
-Maximální poÄet interních kanálů bass:
+[Maximum number of BASS internal channels:]
+Maximální poÄet interních kanálů BASS:
[Output device:]
Výstupní zařízení:
[Volume:]
Hlasitost:
[Quiet time:]
ÄŒas ticha:
-[download bass library]
-stáhnout bass knihovnu
+[download BASS library]
+stáhnout BASS knihovnu
[Play only if]
Povolit pouze ve stavu
[Offline]
@@ -49,8 +49,8 @@ Na obědě
[Preview]
Náhled
;file \plugins\BASS_interface\src\Main.cpp
-[un4seen's bass version: %d.%d.%d.%d]
-Verze un4seen's bass: %d.%d.%d.%d
+[Un4seen's BASS version: %d.%d.%d.%d]
+Verze Un4seen's BASS: %d.%d.%d.%d
[--default device--]
--výchozí zařízení--
[Sounds]
@@ -61,10 +61,12 @@ Zakázat zvuky
Povolit zvuky
[Frame background]
Barva pozadí rámeÄku
+[BASS Interface]
+BASS rozhraní
[Bass Interface]
-Bass rozhraní
+BASS rozhraní
[Bass library]
-Bass knihovna
+BASS knihovna
[Sounds enabled]
Zvuky povoleny
[Sounds disabled]
diff --git a/langpacks/czech/Plugins/BasicHistory.txt b/langpacks/czech/Plugins/BasicHistory.txt
index a14a4b3cb4..880a03527d 100644
--- a/langpacks/czech/Plugins/BasicHistory.txt
+++ b/langpacks/czech/Plugins/BasicHistory.txt
@@ -8,7 +8,7 @@
[History viewer for Miranda NG.]
ZobrazovaÄ historie pro Mirandu NG.
;file \plugins\BasicHistory\res\BasicHistory.rc
-[Message History]
+[Message history]
Historie zpráv
[Settings]
Nastavení
@@ -16,9 +16,9 @@ Nastavení
Vždy zobrazit seznam kontaktů
[Show groups in contact list]
Zobrazit skupiny v seznamu kontaktů
-[Do not show Find control border]
+[Do not show find control border]
Nezobrazovat okraj vyhledávacího pole
-[Default Event Filter]
+[Default event filter]
Výchozí filtr událostí
[Custom filters]
Vlastní filtry
@@ -56,32 +56,32 @@ Omezit zprávy na:
Zobrazit datum v Äasovém údaji
[Show seconds in timestamps]
Zobrazit sekundy v Äasovém údaji
-[Enable Smileys]
+[Enable smileys]
Povolit smajlíky
[Search forward in list group]
Vyhledávat dopředu v seznamu skupin
[Search forward in message window]
Vyhledávat dopředu v okně se zprávami
-[Match Case]
+[Match case]
Rozlišovat velikost písmen
-[Match Whole Word]
+[Match whole word]
Pouze celá slova
-[Only Incoming Messages]
+[Only incoming messages]
Pouze příchozí zprávy
-[Only Outgoing Messages]
+[Only outgoing messages]
Pouze odchozí zprávy
-[Only Selected Group]
+[Only selected group]
Pouze ve vybrané skupině
-[All Contacts]
-Ve všech kontaktech
-[Export To Txt]
-Exportovat do Txt
+[All contacts]
+Všechny kontakty
+[Export to txt]
+Exportovat do txt
[File encoding*]
Kódování souboru*
-[Export To Plain Html]
-Exportovat do Äistého Html
-[Export To Rich Html]
-Exportovat do bohatého Html
+[Export to plain HTML]
+Exportovat do Äistého HTML
+[Export to rich HTML]
+Exportovat do bohatého HTML
[External CSS file]
Externí CSS soubor
[* Choose encoding from combo box or enter code page number and name separated by semicolon, name is used in Content-Type header.]
@@ -141,9 +141,9 @@ Zrušit
;file \plugins\BasicHistory\src\BasicHistory.cpp
[Open History]
Otevřít historii
-[View &History]
+[View &history]
Zobrazit &historii
-[Delete All User History]
+[Delete all user history]
Smazat celou historii uživatele
[Execute history task]
Vykonat úlohu historie
@@ -153,13 +153,13 @@ Příchozí zpráva
Odchozí zpráva
[Status change]
Změna stavu
-[Show Contacts]
+[Show contacts]
Zobrazit kontakty
-[Hide Contacts]
+[Hide contacts]
Skrýt kontakty
-[Find Next]
+[Find next]
Najít další
-[Find Previous]
+[Find previous]
Najít předchozí
[Plus in export]
Plus v exportu
@@ -178,10 +178,10 @@ Historie pro %s
Systém
[Me]
Já
-[Invalid Message]
+[Invalid message]
Neplatná zpráva
;file \plugins\BasicHistory\src\ExportManager.cpp
-[%s Files (*.%s)]
+[%s files (*.%s)]
Soubory %s (*.%s)
[Import]
Importovat
@@ -194,7 +194,7 @@ Soubor je poškozen
;file \plugins\BasicHistory\src\HistoryWindow.cpp
[This operation will PERMANENTLY REMOVE all history for this contact.\nAre you sure you want to do this?]
Tato operace ODSTRANà NATRVALO vÅ¡echnu historii tohoto kontaktu.\nJste si jistí, že chcete pokraÄovat?
-[Are You sure?]
+[Are you sure?]
Opravdu chcete pokraÄovat?
[Do you want to delete all imported messages for this contact?\nNote that next scheduler task import this messages again.]
Přejete si smazat všechny importované zprávy tohoto kontaktu?\nUvědomte si, že další naplánovaná úloha naimportuje tyto zprávy znovu.
@@ -208,12 +208,12 @@ Z&kopírovat odkaz
Zkopírovat
[Delete]
Smazat
-[Send Message]
-Odeslat zprávu
-[Reply &Quoted]
+[Send message]
+Poslat zprávu
+[Reply &quoted]
Odpovědět s &citací
-[Delete Group]
-Smazat skupinu
+[Delete group]
+Odstranit skupinu
[Options]
Možnosti
[Filters]
@@ -224,10 +224,10 @@ Písma a barvy
Ikony
[Hotkeys]
Klávesové zkratky
-[Rich Html]
-Bohaté Html
-[Plain Html]
-Čisté Html
+[Rich HTML]
+Bohaté HTML
+[Plain HTML]
+Čisté HTML
[Txt]
Txt
[Binary]
@@ -301,28 +301,28 @@ Pozadí seznamu kontaktů
Otevřít globální historii
[Find]
Najít
-[Switch Match Case]
+[Switch match case]
Přepnout rozlišování velikosti písmen
-[Switch Match Whole Word]
+[Switch match whole word]
Přepnout vyhledávání pouze celých slov
-[Show/Hide Contacts]
+[Show/hide contacts]
Zobrazit/Skrýt kontakty
-[Switch Only Incoming Messages]
+[Switch only incoming messages]
Přepnout vyhledávání pouze příchozích zpráv
-[Switch Only Outgoing Messages]
+[Switch only outgoing messages]
Přepnout vyhledávání pouze odchozích zpráv
-[Switch Only Selected Group]
+[Switch only selected group]
Přepnout vyhledávání pouze ve vybrané skupině
-[Switch All Contacts]
+[Switch all contacts]
Přepnout vyhledávání ve všech kontaktech
-[Export To Binary]
+[Export to binary]
Exportovat do binárního souboru
-[Import From Binary]
+[Import from binary]
Importovat z binárního souboru
-[Export To Dat (mContacts)]
-Exportovat do souboru Dat (mContacts)
-[Import From Dat (mContacts)]
-Importovat ze souboru Dat (mContacts)
+[Export to dat (mContacts)]
+Exportovat do souboru dat (mContacts)
+[Import from dat (mContacts)]
+Importovat ze souboru dat (mContacts)
[Invalid event number]
Neplatné Äíslo události
[Incoming events]
@@ -333,7 +333,7 @@ Odchozí události
Soubor neexistuje. Zadejte správnou cestu k souboru.
[Invalid file]
Neplatný soubor
-[All Files (*.*)]
+[All files (*.*)]
Všechny soubory (*.*)
[Enter filter name]
Zadejte název filtru
@@ -351,17 +351,17 @@ Zadali jste neplatné kódování. Zvolte kódování z rozbalovacího seznamu n
Neplatné kódování
[Browse CSS file]
Najít CSS soubor
-[Export and Delete]
+[Export and delete]
Exportovat a smazat
-[Import and Merge]
+[Import and merge]
Importovat a sjednotit
[Minute]
minuta
[Hour]
hodina
-[At Start]
+[At start]
Při startu
-[At Finish]
+[At finish]
PÅ™i ukonÄení
[Daily]
Každý den
@@ -407,7 +407,7 @@ Importovat z
** Použijte <date> pro vložení data, <ext> pro vložení přípony, <contact> pro vložení jména kontaktu
;file \plugins\BasicHistory\src\Options.h
;file \plugins\BasicHistory\src\PlainHtmlExport.cpp
-[History Log]
+[History log]
Interní historie
[Filter:]
Filtr:
diff --git a/langpacks/czech/Plugins/Clist_modern.txt b/langpacks/czech/Plugins/Clist_modern.txt
index b84eb7e7c0..c51a95fed3 100644
--- a/langpacks/czech/Plugins/Clist_modern.txt
+++ b/langpacks/czech/Plugins/Clist_modern.txt
@@ -50,6 +50,8 @@ UPOZORNÄšNÃ:\tSkiny mohou pozmÄ›nit váš datový profil, návrat není možný
* Některé ze změn mohou vyžadovat restart programu.
[Skin folder]
Složka se skiny
+[Download more skins]
+Stáhnout další skiny
[Available view modes]
Přehled režimů zobrazení
[Include protocols]
diff --git a/langpacks/czech/Plugins/Clist_nicer.txt b/langpacks/czech/Plugins/Clist_nicer.txt
index a8154dc648..b876003ec9 100644
--- a/langpacks/czech/Plugins/Clist_nicer.txt
+++ b/langpacks/czech/Plugins/Clist_nicer.txt
@@ -380,6 +380,8 @@ Vyplnění skup. shora
Výška záhlaví rámeÄku
[Ignore selection for groups]
Ignorovat výběr skupiny
+[Download more skins]
+Stáhnout další skiny
[Load from skin file]
Importovat skin
[Export to skin file]
diff --git a/langpacks/czech/Plugins/CloudFile.txt b/langpacks/czech/Plugins/CloudFile.txt
index 73452cdd90..81c29c261e 100644
--- a/langpacks/czech/Plugins/CloudFile.txt
+++ b/langpacks/czech/Plugins/CloudFile.txt
@@ -2,7 +2,7 @@
;============================================================
; File: CloudFile.dll
; Plugin: CloudFile
-; Version: 0.11.0.2
+; Version: 0.11.0.3
; Authors: Miranda NG Team
;============================================================
[Allows you to transfer files via cloud services.]
diff --git a/langpacks/czech/Plugins/DbEditorPP.txt b/langpacks/czech/Plugins/DbEditorPP.txt
index fe91128292..42604d52e5 100644
--- a/langpacks/czech/Plugins/DbEditorPP.txt
+++ b/langpacks/czech/Plugins/DbEditorPP.txt
@@ -2,7 +2,7 @@
;============================================================
; File: DbEditorPP.dll
; Plugin: Database editor++
-; Version: 4.0.1.1
+; Version: 4.0.1.2
; Authors: Bio, Jonathan Gordon
;============================================================
[Advanced Database Editor.]
diff --git a/langpacks/czech/Plugins/Fingerprint.txt b/langpacks/czech/Plugins/Fingerprint.txt
index e0b95b68be..51b61f945d 100644
--- a/langpacks/czech/Plugins/Fingerprint.txt
+++ b/langpacks/czech/Plugins/Fingerprint.txt
@@ -46,8 +46,6 @@ Klienti MSN
Klienti QQ
[RSS clients]
Klienti RSS
-[Tlen clients]
-Klienti Tlen
[Weather clients]
Klienti poÄasí
[Yahoo clients]
@@ -107,8 +105,6 @@ Mail.Ru (neznámý klient)
TM 2008 a novější
[Gadu-Gadu client]
Klient Gadu-Gadu
-[Tlen.pl client]
-Klient Tlen.pl
[Python-based clients]
Klienti v Pythonu
[Jabber client]
@@ -139,8 +135,6 @@ Nezjištěný klient
[QQ overlay]
-[Tlen.pl overlay]
-
[Yahoo overlay]
[Mail.Ru Agent overlay]
@@ -175,12 +169,6 @@ Nezjištěný klient
[Gadu-Gadu v8 client]
-[Tlen 7.x overlay]
-
-[Tlen 6.x overlay]
-
-[Tlen 5.x overlay]
-
[TM/QQ 2012 overlay]
[TM/QQ 2011 overlay]
diff --git a/langpacks/czech/Plugins/GmailNotifier.txt b/langpacks/czech/Plugins/GmailNotifier.txt
index 0dcd9858b5..b5e578aaeb 100644
--- a/langpacks/czech/Plugins/GmailNotifier.txt
+++ b/langpacks/czech/Plugins/GmailNotifier.txt
@@ -2,7 +2,7 @@
;============================================================
; File: GmailNotifier.dll
; Plugin: Gmail Multiple Notifier
-; Version: 0.3.1.1
+; Version: 1.0.1.1
; Authors: Mixwind
;============================================================
[Check your Gmail inboxes locally.]
@@ -57,21 +57,19 @@ Zapsat nepÅ™eÄtené zprávy do databáze (historie)
;file \plugins\GmailNotifier\src\check.cpp
[Checking...]
Kontrolování...
-[Can't open Internet!]
-Chyba připojení k internetu!
-[Can't reach server!]
-Chyba připojení k serveru!
[Can't send account data!]
Nelze zaslat data o úÄtu!
-[Can't get RSS feed!]
-Nelze pÅ™eÄíst kanál RSS!
[Wrong name or password!]
Neplatné jméno nebo heslo!
+[Can't get RSS feed!]
+Nelze pÅ™eÄíst kanál RSS!
;file \plugins\GmailNotifier\src\main.cpp
[Other]
Ostatní
[Gmail: New thread(s)]
Gmail: Nové vlákno/a
+[Gmail Notifier connection]
+
[&Check all Gmail inboxes]
&Zkontrolovat vÅ¡echny úÄty (Gmail)
[&Check Gmail inbox]
diff --git a/langpacks/czech/Plugins/IEView.txt b/langpacks/czech/Plugins/IEView.txt
index 40b692a3c4..929e80a38a 100644
--- a/langpacks/czech/Plugins/IEView.txt
+++ b/langpacks/czech/Plugins/IEView.txt
@@ -66,6 +66,8 @@ Zobrazit datum
Použít dlouhý formát data
[Use relative timestamp]
Použít relativní Äasové údaje
+[Download more templates]
+
;file \plugins\IEView\src\HistoryHTMLBuilder.cpp
[Outgoing File Transfer]
Odchozí přenos souboru
diff --git a/langpacks/czech/Plugins/MSN.txt b/langpacks/czech/Plugins/MSN.txt
index 1f6b60ff71..4fb6ca0995 100644
--- a/langpacks/czech/Plugins/MSN.txt
+++ b/langpacks/czech/Plugins/MSN.txt
@@ -2,7 +2,7 @@
;============================================================
; File: MSN.dll
; Plugin: MSN protocol
-; Version: 0.14.0.1
+; Version: 0.14.0.2
; Authors: Boris Krasnovskiy, George Hazan, Richard Hughes, leecher
;============================================================
[Microsoft Network (MSN) protocol support for Miranda NG.]
diff --git a/langpacks/czech/Plugins/New_GPG.txt b/langpacks/czech/Plugins/New_GPG.txt
index b92a507bc3..5d24b201b6 100644
--- a/langpacks/czech/Plugins/New_GPG.txt
+++ b/langpacks/czech/Plugins/New_GPG.txt
@@ -176,86 +176,6 @@ Původní heslo:
[GPG encryption status]
;file \plugins\New_GPG\src\main.cpp
-[Email]
-E-mail
-[Name]
-Jméno
-[Creation date]
-
-[Expire date]
-
-[Key length]
-
-[Accounts]
-ÚÄty
-[Default]
-Výchozí
-[key ID]
-ID klíÄe
-[not set]
-Není zvoleno
-[Default private key ID]
-
-[Failed to open file]
-
-[Error]
-Chyba
-[Generating new random key, please wait]
-
-[Failed to allocate memory]
-Nezdařila se alokace paměti
-[Failed to lock memory with error %d]
-
-[Failed write to clipboard with error %d]
-
-[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
-
-[Warning]
-Upozornění
-[Wrong GPG binary location found in system.\nPlease choose another location]
-
-[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-
-[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-
-["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
-
-[Info]
-Info
-[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
-
-[GPG binary does not exist.\nPlease choose another location]
-
-[Please choose GPG binary location]
-
-[Please set keyring's home directory]
-
-[There is existing key for contact, would you like to replace it with new key?]
-
-[New public key was received, do you want to import it?]
-
-[Replace]
-Nahradit
-[Accept]
-Přijmout
-[Received key from %s]
-
-[You must set encryption algorithm first]
-
-[Key length must be of length from 1024 to 4096 bits]
-
-[Invalid date]
-
-[Name must contain at least 5 characters]
-
-[Name cannot contain '(' or ')']
-
-[Invalid Email]
-Neplatný e-mail
-[Generating new key, please wait...]
-
-[Failed to export public key.]
-
[GPG binary is set and valid (this is good).\n]
[GPG binary unset or invalid (plugin will not work).\n]
@@ -293,6 +213,8 @@ Neplatný e-mail
;file \plugins\New_GPG\src\messages.cpp
[We received encrypted message from contact with encryption turned off.\nDo you want to turn on encryption for this contact?]
+[Warning]
+Upozornění
[Do you want to try to decrypt encrypted message?]
[We're trying to encrypt with untrusted key. Do you want to trust this key permanently?]
@@ -300,22 +222,20 @@ Neplatný e-mail
[Something is wrong, GPG does not understand us, aborting encryption.]
;file \plugins\New_GPG\src\options.cpp
-[Services]
-Služby
-[Main]
-Hlavní
-[GnuPG Variables]
-
-[Messages]
-Zprávy
-[Advanced]
-Extra
[Contact]
Kontakt
[Key ID]
ID klíÄe
+[Name]
+Jméno
+[Email]
+E-mail
[Protocol]
Protokol
+[Default private key ID]
+
+[not set]
+Není zvoleno
[This key is not used by any contact. Do you want to remove it from public keyring?]
[Key info]
@@ -332,6 +252,14 @@ Info
Exportovat veÅ™ejný klíÄ
[.asc pubkey file]
+[Failed to allocate memory]
+Nezdařila se alokace paměti
+[Error]
+Chyba
+[Failed to lock memory with error %d]
+
+[Failed write to clipboard with error %d]
+
[Failed to open clipboard with error %d]
[Set log file]
@@ -340,6 +268,8 @@ Exportovat veÅ™ejný klíÄ
Soubory záznamů
[Choose gpg.exe]
+[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+
[Set home directory]
[Load Public GPG Key for ]
@@ -356,12 +286,83 @@ Soubory záznamů
[Key already in secret keyring.]
+[Info]
+Info
[Set file containing GPG public key]
[GPG public key file]
+[Failed to open file]
+
[There is no public or private key.]
+[Services]
+Služby
+[Main]
+Hlavní
+[GnuPG Variables]
+
+[Messages]
+Zprávy
+[Advanced]
+Extra
+;file \plugins\New_GPG\src\ui.cpp
+[New passwords do not match]
+
+[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+
+[Creation date]
+
+[Expire date]
+
+[Key length]
+
+[Accounts]
+ÚÄty
+[Default]
+Výchozí
+[key ID]
+ID klíÄe
+[Generating new random key, please wait]
+
+[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
+
+[Wrong GPG binary location found in system.\nPlease choose another location]
+
+[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+
+["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
+
+[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
+
+[There is existing key for contact, would you like to replace it with new key?]
+
+[New public key was received, do you want to import it?]
+
+[Replace]
+Nahradit
+[Accept]
+Přijmout
+[Received key from %s]
+
+[You must set encryption algorithm first]
+
+[Key length must be of length from 1024 to 4096 bits]
+
+[Invalid date]
+
+[Name must contain at least 5 characters]
+
+[Name cannot contain '(' or ')']
+
+[Invalid Email]
+Neplatný e-mail
+[Generating new key, please wait...]
+
+[Expiration date]
+
+[Failed to export public key.]
+
;file \plugins\New_GPG\src\utilities.cpp
[Do you want to toggle encryption for all subcontacts?]
@@ -393,7 +394,10 @@ Zapnout šifrování GPG
[Keys import result]
-[New passwords do not match]
+[GPG binary does not exist.\nPlease choose another location]
-[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[Please choose GPG binary location]
+
+[Please set keyring's home directory]
+;file \plugins\New_GPG\src\utilities.h
diff --git a/langpacks/czech/Plugins/SimpleStatusMsg.txt b/langpacks/czech/Plugins/SimpleStatusMsg.txt
index 5266e3e629..2b40e05bf4 100644
--- a/langpacks/czech/Plugins/SimpleStatusMsg.txt
+++ b/langpacks/czech/Plugins/SimpleStatusMsg.txt
@@ -3,7 +3,7 @@
; File: SimpleStatusMsg.dll
; Plugin: Simple status message
; Version: 1.9.0.6
-; Authors: Bartosz 'Dezeath' Bialek, Harven
+; Authors: Bartosz 'Dezeath' Białek, Harven
;============================================================
[Provides a simple way to set status and away messages.]
Umožňuje jednoduchou volbu stavu a stavových zpráv.
diff --git a/langpacks/czech/Plugins/SmileyAdd.txt b/langpacks/czech/Plugins/SmileyAdd.txt
index 90a76ce602..2e951cbb0c 100644
--- a/langpacks/czech/Plugins/SmileyAdd.txt
+++ b/langpacks/czech/Plugins/SmileyAdd.txt
@@ -2,7 +2,7 @@
;============================================================
; File: SmileyAdd.dll
; Plugin: SmileyAdd
-; Version: 0.2.4.2
+; Version: 0.3.0.1
; Authors: Peacow, nightwish, bid, borkra
;============================================================
[Smiley support for Miranda NG.]
@@ -98,16 +98,14 @@ Závisí na protokolu
;file \plugins\SmileyAdd\src\smileys.cpp
[Smiley pack %s for category "%s" not found.\nSelect correct smiley pack in the Options -> Customize -> Smileys.]
Knihovna smajlíků %s pro kategorii "%s" nebyla nalezena.\nVyberte platnou knihovnu smajlíků v Možnosti -> Vlastní úpravy -> Smajlíky.
-[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
-NepodaÅ™ilo se naÄíst požadovanou knihovnu smajlíků.\nDalší informace naleznete v záznamu komunikace po síti.
[Smiley #%u in file %s for smiley pack %s not found.]
Smajlík Ä.%u v souboru %s sady smajlíků %s nebyl nalezen.
+[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
+NepodaÅ™ilo se naÄíst požadovanou knihovnu smajlíků.\nDalší informace naleznete v záznamu komunikace po síti.
[%s global smiley pack]
%s globální sada smajlíků
[Standard]
Standardní
-[Regular expression "%s" in smiley pack "%s" could produce "empty matches".]
-Regulární výraz "%s" v knihovně smajlíků "%s" může vracet "prázdné výsledky".
[Regular expression "%s" in smiley pack "%s" malformed.]
Regulární výraz "%s" v knihovně smajlíků "%s" je neplatný.
;file \plugins\SmileyAdd\src\smltool.cpp
diff --git a/langpacks/czech/Plugins/SplashScreen.txt b/langpacks/czech/Plugins/SplashScreen.txt
index 5e874dba11..8ab886a8c3 100644
--- a/langpacks/czech/Plugins/SplashScreen.txt
+++ b/langpacks/czech/Plugins/SplashScreen.txt
@@ -38,6 +38,8 @@ Doběh:
Doplněk AdvaImg nebyl nalezen. Abyste mohli pracovat s obrázky, stáhněte si jej z https://miranda-ng.org/p/AdvaImg/
[Preview...]
Náhled...
+[Download more splash screens]
+
;file \plugins\SplashScreen\src\options.cpp
[Graphic files]
Grafické soubory
diff --git a/langpacks/czech/Plugins/StatusManager.txt b/langpacks/czech/Plugins/StatusManager.txt
index 283723330c..67e3f2da45 100644
--- a/langpacks/czech/Plugins/StatusManager.txt
+++ b/langpacks/czech/Plugins/StatusManager.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StatusManager.dll
; Plugin: Status manager
-; Version: 0.11.2.3
+; Version: 1.0.1.1
; Authors: P Boon
;============================================================
[A connection checker and auto away module. Also allows you to define the status Miranda should set on startup, configurable per protocol.]
diff --git a/langpacks/czech/Plugins/Steam.txt b/langpacks/czech/Plugins/Steam.txt
index 5dd28cc23e..f3734a4f8d 100644
--- a/langpacks/czech/Plugins/Steam.txt
+++ b/langpacks/czech/Plugins/Steam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Steam.dll
; Plugin: Steam protocol
-; Version: 0.11.6.1
+; Version: 0.11.6.3
; Authors: Miranda NG Team, Robert Pösel
;============================================================
[Steam protocol support for Miranda NG.]
diff --git a/langpacks/czech/Plugins/StopSpam.txt b/langpacks/czech/Plugins/StopSpam.txt
index 9ae373e824..4075c9a620 100644
--- a/langpacks/czech/Plugins/StopSpam.txt
+++ b/langpacks/czech/Plugins/StopSpam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpam.dll
; Plugin: StopSpam+
-; Version: 0.0.1.5
+; Version: 0.1.0.1
; Authors: Roman Miklashevsky, A. Petkevich, Kosh&chka, persei
;============================================================
[Anti-spam plugin for Miranda NG.]
@@ -43,6 +43,9 @@ Ukládat spammery do historie systému
;file \plugins\StopSpamPlus\src\events.cpp
[StopSpam automatic message:\r\n]
Automatická zpráva StopSpam:\r\n
+;file \plugins\StopSpamPlus\src\options.cpp
+[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
+Už žádný další spam! Roboti nemají Å¡anci, zde si povídají lidé!\r\n\r\nTento doplnÄ›k pracuje na jednoduchém principu:\r\nZatímco zprávy od lidí ze seznamu kontaktů projdou vždy, jako by tu žádný filtr nebyl, zprávy od neznámých kontaktů doruÄeny nebudou. Tyto zprávy ale nejsou ignorovány, jen je jejich autorům nejdříve automaticky zaslána jednoduchá otázka. Teprve až po jejím správném zodpovÄ›zení vás může dotyÄný kontaktovat.
[Message sessions]
Komunikace
[General]
@@ -51,15 +54,12 @@ Obecné
Zprávy
[Accounts]
ÚÄty
-;file \plugins\StopSpamPlus\src\options.cpp
-[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
-Už žádný další spam! Roboti nemají Å¡anci, zde si povídají lidé!\r\n\r\nTento doplnÄ›k pracuje na jednoduchém principu:\r\nZatímco zprávy od lidí ze seznamu kontaktů projdou vždy, jako by tu žádný filtr nebyl, zprávy od neznámých kontaktů doruÄeny nebudou. Tyto zprávy ale nejsou ignorovány, jen je jejich autorům nejdříve automaticky zaslána jednoduchá otázka. Teprve až po jejím správném zodpovÄ›zení vás může dotyÄný kontaktovat.
;file \plugins\StopSpamPlus\src\services.cpp
[Not In List]
Není v seznamu
[Complete]
DokonÄeno
-;file \plugins\StopSpamPlus\src\settings.h
+;file \plugins\StopSpamPlus\src\settings.cpp
[Spammers made me to install small anti-spam system you are now speaking with. Please reply "nospam" without quotes and spaces if you want to contact me.]
[StopSpam: send a message and reply to an anti-spam bot question.]
diff --git a/langpacks/czech/Plugins/StopSpamMod.txt b/langpacks/czech/Plugins/StopSpamMod.txt
index c743a0f864..018edfe0d8 100644
--- a/langpacks/czech/Plugins/StopSpamMod.txt
+++ b/langpacks/czech/Plugins/StopSpamMod.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpamMod.dll
; Plugin: StopSpam mod
-; Version: 0.0.2.1
+; Version: 0.0.2.2
; Authors: Roman Miklashevsky, sss, Elzor
;============================================================
[Anti-spam plugin for Miranda NG.]
diff --git a/langpacks/czech/Plugins/TabSRMM.txt b/langpacks/czech/Plugins/TabSRMM.txt
index ed3a72e2d3..c9b66c6cb9 100644
--- a/langpacks/czech/Plugins/TabSRMM.txt
+++ b/langpacks/czech/Plugins/TabSRMM.txt
@@ -516,6 +516,8 @@ Zde můžete exportovat Äi nahrát vÅ¡echna vaÅ¡e nastavení barev a písem. Um
Exportovat do souboru...
[Import from a file...]
Importovat ze souboru...
+[Download more skins]
+Stáhnout další skiny
[Icons]
Ikony
[Event type icons in the message log]
diff --git a/langpacks/czech/Plugins/Tox.txt b/langpacks/czech/Plugins/Tox.txt
index 6aa2a50900..77d964e3a6 100644
--- a/langpacks/czech/Plugins/Tox.txt
+++ b/langpacks/czech/Plugins/Tox.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Tox.dll
; Plugin: Tox protocol
-; Version: 0.11.1.25
+; Version: 0.11.1.26
; Authors: Miranda NG Team
;============================================================
[Tox protocol support for Miranda NG.]
diff --git a/langpacks/czech/Plugins/mRadio.txt b/langpacks/czech/Plugins/mRadio.txt
index dd50930102..25dd0b0573 100644
--- a/langpacks/czech/Plugins/mRadio.txt
+++ b/langpacks/czech/Plugins/mRadio.txt
@@ -101,8 +101,8 @@ Nepřetržité nahrávání
Kamenolom
[Sorry!]
-[BASS.DLL not found!]
-Nelze najít knihovnu BASS.DLL!
+[bass.dll not found!]
+Nelze najít knihovnu bass.dll!
[Station]
Stanice
[Custom INI file]
@@ -199,3 +199,5 @@ Ekvalizér
Nový
[Quick Open]
+[bass.dll not found! Choose bass.dll path manually]
+
diff --git a/langpacks/czech/Untranslated/Fingerprint.txt b/langpacks/czech/Untranslated/Fingerprint.txt
index bc53dca5b6..e4e289a4bc 100644
--- a/langpacks/czech/Untranslated/Fingerprint.txt
+++ b/langpacks/czech/Untranslated/Fingerprint.txt
@@ -17,7 +17,6 @@
[Jabber overlay]
[MSN overlay]
[QQ overlay]
-[Tlen.pl overlay]
[Yahoo overlay]
[Mail.Ru Agent overlay]
[VK overlay]
@@ -35,9 +34,6 @@
[Gadu-Gadu v10 client]
[Gadu-Gadu v9 client]
[Gadu-Gadu v8 client]
-[Tlen 7.x overlay]
-[Tlen 6.x overlay]
-[Tlen 5.x overlay]
[TM/QQ 2012 overlay]
[TM/QQ 2011 overlay]
[TM/QQ 2010 overlay]
diff --git a/langpacks/czech/Untranslated/GmailNotifier.txt b/langpacks/czech/Untranslated/GmailNotifier.txt
new file mode 100644
index 0000000000..fe2bc3771c
--- /dev/null
+++ b/langpacks/czech/Untranslated/GmailNotifier.txt
@@ -0,0 +1 @@
+[Gmail Notifier connection]
diff --git a/langpacks/czech/Untranslated/IEView.txt b/langpacks/czech/Untranslated/IEView.txt
index 1ee743fce8..f312c8569f 100644
--- a/langpacks/czech/Untranslated/IEView.txt
+++ b/langpacks/czech/Untranslated/IEView.txt
@@ -1,3 +1,4 @@
+[Download more templates]
[RTL On]
[RTL Off]
[Group On]
diff --git a/langpacks/czech/Untranslated/New_GPG.txt b/langpacks/czech/Untranslated/New_GPG.txt
index 5a6c4e49ab..a0881d4a08 100644
--- a/langpacks/czech/Untranslated/New_GPG.txt
+++ b/langpacks/czech/Untranslated/New_GPG.txt
@@ -66,33 +66,6 @@
[Export GPG Public keys]
[Import GPG Public keys]
[GPG encryption status]
-[Creation date]
-[Expire date]
-[Key length]
-[Default private key ID]
-[Failed to open file]
-[Generating new random key, please wait]
-[Failed to lock memory with error %d]
-[Failed write to clipboard with error %d]
-[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
-[Wrong GPG binary location found in system.\nPlease choose another location]
-[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
-[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
-[GPG binary does not exist.\nPlease choose another location]
-[Please choose GPG binary location]
-[Please set keyring's home directory]
-[There is existing key for contact, would you like to replace it with new key?]
-[New public key was received, do you want to import it?]
-[Received key from %s]
-[You must set encryption algorithm first]
-[Key length must be of length from 1024 to 4096 bits]
-[Invalid date]
-[Name must contain at least 5 characters]
-[Name cannot contain '(' or ')']
-[Generating new key, please wait...]
-[Failed to export public key.]
[GPG binary is set and valid (this is good).\n]
[GPG binary unset or invalid (plugin will not work).\n]
[Home dir write access granted (this is good).\n]
@@ -114,16 +87,19 @@
[Do you want to try to decrypt encrypted message?]
[We're trying to encrypt with untrusted key. Do you want to trust this key permanently?]
[Something is wrong, GPG does not understand us, aborting encryption.]
-[GnuPG Variables]
+[Default private key ID]
[This key is not used by any contact. Do you want to remove it from public keyring?]
[Key info]
[we have secret key for this public key, do not removing from GPG keyring]
[Key removed from GPG keyring]
[Do you want to remove key from entire metacontact (all subcontacts)?]
[.asc pubkey file]
+[Failed to lock memory with error %d]
+[Failed write to clipboard with error %d]
[Failed to open clipboard with error %d]
[Set log file]
[Choose gpg.exe]
+[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
[Set home directory]
[Load Public GPG Key for ]
[Turn off encryption]
@@ -134,7 +110,31 @@
[Key already in secret keyring.]
[Set file containing GPG public key]
[GPG public key file]
+[Failed to open file]
[There is no public or private key.]
+[GnuPG Variables]
+[New passwords do not match]
+[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[Creation date]
+[Expire date]
+[Key length]
+[Generating new random key, please wait]
+[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
+[Wrong GPG binary location found in system.\nPlease choose another location]
+[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
+[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
+[There is existing key for contact, would you like to replace it with new key?]
+[New public key was received, do you want to import it?]
+[Received key from %s]
+[You must set encryption algorithm first]
+[Key length must be of length from 1024 to 4096 bits]
+[Invalid date]
+[Name must contain at least 5 characters]
+[Name cannot contain '(' or ')']
+[Generating new key, please wait...]
+[Expiration date]
+[Failed to export public key.]
[Do you want to toggle encryption for all subcontacts?]
[Target file exists, do you want to replace it?]
[Capability to decrypt file not found on other side.\nRecipient may be unable to decrypt file(s).\nDo you want to encrypt file(s) anyway?]
@@ -148,5 +148,6 @@
[We have successfully processed %d public keys and some private keys.]
[We have successfully processed %d public keys.]
[Keys import result]
-[New passwords do not match]
-[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[GPG binary does not exist.\nPlease choose another location]
+[Please choose GPG binary location]
+[Please set keyring's home directory]
diff --git a/langpacks/czech/Untranslated/SplashScreen.txt b/langpacks/czech/Untranslated/SplashScreen.txt
new file mode 100644
index 0000000000..0add885a64
--- /dev/null
+++ b/langpacks/czech/Untranslated/SplashScreen.txt
@@ -0,0 +1 @@
+[Download more splash screens]
diff --git a/langpacks/czech/Untranslated/mRadio.txt b/langpacks/czech/Untranslated/mRadio.txt
index 84a0ad5752..7b87d40907 100644
--- a/langpacks/czech/Untranslated/mRadio.txt
+++ b/langpacks/czech/Untranslated/mRadio.txt
@@ -32,3 +32,4 @@
[Mute with Miranda]
[Device list]
[Quick Open]
+[bass.dll not found! Choose bass.dll path manually]
diff --git a/langpacks/english/=CORE=.txt b/langpacks/english/=CORE=.txt
index e92dbeb41f..cb81564614 100644
--- a/langpacks/english/=CORE=.txt
+++ b/langpacks/english/=CORE=.txt
@@ -3,18 +3,6 @@
; Module: Miranda Core
; Version: 0.95.8
;============================================================
-;file \src\core\stdauth\res\resource.rc
-[Authorization request]
-[&Authorize]
-[&Deny]
-[Decide &later]
-[User &details]
-[Reason:]
-[Denial reason:]
-[Add to contact list if authorized]
-[You were added]
-[&Close]
-[&Add]
;file \src\core\stdaway\res\resource.rc
[%s message for %s]
[&Cancel]
@@ -149,6 +137,7 @@
[Total size:]
[Description:]
[&User menu]
+[User &details]
[&History]
[Incoming file transfer]
[A&ccept]
@@ -157,6 +146,7 @@
[Date:]
[Files:]
[Save to:]
+[&Add]
[&Open...]
[Open &folder]
[Transfer completed, open file(s).]
@@ -201,9 +191,6 @@
[Ask me]
[Rename (append " (1)", etc.)]
[You will always be asked about files from people not on your contact list]
-;file \src\core\stdhelp\res\resource.rc
-[About Miranda NG]
-[Credits >]
;file \src\core\stdidle\res\resource.rc
[Become idle if the following is left unattended:]
[Become idle if the screen saver is active]
@@ -368,6 +355,7 @@
[Open contact's chat window]
[Custom name:]
[Group:]
+[Authorization request]
[&Yes]
[&No]
[Contact display options]
@@ -506,6 +494,7 @@
[Warning!\r\nThis menu object not support user defined options.]
[Insert submenu]
[Insert separator]
+[Module:]
[Service:]
[Default]
[Set]
@@ -573,6 +562,16 @@
[Show in chat rooms]
[Gap between buttons:]
[Hide if there isn't enough space]
+[&Authorize]
+[&Deny]
+[Decide &later]
+[Reason:]
+[Denial reason:]
+[Add to contact list if authorized]
+[You were added]
+[&Close]
+[About Miranda NG]
+[Credits >]
[Tray]
[&Hide/Show]
[Nowhere]
@@ -603,25 +602,6 @@
[Wikipedia (en)]
[Google Maps]
[Google Translate]
-;file \src\core\stdauth\src\auth.cpp
-[%s requests authorization]
-[%u requests authorization]
-[%s added you to their contact list]
-[%u added you to their contact list]
-[Alerts]
-[Added event]
-;file \src\core\stdauth\src\authdialogs.cpp
-[View user's details]
-[Add contact permanently to list]
-[<Unknown>]
-[%s added you to the contact list\n%u (%s) on %s]
-[%s added you to the contact list\n%u on %s]
-[%s added you to the contact list\n%s on %s]
-[(Unknown)]
-[%s requested authorization\n%u (%s) on %s]
-[%s requested authorization\n%u on %s]
-[%s requested authorization\n%s on %s]
-[Feature is not supported by protocol]
;file \src\core\stdaway\src\awaymsg.cpp
[Re&ad %s message]
[Re&ad status message]
@@ -689,6 +669,8 @@
;file \src\core\stdfile\src\filerecvdlg.cpp
[Select folder]
[My received files]
+[Add contact permanently to list]
+[View user's details]
[View user's history]
[User menu]
[Canceled]
@@ -724,15 +706,7 @@
[Transfer and virus scan complete]
;file \src\core\stdfile\src\ftmanager.cpp
[Outgoing]
-;file \src\core\stdhelp\src\about.cpp
-[< Copyright]
-;file \src\core\stdhelp\src\help.cpp
-[&Help]
-[&About...]
-[&Support]
-[&Miranda NG homepage]
-[&Report bug]
-;file \src\core\stdidle\src\idle.cpp
+;file \src\core\stdidle\src\options.cpp
[Idle]
;file \src\core\stdmsg\src\chat_manager.cpp
[Chat module]
@@ -978,9 +952,26 @@
[View/change my &details...]
;file \src\core\stduseronline\src\useronline.cpp
[%s is online]
+[Alerts]
;file \src\mir_app\src\addcontact.cpp
[Add %s]
[Please authorize my request and add me to your contact list.]
+;file \src\mir_app\src\auth.cpp
+[%s requests authorization]
+[%u requests authorization]
+[%s added you to their contact list]
+[%u added you to their contact list]
+[Added event]
+;file \src\mir_app\src\authdialogs.cpp
+[<Unknown>]
+[%s added you to the contact list\n%u (%s) on %s]
+[%s added you to the contact list\n%u on %s]
+[%s added you to the contact list\n%s on %s]
+[(Unknown)]
+[%s requested authorization\n%u (%s) on %s]
+[%s requested authorization\n%u on %s]
+[%s requested authorization\n%s on %s]
+[Feature is not supported by protocol]
;file \src\mir_app\src\chat_clist.cpp
[&Join chat]
[&Open chat window]
@@ -1135,6 +1126,13 @@
[Headers]
[Generic text]
[Small text]
+;file \src\mir_app\src\help.cpp
+[< Copyright]
+[&Help]
+[&About...]
+[&Support]
+[&Miranda NG homepage]
+[&Report bug]
;file \src\mir_app\src\hotkey_opts.cpp
[Browser: Back]
[Browser: Forward]
diff --git a/langpacks/english/Plugins/AIM.txt b/langpacks/english/Plugins/AIM.txt
deleted file mode 100644
index 6613f95130..0000000000
--- a/langpacks/english/Plugins/AIM.txt
+++ /dev/null
@@ -1,222 +0,0 @@
-#muuid {3750a5a3-bf0d-490e-b65d-41ac4d29aeb3}
-;============================================================
-; File: AIM.dll
-; Plugin: AIM protocol
-; Version: 0.11.0.1
-; Authors: Boris Krasnovskiy, Aaron Myles Landwehr
-;============================================================
-[AOL Instant Messenger (AIM) protocol support for Miranda NG.]
-;file \protocols\AimOscar\res\aim.rc
-[AIM user details]
-[Screen name:]
-[Display name:]
-[Password:]
-[AIM options]
-[Message delivery confirmation]
-[Do not autoreply when away]
-[Convert incoming messages to BBCode]
-[Convert outgoing messages to HTML]
-[Disable avatars]
-[Disable account type icons]
-[Disable extended status icons]
-[Notify about new mail]
-[Manage server groups]
-[Advanced options]
-[Instant idle on login]
-[Force proxy file transfers]
-[Masquerade as a Sidekick/Hiptop user]
-[Connection]
-[Login server:]
-[Port:]
-[Reset]
-[Disable SSL]
-[Force single client]
-[Use "clientlogin" (recommended)]
-[* Some changes will take effect the next time you connect to the AIM network]
-[Save profile]
-[Create a new AIM account]
-[AIM instant idler]
-[Number of hours:]
-[Number of minutes:]
-[Set idle]
-[Unset idle]
-[Users who can contact me:]
-[Allow all users]
-[Allow only users on contact list]
-[Allow only users below]
-[Block all users]
-[Block only users below]
-[Add]
-[Remove]
-[Idle]
-[Allow contacts to be notified of:]
-[Join chat room]
-[Chat room]
-[&Join]
-[&Cancel]
-[This allows access to user defined chat rooms. To access predefined chat rooms use web links]
-[Change password]
-[Original]
-[New]
-[Repeat]
-[*Passwords don't match.]
-[Screen name]
-[E-mail]
-[Confirm account]
-[*Applied upon reconnect]
-[Save changes]
-[Invite buddy to chat room]
-[&Invite]
-[Invitation reason]
-[Chat room invitation request]
-[&Deny]
-[Message]
-[Room]
-;file \protocols\AimOscar\src\chat.cpp
-[Me]
-[Others]
-[&Invite user...]
-[&Leave chat session]
-[User &details]
-[User &history]
-;file \protocols\AimOscar\src\error.cpp
-[Invalid screen name or password.]
-[Mismatched screen name or password.]
-[You are connecting too frequently. Try waiting 10 minutes to reconnect.]
-[Unknown error occurred when attempting to connect.]
-[Invalid SNAC header.]
-[Server rate limit exceeded.]
-[Client rate limit exceeded]
-[Recipient is not logged in.]
-[Requested service is unavailable.]
-[Requested service is not defined.]
-[You sent obsolete SNAC.]
-[Not supported by server.]
-[Not supported by the client.]
-[Refused by client.]
-[Reply too big.]
-[Response lost.]
-[Request denied.]
-[Incorrect SNAC format.]
-[Insufficient rights.]
-[Recipient blocked.]
-[Sender too evil.]
-[Receiver too evil.]
-[User temporarily unavailable.]
-[No match.]
-[List overflow.]
-[Request ambiguous.]
-[Server queue full.]
-[Not while on AOL.]
-[Check your screen name.]
-[Check your password.]
-[Check your email address.]
-[Service temporarily unavailable.]
-[Field change temporarily unavailable.]
-[Invalid screen name.]
-[Invalid password.]
-[Invalid email.]
-[Invalid registration preference.]
-[Invalid old password.]
-[Invalid screen name Length.]
-[Invalid password length.]
-[Invalid email length.]
-[Invalid old password length.]
-[Need old password.]
-[Read only field.]
-[Write only field.]
-[Unsupported type.]
-[An error has occurred.]
-[Invalid account.]
-[Deleted account.]
-[Expired account.]
-[No database access.]
-[Invalid database fields.]
-[Bad database status.]
-[Migration cancel.]
-[Internal error.]
-[There is already a pending request for this screen name.]
-[Not DT status.]
-[Outstanding confirmation.]
-[No email address.]
-[Over limit.]
-[Email host fail.]
-[DNS fail.]
-;file \protocols\AimOscar\src\file.cpp
-[Failed to open file: %s : %s]
-;file \protocols\AimOscar\src\links.cpp
-[AIM link protocol]
-;file \protocols\AimOscar\src\popup.cpp
-[%s protocol]
-[Open mail account?]
-;file \protocols\AimOscar\src\proto.cpp
-[%s server connection]
-[%s client-to-client connections]
-;file \protocols\AimOscar\src\server.cpp
-[[Auto-response]:]
-[Contact tried to open an audio/video conference (not currently supported)]
-[No information has been provided by the server.]
-[Item you want to delete not found in list.]
-[Failed to add buddy to list: Item already exist.]
-[Error adding buddy (invalid ID or already in list?)]
-[Cannot add buddy. Limit for this type of item exceeded.]
-[Error? Attempting to add ICQ contact to an AIM list.]
-[Cannot add this buddy because it requires authorization.]
-[Unknown error when adding buddy to list. Error code %#x]
-[Item you want to modify not found in list.]
-[Unknown error when attempting to modify a group. Error code %#x]
-[You've got mail! Checked at]
-[Error uploading avatar. (Too small)]
-[Error uploading avatar. (Too big)]
-[Error uploading avatar. (Wrong type)]
-[Error uploading avatar. (Is banned)]
-[Error uploading avatar. (Unknown error)]
-[A confirmation message has been sent to the new email address. Please follow its instructions.]
-[A confirmation message has been sent to your email address. Please follow its instructions.]
-[Unable to confirm at this time. Please try again later.]
-[Your account has already been confirmed.]
-[Can't start the confirmation procedure.]
-;file \protocols\AimOscar\src\theme.cpp
-[Block]
-[Profile]
-[AOL mail]
-[AIM icon]
-[Hiptop]
-[AOL bot]
-[Admin]
-[Confirmed]
-[Not confirmed]
-[Blocked list]
-[Foreground color]
-[Background color]
-[Bold]
-[Not bold]
-[Italic]
-[Not italic]
-[Underline]
-[Not underline]
-[Subscript]
-[Not subscript]
-[Superscript]
-[Not superscript]
-[Normal script]
-[Not normal script]
-[Profile editor]
-[AIM account type]
-[AIM extended status]
-[&Block]
-[&Unblock]
-[Manage account]
-[Instant idle]
-[Read &HTML away message]
-[Read profile]
-[Add to server list]
-;file \protocols\AimOscar\src\ui.cpp
-[Network]
-[Basic]
-[Privacy]
-[Join me in this buddy chat!]
-;file \protocols\AimOscar\src\utility.cpp
-[Please, enter a user name in the options dialog.]
-[Please, enter a password in the options dialog.]
-[Failed to open file: %s %s]
diff --git a/langpacks/english/Plugins/AddContactPlus.txt b/langpacks/english/Plugins/AddContactPlus.txt
index 7d75600b21..cf4d016fcd 100644
--- a/langpacks/english/Plugins/AddContactPlus.txt
+++ b/langpacks/english/Plugins/AddContactPlus.txt
@@ -3,7 +3,7 @@
; File: AddContactPlus.dll
; Plugin: Add contact+
; Version: 0.9.9.2
-; Authors: Bartosz 'Dezeath' Bialek
+; Authors: Bartosz 'Dezeath' Białek
;============================================================
[Provides the ability to quickly add new contacts.]
;file \plugins\AddContactPlus\res\resource.rc
diff --git a/langpacks/english/Plugins/AssocMgr.txt b/langpacks/english/Plugins/AssocMgr.txt
index 55b605751d..f80a6d08fa 100644
--- a/langpacks/english/Plugins/AssocMgr.txt
+++ b/langpacks/english/Plugins/AssocMgr.txt
@@ -5,7 +5,7 @@
; Version: 0.2.1.0
; Authors: H. Herkenrath
;============================================================
-[Handles file type associations and URLs like aim, gg, mirpu, tlen, wpmsg, xmpp, ymsgr.]
+[Handles file type associations and URLs like gg, mirpu, wpmsg, xmpp, ymsgr.]
;file \plugins\AssocMgr\res\resource.rc
[Registered associations for Miranda NG:]
[Miscellaneous]
@@ -36,7 +36,6 @@
[Access failed:\n%.64hs(%.128s)\n%.250hs(%u)\n%.256hs (%u)]
[Registry warning]
;file \plugins\AssocMgr\src\test.cpp
-[AIM link protocol]
[ICQ link shortcut]
[&Add to contact list...]
[Yahoo link protocol]
diff --git a/langpacks/english/Plugins/BASS_interface.txt b/langpacks/english/Plugins/BASS_interface.txt
index 92a7a29a83..c9fdfeff67 100644
--- a/langpacks/english/Plugins/BASS_interface.txt
+++ b/langpacks/english/Plugins/BASS_interface.txt
@@ -1,20 +1,20 @@
#muuid {2f07ea05-05b5-4ff0-875d-c590da2ddac1}
;============================================================
; File: BASS_interface.dll
-; Plugin: BASS interface
+; Plugin: BASS Interface
; Version: 0.0.0.14
; Authors: tico-tico
;============================================================
-[un4seen's BASS interface Miranda NG plugin.]
+[Un4seen's BASS interface Miranda NG plugin.]
;file \plugins\BASS_interface\res\Bass.rc
-[un4seen's bass interface]
+[Un4seen's BASS interface]
[bass.dll loading error]
[Current bass.dll path:]
-[Maximum number of bass internal channels:]
+[Maximum number of BASS internal channels:]
[Output device:]
[Volume:]
[Quiet time:]
-[download bass library]
+[download BASS library]
[Play only if]
[Offline]
[Online]
@@ -28,12 +28,13 @@
[Out to lunch]
[Preview]
;file \plugins\BASS_interface\src\Main.cpp
-[un4seen's bass version: %d.%d.%d.%d]
+[Un4seen's BASS version: %d.%d.%d.%d]
[--default device--]
[Sounds]
[Disable sounds]
[Enable sounds]
[Frame background]
+[BASS Interface]
[Bass Interface]
[Bass library]
[Sounds enabled]
diff --git a/langpacks/english/Plugins/BasicHistory.txt b/langpacks/english/Plugins/BasicHistory.txt
index 0d73571efe..0f5c87b4bf 100644
--- a/langpacks/english/Plugins/BasicHistory.txt
+++ b/langpacks/english/Plugins/BasicHistory.txt
@@ -7,12 +7,12 @@
;============================================================
[History viewer for Miranda NG.]
;file \plugins\BasicHistory\res\BasicHistory.rc
-[Message History]
+[Message history]
[Settings]
[Always show contact list]
[Show groups in contact list]
-[Do not show Find control border]
-[Default Event Filter]
+[Do not show find control border]
+[Default event filter]
[Custom filters]
[Add filter]
[Delete filter]
@@ -31,19 +31,19 @@
[Limit messages to:]
[Show date in timestamps]
[Show seconds in timestamps]
-[Enable Smileys]
+[Enable smileys]
[Search forward in list group]
[Search forward in message window]
-[Match Case]
-[Match Whole Word]
-[Only Incoming Messages]
-[Only Outgoing Messages]
-[Only Selected Group]
-[All Contacts]
-[Export To Txt]
+[Match case]
+[Match whole word]
+[Only incoming messages]
+[Only outgoing messages]
+[Only selected group]
+[All contacts]
+[Export to text file]
[File encoding*]
-[Export To Plain Html]
-[Export To Rich Html]
+[Export to plain HTML]
+[Export to rich HTML]
[External CSS file]
[* Choose encoding from combo box or enter code page number and name separated by semicolon, name is used in Content-Type header.]
[Add task]
@@ -74,16 +74,16 @@
[Cancel]
;file \plugins\BasicHistory\src\BasicHistory.cpp
[Open History]
-[View &History]
-[Delete All User History]
+[View &history]
+[Delete all user history]
[Execute history task]
[Incoming message]
[Outgoing message]
[Status change]
-[Show Contacts]
-[Hide Contacts]
-[Find Next]
-[Find Previous]
+[Show contacts]
+[Hide contacts]
+[Find next]
+[Find previous]
[Plus in export]
[Minus in export]
[History]
@@ -93,32 +93,32 @@
[History for %s]
[System]
[Me]
-[Invalid Message]
+[Invalid message]
;file \plugins\BasicHistory\src\ExportManager.cpp
-[%s Files (*.%s)]
+[%s files (*.%s)]
[Import]
[Export]
[File does not contain selected contact]
[File is corrupted]
;file \plugins\BasicHistory\src\HistoryWindow.cpp
[This operation will PERMANENTLY REMOVE all history for this contact.\nAre you sure you want to do this?]
-[Are You sure?]
+[Are you sure?]
[Do you want to delete all imported messages for this contact?\nNote that next scheduler task import this messages again.]
[Open in &new window]
[&Open in existing window]
[&Copy link]
[Copy]
[Delete]
-[Send Message]
-[Reply &Quoted]
-[Delete Group]
+[Send message]
+[Reply &quoted]
+[Delete group]
[Options]
[Filters]
[Fonts and colors]
[Icons]
[Hotkeys]
-[Rich Html]
-[Plain Html]
+[Rich HTML]
+[Plain HTML]
[Txt]
[Binary]
[Dat (mContacts)]
@@ -156,23 +156,23 @@
[Contact list background]
[Open global history]
[Find]
-[Switch Match Case]
-[Switch Match Whole Word]
-[Show/Hide Contacts]
-[Switch Only Incoming Messages]
-[Switch Only Outgoing Messages]
-[Switch Only Selected Group]
-[Switch All Contacts]
-[Export To Binary]
-[Import From Binary]
-[Export To Dat (mContacts)]
-[Import From Dat (mContacts)]
+[Switch match case]
+[Switch match whole word]
+[Show/hide contacts]
+[Switch only incoming messages]
+[Switch only outgoing messages]
+[Switch only selected group]
+[Switch all contacts]
+[Export to binary]
+[Import from binary]
+[Export to dat (mContacts)]
+[Import from dat (mContacts)]
[Invalid event number]
[Incoming events]
[Outgoing events]
[File does not exist. Enter correct file path.]
[Invalid file]
-[All Files (*.*)]
+[All files (*.*)]
[Enter filter name]
[Filter name exists]
[Event already exists]
@@ -181,12 +181,12 @@
[You've entered invalid codepage. Select codepage from combo box or enter correct number.]
[Invalid codepage]
[Browse CSS file]
-[Export and Delete]
-[Import and Merge]
+[Export and delete]
+[Import and merge]
[Minute]
[Hour]
-[At Start]
-[At Finish]
+[At start]
+[At finish]
[Daily]
[Weekly]
[Monthly]
@@ -210,7 +210,7 @@
[** Use <date> to insert date, <ext> to insert extension, <contact> to insert contact name]
;file \plugins\BasicHistory\src\Options.h
;file \plugins\BasicHistory\src\PlainHtmlExport.cpp
-[History Log]
+[History log]
[Filter:]
[Conversation started at %s]
;file \plugins\BasicHistory\src\RichHtmlExport.cpp
diff --git a/langpacks/english/Plugins/Clist_modern.txt b/langpacks/english/Plugins/Clist_modern.txt
index 06a75185a7..24244bebe5 100644
--- a/langpacks/english/Plugins/Clist_modern.txt
+++ b/langpacks/english/Plugins/Clist_modern.txt
@@ -28,6 +28,7 @@
[WARNING: \tSkins can modify your current profile. Rollback is not possible. \n\t\tPlease BACKUP your database before applying skin.]
[* Restart may be required for all changes to take effect]
[Skin folder]
+[Download more skins]
[Available view modes]
[Include protocols]
[New]
diff --git a/langpacks/english/Plugins/Clist_nicer.txt b/langpacks/english/Plugins/Clist_nicer.txt
index d68fee8cc5..e25ed1e7db 100644
--- a/langpacks/english/Plugins/Clist_nicer.txt
+++ b/langpacks/english/Plugins/Clist_nicer.txt
@@ -193,6 +193,7 @@
[Group top padding]
[Frame title bar height]
[Ignore selection for groups]
+[Download more skins]
[Load from skin file]
[Export to skin file]
[Dialog]
diff --git a/langpacks/english/Plugins/CloudFile.txt b/langpacks/english/Plugins/CloudFile.txt
index f190a09187..b8cc838f50 100644
--- a/langpacks/english/Plugins/CloudFile.txt
+++ b/langpacks/english/Plugins/CloudFile.txt
@@ -2,7 +2,7 @@
;============================================================
; File: CloudFile.dll
; Plugin: CloudFile
-; Version: 0.11.0.2
+; Version: 0.11.0.3
; Authors: Miranda NG Team
;============================================================
[Allows you to transfer files via cloud services.]
diff --git a/langpacks/english/Plugins/DbEditorPP.txt b/langpacks/english/Plugins/DbEditorPP.txt
index 403a098f94..6d6d2f7eca 100644
--- a/langpacks/english/Plugins/DbEditorPP.txt
+++ b/langpacks/english/Plugins/DbEditorPP.txt
@@ -2,7 +2,7 @@
;============================================================
; File: DbEditorPP.dll
; Plugin: Database editor++
-; Version: 4.0.1.1
+; Version: 4.0.1.2
; Authors: Bio, Jonathan Gordon
;============================================================
[Advanced Database Editor.]
diff --git a/langpacks/english/Plugins/Fingerprint.txt b/langpacks/english/Plugins/Fingerprint.txt
index 1dd7d69f6e..09701fd25e 100644
--- a/langpacks/english/Plugins/Fingerprint.txt
+++ b/langpacks/english/Plugins/Fingerprint.txt
@@ -17,7 +17,6 @@
[Unicode overlay]
[Secure overlays]
[Select protocols]
-[AIM clients]
[Gadu-Gadu clients]
[ICQ clients]
[IRC clients]
@@ -26,7 +25,6 @@
[MSN clients]
[QQ clients]
[RSS clients]
-[Tlen clients]
[Weather clients]
[Yahoo clients]
[Facebook clients]
@@ -58,14 +56,12 @@
[Mail.Ru (unknown client)]
[TM 2008 and >]
[Gadu-Gadu client]
-[Tlen.pl client]
[Python-based clients]
[Jabber client]
[XMPP client]
[Client not found]
[Unknown client]
[Undetected client]
-[AIM overlay]
[ICQJ Plus Mod overlay]
[ICQJ overlay]
[IRC overlay]
@@ -74,7 +70,6 @@
[Jabber overlay]
[MSN overlay]
[QQ overlay]
-[Tlen.pl overlay]
[Yahoo overlay]
[Mail.Ru Agent overlay]
[VK overlay]
@@ -92,9 +87,6 @@
[Gadu-Gadu v10 client]
[Gadu-Gadu v9 client]
[Gadu-Gadu v8 client]
-[Tlen 7.x overlay]
-[Tlen 6.x overlay]
-[Tlen 5.x overlay]
[TM/QQ 2012 overlay]
[TM/QQ 2011 overlay]
[TM/QQ 2010 overlay]
diff --git a/langpacks/english/Plugins/GmailNotifier.txt b/langpacks/english/Plugins/GmailNotifier.txt
index 0193753f23..b3f28b7a0a 100644
--- a/langpacks/english/Plugins/GmailNotifier.txt
+++ b/langpacks/english/Plugins/GmailNotifier.txt
@@ -2,7 +2,7 @@
;============================================================
; File: GmailNotifier.dll
; Plugin: Gmail Multiple Notifier
-; Version: 0.3.1.1
+; Version: 1.0.1.1
; Authors: Mixwind
;============================================================
[Check your Gmail inboxes locally.]
@@ -32,14 +32,13 @@
[Log unread threads into database (enable history)]
;file \plugins\GmailNotifier\src\check.cpp
[Checking...]
-[Can't open Internet!]
-[Can't reach server!]
[Can't send account data!]
-[Can't get RSS feed!]
[Wrong name or password!]
+[Can't get RSS feed!]
;file \plugins\GmailNotifier\src\main.cpp
[Other]
[Gmail: New thread(s)]
+[Gmail Notifier connection]
[&Check all Gmail inboxes]
[&Check Gmail inbox]
;file \plugins\GmailNotifier\src\options.cpp
diff --git a/langpacks/english/Plugins/IEView.txt b/langpacks/english/Plugins/IEView.txt
index 33cfb94d7f..b6585dd58d 100644
--- a/langpacks/english/Plugins/IEView.txt
+++ b/langpacks/english/Plugins/IEView.txt
@@ -36,6 +36,7 @@
[Show date]
[Use long date format]
[Use relative timestamp]
+[Download more templates]
;file \plugins\IEView\src\HistoryHTMLBuilder.cpp
[Outgoing File Transfer]
[Incoming File Transfer]
diff --git a/langpacks/english/Plugins/MSN.txt b/langpacks/english/Plugins/MSN.txt
index 801a2437a5..e4a6da9221 100644
--- a/langpacks/english/Plugins/MSN.txt
+++ b/langpacks/english/Plugins/MSN.txt
@@ -2,7 +2,7 @@
;============================================================
; File: MSN.dll
; Plugin: MSN protocol
-; Version: 0.14.0.1
+; Version: 0.14.0.2
; Authors: Boris Krasnovskiy, George Hazan, Richard Hughes, leecher
;============================================================
[Microsoft Network (MSN) protocol support for Miranda NG.]
diff --git a/langpacks/english/Plugins/New_GPG.txt b/langpacks/english/Plugins/New_GPG.txt
index 68372a214f..1995653892 100644
--- a/langpacks/english/Plugins/New_GPG.txt
+++ b/langpacks/english/Plugins/New_GPG.txt
@@ -92,46 +92,6 @@
[Import GPG Public keys]
[GPG encryption status]
;file \plugins\New_GPG\src\main.cpp
-[Email]
-[Name]
-[Creation date]
-[Expire date]
-[Key length]
-[Accounts]
-[Default]
-[key ID]
-[not set]
-[Default private key ID]
-[Failed to open file]
-[Error]
-[Generating new random key, please wait]
-[Failed to allocate memory]
-[Failed to lock memory with error %d]
-[Failed write to clipboard with error %d]
-[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
-[Warning]
-[Wrong GPG binary location found in system.\nPlease choose another location]
-[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
-[Info]
-[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
-[GPG binary does not exist.\nPlease choose another location]
-[Please choose GPG binary location]
-[Please set keyring's home directory]
-[There is existing key for contact, would you like to replace it with new key?]
-[New public key was received, do you want to import it?]
-[Replace]
-[Accept]
-[Received key from %s]
-[You must set encryption algorithm first]
-[Key length must be of length from 1024 to 4096 bits]
-[Invalid date]
-[Name must contain at least 5 characters]
-[Name cannot contain '(' or ')']
-[Invalid Email]
-[Generating new key, please wait...]
-[Failed to export public key.]
[GPG binary is set and valid (this is good).\n]
[GPG binary unset or invalid (plugin will not work).\n]
[Home dir write access granted (this is good).\n]
@@ -151,18 +111,18 @@
[Metacontact detected]
;file \plugins\New_GPG\src\messages.cpp
[We received encrypted message from contact with encryption turned off.\nDo you want to turn on encryption for this contact?]
+[Warning]
[Do you want to try to decrypt encrypted message?]
[We're trying to encrypt with untrusted key. Do you want to trust this key permanently?]
[Something is wrong, GPG does not understand us, aborting encryption.]
;file \plugins\New_GPG\src\options.cpp
-[Services]
-[Main]
-[GnuPG Variables]
-[Messages]
-[Advanced]
[Contact]
[Key ID]
+[Name]
+[Email]
[Protocol]
+[Default private key ID]
+[not set]
[This key is not used by any contact. Do you want to remove it from public keyring?]
[Key info]
[we have secret key for this public key, do not removing from GPG keyring]
@@ -171,10 +131,15 @@
[Do you want to remove key from entire metacontact (all subcontacts)?]
[Export public key]
[.asc pubkey file]
+[Failed to allocate memory]
+[Error]
+[Failed to lock memory with error %d]
+[Failed write to clipboard with error %d]
[Failed to open clipboard with error %d]
[Set log file]
[LOG files]
[Choose gpg.exe]
+[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
[Set home directory]
[Load Public GPG Key for ]
[Turn off encryption]
@@ -183,9 +148,45 @@
[ found in presence.)]
[This is not public or private key]
[Key already in secret keyring.]
+[Info]
[Set file containing GPG public key]
[GPG public key file]
+[Failed to open file]
[There is no public or private key.]
+[Services]
+[Main]
+[GnuPG Variables]
+[Messages]
+[Advanced]
+;file \plugins\New_GPG\src\ui.cpp
+[New passwords do not match]
+[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[Creation date]
+[Expire date]
+[Key length]
+[Accounts]
+[Default]
+[key ID]
+[Generating new random key, please wait]
+[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
+[Wrong GPG binary location found in system.\nPlease choose another location]
+[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
+[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
+[There is existing key for contact, would you like to replace it with new key?]
+[New public key was received, do you want to import it?]
+[Replace]
+[Accept]
+[Received key from %s]
+[You must set encryption algorithm first]
+[Key length must be of length from 1024 to 4096 bits]
+[Invalid date]
+[Name must contain at least 5 characters]
+[Name cannot contain '(' or ')']
+[Invalid Email]
+[Generating new key, please wait...]
+[Expiration date]
+[Failed to export public key.]
;file \plugins\New_GPG\src\utilities.cpp
[Do you want to toggle encryption for all subcontacts?]
[Turn off GPG encryption]
@@ -202,5 +203,7 @@
[We have successfully processed %d public keys and some private keys.]
[We have successfully processed %d public keys.]
[Keys import result]
-[New passwords do not match]
-[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[GPG binary does not exist.\nPlease choose another location]
+[Please choose GPG binary location]
+[Please set keyring's home directory]
+;file \plugins\New_GPG\src\utilities.h
diff --git a/langpacks/english/Plugins/QuickSearch.txt b/langpacks/english/Plugins/QuickSearch.txt
index 05b380f9a2..2e0707edf9 100644
--- a/langpacks/english/Plugins/QuickSearch.txt
+++ b/langpacks/english/Plugins/QuickSearch.txt
@@ -1,7 +1,7 @@
#muuid {e4058506-6494-4d60-9cf4-40bf545f78bd}
;============================================================
; File: QuickSearch.dll
-; Module: Quick Search
+; Plugin: Quick Search
; Version: 1.4.2.0
; Authors: Awkward
;============================================================
diff --git a/langpacks/english/Plugins/Quotes.txt b/langpacks/english/Plugins/Quotes.txt
index b625fe5723..dd31a4bb95 100644
--- a/langpacks/english/Plugins/Quotes.txt
+++ b/langpacks/english/Plugins/Quotes.txt
@@ -111,7 +111,7 @@
[Miranda could not load Quotes plugin. Microsoft HTML parser is missing.]
;file \plugins\Quotes\src\QuoteInfoDlg.cpp
;file \plugins\Quotes\src\QuotesProviderGoogle.cpp
-[Error occurred during html parsing.]
+[Error occurred during HTML parsing.]
[Error occurred during site access.]
;file \plugins\Quotes\src\QuotesProviderVisitorFormatSpecificator.cpp
[Quote Symbol]
diff --git a/langpacks/english/Plugins/SimpleStatusMsg.txt b/langpacks/english/Plugins/SimpleStatusMsg.txt
index db0416ab45..bae2f4f1d6 100644
--- a/langpacks/english/Plugins/SimpleStatusMsg.txt
+++ b/langpacks/english/Plugins/SimpleStatusMsg.txt
@@ -3,7 +3,7 @@
; File: SimpleStatusMsg.dll
; Plugin: Simple status message
; Version: 1.9.0.6
-; Authors: Bartosz 'Dezeath' Bialek, Harven
+; Authors: Bartosz 'Dezeath' Białek, Harven
;============================================================
[Provides a simple way to set status and away messages.]
;file \plugins\SimpleStatusMsg\res\resource.rc
diff --git a/langpacks/english/Plugins/SmileyAdd.txt b/langpacks/english/Plugins/SmileyAdd.txt
index 362b5e064c..352ce29bf6 100644
--- a/langpacks/english/Plugins/SmileyAdd.txt
+++ b/langpacks/english/Plugins/SmileyAdd.txt
@@ -2,7 +2,7 @@
;============================================================
; File: SmileyAdd.dll
; Plugin: SmileyAdd
-; Version: 0.2.4.2
+; Version: 0.3.0.1
; Authors: Peacow, nightwish, bid, borkra
;============================================================
[Smiley support for Miranda NG.]
@@ -55,11 +55,10 @@
[Protocol specific]
;file \plugins\SmileyAdd\src\smileys.cpp
[Smiley pack %s for category "%s" not found.\nSelect correct smiley pack in the Options -> Customize -> Smileys.]
-[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
[Smiley #%u in file %s for smiley pack %s not found.]
+[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
[%s global smiley pack]
[Standard]
-[Regular expression "%s" in smiley pack "%s" could produce "empty matches".]
[Regular expression "%s" in smiley pack "%s" malformed.]
;file \plugins\SmileyAdd\src\smltool.cpp
[d'Oh!]
diff --git a/langpacks/english/Plugins/SplashScreen.txt b/langpacks/english/Plugins/SplashScreen.txt
index 89d6e16ced..61be79962d 100644
--- a/langpacks/english/Plugins/SplashScreen.txt
+++ b/langpacks/english/Plugins/SplashScreen.txt
@@ -22,6 +22,7 @@
[Fade out:]
[AdvaImg plugin not found. Please get it from https://miranda-ng.org/p/AdvaImg/ to be able to use images.]
[Preview...]
+[Download more splash screens]
;file \plugins\SplashScreen\src\options.cpp
[Graphic files]
[Sound Files]
diff --git a/langpacks/english/Plugins/StatusManager.txt b/langpacks/english/Plugins/StatusManager.txt
index 50e00d21ff..2868dc9b2a 100644
--- a/langpacks/english/Plugins/StatusManager.txt
+++ b/langpacks/english/Plugins/StatusManager.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StatusManager.dll
; Plugin: Status manager
-; Version: 0.11.2.3
+; Version: 1.0.1.1
; Authors: P Boon
;============================================================
[A connection checker and auto away module. Also allows you to define the status Miranda should set on startup, configurable per protocol.]
diff --git a/langpacks/english/Plugins/Steam.txt b/langpacks/english/Plugins/Steam.txt
index 8216825dfa..33f698c748 100644
--- a/langpacks/english/Plugins/Steam.txt
+++ b/langpacks/english/Plugins/Steam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Steam.dll
; Plugin: Steam protocol
-; Version: 0.11.6.1
+; Version: 0.11.6.3
; Authors: Miranda NG Team, Robert Pösel
;============================================================
[Steam protocol support for Miranda NG.]
diff --git a/langpacks/english/Plugins/StopSpam.txt b/langpacks/english/Plugins/StopSpam.txt
index 4d347abc7b..2cc53340a7 100644
--- a/langpacks/english/Plugins/StopSpam.txt
+++ b/langpacks/english/Plugins/StopSpam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpam.dll
; Plugin: StopSpam+
-; Version: 0.0.1.5
+; Version: 0.1.0.1
; Authors: Roman Miklashevsky, A. Petkevich, Kosh&chka, persei
;============================================================
[Anti-spam plugin for Miranda NG.]
@@ -25,16 +25,16 @@
[Log Spammers to system history]
;file \plugins\StopSpamPlus\src\events.cpp
[StopSpam automatic message:\r\n]
+;file \plugins\StopSpamPlus\src\options.cpp
+[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
[Message sessions]
[General]
[Messages]
[Accounts]
-;file \plugins\StopSpamPlus\src\options.cpp
-[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
;file \plugins\StopSpamPlus\src\services.cpp
[Not In List]
[Complete]
-;file \plugins\StopSpamPlus\src\settings.h
+;file \plugins\StopSpamPlus\src\settings.cpp
[Spammers made me to install small anti-spam system you are now speaking with. Please reply "nospam" without quotes and spaces if you want to contact me.]
[StopSpam: send a message and reply to an anti-spam bot question.]
[Congratulations! You just passed human/robot test. Now you can write me a message.]
diff --git a/langpacks/english/Plugins/StopSpamMod.txt b/langpacks/english/Plugins/StopSpamMod.txt
index a01652ca21..3646ac5355 100644
--- a/langpacks/english/Plugins/StopSpamMod.txt
+++ b/langpacks/english/Plugins/StopSpamMod.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpamMod.dll
; Plugin: StopSpam mod
-; Version: 0.0.2.1
+; Version: 0.0.2.2
; Authors: Roman Miklashevsky, sss, Elzor
;============================================================
[Anti-spam plugin for Miranda NG.]
diff --git a/langpacks/english/Plugins/TabSRMM.txt b/langpacks/english/Plugins/TabSRMM.txt
index d921b38efc..1ae6fe343a 100644
--- a/langpacks/english/Plugins/TabSRMM.txt
+++ b/langpacks/english/Plugins/TabSRMM.txt
@@ -262,6 +262,7 @@
[You can export and import all your color and font settings here. This allows you to create a Theme file which can be shared between different profiles or with your buddies.]
[Export to a file...]
[Import from a file...]
+[Download more skins]
[Icons]
[Event type icons in the message log]
[Text symbols as event markers]
diff --git a/langpacks/english/Plugins/Tox.txt b/langpacks/english/Plugins/Tox.txt
index 6168903072..1f6d1cd4c6 100644
--- a/langpacks/english/Plugins/Tox.txt
+++ b/langpacks/english/Plugins/Tox.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Tox.dll
; Plugin: Tox protocol
-; Version: 0.11.1.25
+; Version: 0.11.3.0
; Authors: Miranda NG Team
;============================================================
[Tox protocol support for Miranda NG.]
@@ -24,10 +24,14 @@
[Enable IPv6]
[Max connect retries:]
[Max reconnect retries:]
+[Enable UDP hole-punching]
+[Enable local network peer discovery]
+[Remove password]
+[Change password]
+[Set password]
[If this field contains Tox address (76 hex characters), you will be prompted to add it in your friend list. Otherwise, Miranda will search this query via Tox DNS discovery.]
[DNS name:]
[Enter password]
-[Save password]
[Cancel]
[Tox profile is encrypted. Enter the password to continue.]
[Add]
@@ -36,48 +40,25 @@
[IPv6 address (optional)]
[Port]
[Public key]
-[Multimedia]
-[Audio input device]
-[Audio output device]
-[Video input device]
-[Invite contacts to chat room]
-[&Invite]
-[&Cancel]
-[Call]
-[End]
-[Incoming call]
-[Answer]
-[Reject]
-[From:]
-[Date:]
-[&User menu]
-[User &details]
-[&History]
-[Outgoing call]
-[To:]
+[Old password:]
+[New password:]
+[Confirm password:]
;file \protocols\Tox\src\main.cpp
-[Current version of plugin is support Tox API version %i.%i.%i which is incompatible with %s]
-;file \protocols\Tox\src\tox_connection.cpp
-[Unable to initialize Tox core]
-;file \protocols\Tox\src\tox_events.cpp
[Profiles folder]
[Tox URI scheme]
-[Action]
+;file \protocols\Tox\src\tox_connection.cpp
+[Unable to initialize Tox core]
;file \protocols\Tox\src\tox_icons.cpp
[Protocol icon]
-[Audio call]
-[Audio ring]
-[Audio start]
-[Audio end]
[Protocols]
;file \protocols\Tox\src\tox_menus.cpp
[Request authorization]
[Grant authorization]
+[Password]
+[Create password]
;file \protocols\Tox\src\tox_messages.cpp
+[Action]
[You cannot send when you are offline.]
-;file \protocols\Tox\src\tox_multimedia.cpp
-[Incoming call from %s]
-[Outgoing call to %s]
;file \protocols\Tox\src\tox_netlib.cpp
[%s connection]
;file \protocols\Tox\src\tox_options.cpp
@@ -102,6 +83,10 @@
[Unable to open Tox profile]
[Unable to read Tox profile]
[Unable to decrypt Tox profile]
+[Removing the password will lead to decryption of the profile.\r\nAre you sure to remove password?]
+[New password is empty]
+[New password is not equal to confirmation]
+[Old password is not valid]
;file \protocols\Tox\src\tox_proto.cpp
[You cannot add yourself to your contact list]
[Contact already in your contact list]
diff --git a/langpacks/english/Plugins/VKontakte.txt b/langpacks/english/Plugins/VKontakte.txt
index d6478f64f8..ce96b0c70b 100644
--- a/langpacks/english/Plugins/VKontakte.txt
+++ b/langpacks/english/Plugins/VKontakte.txt
@@ -2,7 +2,7 @@
;============================================================
; File: VKontakte.dll
; Plugin: VKontakte protocol
-; Version: 0.1.3.0
+; Version: 0.1.4.0
; Authors: Miranda NG Team
;============================================================
[VKontakte protocol support for Miranda NG.]
@@ -129,6 +129,7 @@
[Can't send messages for users from blacklist]
[Can't send messages for users without dialogs]
[Can't send messages to this user due to their privacy settings]
+[Message is too long]
[Enter the missing digits between %s and %s of the phone number linked to your account]
[Attention!]
[Enter confirmation code]
@@ -244,6 +245,8 @@
[Error loading message history for %s from server.]
[Loading messages for %s is completed.]
;file \protocols\VKontakte\src\vk_messages.cpp
+[Edited message:\n]
+[\nOriginal message:\n]
;file \protocols\VKontakte\src\vk_options.cpp
[Network]
[Account]
diff --git a/langpacks/english/Plugins/YAMN.txt b/langpacks/english/Plugins/YAMN.txt
index eda60b3db0..3b444d853a 100644
--- a/langpacks/english/Plugins/YAMN.txt
+++ b/langpacks/english/Plugins/YAMN.txt
@@ -11,7 +11,6 @@
[Version:]
[Description:]
[Copyright:]
-[E-mail:]
[Homepage:]
[Account]
[Name:]
diff --git a/langpacks/english/Plugins/mRadio.txt b/langpacks/english/Plugins/mRadio.txt
index 3d657d7773..fa5b9e1b30 100644
--- a/langpacks/english/Plugins/mRadio.txt
+++ b/langpacks/english/Plugins/mRadio.txt
@@ -53,7 +53,7 @@
[Continuous record]
[Quarry]
[Sorry!]
-[BASS.DLL not found!]
+[bass.dll not found!]
[Station]
[Custom INI file]
[Radio station URL]
@@ -102,3 +102,4 @@
[Equalizer]
[New]
[Quick Open]
+[bass.dll not found! Choose bass.dll path manually]
diff --git a/langpacks/english/Weather/Intellicast.txt b/langpacks/english/Weather/Intellicast.txt
index f2a0cf431b..552b0225fe 100644
--- a/langpacks/english/Weather/Intellicast.txt
+++ b/langpacks/english/Weather/Intellicast.txt
@@ -1,6 +1,6 @@
;============================================================
; File: Intellicast.ini
-; Module: weather
+; Plugin: Weather
;============================================================
[Ceiling]
[Mon]
diff --git a/langpacks/english/Weather/weatherxml.txt b/langpacks/english/Weather/weatherxml.txt
index d0fbd8edd7..819b67f4d8 100644
--- a/langpacks/english/Weather/weatherxml.txt
+++ b/langpacks/english/Weather/weatherxml.txt
@@ -1,6 +1,6 @@
;============================================================
; File: weatherxml.ini
-; Module: weather
+; Plugin: Weather
;============================================================
[AM Rain]
[Am Clouds / Pm Sun]
diff --git a/langpacks/english/Weather/wundergrnd_intl.txt b/langpacks/english/Weather/wundergrnd_intl.txt
index c03f03ba93..55650122f7 100644
--- a/langpacks/english/Weather/wundergrnd_intl.txt
+++ b/langpacks/english/Weather/wundergrnd_intl.txt
@@ -1,6 +1,6 @@
;============================================================
; File: wundergrnd_intl.ini
-; Module: weather
+; Plugin: Weather
;============================================================
[Alert]
[Blowing Snow]
diff --git a/langpacks/english/Weather/yweather.txt b/langpacks/english/Weather/yweather.txt
index dda2bc564b..f14e079e75 100644
--- a/langpacks/english/Weather/yweather.txt
+++ b/langpacks/english/Weather/yweather.txt
@@ -1,6 +1,6 @@
;============================================================
; File: yweather.ini
-; Module: weather
+; Plugin: Weather
;============================================================
[ENE]
[ESE]
diff --git a/langpacks/english_gb/=CORE=.txt b/langpacks/english_gb/=CORE=.txt
index e04057add5..b5146646f3 100644
--- a/langpacks/english_gb/=CORE=.txt
+++ b/langpacks/english_gb/=CORE=.txt
@@ -3,12 +3,6 @@
; Module: Miranda Core
; Version: 0.95.8
;============================================================
-[Authorization request]
-Authorisation request
-[&Authorize]
-&Authorise
-[Add to contact list if authorized]
-Add to contact list if authorised
[Minimize to tray]
Minimise to tray
[Gray out entire list when:]
@@ -29,6 +23,8 @@ Use default colours
Use custom colours
[Send authorization request]
Send authorisation request
+[Authorization request]
+Authorisation request
[Run program when Miranda NG starts (e.g., tail -f, dbgview, etc.):]
Run program when Miranda NG starts (e.g. tail -f, dbgview, etc.):
[e.g., Workplace]
@@ -45,16 +41,10 @@ Text colour
Base colour:
[Secondary color:]
Secondary colour:
-[%s requests authorization]
-%s requests authorisation
-[%u requests authorization]
-%u requests authorisation
-[%s requested authorization\n%u (%s) on %s]
-%s requested authorisation\n%u (%s) on %s
-[%s requested authorization\n%u on %s]
-%s requested authorisation\n%u on %s
-[%s requested authorization\n%s on %s]
-%s requested authorisation\n%s on %s
+[&Authorize]
+&Authorise
+[Add to contact list if authorized]
+Add to contact list if authorised
[Canceled]
Cancelled
[This file transfer has been canceled by the other side]
@@ -77,6 +67,16 @@ Select a foreground colour for the text (CTRL+K)
Select a background colour for the text (CTRL+L)
[Please authorize my request and add me to your contact list.]
Please authorise my request and add me to your contact list.
+[%s requests authorization]
+%s requests authorisation
+[%u requests authorization]
+%u requests authorisation
+[%s requested authorization\n%u (%s) on %s]
+%s requested authorisation\n%u (%s) on %s
+[%s requested authorization\n%u on %s]
+%s requested authorisation\n%u on %s
+[%s requested authorization\n%s on %s]
+%s requested authorisation\n%s on %s
[Authorization request from %s%s: %s]
Authorisation request from %s%s: %s
[Customize]
diff --git a/langpacks/english_gb/=HEAD=.txt b/langpacks/english_gb/=HEAD=.txt
index d3768e61a6..b06b19c3af 100644
--- a/langpacks/english_gb/=HEAD=.txt
+++ b/langpacks/english_gb/=HEAD=.txt
@@ -3,4 +3,4 @@ Language: English (British)
Locale: 0809
Authors: Boris Kotov
Author-email: doctor.z01db3rg@gmail.com
-Last-Modified-Using: Miranda NG 0.95.7
+Last-Modified-Using: Miranda NG 0.95.8
diff --git a/langpacks/english_gb/Plugins/AIM.txt b/langpacks/english_gb/Plugins/AIM.txt
deleted file mode 100644
index fd4a3a23cd..0000000000
--- a/langpacks/english_gb/Plugins/AIM.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-#muuid {3750a5a3-bf0d-490e-b65d-41ac4d29aeb3}
-;============================================================
-; File: AIM.dll
-; Plugin: AIM protocol
-; Version: 0.11.0.1
-; Authors: Boris Krasnovskiy, Aaron Myles Landwehr
-;============================================================
-[Cannot add this buddy because it requires authorization.]
-Cannot add this buddy because it requires authorisation.
-[Foreground color]
-Foreground colour
-[Background color]
-Background colour
diff --git a/langpacks/english_gb/Plugins/AddContactPlus.txt b/langpacks/english_gb/Plugins/AddContactPlus.txt
index d23e907c73..a7e6d9134f 100644
--- a/langpacks/english_gb/Plugins/AddContactPlus.txt
+++ b/langpacks/english_gb/Plugins/AddContactPlus.txt
@@ -3,7 +3,7 @@
; File: AddContactPlus.dll
; Plugin: Add contact+
; Version: 0.9.9.2
-; Authors: Bartosz 'Dezeath' Bialek
+; Authors: Bartosz 'Dezeath' Białek
;============================================================
[Send authorization request]
Send authorisation request
diff --git a/langpacks/english_gb/Plugins/AsSingleWindow.txt b/langpacks/english_gb/Plugins/AsSingleWindow.txt
new file mode 100644
index 0000000000..c160075526
--- /dev/null
+++ b/langpacks/english_gb/Plugins/AsSingleWindow.txt
@@ -0,0 +1,9 @@
+#muuid {0F6C73B4-2B2B-711D-FBB6-BB267DFD7208}
+;============================================================
+; File: AsSingleWindow.dll
+; Plugin: AsSingleWindow
+; Version: 0.1.2.2
+; Authors: Aleksey Smyrnov aka Soar
+;============================================================
+[Customize]
+Customise
diff --git a/langpacks/english_gb/Plugins/DbEditorPP.txt b/langpacks/english_gb/Plugins/DbEditorPP.txt
index 03c7cdf6eb..1dc44afaf5 100644
--- a/langpacks/english_gb/Plugins/DbEditorPP.txt
+++ b/langpacks/english_gb/Plugins/DbEditorPP.txt
@@ -2,7 +2,7 @@
;============================================================
; File: DbEditorPP.dll
; Plugin: Database editor++
-; Version: 4.0.1.1
+; Version: 4.0.1.2
; Authors: Bio, Jonathan Gordon
;============================================================
[Background color]
diff --git a/langpacks/english_gb/Plugins/MSN.txt b/langpacks/english_gb/Plugins/MSN.txt
index bebb5db748..9ca8f3e3af 100644
--- a/langpacks/english_gb/Plugins/MSN.txt
+++ b/langpacks/english_gb/Plugins/MSN.txt
@@ -2,7 +2,7 @@
;============================================================
; File: MSN.dll
; Plugin: MSN protocol
-; Version: 0.14.0.1
+; Version: 0.14.0.2
; Authors: Boris Krasnovskiy, George Hazan, Richard Hughes, leecher
;============================================================
[Send message font color/size info inside messages]
diff --git a/langpacks/english_gb/Plugins/Ping.txt b/langpacks/english_gb/Plugins/Ping.txt
deleted file mode 100644
index 8db72e7bc4..0000000000
--- a/langpacks/english_gb/Plugins/Ping.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-#muuid {760ea901-c0c2-446c-8029-94c3bc47c45e}
-;============================================================
-; File: Ping.dll
-; Plugin: Ping
-; Version: 0.9.1.1
-; Authors: Scott Ellis
-;============================================================
diff --git a/langpacks/english_gb/Plugins/SimpleStatusMsg.txt b/langpacks/english_gb/Plugins/SimpleStatusMsg.txt
index c8778cb768..3e81048b25 100644
--- a/langpacks/english_gb/Plugins/SimpleStatusMsg.txt
+++ b/langpacks/english_gb/Plugins/SimpleStatusMsg.txt
@@ -3,7 +3,7 @@
; File: SimpleStatusMsg.dll
; Plugin: Simple status message
; Version: 1.9.0.6
-; Authors: Bartosz 'Dezeath' Bialek, Harven
+; Authors: Bartosz 'Dezeath' Białek, Harven
;============================================================
[Behavior on status change]
Behaviour on status change
diff --git a/langpacks/english_gb/Plugins/SmileyAdd.txt b/langpacks/english_gb/Plugins/SmileyAdd.txt
index 5ca30bbcc8..1717818916 100644
--- a/langpacks/english_gb/Plugins/SmileyAdd.txt
+++ b/langpacks/english_gb/Plugins/SmileyAdd.txt
@@ -2,7 +2,7 @@
;============================================================
; File: SmileyAdd.dll
; Plugin: SmileyAdd
-; Version: 0.2.4.2
+; Version: 0.3.0.1
; Authors: Peacow, nightwish, bid, borkra
;============================================================
[Background color]
diff --git a/langpacks/english_gb/Plugins/StatusManager.txt b/langpacks/english_gb/Plugins/StatusManager.txt
index e4ff4b6bc0..b35bc6056c 100644
--- a/langpacks/english_gb/Plugins/StatusManager.txt
+++ b/langpacks/english_gb/Plugins/StatusManager.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StatusManager.dll
; Plugin: Status manager
-; Version: 0.11.2.3
+; Version: 1.0.1.1
; Authors: P Boon
;============================================================
[Background color]
diff --git a/langpacks/english_gb/Plugins/Steam.txt b/langpacks/english_gb/Plugins/Steam.txt
index 5a2d410117..9249e0f9ed 100644
--- a/langpacks/english_gb/Plugins/Steam.txt
+++ b/langpacks/english_gb/Plugins/Steam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Steam.dll
; Plugin: Steam protocol
-; Version: 0.11.6.1
+; Version: 0.11.6.3
; Authors: Miranda NG Team, Robert Pösel
;============================================================
[Show chat state events (i.e., user closed chat session)]
diff --git a/langpacks/english_gb/Plugins/StopSpamMod.txt b/langpacks/english_gb/Plugins/StopSpamMod.txt
index 7dbafa3ebd..2c89daa4fc 100644
--- a/langpacks/english_gb/Plugins/StopSpamMod.txt
+++ b/langpacks/english_gb/Plugins/StopSpamMod.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpamMod.dll
; Plugin: StopSpam mod
-; Version: 0.0.2.1
+; Version: 0.0.2.2
; Authors: Roman Miklashevsky, sss, Elzor
;============================================================
[Automatically grant authorization]
diff --git a/langpacks/english_gb/Plugins/Tox.txt b/langpacks/english_gb/Plugins/Tox.txt
index ca9f2cff42..2456ff6c38 100644
--- a/langpacks/english_gb/Plugins/Tox.txt
+++ b/langpacks/english_gb/Plugins/Tox.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Tox.dll
; Plugin: Tox protocol
-; Version: 0.11.1.25
+; Version: 0.11.1.26
; Authors: Miranda NG Team
;============================================================
[Unable to initialize Tox core]
diff --git a/langpacks/french/=CORE=.txt b/langpacks/french/=CORE=.txt
index 5c1861d202..5d69d0cab1 100644
--- a/langpacks/french/=CORE=.txt
+++ b/langpacks/french/=CORE=.txt
@@ -3,29 +3,6 @@
; Module: Miranda Core
; Version: 0.95.8
;============================================================
-;file \src\core\stdauth\res\resource.rc
-[Authorization request]
-Demande d'autorisation
-[&Authorize]
-&Autoriser
-[&Deny]
-&Refuser
-[Decide &later]
-Décider plus &tard
-[User &details]
-&Détails du contact
-[Reason:]
-Motif :
-[Denial reason:]
-Raison du refus :
-[Add to contact list if authorized]
-Ajouter à la liste de contacts si autorisé
-[You were added]
-Vous avez été ajouté
-[&Close]
-&Fermer
-[&Add]
-&Ajouter
;file \src\core\stdaway\res\resource.rc
[%s message for %s]
Message %s pour %s
@@ -291,6 +268,8 @@ Taille totale :
Description :
[&User menu]
&Menu utilisateur
+[User &details]
+&Détails du contact
[&History]
&Historique
[Incoming file transfer]
@@ -307,6 +286,8 @@ Date :
Fichiers :
[Save to:]
Enregistrer sous :
+[&Add]
+&Ajouter
[&Open...]
Ouvrir...
[Open &folder]
@@ -395,11 +376,6 @@ Me demander
Renommer (ajouter (1), (2), etc.)
[You will always be asked about files from people not on your contact list]
Vous serez avisé des fichiers ne provenant pas de votre liste de contacts
-;file \src\core\stdhelp\res\resource.rc
-[About Miranda NG]
-À propos de Miranda NG
-[Credits >]
-Crédits >
;file \src\core\stdidle\res\resource.rc
[Become idle if the following is left unattended:]
Devient "Inactif" si inactivité de :
@@ -723,6 +699,8 @@ Ouvrir la fenêtre de discussion du contact
Nom à afficher :
[Group:]
Groupe :
+[Authorization request]
+Demande d'autorisation
[&Yes]
&Oui
[&No]
@@ -999,6 +977,8 @@ Déplacer dans la barre de status
[Insert separator]
Insérer un séparateur
+[Module:]
+Module :
[Service:]
Service :
[Default]
@@ -1133,6 +1113,26 @@ Télécharger plus de pack de traduction
[Hide if there isn't enough space]
+[&Authorize]
+&Autoriser
+[&Deny]
+&Refuser
+[Decide &later]
+Décider plus &tard
+[Reason:]
+Motif :
+[Denial reason:]
+Raison du refus :
+[Add to contact list if authorized]
+Ajouter à la liste de contacts si autorisé
+[You were added]
+Vous avez été ajouté
+[&Close]
+&Fermer
+[About Miranda NG]
+À propos de Miranda NG
+[Credits >]
+Crédits >
[Tray]
Tray
[&Hide/Show]
@@ -1193,42 +1193,6 @@ Wikipedia (en)
Google Maps
[Google Translate]
Google Translate
-;file \src\core\stdauth\src\auth.cpp
-[%s requests authorization]
-%s demande une autorisation
-[%u requests authorization]
-%u demande une autorisation
-[%s added you to their contact list]
-%s vous a ajouté à sa liste de contacts
-[%u added you to their contact list]
-%u vous a ajouté à sa liste de contacts
-[Alerts]
-Notifications
-[Added event]
-
-;file \src\core\stdauth\src\authdialogs.cpp
-[View user's details]
-Voir les détails du contact
-[Add contact permanently to list]
-Ajouter le contact à la liste
-[<Unknown>]
-<inconnu>
-[%s added you to the contact list\n%u (%s) on %s]
-
-[%s added you to the contact list\n%u on %s]
-
-[%s added you to the contact list\n%s on %s]
-
-[(Unknown)]
-(Inconnu)
-[%s requested authorization\n%u (%s) on %s]
-
-[%s requested authorization\n%u on %s]
-
-[%s requested authorization\n%s on %s]
-
-[Feature is not supported by protocol]
-Cette fonctionnalité n'est pas supportée par le protocole
;file \src\core\stdaway\src\awaymsg.cpp
[Re&ad %s message]
&Message d'état de "%s"
@@ -1351,6 +1315,10 @@ Fichiers exécutables
Sélectionnez un répertoire
[My received files]
Mes fichiers reçus
+[Add contact permanently to list]
+Ajouter le contact à la liste
+[View user's details]
+Voir les détails du contact
[View user's history]
Voir l'historique
[User menu]
@@ -1418,20 +1386,6 @@ Transfert et analyse de virus achevés
;file \src\core\stdfile\src\ftmanager.cpp
[Outgoing]
Sortant
-;file \src\core\stdhelp\src\about.cpp
-[< Copyright]
-< Crédits
-;file \src\core\stdhelp\src\help.cpp
-[&Help]
-&Aide
-[&About...]
-À &propos...
-[&Support]
-
-[&Miranda NG homepage]
-&Miranda NG page web
-[&Report bug]
-Rapport de bogue
;file \src\core\stdidle\src\idle.cpp
[Idle]
Inactif
@@ -1907,11 +1861,43 @@ Voir/Changer mes &détails...
;file \src\core\stduseronline\src\useronline.cpp
[%s is online]
%s est en ligne
+[Alerts]
+Notifications
;file \src\mir_app\src\addcontact.cpp
[Add %s]
Ajouter %s
[Please authorize my request and add me to your contact list.]
Veuillez autoriser ma demande et m'ajouter à votre liste de contact.
+;file \src\mir_app\src\auth.cpp
+[%s requests authorization]
+%s demande une autorisation
+[%u requests authorization]
+%u demande une autorisation
+[%s added you to their contact list]
+%s vous a ajouté à sa liste de contacts
+[%u added you to their contact list]
+%u vous a ajouté à sa liste de contacts
+[Added event]
+
+;file \src\mir_app\src\authdialogs.cpp
+[<Unknown>]
+<inconnu>
+[%s added you to the contact list\n%u (%s) on %s]
+
+[%s added you to the contact list\n%u on %s]
+
+[%s added you to the contact list\n%s on %s]
+
+[(Unknown)]
+(Inconnu)
+[%s requested authorization\n%u (%s) on %s]
+
+[%s requested authorization\n%u on %s]
+
+[%s requested authorization\n%s on %s]
+
+[Feature is not supported by protocol]
+Cette fonctionnalité n'est pas supportée par le protocole
;file \src\mir_app\src\chat_clist.cpp
[&Join chat]
Re&joindre
@@ -2200,6 +2186,19 @@ Apparence
[Small text]
Petit texte
+;file \src\mir_app\src\help.cpp
+[< Copyright]
+< Crédits
+[&Help]
+&Aide
+[&About...]
+À &propos...
+[&Support]
+
+[&Miranda NG homepage]
+&Miranda NG page web
+[&Report bug]
+Rapport de bogue
;file \src\mir_app\src\hotkey_opts.cpp
[Browser: Back]
diff --git a/langpacks/french/=HEAD=.txt b/langpacks/french/=HEAD=.txt
index 76c7336306..518b0200fb 100644
--- a/langpacks/french/=HEAD=.txt
+++ b/langpacks/french/=HEAD=.txt
@@ -2,6 +2,6 @@ Miranda Language Pack Version 1
Language: French (France)
Locale: 040c
Authors: Dagobert_78, Jerbifor, soopah
-Last-Modified-Using: Miranda NG 0.95.7
+Last-Modified-Using: Miranda NG 0.95.8
; This translation is automatically generated from the French langpack Miranda IM by Dagobert_78.
; If you want to add, visit the forum https://forum.miranda-ng.org/index.php?board=36.0 \ No newline at end of file
diff --git a/langpacks/french/Plugins/AIM.txt b/langpacks/french/Deprecated/AIM.txt
index 5dcc3547cb..5dcc3547cb 100644
--- a/langpacks/french/Plugins/AIM.txt
+++ b/langpacks/french/Deprecated/AIM.txt
diff --git a/langpacks/french/Plugins/AddContactPlus.txt b/langpacks/french/Plugins/AddContactPlus.txt
index 11100a886a..e0549282ac 100644
--- a/langpacks/french/Plugins/AddContactPlus.txt
+++ b/langpacks/french/Plugins/AddContactPlus.txt
@@ -3,7 +3,7 @@
; File: AddContactPlus.dll
; Plugin: Add contact+
; Version: 0.9.9.2
-; Authors: Bartosz 'Dezeath' Bialek
+; Authors: Bartosz 'Dezeath' Białek
;============================================================
[Provides the ability to quickly add new contacts.]
Offre la possibilité d'ajouter rapidement de nouveaux contacts.
diff --git a/langpacks/french/Plugins/AssocMgr.txt b/langpacks/french/Plugins/AssocMgr.txt
index b4260a73a3..460e7b18d5 100644
--- a/langpacks/french/Plugins/AssocMgr.txt
+++ b/langpacks/french/Plugins/AssocMgr.txt
@@ -5,8 +5,8 @@
; Version: 0.2.1.0
; Authors: H. Herkenrath
;============================================================
-[Handles file type associations and URLs like aim, gg, mirpu, tlen, wpmsg, xmpp, ymsgr.]
-Permet de gérer les associations de fichier et d'ULR comme AIM, Gadu-Gadu, Jabber, MSN messenger, PluginUpdater, Tlen et Yahoo messenger.
+[Handles file type associations and URLs like aim, gg, mirpu, wpmsg, xmpp, ymsgr.]
+Permet de gérer les associations de fichier et d'ULR comme AIM, Gadu-Gadu, Jabber, MSN messenger, PluginUpdater et Yahoo messenger.
;file \plugins\AssocMgr\res\resource.rc
[Registered associations for Miranda NG:]
Associations enregistrées pour Miranda-NG :
diff --git a/langpacks/french/Plugins/BASS_interface.txt b/langpacks/french/Plugins/BASS_interface.txt
index 7d34a8425a..25b2bfc426 100644
--- a/langpacks/french/Plugins/BASS_interface.txt
+++ b/langpacks/french/Plugins/BASS_interface.txt
@@ -1,20 +1,20 @@
#muuid {2f07ea05-05b5-4ff0-875d-c590da2ddac1}
;============================================================
; File: BASS_interface.dll
-; Plugin: BASS interface
+; Plugin: BASS Interface
; Version: 0.0.0.14
; Authors: tico-tico
;============================================================
-[un4seen's BASS interface Miranda NG plugin.]
+[Un4seen's BASS interface Miranda NG plugin.]
;file \plugins\BASS_interface\res\Bass.rc
-[un4seen's bass interface]
+[Un4seen's BASS interface]
[bass.dll loading error]
[Current bass.dll path:]
-[Maximum number of bass internal channels:]
+[Maximum number of BASS internal channels:]
[Output device:]
@@ -22,7 +22,7 @@
[Quiet time:]
-[download bass library]
+[download BASS library]
[Play only if]
@@ -49,7 +49,7 @@ Parti manger
[Preview]
Aperçu
;file \plugins\BASS_interface\src\Main.cpp
-[un4seen's bass version: %d.%d.%d.%d]
+[Un4seen's BASS version: %d.%d.%d.%d]
[--default device--]
@@ -61,6 +61,8 @@ Sons désactivés
[Frame background]
+[BASS Interface]
+
[Bass Interface]
[Bass library]
diff --git a/langpacks/french/Plugins/BasicHistory.txt b/langpacks/french/Plugins/BasicHistory.txt
index 9cc5c6e292..72031dfab0 100644
--- a/langpacks/french/Plugins/BasicHistory.txt
+++ b/langpacks/french/Plugins/BasicHistory.txt
@@ -8,7 +8,7 @@
[History viewer for Miranda NG.]
;file \plugins\BasicHistory\res\BasicHistory.rc
-[Message History]
+[Message history]
Historique des messages
[Settings]
Paramètres
@@ -16,9 +16,9 @@ Paramètres
[Show groups in contact list]
-[Do not show Find control border]
+[Do not show find control border]
-[Default Event Filter]
+[Default event filter]
[Custom filters]
@@ -56,31 +56,31 @@ heures
[Show seconds in timestamps]
-[Enable Smileys]
+[Enable smileys]
[Search forward in list group]
[Search forward in message window]
-[Match Case]
+[Match case]
-[Match Whole Word]
+[Match whole word]
-[Only Incoming Messages]
+[Only incoming messages]
-[Only Outgoing Messages]
+[Only outgoing messages]
-[Only Selected Group]
+[Only selected group]
-[All Contacts]
+[All contacts]
tous les contacts
-[Export To Txt]
+[Export to txt]
[File encoding*]
-[Export To Plain Html]
+[Export to plain HTML]
-[Export To Rich Html]
+[Export to rich HTML]
[External CSS file]
Fichier CSS externe
@@ -141,9 +141,9 @@ Annuler
;file \plugins\BasicHistory\src\BasicHistory.cpp
[Open History]
Ouvrir historique
-[View &History]
+[View &history]
Voir l'&historique
-[Delete All User History]
+[Delete all user history]
[Execute history task]
@@ -153,13 +153,13 @@ Message reçu
Message envoyé
[Status change]
Changement d'état
-[Show Contacts]
+[Show contacts]
-[Hide Contacts]
+[Hide contacts]
-[Find Next]
+[Find next]
&Suivant
-[Find Previous]
+[Find previous]
Précédent
[Plus in export]
@@ -178,10 +178,10 @@ Historique de %s
Système
[Me]
-[Invalid Message]
+[Invalid message]
Message invalide
;file \plugins\BasicHistory\src\ExportManager.cpp
-[%s Files (*.%s)]
+[%s files (*.%s)]
[Import]
@@ -194,7 +194,7 @@ Message invalide
;file \plugins\BasicHistory\src\HistoryWindow.cpp
[This operation will PERMANENTLY REMOVE all history for this contact.\nAre you sure you want to do this?]
-[Are You sure?]
+[Are you sure?]
Etes-vous sûr?
[Do you want to delete all imported messages for this contact?\nNote that next scheduler task import this messages again.]
@@ -208,11 +208,11 @@ Ouvrir dans une fenêtre existante
Copier
[Delete]
Effacer
-[Send Message]
+[Send message]
-[Reply &Quoted]
+[Reply &quoted]
Répondre en citant
-[Delete Group]
+[Delete group]
Effacer un groupe
[Options]
Paramètres
@@ -224,9 +224,9 @@ Police et couleur
Icônes
[Hotkeys]
Raccourcis clavier
-[Rich Html]
+[Rich HTML]
-[Plain Html]
+[Plain HTML]
[Txt]
@@ -301,27 +301,27 @@ Arrière-plan de la liste
[Find]
Chercher
-[Switch Match Case]
+[Switch match case]
-[Switch Match Whole Word]
+[Switch match whole word]
-[Show/Hide Contacts]
+[Show/hide contacts]
-[Switch Only Incoming Messages]
+[Switch only incoming messages]
-[Switch Only Outgoing Messages]
+[Switch only outgoing messages]
-[Switch Only Selected Group]
+[Switch only selected group]
-[Switch All Contacts]
+[Switch all contacts]
-[Export To Binary]
+[Export to binary]
-[Import From Binary]
+[Import from binary]
-[Export To Dat (mContacts)]
+[Export to dat (mContacts)]
-[Import From Dat (mContacts)]
+[Import from dat (mContacts)]
[Invalid event number]
@@ -333,7 +333,7 @@ Chercher
[Invalid file]
-[All Files (*.*)]
+[All files (*.*)]
Tous les fichiers (*.*)
[Enter filter name]
@@ -351,17 +351,17 @@ Vous avez entré une page de codes invalide. Sélectionnez la page de codes dans
Page de code invalide
[Browse CSS file]
-[Export and Delete]
+[Export and delete]
-[Import and Merge]
+[Import and merge]
[Minute]
[Hour]
-[At Start]
+[At start]
-[At Finish]
+[At finish]
[Daily]
@@ -407,7 +407,7 @@ Page de code invalide
;file \plugins\BasicHistory\src\Options.h
;file \plugins\BasicHistory\src\PlainHtmlExport.cpp
-[History Log]
+[History log]
[Filter:]
diff --git a/langpacks/french/Plugins/Clist_modern.txt b/langpacks/french/Plugins/Clist_modern.txt
index 5906405f36..f127145f57 100644
--- a/langpacks/french/Plugins/Clist_modern.txt
+++ b/langpacks/french/Plugins/Clist_modern.txt
@@ -50,6 +50,8 @@ ATTENTION : \tDes skins peuvent modifier votre profil. Un retour ne sera pas pos
* Relancer Miranda pour valider tous les changements
[Skin folder]
+[Download more skins]
+
[Available view modes]
Mode d'affichages disponibles
[Include protocols]
diff --git a/langpacks/french/Plugins/Clist_nicer.txt b/langpacks/french/Plugins/Clist_nicer.txt
index e71160b6c1..9243f9f097 100644
--- a/langpacks/french/Plugins/Clist_nicer.txt
+++ b/langpacks/french/Plugins/Clist_nicer.txt
@@ -380,6 +380,8 @@ Décalage du haut des groupes
Hauteur de la barre de titre des cadres
[Ignore selection for groups]
Ignorer la sélection des groupes
+[Download more skins]
+
[Load from skin file]
Charger depuis un fichier de skin
[Export to skin file]
diff --git a/langpacks/french/Plugins/CloudFile.txt b/langpacks/french/Plugins/CloudFile.txt
index 8b8708a5fc..a08a2cf033 100644
--- a/langpacks/french/Plugins/CloudFile.txt
+++ b/langpacks/french/Plugins/CloudFile.txt
@@ -2,7 +2,7 @@
;============================================================
; File: CloudFile.dll
; Plugin: CloudFile
-; Version: 0.11.0.2
+; Version: 0.11.0.3
; Authors: Miranda NG Team
;============================================================
[Allows you to transfer files via cloud services.]
diff --git a/langpacks/french/Plugins/DbEditorPP.txt b/langpacks/french/Plugins/DbEditorPP.txt
index f1eae15213..c5cc4f2b2a 100644
--- a/langpacks/french/Plugins/DbEditorPP.txt
+++ b/langpacks/french/Plugins/DbEditorPP.txt
@@ -2,7 +2,7 @@
;============================================================
; File: DbEditorPP.dll
; Plugin: Database editor++
-; Version: 4.0.1.1
+; Version: 4.0.1.2
; Authors: Bio, Jonathan Gordon
;============================================================
[Advanced Database Editor.]
diff --git a/langpacks/french/Plugins/Fingerprint.txt b/langpacks/french/Plugins/Fingerprint.txt
index bc17df878d..62ab03806d 100644
--- a/langpacks/french/Plugins/Fingerprint.txt
+++ b/langpacks/french/Plugins/Fingerprint.txt
@@ -46,8 +46,6 @@
[RSS clients]
-[Tlen clients]
-
[Weather clients]
[Yahoo clients]
@@ -107,8 +105,6 @@ Protocole
[Gadu-Gadu client]
-[Tlen.pl client]
-
[Python-based clients]
[Jabber client]
@@ -139,8 +135,6 @@ Protocole
[QQ overlay]
-[Tlen.pl overlay]
-
[Yahoo overlay]
[Mail.Ru Agent overlay]
@@ -175,12 +169,6 @@ Protocole
[Gadu-Gadu v8 client]
-[Tlen 7.x overlay]
-
-[Tlen 6.x overlay]
-
-[Tlen 5.x overlay]
-
[TM/QQ 2012 overlay]
[TM/QQ 2011 overlay]
diff --git a/langpacks/french/Plugins/GmailNotifier.txt b/langpacks/french/Plugins/GmailNotifier.txt
index 7e6a150452..f3fa1f2b33 100644
--- a/langpacks/french/Plugins/GmailNotifier.txt
+++ b/langpacks/french/Plugins/GmailNotifier.txt
@@ -2,7 +2,7 @@
;============================================================
; File: GmailNotifier.dll
; Plugin: Gmail Multiple Notifier
-; Version: 0.3.1.1
+; Version: 1.0.1.1
; Authors: Mixwind
;============================================================
[Check your Gmail inboxes locally.]
@@ -57,21 +57,19 @@ secondes
;file \plugins\GmailNotifier\src\check.cpp
[Checking...]
-[Can't open Internet!]
-
-[Can't reach server!]
-
[Can't send account data!]
-[Can't get RSS feed!]
-
[Wrong name or password!]
+[Can't get RSS feed!]
+
;file \plugins\GmailNotifier\src\main.cpp
[Other]
Autre
[Gmail: New thread(s)]
+[Gmail Notifier connection]
+
[&Check all Gmail inboxes]
[&Check Gmail inbox]
diff --git a/langpacks/french/Plugins/IEView.txt b/langpacks/french/Plugins/IEView.txt
index 12d8dd4515..65831f064f 100644
--- a/langpacks/french/Plugins/IEView.txt
+++ b/langpacks/french/Plugins/IEView.txt
@@ -66,6 +66,8 @@ Voir la date
Utiliser date long format
[Use relative timestamp]
Utiliser la date relative
+[Download more templates]
+
;file \plugins\IEView\src\HistoryHTMLBuilder.cpp
[Outgoing File Transfer]
Transfert de fichiers sortants
diff --git a/langpacks/french/Plugins/MSN.txt b/langpacks/french/Plugins/MSN.txt
index f1409ec507..0dff3ea507 100644
--- a/langpacks/french/Plugins/MSN.txt
+++ b/langpacks/french/Plugins/MSN.txt
@@ -2,7 +2,7 @@
;============================================================
; File: MSN.dll
; Plugin: MSN protocol
-; Version: 0.14.0.1
+; Version: 0.14.0.2
; Authors: Boris Krasnovskiy, George Hazan, Richard Hughes, leecher
;============================================================
[Microsoft Network (MSN) protocol support for Miranda NG.]
diff --git a/langpacks/french/Plugins/New_GPG.txt b/langpacks/french/Plugins/New_GPG.txt
index 9b156345b5..acb6401c20 100644
--- a/langpacks/french/Plugins/New_GPG.txt
+++ b/langpacks/french/Plugins/New_GPG.txt
@@ -176,86 +176,6 @@ Passe actuel :
[GPG encryption status]
;file \plugins\New_GPG\src\main.cpp
-[Email]
-
-[Name]
-Nom
-[Creation date]
-
-[Expire date]
-
-[Key length]
-
-[Accounts]
-Comptes
-[Default]
-Défaut
-[key ID]
-
-[not set]
-
-[Default private key ID]
-
-[Failed to open file]
-
-[Error]
-Erreur
-[Generating new random key, please wait]
-
-[Failed to allocate memory]
-
-[Failed to lock memory with error %d]
-
-[Failed write to clipboard with error %d]
-
-[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
-
-[Warning]
-Avertissement
-[Wrong GPG binary location found in system.\nPlease choose another location]
-
-[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-
-[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-
-["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
-
-[Info]
-Info
-[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
-
-[GPG binary does not exist.\nPlease choose another location]
-
-[Please choose GPG binary location]
-
-[Please set keyring's home directory]
-
-[There is existing key for contact, would you like to replace it with new key?]
-
-[New public key was received, do you want to import it?]
-
-[Replace]
-Remplacer :
-[Accept]
-Accepter
-[Received key from %s]
-
-[You must set encryption algorithm first]
-
-[Key length must be of length from 1024 to 4096 bits]
-
-[Invalid date]
-
-[Name must contain at least 5 characters]
-
-[Name cannot contain '(' or ')']
-
-[Invalid Email]
-
-[Generating new key, please wait...]
-
-[Failed to export public key.]
-
[GPG binary is set and valid (this is good).\n]
[GPG binary unset or invalid (plugin will not work).\n]
@@ -293,6 +213,8 @@ Accepter
;file \plugins\New_GPG\src\messages.cpp
[We received encrypted message from contact with encryption turned off.\nDo you want to turn on encryption for this contact?]
+[Warning]
+Avertissement
[Do you want to try to decrypt encrypted message?]
[We're trying to encrypt with untrusted key. Do you want to trust this key permanently?]
@@ -300,22 +222,20 @@ Accepter
[Something is wrong, GPG does not understand us, aborting encryption.]
;file \plugins\New_GPG\src\options.cpp
-[Services]
-Services
-[Main]
-Principales
-[GnuPG Variables]
-
-[Messages]
-Messages
-[Advanced]
-Avancé
[Contact]
Contact
[Key ID]
+[Name]
+Nom
+[Email]
+
[Protocol]
Protocole
+[Default private key ID]
+
+[not set]
+
[This key is not used by any contact. Do you want to remove it from public keyring?]
[Key info]
@@ -332,6 +252,14 @@ info
[.asc pubkey file]
+[Failed to allocate memory]
+
+[Error]
+Erreur
+[Failed to lock memory with error %d]
+
+[Failed write to clipboard with error %d]
+
[Failed to open clipboard with error %d]
[Set log file]
@@ -340,6 +268,8 @@ info
[Choose gpg.exe]
+[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+
[Set home directory]
[Load Public GPG Key for ]
@@ -356,12 +286,83 @@ info
[Key already in secret keyring.]
+[Info]
+Info
[Set file containing GPG public key]
[GPG public key file]
+[Failed to open file]
+
[There is no public or private key.]
+[Services]
+Services
+[Main]
+Principales
+[GnuPG Variables]
+
+[Messages]
+Messages
+[Advanced]
+Avancé
+;file \plugins\New_GPG\src\ui.cpp
+[New passwords do not match]
+
+[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+
+[Creation date]
+
+[Expire date]
+
+[Key length]
+
+[Accounts]
+Comptes
+[Default]
+Défaut
+[key ID]
+
+[Generating new random key, please wait]
+
+[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
+
+[Wrong GPG binary location found in system.\nPlease choose another location]
+
+[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+
+["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
+
+[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
+
+[There is existing key for contact, would you like to replace it with new key?]
+
+[New public key was received, do you want to import it?]
+
+[Replace]
+Remplacer :
+[Accept]
+Accepter
+[Received key from %s]
+
+[You must set encryption algorithm first]
+
+[Key length must be of length from 1024 to 4096 bits]
+
+[Invalid date]
+
+[Name must contain at least 5 characters]
+
+[Name cannot contain '(' or ')']
+
+[Invalid Email]
+
+[Generating new key, please wait...]
+
+[Expiration date]
+
+[Failed to export public key.]
+
;file \plugins\New_GPG\src\utilities.cpp
[Do you want to toggle encryption for all subcontacts?]
@@ -393,7 +394,10 @@ info
[Keys import result]
-[New passwords do not match]
+[GPG binary does not exist.\nPlease choose another location]
-[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[Please choose GPG binary location]
+
+[Please set keyring's home directory]
+;file \plugins\New_GPG\src\utilities.h
diff --git a/langpacks/french/Plugins/SimpleStatusMsg.txt b/langpacks/french/Plugins/SimpleStatusMsg.txt
index fa33f5c510..4e3fcb570d 100644
--- a/langpacks/french/Plugins/SimpleStatusMsg.txt
+++ b/langpacks/french/Plugins/SimpleStatusMsg.txt
@@ -3,7 +3,7 @@
; File: SimpleStatusMsg.dll
; Plugin: Simple status message
; Version: 1.9.0.6
-; Authors: Bartosz 'Dezeath' Bialek, Harven
+; Authors: Bartosz 'Dezeath' Białek, Harven
;============================================================
[Provides a simple way to set status and away messages.]
diff --git a/langpacks/french/Plugins/SmileyAdd.txt b/langpacks/french/Plugins/SmileyAdd.txt
index 9f67b98332..154fc7dcfc 100644
--- a/langpacks/french/Plugins/SmileyAdd.txt
+++ b/langpacks/french/Plugins/SmileyAdd.txt
@@ -2,7 +2,7 @@
;============================================================
; File: SmileyAdd.dll
; Plugin: SmileyAdd
-; Version: 0.2.4.2
+; Version: 0.3.0.1
; Authors: Peacow, nightwish, bid, borkra
;============================================================
[Smiley support for Miranda NG.]
@@ -98,16 +98,14 @@ Apparence
;file \plugins\SmileyAdd\src\smileys.cpp
[Smiley pack %s for category "%s" not found.\nSelect correct smiley pack in the Options -> Customize -> Smileys.]
-[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
-Il s'est produit une erreur lors du chargement du pack de smileys (il doit être corrigé).\nLisez l'enregistrement réseau pour plus de détails.
[Smiley #%u in file %s for smiley pack %s not found.]
le smiley #%u, du fichier %s, du pack %s, est introuvable.
+[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
+Il s'est produit une erreur lors du chargement du pack de smileys (il doit être corrigé).\nLisez l'enregistrement réseau pour plus de détails.
[%s global smiley pack]
[Standard]
-[Regular expression "%s" in smiley pack "%s" could produce "empty matches".]
-L'expression régulière "%s" du pack de smileys "%s" pourrait produire des "empty matches".
[Regular expression "%s" in smiley pack "%s" malformed.]
L'expression régulière "%s" du pack de smileys "%s" est mal construite.
;file \plugins\SmileyAdd\src\smltool.cpp
diff --git a/langpacks/french/Plugins/SplashScreen.txt b/langpacks/french/Plugins/SplashScreen.txt
index af467f24b0..886ad4dc2f 100644
--- a/langpacks/french/Plugins/SplashScreen.txt
+++ b/langpacks/french/Plugins/SplashScreen.txt
@@ -38,6 +38,8 @@ ms
[Preview...]
Aperçu...
+[Download more splash screens]
+
;file \plugins\SplashScreen\src\options.cpp
[Graphic files]
diff --git a/langpacks/french/Plugins/StatusManager.txt b/langpacks/french/Plugins/StatusManager.txt
index 3f40109b82..7ee4fab5f7 100644
--- a/langpacks/french/Plugins/StatusManager.txt
+++ b/langpacks/french/Plugins/StatusManager.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StatusManager.dll
; Plugin: Status manager
-; Version: 0.11.2.3
+; Version: 1.0.1.1
; Authors: P Boon
;============================================================
[A connection checker and auto away module. Also allows you to define the status Miranda should set on startup, configurable per protocol.]
diff --git a/langpacks/french/Plugins/Steam.txt b/langpacks/french/Plugins/Steam.txt
index b665ebf76f..0de987a8c8 100644
--- a/langpacks/french/Plugins/Steam.txt
+++ b/langpacks/french/Plugins/Steam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Steam.dll
; Plugin: Steam protocol
-; Version: 0.11.6.1
+; Version: 0.11.6.3
; Authors: Miranda NG Team, Robert Pösel
;============================================================
[Steam protocol support for Miranda NG.]
diff --git a/langpacks/french/Plugins/StopSpam.txt b/langpacks/french/Plugins/StopSpam.txt
index 887c1a4f4a..37387e63fe 100644
--- a/langpacks/french/Plugins/StopSpam.txt
+++ b/langpacks/french/Plugins/StopSpam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpam.dll
; Plugin: StopSpam+
-; Version: 0.0.1.5
+; Version: 0.1.0.1
; Authors: Roman Miklashevsky, A. Petkevich, Kosh&chka, persei
;============================================================
[Anti-spam plugin for Miranda NG.]
@@ -43,6 +43,9 @@ Ajouter le contact
;file \plugins\StopSpamPlus\src\events.cpp
[StopSpam automatic message:\r\n]
+;file \plugins\StopSpamPlus\src\options.cpp
+[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
+
[Message sessions]
Sessions de message
[General]
@@ -51,15 +54,12 @@ Général
Messages
[Accounts]
Comptes
-;file \plugins\StopSpamPlus\src\options.cpp
-[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
-
;file \plugins\StopSpamPlus\src\services.cpp
[Not In List]
[Complete]
Terminé
-;file \plugins\StopSpamPlus\src\settings.h
+;file \plugins\StopSpamPlus\src\settings.cpp
[Spammers made me to install small anti-spam system you are now speaking with. Please reply "nospam" without quotes and spaces if you want to contact me.]
[StopSpam: send a message and reply to an anti-spam bot question.]
diff --git a/langpacks/french/Plugins/StopSpamMod.txt b/langpacks/french/Plugins/StopSpamMod.txt
index 9d5ab6fd81..f577cf00cc 100644
--- a/langpacks/french/Plugins/StopSpamMod.txt
+++ b/langpacks/french/Plugins/StopSpamMod.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpamMod.dll
; Plugin: StopSpam mod
-; Version: 0.0.2.1
+; Version: 0.0.2.2
; Authors: Roman Miklashevsky, sss, Elzor
;============================================================
[Anti-spam plugin for Miranda NG.]
diff --git a/langpacks/french/Plugins/TabSRMM.txt b/langpacks/french/Plugins/TabSRMM.txt
index a97768fec6..9e53deb218 100644
--- a/langpacks/french/Plugins/TabSRMM.txt
+++ b/langpacks/french/Plugins/TabSRMM.txt
@@ -516,6 +516,8 @@ Utiliser le modèle du skin (attention, ceci remplacera votre modèle)
[Import from a file...]
+[Download more skins]
+
[Icons]
Icônes
[Event type icons in the message log]
diff --git a/langpacks/french/Plugins/Tox.txt b/langpacks/french/Plugins/Tox.txt
index f4ea7f1fdf..cd0e6dcf6f 100644
--- a/langpacks/french/Plugins/Tox.txt
+++ b/langpacks/french/Plugins/Tox.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Tox.dll
; Plugin: Tox protocol
-; Version: 0.11.1.25
+; Version: 0.11.1.26
; Authors: Miranda NG Team
;============================================================
[Tox protocol support for Miranda NG.]
diff --git a/langpacks/french/Plugins/mRadio.txt b/langpacks/french/Plugins/mRadio.txt
index e3a19f3bf8..a524626c90 100644
--- a/langpacks/french/Plugins/mRadio.txt
+++ b/langpacks/french/Plugins/mRadio.txt
@@ -101,7 +101,7 @@ débit
[Sorry!]
-[BASS.DLL not found!]
+[bass.dll not found!]
[Station]
@@ -199,3 +199,5 @@ Avancé
Nouveau
[Quick Open]
+[bass.dll not found! Choose bass.dll path manually]
+
diff --git a/langpacks/french/Untranslated/=CORE=.txt b/langpacks/french/Untranslated/=CORE=.txt
index 08d40d3cae..0088d4f784 100644
--- a/langpacks/french/Untranslated/=CORE=.txt
+++ b/langpacks/french/Untranslated/=CORE=.txt
@@ -11,17 +11,9 @@
[Show in chat rooms]
[Gap between buttons:]
[Hide if there isn't enough space]
-[Added event]
-[%s added you to the contact list\n%u (%s) on %s]
-[%s added you to the contact list\n%u on %s]
-[%s added you to the contact list\n%s on %s]
-[%s requested authorization\n%u (%s) on %s]
-[%s requested authorization\n%u on %s]
-[%s requested authorization\n%s on %s]
[Re&ad status message]
[Standard crypto provider]
[This file transfer has been canceled by the other side]
-[&Support]
[Group chat log background]
[Nick list background (selected)]
[Add ':' to auto-completed user names]
@@ -63,6 +55,13 @@
[Actively searching]
[It's complicated]
[In a civil union]
+[Added event]
+[%s added you to the contact list\n%u (%s) on %s]
+[%s added you to the contact list\n%u on %s]
+[%s added you to the contact list\n%s on %s]
+[%s requested authorization\n%u (%s) on %s]
+[%s requested authorization\n%u on %s]
+[%s requested authorization\n%s on %s]
[ (set by %s on %s)]
[%s enables '%s' status for %s]
[%s disables '%s' status for %s]
@@ -89,6 +88,7 @@
[Configuration files]
[Headers]
[Generic text]
+[&Support]
[Browser: Back]
[Browser: Forward]
[Browser: Refresh]
diff --git a/langpacks/french/Untranslated/AIM.txt b/langpacks/french/Untranslated/AIM.txt
deleted file mode 100644
index 3396fa9794..0000000000
--- a/langpacks/french/Untranslated/AIM.txt
+++ /dev/null
@@ -1,118 +0,0 @@
-[Screen name:]
-[Display name:]
-[AIM options]
-[Notify about new mail]
-[Masquerade as a Sidekick/Hiptop user]
-[Connection]
-[Login server:]
-[Disable SSL]
-[Force single client]
-[Use "clientlogin" (recommended)]
-[Create a new AIM account]
-[Users who can contact me:]
-[Allow all users]
-[Allow only users on contact list]
-[Allow only users below]
-[Block all users]
-[Block only users below]
-[Allow contacts to be notified of:]
-[Join chat room]
-[Chat room]
-[This allows access to user defined chat rooms. To access predefined chat rooms use web links]
-[Original]
-[Repeat]
-[*Passwords don't match.]
-[Screen name]
-[Confirm account]
-[*Applied upon reconnect]
-[Invite buddy to chat room]
-[Invitation reason]
-[Chat room invitation request]
-[Room]
-[Me]
-[&Leave chat session]
-[User &history]
-[Invalid screen name or password.]
-[Mismatched screen name or password.]
-[Unknown error occurred when attempting to connect.]
-[Client rate limit exceeded]
-[Not while on AOL.]
-[Check your screen name.]
-[Check your password.]
-[Check your email address.]
-[Service temporarily unavailable.]
-[Field change temporarily unavailable.]
-[Invalid screen name.]
-[Invalid password.]
-[Invalid email.]
-[Invalid registration preference.]
-[Invalid old password.]
-[Invalid screen name Length.]
-[Invalid password length.]
-[Invalid email length.]
-[Invalid old password length.]
-[Need old password.]
-[Read only field.]
-[Write only field.]
-[Unsupported type.]
-[An error has occurred.]
-[Invalid account.]
-[Deleted account.]
-[Expired account.]
-[No database access.]
-[Invalid database fields.]
-[Bad database status.]
-[Migration cancel.]
-[Internal error.]
-[There is already a pending request for this screen name.]
-[Not DT status.]
-[Outstanding confirmation.]
-[No email address.]
-[Over limit.]
-[Email host fail.]
-[DNS fail.]
-[Failed to open file: %s : %s]
-[Open mail account?]
-[Contact tried to open an audio/video conference (not currently supported)]
-[Error adding buddy (invalid ID or already in list?)]
-[Unknown error when adding buddy to list. Error code %#x]
-[Unknown error when attempting to modify a group. Error code %#x]
-[You've got mail! Checked at]
-[Error uploading avatar. (Too small)]
-[Error uploading avatar. (Too big)]
-[Error uploading avatar. (Wrong type)]
-[Error uploading avatar. (Is banned)]
-[Error uploading avatar. (Unknown error)]
-[A confirmation message has been sent to the new email address. Please follow its instructions.]
-[A confirmation message has been sent to your email address. Please follow its instructions.]
-[Unable to confirm at this time. Please try again later.]
-[Your account has already been confirmed.]
-[Can't start the confirmation procedure.]
-[AOL mail]
-[AIM icon]
-[Hiptop]
-[AOL bot]
-[Admin]
-[Confirmed]
-[Not confirmed]
-[Blocked list]
-[Foreground color]
-[Not bold]
-[Italic]
-[Not italic]
-[Underline]
-[Not underline]
-[Subscript]
-[Not subscript]
-[Superscript]
-[Not superscript]
-[Normal script]
-[Not normal script]
-[Profile editor]
-[AIM account type]
-[AIM extended status]
-[&Block]
-[&Unblock]
-[Privacy]
-[Join me in this buddy chat!]
-[Failed to open file: %s %s]
diff --git a/langpacks/french/Untranslated/BASS_interface.txt b/langpacks/french/Untranslated/BASS_interface.txt
index 2d0782bd7a..f0f6534acf 100644
--- a/langpacks/french/Untranslated/BASS_interface.txt
+++ b/langpacks/french/Untranslated/BASS_interface.txt
@@ -1,17 +1,18 @@
-[un4seen's BASS interface Miranda NG plugin.]
-[un4seen's bass interface]
+[Un4seen's BASS interface Miranda NG plugin.]
+[Un4seen's BASS interface]
[bass.dll loading error]
[Current bass.dll path:]
-[Maximum number of bass internal channels:]
+[Maximum number of BASS internal channels:]
[Output device:]
[Volume:]
[Quiet time:]
-[download bass library]
+[download BASS library]
[Play only if]
-[un4seen's bass version: %d.%d.%d.%d]
+[Un4seen's BASS version: %d.%d.%d.%d]
[--default device--]
[Enable sounds]
[Frame background]
+[BASS Interface]
[Bass Interface]
[Bass library]
[Sounds enabled]
diff --git a/langpacks/french/Untranslated/BasicHistory.txt b/langpacks/french/Untranslated/BasicHistory.txt
index c47c119dbd..c3ce83a43c 100644
--- a/langpacks/french/Untranslated/BasicHistory.txt
+++ b/langpacks/french/Untranslated/BasicHistory.txt
@@ -1,8 +1,8 @@
[History viewer for Miranda NG.]
[Always show contact list]
[Show groups in contact list]
-[Do not show Find control border]
-[Default Event Filter]
+[Do not show find control border]
+[Default event filter]
[Custom filters]
[Add filter]
[Delete filter]
@@ -17,18 +17,18 @@
[Limit messages to:]
[Show date in timestamps]
[Show seconds in timestamps]
-[Enable Smileys]
+[Enable smileys]
[Search forward in list group]
[Search forward in message window]
-[Match Case]
-[Match Whole Word]
-[Only Incoming Messages]
-[Only Outgoing Messages]
-[Only Selected Group]
-[Export To Txt]
+[Match case]
+[Match whole word]
+[Only incoming messages]
+[Only outgoing messages]
+[Only selected group]
+[Export to txt]
[File encoding*]
-[Export To Plain Html]
-[Export To Rich Html]
+[Export to plain HTML]
+[Export to rich HTML]
[* Choose encoding from combo box or enter code page number and name separated by semicolon, name is used in Content-Type header.]
[Add task]
[Edit task]
@@ -50,25 +50,25 @@
[Export imported messages]
[* Use negative values to filter younger events]
[Execute task for specified contacts]
-[Delete All User History]
+[Delete all user history]
[Execute history task]
-[Show Contacts]
-[Hide Contacts]
+[Show contacts]
+[Hide contacts]
[Plus in export]
[Minus in export]
[Default history events]
[Me]
-[%s Files (*.%s)]
+[%s files (*.%s)]
[Import]
[Export]
[File does not contain selected contact]
[File is corrupted]
[This operation will PERMANENTLY REMOVE all history for this contact.\nAre you sure you want to do this?]
[Do you want to delete all imported messages for this contact?\nNote that next scheduler task import this messages again.]
-[Send Message]
+[Send message]
[Filters]
-[Rich Html]
-[Plain Html]
+[Rich HTML]
+[Plain HTML]
[Txt]
[Binary]
[Dat (mContacts)]
@@ -94,17 +94,17 @@
[Find window background]
[Window background]
[Open global history]
-[Switch Match Case]
-[Switch Match Whole Word]
-[Show/Hide Contacts]
-[Switch Only Incoming Messages]
-[Switch Only Outgoing Messages]
-[Switch Only Selected Group]
-[Switch All Contacts]
-[Export To Binary]
-[Import From Binary]
-[Export To Dat (mContacts)]
-[Import From Dat (mContacts)]
+[Switch match case]
+[Switch match whole word]
+[Show/hide contacts]
+[Switch only incoming messages]
+[Switch only outgoing messages]
+[Switch only selected group]
+[Switch all contacts]
+[Export to binary]
+[Import from binary]
+[Export to dat (mContacts)]
+[Import from dat (mContacts)]
[Invalid event number]
[File does not exist. Enter correct file path.]
[Invalid file]
@@ -114,12 +114,12 @@
[Browse WinSCP file]
[Save WinSCP log file]
[Browse CSS file]
-[Export and Delete]
-[Import and Merge]
+[Export and delete]
+[Import and merge]
[Minute]
[Hour]
-[At Start]
-[At Finish]
+[At start]
+[At finish]
[Daily]
[Weekly]
[Monthly]
@@ -141,7 +141,7 @@
[Download from FTP (WinSCP requred)]
[Import from]
[** Use <date> to insert date, <ext> to insert extension, <contact> to insert contact name]
-[History Log]
+[History log]
[Filter:]
[Conversation started at %s]
[Open all]
diff --git a/langpacks/french/Untranslated/Clist_modern.txt b/langpacks/french/Untranslated/Clist_modern.txt
index 3a6ee00453..e96d1273af 100644
--- a/langpacks/french/Untranslated/Clist_modern.txt
+++ b/langpacks/french/Untranslated/Clist_modern.txt
@@ -1,6 +1,7 @@
[Tile vertically according to row height]
[Rescan]
[Skin folder]
+[Download more skins]
[Sticky contacts]
[Editing view mode]
[[Ctrl]+[Left Click] to filter only protocol. Click on empty space to show all.]
diff --git a/langpacks/french/Untranslated/Clist_nicer.txt b/langpacks/french/Untranslated/Clist_nicer.txt
index 0b1fb5a4c0..857e32c426 100644
--- a/langpacks/french/Untranslated/Clist_nicer.txt
+++ b/langpacks/french/Untranslated/Clist_nicer.txt
@@ -5,6 +5,7 @@
[Tree gray out]
[Sticky contacts]
[Editing view mode]
+[Download more skins]
[Setup accounts]
[Overlay icons]
[Connecting icons]
diff --git a/langpacks/french/Untranslated/Fingerprint.txt b/langpacks/french/Untranslated/Fingerprint.txt
index ce049989d2..03635337f3 100644
--- a/langpacks/french/Untranslated/Fingerprint.txt
+++ b/langpacks/french/Untranslated/Fingerprint.txt
@@ -18,7 +18,6 @@
[MSN clients]
[QQ clients]
[RSS clients]
-[Tlen clients]
[Weather clients]
[Yahoo clients]
[Facebook clients]
@@ -45,7 +44,6 @@
[Mail.Ru (unknown client)]
[TM 2008 and >]
[Gadu-Gadu client]
-[Tlen.pl client]
[Python-based clients]
[Jabber client]
[XMPP client]
@@ -61,7 +59,6 @@
[Jabber overlay]
[MSN overlay]
[QQ overlay]
-[Tlen.pl overlay]
[Yahoo overlay]
[Mail.Ru Agent overlay]
[VK overlay]
@@ -79,9 +76,6 @@
[Gadu-Gadu v10 client]
[Gadu-Gadu v9 client]
[Gadu-Gadu v8 client]
-[Tlen 7.x overlay]
-[Tlen 6.x overlay]
-[Tlen 5.x overlay]
[TM/QQ 2012 overlay]
[TM/QQ 2011 overlay]
[TM/QQ 2010 overlay]
diff --git a/langpacks/french/Untranslated/GmailNotifier.txt b/langpacks/french/Untranslated/GmailNotifier.txt
index 565df7f476..d8e3b5819f 100644
--- a/langpacks/french/Untranslated/GmailNotifier.txt
+++ b/langpacks/french/Untranslated/GmailNotifier.txt
@@ -15,12 +15,11 @@
[This is a shared computer so disable auto login]
[Log unread threads into database (enable history)]
[Checking...]
-[Can't open Internet!]
-[Can't reach server!]
[Can't send account data!]
-[Can't get RSS feed!]
[Wrong name or password!]
+[Can't get RSS feed!]
[Gmail: New thread(s)]
+[Gmail Notifier connection]
[&Check all Gmail inboxes]
[&Check Gmail inbox]
[GmailNotifier]
diff --git a/langpacks/french/Untranslated/IEView.txt b/langpacks/french/Untranslated/IEView.txt
index d72c220c17..f0790c2930 100644
--- a/langpacks/french/Untranslated/IEView.txt
+++ b/langpacks/french/Untranslated/IEView.txt
@@ -3,6 +3,7 @@
[Enable BBCodes]
[Embed YouTube videos]
[Mode]
+[Download more templates]
[URL sent]
[URL received]
[ was added.]
diff --git a/langpacks/french/Untranslated/New_GPG.txt b/langpacks/french/Untranslated/New_GPG.txt
index 3b397e4e11..9c2491d26a 100644
--- a/langpacks/french/Untranslated/New_GPG.txt
+++ b/langpacks/french/Untranslated/New_GPG.txt
@@ -73,38 +73,6 @@
[Export GPG Public keys]
[Import GPG Public keys]
[GPG encryption status]
-[Email]
-[Creation date]
-[Expire date]
-[Key length]
-[key ID]
-[not set]
-[Default private key ID]
-[Failed to open file]
-[Generating new random key, please wait]
-[Failed to allocate memory]
-[Failed to lock memory with error %d]
-[Failed write to clipboard with error %d]
-[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
-[Wrong GPG binary location found in system.\nPlease choose another location]
-[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
-[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
-[GPG binary does not exist.\nPlease choose another location]
-[Please choose GPG binary location]
-[Please set keyring's home directory]
-[There is existing key for contact, would you like to replace it with new key?]
-[New public key was received, do you want to import it?]
-[Received key from %s]
-[You must set encryption algorithm first]
-[Key length must be of length from 1024 to 4096 bits]
-[Invalid date]
-[Name must contain at least 5 characters]
-[Name cannot contain '(' or ')']
-[Invalid Email]
-[Generating new key, please wait...]
-[Failed to export public key.]
[GPG binary is set and valid (this is good).\n]
[GPG binary unset or invalid (plugin will not work).\n]
[Home dir write access granted (this is good).\n]
@@ -126,8 +94,10 @@
[Do you want to try to decrypt encrypted message?]
[We're trying to encrypt with untrusted key. Do you want to trust this key permanently?]
[Something is wrong, GPG does not understand us, aborting encryption.]
-[GnuPG Variables]
[Key ID]
+[Email]
+[Default private key ID]
+[not set]
[This key is not used by any contact. Do you want to remove it from public keyring?]
[Key info]
[we have secret key for this public key, do not removing from GPG keyring]
@@ -135,10 +105,14 @@
[Do you want to remove key from entire metacontact (all subcontacts)?]
[Export public key]
[.asc pubkey file]
+[Failed to allocate memory]
+[Failed to lock memory with error %d]
+[Failed write to clipboard with error %d]
[Failed to open clipboard with error %d]
[Set log file]
[LOG files]
[Choose gpg.exe]
+[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
[Set home directory]
[Load Public GPG Key for ]
[Turn off encryption]
@@ -149,7 +123,33 @@
[Key already in secret keyring.]
[Set file containing GPG public key]
[GPG public key file]
+[Failed to open file]
[There is no public or private key.]
+[GnuPG Variables]
+[New passwords do not match]
+[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[Creation date]
+[Expire date]
+[Key length]
+[key ID]
+[Generating new random key, please wait]
+[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
+[Wrong GPG binary location found in system.\nPlease choose another location]
+[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
+[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
+[There is existing key for contact, would you like to replace it with new key?]
+[New public key was received, do you want to import it?]
+[Received key from %s]
+[You must set encryption algorithm first]
+[Key length must be of length from 1024 to 4096 bits]
+[Invalid date]
+[Name must contain at least 5 characters]
+[Name cannot contain '(' or ')']
+[Invalid Email]
+[Generating new key, please wait...]
+[Expiration date]
+[Failed to export public key.]
[Do you want to toggle encryption for all subcontacts?]
[Turn off GPG encryption]
[Turn on GPG encryption]
@@ -165,5 +165,6 @@
[We have successfully processed %d public keys and some private keys.]
[We have successfully processed %d public keys.]
[Keys import result]
-[New passwords do not match]
-[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[GPG binary does not exist.\nPlease choose another location]
+[Please choose GPG binary location]
+[Please set keyring's home directory]
diff --git a/langpacks/french/Untranslated/SplashScreen.txt b/langpacks/french/Untranslated/SplashScreen.txt
index 860f334129..bb5779b0d5 100644
--- a/langpacks/french/Untranslated/SplashScreen.txt
+++ b/langpacks/french/Untranslated/SplashScreen.txt
@@ -8,5 +8,6 @@
[steps]
[Fade out:]
[AdvaImg plugin not found. Please get it from https://miranda-ng.org/p/AdvaImg/ to be able to use images.]
+[Download more splash screens]
[Graphic files]
[Splash Screen]
diff --git a/langpacks/french/Untranslated/TabSRMM.txt b/langpacks/french/Untranslated/TabSRMM.txt
index eae36b7818..10ba6c52b7 100644
--- a/langpacks/french/Untranslated/TabSRMM.txt
+++ b/langpacks/french/Untranslated/TabSRMM.txt
@@ -100,6 +100,7 @@
[You can export and import all your color and font settings here. This allows you to create a Theme file which can be shared between different profiles or with your buddies.]
[Export to a file...]
[Import from a file...]
+[Download more skins]
[Event type icons in the message log]
[Text symbols as event markers]
[Show timestamps]
diff --git a/langpacks/french/Untranslated/mRadio.txt b/langpacks/french/Untranslated/mRadio.txt
index 55a4276553..300cec4ded 100644
--- a/langpacks/french/Untranslated/mRadio.txt
+++ b/langpacks/french/Untranslated/mRadio.txt
@@ -45,7 +45,7 @@
[Continuous record]
[Quarry]
[Sorry!]
-[BASS.DLL not found!]
+[bass.dll not found!]
[Station]
[Custom INI file]
[Radio station URL]
@@ -91,3 +91,4 @@
[Device list]
[Equalizer]
[Quick Open]
+[bass.dll not found! Choose bass.dll path manually]
diff --git a/langpacks/german/=CORE=.txt b/langpacks/german/=CORE=.txt
index 3a8b73a663..e848339091 100644
--- a/langpacks/german/=CORE=.txt
+++ b/langpacks/german/=CORE=.txt
@@ -3,29 +3,6 @@
; Module: Miranda Core
; Version: 0.95.8
;============================================================
-;file \src\core\stdauth\res\resource.rc
-[Authorization request]
-Autorisierungsanfrage
-[&Authorize]
-&Autorisieren
-[&Deny]
-&Ablehnen
-[Decide &later]
-&Später entscheiden
-[User &details]
-Kontakt&profil
-[Reason:]
-Grund:
-[Denial reason:]
-Grund der Ablehnung:
-[Add to contact list if authorized]
-Zur Kontaktliste hinzufügen, falls autorisiert
-[You were added]
-Sie wurden hinzugefügt
-[&Close]
-S&chließen
-[&Add]
-&Hinzufügen
;file \src\core\stdaway\res\resource.rc
[%s message for %s]
'%s'-Nachricht von %s
@@ -291,6 +268,8 @@ Gesamtgröße:
Beschreibung:
[&User menu]
&Kontaktmenü
+[User &details]
+Kontakt&profil
[&History]
&Verlauf
[Incoming file transfer]
@@ -307,6 +286,8 @@ Datum:
Dateien:
[Save to:]
Speichern nach:
+[&Add]
+&Hinzufügen
[&Open...]
&Öffnen...
[Open &folder]
@@ -395,11 +376,6 @@ Nachfragen
Umbenennen (Zusatz: (1), (2), ...)
[You will always be asked about files from people not on your contact list]
Beim Empfang von unbekannten Kontakten wird immer nachgefragt.
-;file \src\core\stdhelp\res\resource.rc
-[About Miranda NG]
-Über Miranda NG
-[Credits >]
-Dank an >
;file \src\core\stdidle\res\resource.rc
[Become idle if the following is left unattended:]
Untätig werden, wenn keine Aktion innerhalb von:
@@ -723,6 +699,8 @@ Chatfenster des Kontaktes öffnen
Eigener Name:
[Group:]
Gruppe:
+[Authorization request]
+Autorisierungsanfrage
[&Yes]
&Ja
[&No]
@@ -999,6 +977,8 @@ Warnung!\r\nDieses Menüobjekt kann nicht vom Benutzer angepasst werden!
Untermenü einfügen
[Insert separator]
Trennlinie einfügen
+[Module:]
+Modul:
[Service:]
Dienst:
[Default]
@@ -1133,6 +1113,26 @@ In Gruppenchats anzeigen
Schaltflächenabstand:
[Hide if there isn't enough space]
Verstecken, wenn nicht genügend Platz
+[&Authorize]
+&Autorisieren
+[&Deny]
+&Ablehnen
+[Decide &later]
+&Später entscheiden
+[Reason:]
+Grund:
+[Denial reason:]
+Grund der Ablehnung:
+[Add to contact list if authorized]
+Zur Kontaktliste hinzufügen, falls autorisiert
+[You were added]
+Sie wurden hinzugefügt
+[&Close]
+S&chließen
+[About Miranda NG]
+Über Miranda NG
+[Credits >]
+Dank an >
[Tray]
Tray
[&Hide/Show]
@@ -1193,42 +1193,6 @@ Wikipedia (en)
Google Maps
[Google Translate]
Google Translate
-;file \src\core\stdauth\src\auth.cpp
-[%s requests authorization]
-%s fragt nach Autorisierung
-[%u requests authorization]
-%u fragt nach Autorisierung
-[%s added you to their contact list]
-%s fügte Sie zu seiner Kontaktliste hinzu
-[%u added you to their contact list]
-%u fügte Sie zu seiner Kontaktliste hinzu
-[Alerts]
-Hinweis
-[Added event]
-Sie wurden von jemandem hinzugefügt
-;file \src\core\stdauth\src\authdialogs.cpp
-[View user's details]
-Kontaktprofil anzeigen
-[Add contact permanently to list]
-Kontakt dauerhaft zur Liste hinzufügen
-[<Unknown>]
-<Unbekannt>
-[%s added you to the contact list\n%u (%s) on %s]
-%s hat Sie zu Ihrer Kontaktliste hinzugefügt\n%u (%s) in %s
-[%s added you to the contact list\n%u on %s]
-%s hat Sie zu Ihrer Kontaktliste hinzugefügt\n%u in %s
-[%s added you to the contact list\n%s on %s]
-%s hat Sie zu Ihrer Kontaktliste hinzugefügt\n%s in %s
-[(Unknown)]
-(Unbekannt)
-[%s requested authorization\n%u (%s) on %s]
-%s fragt nach einer Autorisierung\n%u (%s) unter %s
-[%s requested authorization\n%u on %s]
-%s fragt nach einer Autorisierung\n%u unter %s
-[%s requested authorization\n%s on %s]
-%s fragt nach einer Autorisierung\n%s unter %s
-[Feature is not supported by protocol]
-Diese Funktion wird durch dieses Protokoll nicht unterstützt
;file \src\core\stdaway\src\awaymsg.cpp
[Re&ad %s message]
'%s'-N&achricht lesen
@@ -1351,6 +1315,10 @@ Ereignisse
Ordner wählen
[My received files]
Meine empfangenen Dateien
+[Add contact permanently to list]
+Kontakt dauerhaft zur Liste hinzufügen
+[View user's details]
+Kontaktprofil anzeigen
[View user's history]
Verlauf anzeigen
[User menu]
@@ -1418,20 +1386,6 @@ Untersuche auf Viren...
;file \src\core\stdfile\src\ftmanager.cpp
[Outgoing]
Ausgehend
-;file \src\core\stdhelp\src\about.cpp
-[< Copyright]
-< Copyright
-;file \src\core\stdhelp\src\help.cpp
-[&Help]
-&Hilfe
-[&About...]
-&Über...
-[&Support]
-Hilfe&seite
-[&Miranda NG homepage]
-&Miranda-NG-Webseite
-[&Report bug]
-Fehle&r melden
;file \src\core\stdidle\src\idle.cpp
[Idle]
Untätigkeit
@@ -1907,11 +1861,43 @@ Mein Profil än&dern...
;file \src\core\stduseronline\src\useronline.cpp
[%s is online]
%s ist online
+[Alerts]
+Hinweis
;file \src\mir_app\src\addcontact.cpp
[Add %s]
%s hinzufügen
[Please authorize my request and add me to your contact list.]
Bitte autorisieren Sie mich und fügen Sie mich Ihrer Kontaktliste hinzu.
+;file \src\mir_app\src\auth.cpp
+[%s requests authorization]
+%s fragt nach Autorisierung
+[%u requests authorization]
+%u fragt nach Autorisierung
+[%s added you to their contact list]
+%s fügte Sie zu seiner Kontaktliste hinzu
+[%u added you to their contact list]
+%u fügte Sie zu seiner Kontaktliste hinzu
+[Added event]
+Sie wurden von jemandem hinzugefügt
+;file \src\mir_app\src\authdialogs.cpp
+[<Unknown>]
+<Unbekannt>
+[%s added you to the contact list\n%u (%s) on %s]
+%s hat Sie zu Ihrer Kontaktliste hinzugefügt\n%u (%s) in %s
+[%s added you to the contact list\n%u on %s]
+%s hat Sie zu Ihrer Kontaktliste hinzugefügt\n%u in %s
+[%s added you to the contact list\n%s on %s]
+%s hat Sie zu Ihrer Kontaktliste hinzugefügt\n%s in %s
+[(Unknown)]
+(Unbekannt)
+[%s requested authorization\n%u (%s) on %s]
+%s fragt nach einer Autorisierung\n%u (%s) unter %s
+[%s requested authorization\n%u on %s]
+%s fragt nach einer Autorisierung\n%u unter %s
+[%s requested authorization\n%s on %s]
+%s fragt nach einer Autorisierung\n%s unter %s
+[Feature is not supported by protocol]
+Diese Funktion wird durch dieses Protokoll nicht unterstützt
;file \src\mir_app\src\chat_clist.cpp
[&Join chat]
Chat &betreten
@@ -2200,6 +2186,19 @@ Kopfzeilen
Allgemeiner Text
[Small text]
Kleiner Text
+;file \src\mir_app\src\help.cpp
+[< Copyright]
+< Copyright
+[&Help]
+&Hilfe
+[&About...]
+&Über...
+[&Support]
+Hilfe&seite
+[&Miranda NG homepage]
+&Miranda-NG-Webseite
+[&Report bug]
+Fehle&r melden
;file \src\mir_app\src\hotkey_opts.cpp
[Browser: Back]
Browser: Zurück
diff --git a/langpacks/german/=HEAD=.txt b/langpacks/german/=HEAD=.txt
index 42304debcb..e57a9c454a 100644
--- a/langpacks/german/=HEAD=.txt
+++ b/langpacks/german/=HEAD=.txt
@@ -4,7 +4,7 @@ Locale: 0407
Authors: Wishmaster, TuxX
; Miranda-im.de Projekt Sprachdatei - diverse Autoren
Author-email: wishmaster51 at googlemail.com
-Last-Modified-Using: Miranda NG 0.95.7
+Last-Modified-Using: Miranda NG 0.95.8
; License: Creative Commons 3.0 (Attribution-Noncommercial-Share Alike)
; basiert auf deutsche Sprachdatei für Miranda IM
; Author-email: sprachdatei@miranda-im.de (original authors Herzog, Lastwebpage, CHEF-KOCH and more)
diff --git a/langpacks/german/Plugins/AIM.txt b/langpacks/german/Deprecated/AIM.txt
index 5dc9a30be7..5dc9a30be7 100644
--- a/langpacks/german/Plugins/AIM.txt
+++ b/langpacks/german/Deprecated/AIM.txt
diff --git a/langpacks/german/Plugins/AddContactPlus.txt b/langpacks/german/Plugins/AddContactPlus.txt
index ef08a5adbc..8b5e7b1c5b 100644
--- a/langpacks/german/Plugins/AddContactPlus.txt
+++ b/langpacks/german/Plugins/AddContactPlus.txt
@@ -3,7 +3,7 @@
; File: AddContactPlus.dll
; Plugin: Add contact+
; Version: 0.9.9.2
-; Authors: Bartosz 'Dezeath' Bialek
+; Authors: Bartosz 'Dezeath' Białek
;============================================================
[Provides the ability to quickly add new contacts.]
Möglichkeit, neue Kontakte schnell hinzuzufügen.
diff --git a/langpacks/german/Plugins/AssocMgr.txt b/langpacks/german/Plugins/AssocMgr.txt
index fe4ac47531..eff370523d 100644
--- a/langpacks/german/Plugins/AssocMgr.txt
+++ b/langpacks/german/Plugins/AssocMgr.txt
@@ -5,8 +5,8 @@
; Version: 0.2.1.0
; Authors: H. Herkenrath
;============================================================
-[Handles file type associations and URLs like aim, gg, mirpu, tlen, wpmsg, xmpp, ymsgr.]
-Verwaltet Verknüpfungen mit Dateien und URLs wie aim, gg, mirpu, tlen, wpmsg, xmpp, ymsgr.
+[Handles file type associations and URLs like aim, gg, mirpu, wpmsg, xmpp, ymsgr.]
+Verwaltet Verknüpfungen mit Dateien und URLs wie aim, gg, mirpu, wpmsg, xmpp, ymsgr.
;file \plugins\AssocMgr\res\resource.rc
[Registered associations for Miranda NG:]
Mit Miranda NG registrierte Verknüpfungen:
diff --git a/langpacks/german/Plugins/BASS_interface.txt b/langpacks/german/Plugins/BASS_interface.txt
index 1d207c9f12..3aab4f4393 100644
--- a/langpacks/german/Plugins/BASS_interface.txt
+++ b/langpacks/german/Plugins/BASS_interface.txt
@@ -1,20 +1,20 @@
#muuid {2f07ea05-05b5-4ff0-875d-c590da2ddac1}
;============================================================
; File: BASS_interface.dll
-; Plugin: BASS interface
+; Plugin: BASS Interface
; Version: 0.0.0.14
; Authors: tico-tico
;============================================================
-[un4seen's BASS interface Miranda NG plugin.]
-un4seen's BASS interface Plugin für Miranda NG.
+[Un4seen's BASS interface Miranda NG plugin.]
+Un4seen's BASS interface Plugin für Miranda NG.
;file \plugins\BASS_interface\res\Bass.rc
-[un4seen's bass interface]
-un4seen's BASS Interface
+[Un4seen's BASS interface]
+Un4seen's BASS Interface
[bass.dll loading error]
-Fehler beim Laden der BASS.dll
+Fehler beim Laden der bass.dll
[Current bass.dll path:]
-Aktuelles Verzeichnis der BASS.dll:
-[Maximum number of bass internal channels:]
+Aktuelles Verzeichnis der bass.dll:
+[Maximum number of BASS internal channels:]
Maximum an internen aktivierten Lautsprechern
[Output device:]
Ausgabegerät:
@@ -22,7 +22,7 @@ Ausgabegerät:
Lautstärke
[Quiet time:]
Ruhezeit:
-[download bass library]
+[download BASS library]
Herunterladen der BASS-Bibliothek
[Play only if]
Spiele nur, wenn:
@@ -49,8 +49,8 @@ Zum Essen
[Preview]
Vorschau
;file \plugins\BASS_interface\src\Main.cpp
-[un4seen's bass version: %d.%d.%d.%d]
-Un4seen's Bass Version: %d.%d.%d.%d
+[Un4seen's BASS version: %d.%d.%d.%d]
+Un4seen's BASS Version: %d.%d.%d.%d
[--default device--]
Standard-Ausgabegerät
[Sounds]
@@ -61,10 +61,12 @@ Klänge deaktivieren
Klänge aktivieren
[Frame background]
Frame-Hintergrund
+[BASS Interface]
+BASS-Schnittstelle
[Bass Interface]
-Bass-Schnittstelle
+BASS-Schnittstelle
[Bass library]
-Bass-Bibliothek
+BASS-Bibliothek
[Sounds enabled]
Klänge aktiviert
[Sounds disabled]
diff --git a/langpacks/german/Plugins/BasicHistory.txt b/langpacks/german/Plugins/BasicHistory.txt
index 1789fc0503..7e42057b72 100644
--- a/langpacks/german/Plugins/BasicHistory.txt
+++ b/langpacks/german/Plugins/BasicHistory.txt
@@ -8,7 +8,7 @@
[History viewer for Miranda NG.]
Verlaufsbetrachter für Miranda NG.
;file \plugins\BasicHistory\res\BasicHistory.rc
-[Message History]
+[Message history]
Nachrichtenverlauf
[Settings]
Einstellungen
@@ -16,9 +16,9 @@ Einstellungen
Immer Kontaktliste anzeigen
[Show groups in contact list]
Gruppen in Kontaktliste anzeigen
-[Do not show Find control border]
+[Do not show find control border]
Rahmen um Finde-Feld nicht anzeigen
-[Default Event Filter]
+[Default event filter]
Standard Ereignisfilter
[Custom filters]
Eigene Filter
@@ -56,31 +56,31 @@ Limitiere Nachrichten auf:
Datum im Zeitstempel anzeigen
[Show seconds in timestamps]
Sekunden im Zeitstempel anzeigen
-[Enable Smileys]
+[Enable smileys]
Smileys aktivieren
[Search forward in list group]
Vorwärtssuche in gelisteten Gruppen
[Search forward in message window]
Vorwärtssuche im Nachrichtenfenster
-[Match Case]
+[Match case]
Groß-/Kleinschreibung
-[Match Whole Word]
+[Match whole word]
Ganzes Wort berücksichtigen
-[Only Incoming Messages]
+[Only incoming messages]
Nur eingehende Nachrichten
-[Only Outgoing Messages]
+[Only outgoing messages]
Nur ausgehende Nachrichten
-[Only Selected Group]
+[Only selected group]
Nur ausgewählte Gruppen
-[All Contacts]
+[All contacts]
Alle Kontakte
-[Export To Txt]
+[Export to txt]
Als Text exportieren
[File encoding*]
Datei-Encoding*
-[Export To Plain Html]
+[Export to plain HTML]
Als Plain-HTML exportieren
-[Export To Rich Html]
+[Export to rich HTML]
Als Rich-HTML exportieren
[External CSS file]
Externe CSS-Datei
@@ -141,9 +141,9 @@ Abbrechen
;file \plugins\BasicHistory\src\BasicHistory.cpp
[Open History]
Verlauf öffnen
-[View &History]
+[View &history]
Verlauf anzeigen
-[Delete All User History]
+[Delete all user history]
Kompletten Benutzerverlauf löschen
[Execute history task]
Verlaufs-Aktion ausführen
@@ -153,13 +153,13 @@ Eingehende Nachricht
Ausgehende Nachricht
[Status change]
Statuswechsel
-[Show Contacts]
+[Show contacts]
Kontakte anzeigen
-[Hide Contacts]
+[Hide contacts]
Kontakte verstecken
-[Find Next]
+[Find next]
Finde nächste
-[Find Previous]
+[Find previous]
Finde vorherige
[Plus in export]
Plus in Export
@@ -178,10 +178,10 @@ Verlauf von %s
System
[Me]
Ich
-[Invalid Message]
+[Invalid message]
Ungültige Nachricht
;file \plugins\BasicHistory\src\ExportManager.cpp
-[%s Files (*.%s)]
+[%s files (*.%s)]
%s-Dateien (*.%s)
[Import]
Importieren
@@ -194,8 +194,8 @@ Datei ist beschädigt.
;file \plugins\BasicHistory\src\HistoryWindow.cpp
[This operation will PERMANENTLY REMOVE all history for this contact.\nAre you sure you want to do this?]
Diese Operation wird alle Verlaufseinträge für diesen Kontakt DAUERHAFT LÖSCHEN.\nSind Sie sich sicher, dass Sie dies machen wollen?
-[Are You sure?]
-Sind Sie sicher?
+[Are you sure?]
+Sind Sie sich sicher?
[Do you want to delete all imported messages for this contact?\nNote that next scheduler task import this messages again.]
Wollen Sie alle importierten Nachrichten für diesen Kontakt löschen?\nBeachten Sie, dass der nächste Sheduler-Task diese Nachrichten wieder importiert.
[Open in &new window]
@@ -208,11 +208,11 @@ Link kopieren
Kopieren
[Delete]
Löschen
-[Send Message]
+[Send message]
Nachricht senden
-[Reply &Quoted]
+[Reply &quoted]
Mit Zitat antworten
-[Delete Group]
+[Delete group]
Gruppe löschen
[Options]
Einstellungen
@@ -224,9 +224,9 @@ Schriften && Farben
Icons
[Hotkeys]
Hotkeys
-[Rich Html]
+[Rich HTML]
Erweitertes HTML
-[Plain Html]
+[Plain HTML]
Reines HTML
[Txt]
Text
@@ -301,27 +301,27 @@ Kontaktlisten-Hintergrund
Globalen Verlauf öffnen
[Find]
Suchen
-[Switch Match Case]
+[Switch match case]
Wechsel zu Groß-/Kleinschreibung
-[Switch Match Whole Word]
+[Switch match whole word]
Wechsel zu ganzes Wort
-[Show/Hide Contacts]
+[Show/hide contacts]
Zeige/Verstecke Kontakte
-[Switch Only Incoming Messages]
+[Switch only incoming messages]
Wechsel zu eingehende Nachrichten
-[Switch Only Outgoing Messages]
+[Switch only outgoing messages]
Wechsel zu ausgehende Nachrichten
-[Switch Only Selected Group]
+[Switch only selected group]
Wechsel zu 'Nur ausgewählte Gruppen'
-[Switch All Contacts]
+[Switch all contacts]
Alle Kontakte wechseln
-[Export To Binary]
+[Export to binary]
Als Binär exportieren
-[Import From Binary]
+[Import from binary]
Aus Binär exportieren
-[Export To Dat (mContacts)]
+[Export to dat (mContacts)]
Als Dat exportieren (mContacts)
-[Import From Dat (mContacts)]
+[Import from dat (mContacts)]
Aus Dat importieren (mContacts)
[Invalid event number]
Falsche Eventnummer
@@ -333,7 +333,7 @@ Ausgehende Ereignisse
Datei existiert nicht. Geben Sie den richtigen Pfad ein.
[Invalid file]
Ungültige Datei
-[All Files (*.*)]
+[All files (*.*)]
Alle Dateien (*.*)
[Enter filter name]
Filtername eingeben
@@ -351,17 +351,17 @@ Sie haben eine falsche Kodierung gewählt. Bitte wählen Sie aus dem Listenfeld
Falsche Kodierung
[Browse CSS file]
CSS-Datei auswählen
-[Export and Delete]
+[Export and delete]
Exportieren und Löschen
-[Import and Merge]
+[Import and merge]
Importieren und Zusammenführen
[Minute]
Minute
[Hour]
Stunde
-[At Start]
+[At start]
Beim Start
-[At Finish]
+[At finish]
Beim Beenden
[Daily]
Täglich
@@ -407,7 +407,7 @@ Importiere aus
** Verwende Sie <date> für Datum, <ext> für Erweiterung, <contact> für Kontaktname
;file \plugins\BasicHistory\src\Options.h
;file \plugins\BasicHistory\src\PlainHtmlExport.cpp
-[History Log]
+[History log]
Logverlauf
[Filter:]
Filter:
diff --git a/langpacks/german/Plugins/Clist_modern.txt b/langpacks/german/Plugins/Clist_modern.txt
index 6fd1aef164..c4d853a924 100644
--- a/langpacks/german/Plugins/Clist_modern.txt
+++ b/langpacks/german/Plugins/Clist_modern.txt
@@ -50,6 +50,8 @@ WARNUNG: Skins können Ihre Einstellungen überschreiben. Es ist nicht möglich,
* Evtl. Neustart erforderlich um alle Änderungen zu übernehmen
[Skin folder]
Skinverzeichnis
+[Download more skins]
+Weitere Skins herunterladen
[Available view modes]
Verfügbare Kontaktfilter
[Include protocols]
diff --git a/langpacks/german/Plugins/Clist_nicer.txt b/langpacks/german/Plugins/Clist_nicer.txt
index 8455443fcf..e9f87e58f1 100644
--- a/langpacks/german/Plugins/Clist_nicer.txt
+++ b/langpacks/german/Plugins/Clist_nicer.txt
@@ -380,6 +380,8 @@ Gruppenabstand oben
Höhe der Titelzeilen
[Ignore selection for groups]
Markierungen für Gruppen ignorieren
+[Download more skins]
+Weitere Skins herunterladen
[Load from skin file]
Aus Skindatei laden
[Export to skin file]
diff --git a/langpacks/german/Plugins/CloudFile.txt b/langpacks/german/Plugins/CloudFile.txt
index f074c8d3c4..4d8f315766 100644
--- a/langpacks/german/Plugins/CloudFile.txt
+++ b/langpacks/german/Plugins/CloudFile.txt
@@ -2,7 +2,7 @@
;============================================================
; File: CloudFile.dll
; Plugin: CloudFile
-; Version: 0.11.0.2
+; Version: 0.11.0.3
; Authors: Miranda NG Team
;============================================================
[Allows you to transfer files via cloud services.]
diff --git a/langpacks/german/Plugins/DbEditorPP.txt b/langpacks/german/Plugins/DbEditorPP.txt
index 535360b6d4..0bb2692e94 100644
--- a/langpacks/german/Plugins/DbEditorPP.txt
+++ b/langpacks/german/Plugins/DbEditorPP.txt
@@ -2,7 +2,7 @@
;============================================================
; File: DbEditorPP.dll
; Plugin: Database editor++
-; Version: 4.0.1.1
+; Version: 4.0.1.2
; Authors: Bio, Jonathan Gordon
;============================================================
[Advanced Database Editor.]
diff --git a/langpacks/german/Plugins/Fingerprint.txt b/langpacks/german/Plugins/Fingerprint.txt
index ab8db95334..2df9fef91a 100644
--- a/langpacks/german/Plugins/Fingerprint.txt
+++ b/langpacks/german/Plugins/Fingerprint.txt
@@ -46,8 +46,6 @@ MSN-Clients
QQ-Clients
[RSS clients]
RSS-Clients
-[Tlen clients]
-Tlen-Clients
[Weather clients]
Weather-Clients
[Yahoo clients]
@@ -107,8 +105,6 @@ Mail.Ru (unbekannter Client)
TM 2008 und höher
[Gadu-Gadu client]
Gadu-Gadu-Client
-[Tlen.pl client]
-Tlen.pl-Client
[Python-based clients]
Python-basierte Clients
[Jabber client]
@@ -139,8 +135,6 @@ Jabber overlay
MSN overlay
[QQ overlay]
QQ overlay
-[Tlen.pl overlay]
-Tlen.pl overlay
[Yahoo overlay]
Yahoo overlay
[Mail.Ru Agent overlay]
@@ -175,12 +169,6 @@ Gadu-Gadu v10 client
Gadu-Gadu v9 client
[Gadu-Gadu v8 client]
Gadu-Gadu v8 client
-[Tlen 7.x overlay]
-Tlen 7.x overlay
-[Tlen 6.x overlay]
-Tlen 6.x overlay
-[Tlen 5.x overlay]
-Tlen 5.x overlay
[TM/QQ 2012 overlay]
TM/QQ 2012 overlay
[TM/QQ 2011 overlay]
diff --git a/langpacks/german/Plugins/GmailNotifier.txt b/langpacks/german/Plugins/GmailNotifier.txt
index 23256f5e44..cfcfbdad00 100644
--- a/langpacks/german/Plugins/GmailNotifier.txt
+++ b/langpacks/german/Plugins/GmailNotifier.txt
@@ -2,7 +2,7 @@
;============================================================
; File: GmailNotifier.dll
; Plugin: Gmail Multiple Notifier
-; Version: 0.3.1.1
+; Version: 1.0.1.1
; Authors: Mixwind
;============================================================
[Check your Gmail inboxes locally.]
@@ -57,21 +57,19 @@ Ungelesene Nachrichten protokollieren
;file \plugins\GmailNotifier\src\check.cpp
[Checking...]
Prüfen...
-[Can't open Internet!]
-Keine Internetverbindung!
-[Can't reach server!]
-Kann Server nicht erreichen!
[Can't send account data!]
Kann Kontodaten nicht senden!
-[Can't get RSS feed!]
-Kann RSS Feed nicht empfangen!
[Wrong name or password!]
Falscher Nutzername oder Passwort!
+[Can't get RSS feed!]
+Kann RSS Feed nicht empfangen!
;file \plugins\GmailNotifier\src\main.cpp
[Other]
Sonstige
[Gmail: New thread(s)]
Gmail: Neue Themen
+[Gmail Notifier connection]
+
[&Check all Gmail inboxes]
Alle &GMail-Posteingänge prüfen
[&Check Gmail inbox]
diff --git a/langpacks/german/Plugins/IEView.txt b/langpacks/german/Plugins/IEView.txt
index 7632dea735..fdaac5b01a 100644
--- a/langpacks/german/Plugins/IEView.txt
+++ b/langpacks/german/Plugins/IEView.txt
@@ -66,6 +66,8 @@ Datum anzeigen
Langes Datumsformat verwenden
[Use relative timestamp]
Relativen Zeitstempel verwenden
+[Download more templates]
+
;file \plugins\IEView\src\HistoryHTMLBuilder.cpp
[Outgoing File Transfer]
Ausgehende Dateiübertragung
diff --git a/langpacks/german/Plugins/MSN.txt b/langpacks/german/Plugins/MSN.txt
index d66c1fc5b1..66b9ba2a79 100644
--- a/langpacks/german/Plugins/MSN.txt
+++ b/langpacks/german/Plugins/MSN.txt
@@ -2,7 +2,7 @@
;============================================================
; File: MSN.dll
; Plugin: MSN protocol
-; Version: 0.14.0.1
+; Version: 0.14.0.2
; Authors: Boris Krasnovskiy, George Hazan, Richard Hughes, leecher
;============================================================
[Microsoft Network (MSN) protocol support for Miranda NG.]
diff --git a/langpacks/german/Plugins/New_GPG.txt b/langpacks/german/Plugins/New_GPG.txt
index 44f6ca0712..8a9f389fa3 100644
--- a/langpacks/german/Plugins/New_GPG.txt
+++ b/langpacks/german/Plugins/New_GPG.txt
@@ -176,86 +176,6 @@ GPG-Verschlüsselung umschalten
[GPG encryption status]
GPG-Verschlüsselungsstatus
;file \plugins\New_GPG\src\main.cpp
-[Email]
-E-Mail
-[Name]
-Name
-[Creation date]
-Erstelldatum
-[Expire date]
-Ablaufdatum
-[Key length]
-Schlüssellänge
-[Accounts]
-Konten
-[Default]
-Standard
-[key ID]
-Schlüssel-ID
-[not set]
-nicht gesetzt
-[Default private key ID]
-Standard private Schlüssel-ID
-[Failed to open file]
-Konnte die Datei nicht öffnen
-[Error]
-Fehler
-[Generating new random key, please wait]
-Erstelle neuen zufälligen Schlüssel, bitte warten
-[Failed to allocate memory]
-Konnte Speicher nicht zuweisen
-[Failed to lock memory with error %d]
-Sperren des Speichers mit Fehler %d fehlgeschlagen.
-[Failed write to clipboard with error %d]
-Schreiben in Zwischenablage mit Fehler %d fehlgeschlagen.
-[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
-Das GPG-Verzeichnis wurde im Miranda-Verzeichnis gefunden, allerdings existiert das englische Locale nicht.\nEs ist sehr wichtig die \\gnupg.nls\\en@quot.mo im GnuPG-Verzeichnis im Miranda-NG-Verzeichnis zu legen.\nOhne diese Datei haben Sie viele Probleme mit der GPG-Ausgabe auf nicht-englischen Systemen.\nPlugin kann evtl. nicht richtig funktionieren.\nSeien Sie gewarnt!
-[Warning]
-Warnung
-[Wrong GPG binary location found in system.\nPlease choose another location]
-Ein falsches GPG-Verzeichnis wurde im System gefunden.\nBitte wählen Sie ein anderes Verzeichnis aus.
-[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-Dies ist keine GnuPG-Binärdatei!\nEs wird empfohlen GnuPG v1.x.x mit diesem Plugin zu verwenden.
-[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-Eine nicht unterstützte GnuPG-Version wurde gefunden, benutzen Sie diese auf eigenes Risiko!\nEs wird empfohlen, GnuPG v1.x.x mit diesem Plugin zu benutzen.
-["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
-"GPG"-Verzeichnis im Miranda-Hauptverzeichnis gefunden.\nNehme an, dass dies das GPG-Heimverzeichnis ist.\nGPG-Heimverzeichnis gesetzt.
-[Info]
-Info
-[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
-Ihre GPG-Version wird unterstützt. Die Sprachdatei wurde gefunden.\nDas GPG-Plugin sollte funktionieren.\nKlicken Sie auf OK, um fortzufahren.
-[GPG binary does not exist.\nPlease choose another location]
-GPG-Verzeichnis existiert nicht.\nBitte wählen Sie ein anderes Verzeichnis aus.
-[Please choose GPG binary location]
-Bitte wählen Sie das GPG-Hauptverzeichnis aus.
-[Please set keyring's home directory]
-Bitte setzen Sie den Hauptordner für die Schlüssel
-[There is existing key for contact, would you like to replace it with new key?]
-Für diesen Kontakt existiert bereits ein Schlüssel, wollen Sie ihn durch einen neuen Schlüssel ersetzen?
-[New public key was received, do you want to import it?]
-Ein neuer öffentlicher Schlüssel wurde empfangen, wollen Sie ihn importieren?
-[Replace]
-Ersetzen
-[Accept]
-Akzeptieren
-[Received key from %s]
-Schlüssel von %s empfangen
-[You must set encryption algorithm first]
-Sie müssen als Erstes einen Verschlüsselungsalgorithmus setzen
-[Key length must be of length from 1024 to 4096 bits]
-Schlüssellänge muss zwischen 1024 und 4096 Bit betragen.
-[Invalid date]
-Ungültiges Datum
-[Name must contain at least 5 characters]
-Der Name muss mind. 5 Zeichen beinhalten.
-[Name cannot contain '(' or ')']
-Der Name darf kein '(' oder ')' beinhalten
-[Invalid Email]
-Ungültige E-Mail-Adresse
-[Generating new key, please wait...]
-Erzeuge neuen Schlüssel, bitte warten Sie...
-[Failed to export public key.]
-Konnte öffentlichen Schlüssel nicht exportieren.
[GPG binary is set and valid (this is good).\n]
GPG-Programm ist gesetzt und gültig (das ist gut).\n
[GPG binary unset or invalid (plugin will not work).\n]
@@ -293,6 +213,8 @@ Metakontakt entdeckt
;file \plugins\New_GPG\src\messages.cpp
[We received encrypted message from contact with encryption turned off.\nDo you want to turn on encryption for this contact?]
Sie haben eine verschlüsselte Nachricht von einem Kontakt empfangen der die Verschlüsselung deaktiviert hat.\nWollen Sie die Verschlüsselung für diesen Kontakt deaktivieren?
+[Warning]
+Warnung
[Do you want to try to decrypt encrypted message?]
Wollen Sie versuchen, die verschlüsselte Nachricht zu entschlüsseln?
[We're trying to encrypt with untrusted key. Do you want to trust this key permanently?]
@@ -300,22 +222,20 @@ Sie versuchen, mit nicht vertrauenswürdigem Schlüssel zu verschlüsseln, wolle
[Something is wrong, GPG does not understand us, aborting encryption.]
Etwas läuft falsch, GPG versteht uns nicht, breche Verschlüsselung ab.
;file \plugins\New_GPG\src\options.cpp
-[Services]
-Dienste
-[Main]
-Allgemein
-[GnuPG Variables]
-GnuPG-Variablen
-[Messages]
-Nachrichten
-[Advanced]
-Erweitert
[Contact]
Kontakt
[Key ID]
Schlüssel-ID
+[Name]
+Name
+[Email]
+E-Mail
[Protocol]
Protokoll
+[Default private key ID]
+Standard private Schlüssel-ID
+[not set]
+nicht gesetzt
[This key is not used by any contact. Do you want to remove it from public keyring?]
Dieser Schlüssel wird von keinem Kontakt verwendet. Wollen Sie ihn aus dem öffentlichen Schlüsselbund entfernen?
[Key info]
@@ -332,6 +252,14 @@ Wollen Sie den Schlüssel für den gesamten Metakontakt (und Unterkontakte) lös
Öffentlichen Schlüssel exportieren
[.asc pubkey file]
.asc-Pubkey-Datei
+[Failed to allocate memory]
+Konnte Speicher nicht zuweisen
+[Error]
+Fehler
+[Failed to lock memory with error %d]
+Sperren des Speichers mit Fehler %d fehlgeschlagen.
+[Failed write to clipboard with error %d]
+Schreiben in Zwischenablage mit Fehler %d fehlgeschlagen.
[Failed to open clipboard with error %d]
Öffnen der Zwischenablage mit Fehler %d fehlgeschlagen.
[Set log file]
@@ -340,6 +268,8 @@ Logdatei setzen
Logdateien
[Choose gpg.exe]
Wählen Sie den Pfad zur gpg.exe aus
+[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+Dies ist keine GnuPG-Binärdatei!\nEs wird empfohlen GnuPG v1.x.x mit diesem Plugin zu verwenden.
[Set home directory]
Heimverzeichnis setzen
[Load Public GPG Key for ]
@@ -356,12 +286,83 @@ Lade offentlichen GPG-Schlussel (Schlussel-ID:\s
Dies ist kein öffentlicher oder privater Schlüssel
[Key already in secret keyring.]
Der Schlüssel ist bereits im geheimen Schlüsselbund.
+[Info]
+Info
[Set file containing GPG public key]
Setzen Sie die Datei, die den öffentlichen GPG-Schlüssel enthält
[GPG public key file]
GPG öffentliche Schlüsseldatei
+[Failed to open file]
+Konnte die Datei nicht öffnen
[There is no public or private key.]
Es gibt keinen öffentlichen oder privaten Schlüssel.
+[Services]
+Dienste
+[Main]
+Allgemein
+[GnuPG Variables]
+GnuPG-Variablen
+[Messages]
+Nachrichten
+[Advanced]
+Erweitert
+;file \plugins\New_GPG\src\ui.cpp
+[New passwords do not match]
+Die neuen Passwörter stimmen nicht überein
+[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+Altes Passwort stimmt nicht, Sie können fortfahren, aber GPG wird das falsche Passwort ablehnen.\nMöchten Sie fortfahren?
+[Creation date]
+Erstelldatum
+[Expire date]
+Ablaufdatum
+[Key length]
+Schlüssellänge
+[Accounts]
+Konten
+[Default]
+Standard
+[key ID]
+Schlüssel-ID
+[Generating new random key, please wait]
+Erstelle neuen zufälligen Schlüssel, bitte warten
+[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
+Das GPG-Verzeichnis wurde im Miranda-Verzeichnis gefunden, allerdings existiert das englische Locale nicht.\nEs ist sehr wichtig die \\gnupg.nls\\en@quot.mo im GnuPG-Verzeichnis im Miranda-NG-Verzeichnis zu legen.\nOhne diese Datei haben Sie viele Probleme mit der GPG-Ausgabe auf nicht-englischen Systemen.\nPlugin kann evtl. nicht richtig funktionieren.\nSeien Sie gewarnt!
+[Wrong GPG binary location found in system.\nPlease choose another location]
+Ein falsches GPG-Verzeichnis wurde im System gefunden.\nBitte wählen Sie ein anderes Verzeichnis aus.
+[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+Eine nicht unterstützte GnuPG-Version wurde gefunden, benutzen Sie diese auf eigenes Risiko!\nEs wird empfohlen, GnuPG v1.x.x mit diesem Plugin zu benutzen.
+["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
+"GPG"-Verzeichnis im Miranda-Hauptverzeichnis gefunden.\nNehme an, dass dies das GPG-Heimverzeichnis ist.\nGPG-Heimverzeichnis gesetzt.
+[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
+Ihre GPG-Version wird unterstützt. Die Sprachdatei wurde gefunden.\nDas GPG-Plugin sollte funktionieren.\nKlicken Sie auf OK, um fortzufahren.
+[There is existing key for contact, would you like to replace it with new key?]
+Für diesen Kontakt existiert bereits ein Schlüssel, wollen Sie ihn durch einen neuen Schlüssel ersetzen?
+[New public key was received, do you want to import it?]
+Ein neuer öffentlicher Schlüssel wurde empfangen, wollen Sie ihn importieren?
+[Replace]
+Ersetzen
+[Accept]
+Akzeptieren
+[Received key from %s]
+Schlüssel von %s empfangen
+[You must set encryption algorithm first]
+Sie müssen als Erstes einen Verschlüsselungsalgorithmus setzen
+[Key length must be of length from 1024 to 4096 bits]
+Schlüssellänge muss zwischen 1024 und 4096 Bit betragen.
+[Invalid date]
+Ungültiges Datum
+[Name must contain at least 5 characters]
+Der Name muss mind. 5 Zeichen beinhalten.
+[Name cannot contain '(' or ')']
+Der Name darf kein '(' oder ')' beinhalten
+[Invalid Email]
+Ungültige E-Mail-Adresse
+[Generating new key, please wait...]
+Erzeuge neuen Schlüssel, bitte warten Sie...
+[Expiration date]
+
+[Failed to export public key.]
+Konnte öffentlichen Schlüssel nicht exportieren.
;file \plugins\New_GPG\src\utilities.cpp
[Do you want to toggle encryption for all subcontacts?]
Wollen Sie die Verschlüsselung für alle Unterkontakte wechseln?
@@ -393,7 +394,10 @@ Wir haben %d öffentliche Schlüssel und einige private Schlüssel erfolgreich v
Wir haben %d öffentliche Schlüssel erfolgreich verarbeitet.
[Keys import result]
Ergebnis Schlüssel importieren
-[New passwords do not match]
-Die neuen Passwörter stimmen nicht überein
-[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
-Altes Passwort stimmt nicht, Sie können fortfahren, aber GPG wird das falsche Passwort ablehnen.\nMöchten Sie fortfahren?
+[GPG binary does not exist.\nPlease choose another location]
+GPG-Verzeichnis existiert nicht.\nBitte wählen Sie ein anderes Verzeichnis aus.
+[Please choose GPG binary location]
+Bitte wählen Sie das GPG-Hauptverzeichnis aus.
+[Please set keyring's home directory]
+Bitte setzen Sie den Hauptordner für die Schlüssel
+;file \plugins\New_GPG\src\utilities.h
diff --git a/langpacks/german/Plugins/SimpleStatusMsg.txt b/langpacks/german/Plugins/SimpleStatusMsg.txt
index 7a52aea5bb..54a6adfbbf 100644
--- a/langpacks/german/Plugins/SimpleStatusMsg.txt
+++ b/langpacks/german/Plugins/SimpleStatusMsg.txt
@@ -3,7 +3,7 @@
; File: SimpleStatusMsg.dll
; Plugin: Simple status message
; Version: 1.9.0.6
-; Authors: Bartosz 'Dezeath' Bialek, Harven
+; Authors: Bartosz 'Dezeath' Białek, Harven
;============================================================
[Provides a simple way to set status and away messages.]
Einfacher Weg um Statusnachrichten einzustellen.
diff --git a/langpacks/german/Plugins/SmileyAdd.txt b/langpacks/german/Plugins/SmileyAdd.txt
index c61e1c3abd..57bc85a4ff 100644
--- a/langpacks/german/Plugins/SmileyAdd.txt
+++ b/langpacks/german/Plugins/SmileyAdd.txt
@@ -2,7 +2,7 @@
;============================================================
; File: SmileyAdd.dll
; Plugin: SmileyAdd
-; Version: 0.2.4.2
+; Version: 0.3.0.1
; Authors: Peacow, nightwish, bid, borkra
;============================================================
[Smiley support for Miranda NG.]
@@ -98,16 +98,14 @@ protokollspezifisch
;file \plugins\SmileyAdd\src\smileys.cpp
[Smiley pack %s for category "%s" not found.\nSelect correct smiley pack in the Options -> Customize -> Smileys.]
Smileypack %s für Kategorie "%s" nicht gefunden.\nBitte korrektes Smileypack in Einstellungen -> Customize -> Smileys auswählen.
-[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
-Das verwendete Smileypack ist fehlerhaft und muss korrigiert werden.\nDetails finden sich im Netzwerklog.
[Smiley #%u in file %s for smiley pack %s not found.]
Smiley #%u in Datei %s für Smileypack %s nicht gefunden.
+[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
+Das verwendete Smileypack ist fehlerhaft und muss korrigiert werden.\nDetails finden sich im Netzwerklog.
[%s global smiley pack]
%s globales Smileypack
[Standard]
Standard
-[Regular expression "%s" in smiley pack "%s" could produce "empty matches".]
-Regulärer Ausdruck "%s" in Smileypack "%s" könnte "leere Treffer" verursachen.
[Regular expression "%s" in smiley pack "%s" malformed.]
Regulärer Ausdruck "%s" in Smileypack "%s" deformiert.
;file \plugins\SmileyAdd\src\smltool.cpp
diff --git a/langpacks/german/Plugins/SplashScreen.txt b/langpacks/german/Plugins/SplashScreen.txt
index a0f5e093b6..a79d5403af 100644
--- a/langpacks/german/Plugins/SplashScreen.txt
+++ b/langpacks/german/Plugins/SplashScreen.txt
@@ -38,6 +38,8 @@ Ausblenden:
Advaimg.dll nicht gefunden. Bitte entnehmen Sie die Datei aus der aktuellen Stable-/Testing-Version.
[Preview...]
Vorschau...
+[Download more splash screens]
+
;file \plugins\SplashScreen\src\options.cpp
[Graphic files]
Grafikdateien
diff --git a/langpacks/german/Plugins/StatusManager.txt b/langpacks/german/Plugins/StatusManager.txt
index 2a0ba5073e..18518710b4 100644
--- a/langpacks/german/Plugins/StatusManager.txt
+++ b/langpacks/german/Plugins/StatusManager.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StatusManager.dll
; Plugin: Status manager
-; Version: 0.11.2.3
+; Version: 1.0.1.1
; Authors: P Boon
;============================================================
[A connection checker and auto away module. Also allows you to define the status Miranda should set on startup, configurable per protocol.]
diff --git a/langpacks/german/Plugins/Steam.txt b/langpacks/german/Plugins/Steam.txt
index df7cb9369a..cd5c3a2f00 100644
--- a/langpacks/german/Plugins/Steam.txt
+++ b/langpacks/german/Plugins/Steam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Steam.dll
; Plugin: Steam protocol
-; Version: 0.11.6.1
+; Version: 0.11.6.3
; Authors: Miranda NG Team, Robert Pösel
;============================================================
[Steam protocol support for Miranda NG.]
diff --git a/langpacks/german/Plugins/StopSpam.txt b/langpacks/german/Plugins/StopSpam.txt
index 2b60ec9f79..49a6db9e2e 100644
--- a/langpacks/german/Plugins/StopSpam.txt
+++ b/langpacks/german/Plugins/StopSpam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpam.dll
; Plugin: StopSpam+
-; Version: 0.0.1.5
+; Version: 0.1.0.1
; Authors: Roman Miklashevsky, A. Petkevich, Kosh&chka, persei
;============================================================
[Anti-spam plugin for Miranda NG.]
@@ -43,6 +43,9 @@ Spammer in den Systemverlauf eintragen
;file \plugins\StopSpamPlus\src\events.cpp
[StopSpam automatic message:\r\n]
Automatische StopSpam-Nachricht:\r\n
+;file \plugins\StopSpamPlus\src\options.cpp
+[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
+Nie wieder Spam! Spambots haben keine Chance! Nur Menschen sind eingeladen!\r\n\r\nDieses Plugin arbeitet sehr einfach:\r\nNachrichten von Ihren Kontakten werden behandelt, als gäbe es kein Anti-Spam-System. Auf der anderen Seite werden Nachrichten von unbekannten Kontakten nicht direkt an Sie weitergeleitet. Sie werden aber auch nicht ignoriert, sondern dieses Plugin stellt eine einfache Frage. Wird diese richtig beantwortet, wird der Kontakt ihrer Kontaktliste hinzugefügt und kann Sie nun kontaktieren.
[Message sessions]
Nachrichtensitzungen
[General]
@@ -51,21 +54,18 @@ Allgemein
Nachrichten
[Accounts]
Konten
-;file \plugins\StopSpamPlus\src\options.cpp
-[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
-Nie wieder Spam! Spambots haben keine Chance! Nur Menschen sind eingeladen!\r\n\r\nDieses Plugin arbeitet sehr einfach:\r\nNachrichten von Ihren Kontakten werden behandelt, als gäbe es kein Anti-Spam-System. Auf der anderen Seite werden Nachrichten von unbekannten Kontakten nicht direkt an Sie weitergeleitet. Sie werden aber auch nicht ignoriert, sondern dieses Plugin stellt eine einfache Frage. Wird diese richtig beantwortet, wird der Kontakt ihrer Kontaktliste hinzugefügt und kann Sie nun kontaktieren.
;file \plugins\StopSpamPlus\src\services.cpp
[Not In List]
Nicht auf der Liste
[Complete]
Fertig
-;file \plugins\StopSpamPlus\src\settings.h
+;file \plugins\StopSpamPlus\src\settings.cpp
[Spammers made me to install small anti-spam system you are now speaking with. Please reply "nospam" without quotes and spaces if you want to contact me.]
Spammer haben mich dazu gebracht, ein kleines Anti-Spam-System zu installieren, mit dem Sie nun sprechen. Bitte antworten Sie mit "nospam" ohne Anführungszeichen, wenn Sie mich kontaktieren möchten.
-[Congratulations! You just passed human/robot test. Now you can write me a message.]
-Glückwunsch! Sie haben gerade den Mensch-/Robotertest bestanden. Nun können Sie eine Nachricht schreiben.
[StopSpam: send a message and reply to an anti-spam bot question.]
StopSpam: senden Sie eine Nachricht und antworten Sie auf die Frage des Anti-Spam-Bots.
+[Congratulations! You just passed human/robot test. Now you can write me a message.]
+Glückwunsch! Sie haben gerade den Mensch-/Robotertest bestanden. Nun können Sie eine Nachricht schreiben.
;file \plugins\StopSpamPlus\src\stdafx.h
[StopSpam]
StopSpam
diff --git a/langpacks/german/Plugins/StopSpamMod.txt b/langpacks/german/Plugins/StopSpamMod.txt
index 2e1adb1949..5c63080adb 100644
--- a/langpacks/german/Plugins/StopSpamMod.txt
+++ b/langpacks/german/Plugins/StopSpamMod.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpamMod.dll
; Plugin: StopSpam mod
-; Version: 0.0.2.1
+; Version: 0.0.2.2
; Authors: Roman Miklashevsky, sss, Elzor
;============================================================
[Anti-spam plugin for Miranda NG.]
diff --git a/langpacks/german/Plugins/TabSRMM.txt b/langpacks/german/Plugins/TabSRMM.txt
index 8433c59f76..e0173b2a45 100644
--- a/langpacks/german/Plugins/TabSRMM.txt
+++ b/langpacks/german/Plugins/TabSRMM.txt
@@ -516,6 +516,8 @@ Sie können all Ihre Farben sowie die Schriftart-Einstellungen exportieren und i
Exportiere in eine Datei...
[Import from a file...]
Importiere aus einer Datei...
+[Download more skins]
+Weitere Skins herunterladen
[Icons]
Icons
[Event type icons in the message log]
diff --git a/langpacks/german/Plugins/Tox.txt b/langpacks/german/Plugins/Tox.txt
index b692ff9108..b0decc42fe 100644
--- a/langpacks/german/Plugins/Tox.txt
+++ b/langpacks/german/Plugins/Tox.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Tox.dll
; Plugin: Tox protocol
-; Version: 0.11.1.25
+; Version: 0.11.1.26
; Authors: Miranda NG Team
;============================================================
[Tox protocol support for Miranda NG.]
diff --git a/langpacks/german/Plugins/mRadio.txt b/langpacks/german/Plugins/mRadio.txt
index 3481fe2ec5..0bf82c658c 100644
--- a/langpacks/german/Plugins/mRadio.txt
+++ b/langpacks/german/Plugins/mRadio.txt
@@ -101,8 +101,8 @@ Durchgängige Aufnahme
Steinbruch
[Sorry!]
Entschuldigung!
-[BASS.DLL not found!]
-Bass.dll nicht gefunden!
+[bass.dll not found!]
+bass.dll nicht gefunden!
[Station]
Station
[Custom INI file]
@@ -156,7 +156,7 @@ EQ-Preset hinzufügen
[Delete EQ preset]
EQ-Preset löschen
[BASS library path (empty for default)]
-Bass.dll-Bibliothekverzeichnis (Standard leer)
+bass.dll-Bibliothekverzeichnis (Standard leer)
[Tries to connect]
Versuche zu verbinden
[Mute]
@@ -199,3 +199,5 @@ Equalizer
Neu
[Quick Open]
Schnell öffnen
+[bass.dll not found! Choose bass.dll path manually]
+Bass.dll nicht gefunden! Wählen Sie das bass.dll Verzeichnis manuell.
diff --git a/langpacks/german/Untranslated/GmailNotifier.txt b/langpacks/german/Untranslated/GmailNotifier.txt
new file mode 100644
index 0000000000..fe2bc3771c
--- /dev/null
+++ b/langpacks/german/Untranslated/GmailNotifier.txt
@@ -0,0 +1 @@
+[Gmail Notifier connection]
diff --git a/langpacks/german/Untranslated/IEView.txt b/langpacks/german/Untranslated/IEView.txt
index 8cdc35f244..bd9cf992f4 100644
--- a/langpacks/german/Untranslated/IEView.txt
+++ b/langpacks/german/Untranslated/IEView.txt
@@ -1,3 +1,4 @@
+[Download more templates]
[IID_IOleObject failed.]
[IID_IOleInPlaceObject failed.]
[Failed to Advise]
diff --git a/langpacks/german/Untranslated/New_GPG.txt b/langpacks/german/Untranslated/New_GPG.txt
new file mode 100644
index 0000000000..8c633b12eb
--- /dev/null
+++ b/langpacks/german/Untranslated/New_GPG.txt
@@ -0,0 +1 @@
+[Expiration date]
diff --git a/langpacks/german/Untranslated/SplashScreen.txt b/langpacks/german/Untranslated/SplashScreen.txt
new file mode 100644
index 0000000000..0add885a64
--- /dev/null
+++ b/langpacks/german/Untranslated/SplashScreen.txt
@@ -0,0 +1 @@
+[Download more splash screens]
diff --git a/langpacks/polish/=CORE=.txt b/langpacks/polish/=CORE=.txt
index c941a7c60a..0f9ff9a6f8 100644
--- a/langpacks/polish/=CORE=.txt
+++ b/langpacks/polish/=CORE=.txt
@@ -3,29 +3,6 @@
; Module: Miranda Core
; Version: 0.95.8
;============================================================
-;file \src\core\stdauth\res\resource.rc
-[Authorization request]
-Prośba o autoryzację
-[&Authorize]
-&Autoryzuj
-[&Deny]
-&Odrzuć
-[Decide &later]
-Przypomnij &później
-[User &details]
-Dane &kontaktu
-[Reason:]
-Powód:
-[Denial reason:]
-Powód odmowy:
-[Add to contact list if authorized]
-Dodaj kontakt do listy jeśli autoryzowany
-[You were added]
-Zostałeś dodany
-[&Close]
-&Zamknij
-[&Add]
-&Dodaj
;file \src\core\stdaway\res\resource.rc
[%s message for %s]
Opis statusu "%s" - %s
@@ -291,6 +268,8 @@ Całkowity rozmiar:
Opis:
[&User menu]
Menu &użytkownika
+[User &details]
+Dane &kontaktu
[&History]
&Historia
[Incoming file transfer]
@@ -307,6 +286,8 @@ Data:
Pliki:
[Save to:]
Zapisz do:
+[&Add]
+&Dodaj
[&Open...]
&Otwórz...
[Open &folder]
@@ -395,11 +376,6 @@ Pytaj mnie
Zmień nazwę (dodaj " (1)", itp.)
[You will always be asked about files from people not on your contact list]
Zawsze będziesz pytany o pliki od osób spoza twojej listy kontaktów
-;file \src\core\stdhelp\res\resource.rc
-[About Miranda NG]
-O Mirandzie NG
-[Credits >]
-Autorzy >
;file \src\core\stdidle\res\resource.rc
[Become idle if the following is left unattended:]
Przejdź w bezczynność jeśli aktywności nie wykazuje:
@@ -723,6 +699,8 @@ Otwórz okno rozmowy z kontaktem
Nazwa:
[Group:]
Grupa:
+[Authorization request]
+Prośba o autoryzację
[&Yes]
&Tak
[&No]
@@ -999,6 +977,8 @@ Uwaga!\r\nTen obiekt menu nie obsługuje opcji użytkownika.
Wstaw podmenu
[Insert separator]
Wstaw separator
+[Module:]
+Moduł:
[Service:]
Usługa:
[Default]
@@ -1133,6 +1113,26 @@ Pokaż w oknie czatu
Odstępy przycisków:
[Hide if there isn't enough space]
Ukryj, jeśli nie ma miejsca
+[&Authorize]
+&Autoryzuj
+[&Deny]
+&Odrzuć
+[Decide &later]
+Przypomnij &później
+[Reason:]
+Powód:
+[Denial reason:]
+Powód odmowy:
+[Add to contact list if authorized]
+Dodaj kontakt do listy jeśli autoryzowany
+[You were added]
+Zostałeś dodany
+[&Close]
+&Zamknij
+[About Miranda NG]
+O Mirandzie NG
+[Credits >]
+Autorzy >
[Tray]
Zasobnik
[&Hide/Show]
@@ -1193,42 +1193,6 @@ Wikipedia
Google Maps
[Google Translate]
Google Translate
-;file \src\core\stdauth\src\auth.cpp
-[%s requests authorization]
-%s prosi o autoryzacjÄ™
-[%u requests authorization]
-%u prosi o autoryzacjÄ™
-[%s added you to their contact list]
-%s dodał(a) cię do listy kontaktów
-[%u added you to their contact list]
-%u dodał(a) cię do swojej listy kontaktów
-[Alerts]
-Alarmy
-[Added event]
-Dodanie kontaktu
-;file \src\core\stdauth\src\authdialogs.cpp
-[View user's details]
-Zobacz dane kontaktu
-[Add contact permanently to list]
-Dodaj kontakt na stałe do listy
-[<Unknown>]
-<Nieznany>
-[%s added you to the contact list\n%u (%s) on %s]
-%s dodał(a) cię do listy kontaktów\n%u (%s) na %s
-[%s added you to the contact list\n%u on %s]
-%s dodał(a) cię do listy kontaktów\n%u na %s
-[%s added you to the contact list\n%s on %s]
-%s dodał(a) cię do listy kontaktów\n%s na %s
-[(Unknown)]
-(Nieznany)
-[%s requested authorization\n%u (%s) on %s]
-%s poprosił(a) o autoryzację\n%u (%s) na koncie %s
-[%s requested authorization\n%u on %s]
-%s poprosił(a) o autoryzację \n%u na koncie %s
-[%s requested authorization\n%s on %s]
-%s poprosił(a) o autoryzację\n%s na koncie %s
-[Feature is not supported by protocol]
-Funkcja nie wspierana przez protokół
;file \src\core\stdaway\src\awaymsg.cpp
[Re&ad %s message]
Po&każ opis "%s"
@@ -1351,6 +1315,10 @@ Zdarzenia
Wybierz folder
[My received files]
Moje odebrane pliki
+[Add contact permanently to list]
+Dodaj kontakt na stałe do listy
+[View user's details]
+Zobacz dane kontaktu
[View user's history]
Zobacz historię użytkownika
[User menu]
@@ -1418,20 +1386,6 @@ Ukończono przesyłanie i skanowanie wirusów
;file \src\core\stdfile\src\ftmanager.cpp
[Outgoing]
WychodzÄ…ce
-;file \src\core\stdhelp\src\about.cpp
-[< Copyright]
-< Prawa aut.
-;file \src\core\stdhelp\src\help.cpp
-[&Help]
-&Pomoc
-[&About...]
-&O programie...
-[&Support]
-&Wsparcie techniczne
-[&Miranda NG homepage]
-Strona domowa &Mirandy
-[&Report bug]
-&Zgłoś błąd
;file \src\core\stdidle\src\idle.cpp
[Idle]
Bezczynność
@@ -1907,11 +1861,43 @@ Pokaż/Zmień moje &dane...
;file \src\core\stduseronline\src\useronline.cpp
[%s is online]
%s jest Dostępny
+[Alerts]
+Alarmy
;file \src\mir_app\src\addcontact.cpp
[Add %s]
Dodaj %s
[Please authorize my request and add me to your contact list.]
Proszę, autoryzuj mnie i dodaj do swojej listy kontaktów.
+;file \src\mir_app\src\auth.cpp
+[%s requests authorization]
+%s prosi o autoryzacjÄ™
+[%u requests authorization]
+%u prosi o autoryzacjÄ™
+[%s added you to their contact list]
+%s dodał(a) cię do listy kontaktów
+[%u added you to their contact list]
+%u dodał(a) cię do swojej listy kontaktów
+[Added event]
+Dodanie kontaktu
+;file \src\mir_app\src\authdialogs.cpp
+[<Unknown>]
+<Nieznany>
+[%s added you to the contact list\n%u (%s) on %s]
+%s dodał(a) cię do listy kontaktów\n%u (%s) na %s
+[%s added you to the contact list\n%u on %s]
+%s dodał(a) cię do listy kontaktów\n%u na %s
+[%s added you to the contact list\n%s on %s]
+%s dodał(a) cię do listy kontaktów\n%s na %s
+[(Unknown)]
+(Nieznany)
+[%s requested authorization\n%u (%s) on %s]
+%s poprosił(a) o autoryzację\n%u (%s) na koncie %s
+[%s requested authorization\n%u on %s]
+%s poprosił(a) o autoryzację \n%u na koncie %s
+[%s requested authorization\n%s on %s]
+%s poprosił(a) o autoryzację\n%s na koncie %s
+[Feature is not supported by protocol]
+Funkcja nie wspierana przez protokół
;file \src\mir_app\src\chat_clist.cpp
[&Join chat]
&Dołącz do czatu
@@ -2200,6 +2186,19 @@ Nagłówki
Ogólny tekst
[Small text]
Mały tekst
+;file \src\mir_app\src\help.cpp
+[< Copyright]
+< Prawa aut.
+[&Help]
+&Pomoc
+[&About...]
+&O programie...
+[&Support]
+&Wsparcie techniczne
+[&Miranda NG homepage]
+Strona domowa &Mirandy
+[&Report bug]
+&Zgłoś błąd
;file \src\mir_app\src\hotkey_opts.cpp
[Browser: Back]
PrzeglÄ…darka: wstecz
diff --git a/langpacks/polish/=HEAD=.txt b/langpacks/polish/=HEAD=.txt
index 85f0d00eda..0b03118ff8 100644
--- a/langpacks/polish/=HEAD=.txt
+++ b/langpacks/polish/=HEAD=.txt
@@ -1,5 +1,5 @@
Miranda Language Pack Version 1
Language: Polish (PL)
Locale: 0415
-Last-Modified-Using: Miranda NG 0.95.7
+Last-Modified-Using: Miranda NG 0.95.8
Authors: bunnyhoney, Xantros, Goraf, Piciok \ No newline at end of file
diff --git a/langpacks/polish/Plugins/AIM.txt b/langpacks/polish/Deprecated/AIM.txt
index 3f4454d7df..3f4454d7df 100644
--- a/langpacks/polish/Plugins/AIM.txt
+++ b/langpacks/polish/Deprecated/AIM.txt
diff --git a/langpacks/polish/Plugins/AddContactPlus.txt b/langpacks/polish/Plugins/AddContactPlus.txt
index ecf10618de..b3841c67b2 100644
--- a/langpacks/polish/Plugins/AddContactPlus.txt
+++ b/langpacks/polish/Plugins/AddContactPlus.txt
@@ -3,7 +3,7 @@
; File: AddContactPlus.dll
; Plugin: Add contact+
; Version: 0.9.9.2
-; Authors: Bartosz 'Dezeath' Bialek
+; Authors: Bartosz 'Dezeath' Białek
;============================================================
[Provides the ability to quickly add new contacts.]
Umożliwia szybkie dodawanie nowych kontaktów.
diff --git a/langpacks/polish/Plugins/AssocMgr.txt b/langpacks/polish/Plugins/AssocMgr.txt
index b9115f519e..ca1bb1661b 100644
--- a/langpacks/polish/Plugins/AssocMgr.txt
+++ b/langpacks/polish/Plugins/AssocMgr.txt
@@ -5,8 +5,8 @@
; Version: 0.2.1.0
; Authors: H. Herkenrath
;============================================================
-[Handles file type associations and URLs like aim, gg, mirpu, tlen, wpmsg, xmpp, ymsgr.]
-Obsługuje skojarzenia rozszerzeń plików i linków protokołów AIM, Gadu-Gadu, Jabber, MSN, PluginUpdater, Tlen, Yahoo.
+[Handles file type associations and URLs like aim, gg, mirpu, wpmsg, xmpp, ymsgr.]
+Obsługuje skojarzenia rozszerzeń plików i linków protokołów AIM, Gadu-Gadu, Jabber, MSN, PluginUpdater, Yahoo.
;file \plugins\AssocMgr\res\resource.rc
[Registered associations for Miranda NG:]
Zarejestrowane powiÄ…zania dla Mirandy NG
diff --git a/langpacks/polish/Plugins/BASS_interface.txt b/langpacks/polish/Plugins/BASS_interface.txt
index 64d4463128..88efe1e658 100644
--- a/langpacks/polish/Plugins/BASS_interface.txt
+++ b/langpacks/polish/Plugins/BASS_interface.txt
@@ -1,20 +1,20 @@
#muuid {2f07ea05-05b5-4ff0-875d-c590da2ddac1}
;============================================================
; File: BASS_interface.dll
-; Plugin: BASS interface
+; Plugin: BASS Interface
; Version: 0.0.0.14
; Authors: tico-tico
;============================================================
-[un4seen's BASS interface Miranda NG plugin.]
+[Un4seen's BASS interface Miranda NG plugin.]
Wtyczka interfejsu Un4seen's BASS dla Mirandy NG.
;file \plugins\BASS_interface\res\Bass.rc
-[un4seen's bass interface]
-Interfejs un4seen's bass
+[Un4seen's BASS interface]
+Interfejs Un4seen's BASS
[bass.dll loading error]
-Błąd wczytywania Sterownika BASS.dll
+Błąd wczytywania sterownika bass.dll
[Current bass.dll path:]
-Folder docelowy BASS.dll:
-[Maximum number of bass internal channels:]
+Folder docelowy bass.dll:
+[Maximum number of BASS internal channels:]
Maksymalna ilość kanałów:
[Output device:]
Sterownik audio:
@@ -22,7 +22,7 @@ Sterownik audio:
Głośność:
[Quiet time:]
Okres ciszy:
-[download bass library]
+[download BASS library]
Pobierz biblioteki BASS
[Play only if]
Graj tylko gdy:
@@ -49,8 +49,8 @@ Na obiedzie
[Preview]
PodglÄ…d
;file \plugins\BASS_interface\src\Main.cpp
-[un4seen's bass version: %d.%d.%d.%d]
-Wersja un4seen's bass: %d.%d.%d.%d
+[Un4seen's BASS version: %d.%d.%d.%d]
+Wersja Un4seen's BASS: %d.%d.%d.%d
[--default device--]
--domyślne sterowniki--
[Sounds]
@@ -61,6 +61,8 @@ Wyłącz dźwięki
Włącz dźwięki
[Frame background]
Tło ramki
+[BASS Interface]
+Interfejs BASS
[Bass Interface]
Interfejs BASS
[Bass library]
diff --git a/langpacks/polish/Plugins/BasicHistory.txt b/langpacks/polish/Plugins/BasicHistory.txt
index 5537aa46ff..136d9f8fd1 100644
--- a/langpacks/polish/Plugins/BasicHistory.txt
+++ b/langpacks/polish/Plugins/BasicHistory.txt
@@ -8,7 +8,7 @@
[History viewer for Miranda NG.]
Pokazuje historię wiadomości.
;file \plugins\BasicHistory\res\BasicHistory.rc
-[Message History]
+[Message history]
Historia wiadomości
[Settings]
Ustawienia
@@ -16,9 +16,9 @@ Ustawienia
Zawsze pokazuj listę kontaktów
[Show groups in contact list]
Pokaż grupy na liście kontaktów
-[Do not show Find control border]
+[Do not show find control border]
Nie pokazuj paska szukania
-[Default Event Filter]
+[Default event filter]
Domyślne ustaw. zdarzeń
[Custom filters]
Filtry użytkownika
@@ -56,31 +56,31 @@ Limituj wiadomości do:
Pokaż datę przy czasie
[Show seconds in timestamps]
Pokaż sekundy w czasie
-[Enable Smileys]
+[Enable smileys]
Włącz emotikony
[Search forward in list group]
Wyszukuj do przodu na liście grup
[Search forward in message window]
Wyszukuj do przodu w oknie rozmowy
-[Match Case]
+[Match case]
Po wielkości liter
-[Match Whole Word]
+[Match whole word]
Po całych wyrazach
-[Only Incoming Messages]
+[Only incoming messages]
Tylko przychodzące wiadomości
-[Only Outgoing Messages]
+[Only outgoing messages]
Tylko wychodzące wiadomości
-[Only Selected Group]
+[Only selected group]
Tylko zaznaczona grupa
-[All Contacts]
+[All contacts]
Wszystkie kontakty
-[Export To Txt]
+[Export to txt]
Eksportuj do pliku tekstowego
[File encoding*]
Kodowanie pliku*
-[Export To Plain Html]
+[Export to plain HTML]
Eksportuj do czystego HTML
-[Export To Rich Html]
+[Export to rich HTML]
Eksportuj do rozszerzonego HTML
[External CSS file]
Zewnętrzny plik CSS
@@ -141,9 +141,9 @@ Anuluj
;file \plugins\BasicHistory\src\BasicHistory.cpp
[Open History]
Otwórz historię
-[View &History]
+[View &history]
Zobacz &historiÄ™
-[Delete All User History]
+[Delete all user history]
Usuń całą historię
[Execute history task]
Wykonaj zadanie historii
@@ -153,13 +153,13 @@ Przychodząca wiadomość
Wychodząca wiadomość
[Status change]
Zmiana statusu
-[Show Contacts]
+[Show contacts]
Pokaż kontakty
-[Hide Contacts]
+[Hide contacts]
Ukryj kontakty
-[Find Next]
+[Find next]
Wyszukaj następny
-[Find Previous]
+[Find previous]
Wyszukaj poprzedni
[Plus in export]
Plus w eksporcie
@@ -178,10 +178,10 @@ Historia dla "%s"
System
[Me]
Ja
-[Invalid Message]
-Nieprawidłowa Wiadomość
+[Invalid message]
+Nieprawidłowa wiadomość
;file \plugins\BasicHistory\src\ExportManager.cpp
-[%s Files (*.%s)]
+[%s files (*.%s)]
%s Pliki (*.%s)
[Import]
Importuj
@@ -194,7 +194,7 @@ Plik jest nieprawidłowy
;file \plugins\BasicHistory\src\HistoryWindow.cpp
[This operation will PERMANENTLY REMOVE all history for this contact.\nAre you sure you want to do this?]
Ta operacja TRWALE USUNIE całą historię tego kontaktu.\nCzy na pewno chcesz to zrobić?
-[Are You sure?]
+[Are you sure?]
Czy na pewno?
[Do you want to delete all imported messages for this contact?\nNote that next scheduler task import this messages again.]
Czy chcesz usunąć wszystkie zaimportowane wiadomości dla tego kontaktu?\nZauważ, że następne zadanie harmonogramu zaimportuje tą wiadomość ponownie.
@@ -208,11 +208,11 @@ Otwórz w &nowym oknie
Kopiuj
[Delete]
Usuń
-[Send Message]
+[Send message]
Wyślij wiadomość
-[Reply &Quoted]
+[Reply &quoted]
Odpowiedz &cytujÄ…c
-[Delete Group]
+[Delete group]
Usuń grupę
[Options]
Opcje
@@ -224,10 +224,10 @@ Czcionki i kolory
Ikony
[Hotkeys]
Skróty
-[Rich Html]
-Rozszerzony Html
-[Plain Html]
-Czysty Html
+[Rich HTML]
+Rozszerzony HTML
+[Plain HTML]
+Czysty HTML
[Txt]
Plik tekstowy
[Binary]
@@ -301,27 +301,27 @@ Tło listy kontaktów
Otwórz globalną historię
[Find]
Szukaj
-[Switch Match Case]
+[Switch match case]
Przełącz wielkość liter
-[Switch Match Whole Word]
+[Switch match whole word]
Przełącz całe wyrazy
-[Show/Hide Contacts]
+[Show/hide contacts]
Pokaż/Ukryj kontakty
-[Switch Only Incoming Messages]
+[Switch only incoming messages]
Przełącz na przychodzące wiadomości
-[Switch Only Outgoing Messages]
+[Switch only outgoing messages]
Przełącz na wychodzące wiadomości
-[Switch Only Selected Group]
+[Switch only selected group]
Przełącz na tylko zaznaczoną grupę
-[Switch All Contacts]
+[Switch all contacts]
Przełącz wszystkie kontakty
-[Export To Binary]
+[Export to binary]
Eksportuj do pliku biniarnego
-[Import From Binary]
+[Import from binary]
Importuj z pliku biniarnego
-[Export To Dat (mContacts)]
+[Export to dat (mContacts)]
Eksportuj do pliku .dat (mContacts)
-[Import From Dat (mContacts)]
+[Import from dat (mContacts)]
Importuj z pliku .dat (mContacts)
[Invalid event number]
Nieprawidłowy numer zdarzenia
@@ -333,7 +333,7 @@ WychodzÄ…ce zdarzenia
Plik nie istnieje. Wprowadź poprawną ścieżkę do pliku.
[Invalid file]
Nieprawidłowy plik
-[All Files (*.*)]
+[All files (*.*)]
Wszystkie pliki (*.*)
[Enter filter name]
Wpisz nazwÄ™ filtra
@@ -351,17 +351,17 @@ Wprowadziłeś nieprawidłową stronę kodową. Wybierz ją z combo boxa lub wpr
Nieprawidłowa strona kodowa
[Browse CSS file]
Wybierz plik CSS
-[Export and Delete]
+[Export and delete]
Eksportuj i usuń
-[Import and Merge]
+[Import and merge]
Importuj i scal
[Minute]
Minut
[Hour]
Godzin
-[At Start]
+[At start]
Na starcie
-[At Finish]
+[At finish]
Przy wyłączaniu
[Daily]
Dziennie
@@ -407,7 +407,7 @@ Importuj z
** Użyj <date> do umieszczenia daty, <ext> do umieszczenia rozszerzenia, <contact> do umieszczenia nazwy kontaktu
;file \plugins\BasicHistory\src\Options.h
;file \plugins\BasicHistory\src\PlainHtmlExport.cpp
-[History Log]
+[History log]
Historia
[Filter:]
Filtruj:
diff --git a/langpacks/polish/Plugins/Clist_modern.txt b/langpacks/polish/Plugins/Clist_modern.txt
index 9bab1d349e..2ca39e1875 100644
--- a/langpacks/polish/Plugins/Clist_modern.txt
+++ b/langpacks/polish/Plugins/Clist_modern.txt
@@ -50,6 +50,8 @@ UWAGA: \tSkórki mogą zmodyfikować twój profil. Przywrócenie zmian nie jest
* Miranda NG musi zostać zrestartowana aby zmiany przyniosły efekt
[Skin folder]
Folder skórek
+[Download more skins]
+Pobierz więcej skórek
[Available view modes]
Dostępne tryby widoku
[Include protocols]
diff --git a/langpacks/polish/Plugins/Clist_nicer.txt b/langpacks/polish/Plugins/Clist_nicer.txt
index 8ab49918e6..4c2e9639d3 100644
--- a/langpacks/polish/Plugins/Clist_nicer.txt
+++ b/langpacks/polish/Plugins/Clist_nicer.txt
@@ -380,6 +380,8 @@ Położenie grupy
Wysokość paska tytułu
[Ignore selection for groups]
Ignoruj zaznaczenie dla grup
+[Download more skins]
+Pobierz więcej skórek
[Load from skin file]
Załaduj skórkę z pliku
[Export to skin file]
diff --git a/langpacks/polish/Plugins/CloudFile.txt b/langpacks/polish/Plugins/CloudFile.txt
index ef50ad059a..4ed50bec07 100644
--- a/langpacks/polish/Plugins/CloudFile.txt
+++ b/langpacks/polish/Plugins/CloudFile.txt
@@ -2,7 +2,7 @@
;============================================================
; File: CloudFile.dll
; Plugin: CloudFile
-; Version: 0.11.0.2
+; Version: 0.11.0.3
; Authors: Miranda NG Team
;============================================================
[Allows you to transfer files via cloud services.]
diff --git a/langpacks/polish/Plugins/DbEditorPP.txt b/langpacks/polish/Plugins/DbEditorPP.txt
index 02d1b277ef..c8732028e1 100644
--- a/langpacks/polish/Plugins/DbEditorPP.txt
+++ b/langpacks/polish/Plugins/DbEditorPP.txt
@@ -2,7 +2,7 @@
;============================================================
; File: DbEditorPP.dll
; Plugin: Database editor++
-; Version: 4.0.1.1
+; Version: 4.0.1.2
; Authors: Bio, Jonathan Gordon
;============================================================
[Advanced Database Editor.]
diff --git a/langpacks/polish/Plugins/Fingerprint.txt b/langpacks/polish/Plugins/Fingerprint.txt
index 55108fe574..a79ab0a68f 100644
--- a/langpacks/polish/Plugins/Fingerprint.txt
+++ b/langpacks/polish/Plugins/Fingerprint.txt
@@ -46,8 +46,6 @@ Klienty MSN
Klienty QQ
[RSS clients]
Klienty RSS
-[Tlen clients]
-Klienty Tlen
[Weather clients]
Klienty Pogodowe
[Yahoo clients]
@@ -107,8 +105,6 @@ MRA (nieznany klient)
TM 2008 i >
[Gadu-Gadu client]
Klient Gadu-Gadu
-[Tlen.pl client]
-Klient Tlen.pl
[Python-based clients]
Klient bazujÄ…cy na Phytonie
[Jabber client]
@@ -139,8 +135,6 @@ Nakładka Jabber
Nakładka MSN
[QQ overlay]
Nakładka QQ
-[Tlen.pl overlay]
-Nakładka Tlen.pl
[Yahoo overlay]
Nakładka Yahoo
[Mail.Ru Agent overlay]
@@ -175,12 +169,6 @@ Klient Gadu-Gadu v10
Klient Gadu-Gadu v9
[Gadu-Gadu v8 client]
Klient Gadu-Gadu v8
-[Tlen 7.x overlay]
-Nakładka Tlen 7.x
-[Tlen 6.x overlay]
-Nakładka Tlen 6.x
-[Tlen 5.x overlay]
-Nakładka Tlen 5.x
[TM/QQ 2012 overlay]
Nakładka TM/QQ 2012
[TM/QQ 2011 overlay]
diff --git a/langpacks/polish/Plugins/GmailNotifier.txt b/langpacks/polish/Plugins/GmailNotifier.txt
index 584062dd4a..dc1e84a4e6 100644
--- a/langpacks/polish/Plugins/GmailNotifier.txt
+++ b/langpacks/polish/Plugins/GmailNotifier.txt
@@ -2,7 +2,7 @@
;============================================================
; File: GmailNotifier.dll
; Plugin: Gmail Multiple Notifier
-; Version: 0.3.1.1
+; Version: 1.0.1.1
; Authors: Mixwind
;============================================================
[Check your Gmail inboxes locally.]
@@ -57,21 +57,19 @@ Zapisuj nieczytane wątki w bazie danych(włącz historię)
;file \plugins\GmailNotifier\src\check.cpp
[Checking...]
Sprawdzanie...
-[Can't open Internet!]
-Nie udało się otworzyć przeglądarki!
-[Can't reach server!]
-Nie udało się połączyć z serwerem!
[Can't send account data!]
Nie udało się wysłać danych konta!
-[Can't get RSS feed!]
-Nie można pobrać kanału RSS!
[Wrong name or password!]
Błędna nazwa użytkownika lub hasło!
+[Can't get RSS feed!]
+Nie można pobrać kanału RSS!
;file \plugins\GmailNotifier\src\main.cpp
[Other]
Inne
[Gmail: New thread(s)]
Gmail: Nowy wÄ…tek(ki)
+[Gmail Notifier connection]
+
[&Check all Gmail inboxes]
Sprawdź wszystkie skrzynki Gmail
[&Check Gmail inbox]
diff --git a/langpacks/polish/Plugins/IEView.txt b/langpacks/polish/Plugins/IEView.txt
index ccc419d6a9..6f4e7d7122 100644
--- a/langpacks/polish/Plugins/IEView.txt
+++ b/langpacks/polish/Plugins/IEView.txt
@@ -66,6 +66,8 @@ Pokaż datę
Użyj długiego formatu daty
[Use relative timestamp]
Użyj relatywnego czasu i daty
+[Download more templates]
+
;file \plugins\IEView\src\HistoryHTMLBuilder.cpp
[Outgoing File Transfer]
WychodzÄ…ce transfery
diff --git a/langpacks/polish/Plugins/MSN.txt b/langpacks/polish/Plugins/MSN.txt
index e79f32774a..248bc163bf 100644
--- a/langpacks/polish/Plugins/MSN.txt
+++ b/langpacks/polish/Plugins/MSN.txt
@@ -2,7 +2,7 @@
;============================================================
; File: MSN.dll
; Plugin: MSN protocol
-; Version: 0.14.0.1
+; Version: 0.14.0.2
; Authors: Boris Krasnovskiy, George Hazan, Richard Hughes, leecher
;============================================================
[Microsoft Network (MSN) protocol support for Miranda NG.]
diff --git a/langpacks/polish/Plugins/New_GPG.txt b/langpacks/polish/Plugins/New_GPG.txt
index c660dbec1f..c4072a465b 100644
--- a/langpacks/polish/Plugins/New_GPG.txt
+++ b/langpacks/polish/Plugins/New_GPG.txt
@@ -176,86 +176,6 @@ Importuj klucze publiczne GPG
[GPG encryption status]
Status szyfrowania GPG
;file \plugins\New_GPG\src\main.cpp
-[Email]
-E-mail
-[Name]
-Nazwa
-[Creation date]
-Data utworzenia
-[Expire date]
-Data wygaśnięcia
-[Key length]
-Długość klucza
-[Accounts]
-Konta
-[Default]
-Domyślny
-[key ID]
-ID klucza
-[not set]
-nie ustawiono
-[Default private key ID]
-Domyślny prywatny ID klucza
-[Failed to open file]
-Błąd otwierania pliku
-[Error]
-Błąd
-[Generating new random key, please wait]
-Generuj nowy losowy klucz, proszę czekać
-[Failed to allocate memory]
-Nie udało się przydzielić pamięci
-[Failed to lock memory with error %d]
-Nie udało się zablokować pamięci z błędem %d
-[Failed write to clipboard with error %d]
-Nie udało się zapisać w schowku z błędem %d
-[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
-Znaleziono plik binarny GPG w folderze Mirandy, ale angielskie ustawienia regionalne nie istnieją.\nWysoce zaleca się umieszczenie \\gnupg.nls\\en@quot.mo w folderze GnuPG w głównym folderze Mirandy.\nBez tego pliku możesz doświadczyć wielu problemów z wyjściem GPG w systemach innych niż angielski,\na wtyczka może w ogóle nie działać.\nZostałeś ostrzeżony.
-[Warning]
-Ostrzeżenie
-[Wrong GPG binary location found in system.\nPlease choose another location]
-Znaleziono niepoprawną lokalizację pliku binarnego GPG w systemie.\nProszę wybrać inną lokalizację
-[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-To nie jest plik binarny GnuPG !\nZalecana wersja to v1.x.x.
-[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-Znaleziono niewspieraną wersję GnuPG. Używasz na własną odpowiedzialność!\nZaleca się używania gnupg v1.x.x w połączeniu z tą wtyczką.
-["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
-Znaleziono katalog "GPG" w folderze Mirandy.\nZakładam, że jest to katalog domowy "GPG".\nUstawiono katalog domowy GPG.
-[Info]
-Info
-[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
-Twoja wersja GPG jest wspierana. Znaleziono plik językowy.\nWtyczka GPG powinna działać poprawnie.\nNaciśnij OK, aby kontynuować.
-[GPG binary does not exist.\nPlease choose another location]
-Plik binarny gpg nie istnieje.\nProszę wybrać inną lokalizację.
-[Please choose GPG binary location]
-Proszę wybrać lokalizację pliku binarnego GPG
-[Please set keyring's home directory]
-Proszę ustawić katalog domowy breloka
-[There is existing key for contact, would you like to replace it with new key?]
-Istnieje już klucz dla tego kontaktu. Czy chcesz zastąpić go nowym?
-[New public key was received, do you want to import it?]
-Otrzymano nowy klucz publiczny. Czy chcesz go zaimportować?
-[Replace]
-ZastÄ…p
-[Accept]
-Akceptuj
-[Received key from %s]
-Otrzymano klucz od %s
-[You must set encryption algorithm first]
-Musisz najpierw ustawić algorytm szyfrujący
-[Key length must be of length from 1024 to 4096 bits]
-Długość klucza musi mieć od 1024 do 4096 bitów
-[Invalid date]
-Niepoprawna data
-[Name must contain at least 5 characters]
-Nazwa musi zawierać co najmniej 5 znaków
-[Name cannot contain '(' or ')']
-Nazwa nie może zawierać "(", ani ")"
-[Invalid Email]
-Niepoprawny adres e-mail
-[Generating new key, please wait...]
-Generuj nowy klucz, proszę czekać...
-[Failed to export public key.]
-Błąd eksportu kluczu publicznego.
[GPG binary is set and valid (this is good).\n]
Plik binarny GPG został ustawiony i jest poprawny (to dobrze).\n
[GPG binary unset or invalid (plugin will not work).\n]
@@ -293,6 +213,8 @@ Wykryto metakontakt
;file \plugins\New_GPG\src\messages.cpp
[We received encrypted message from contact with encryption turned off.\nDo you want to turn on encryption for this contact?]
Otrzymano zaszyfrowaną wiadomość od kontaktu, dla którego szyfrowanie jest wyłączone.\nCzy chcesz włączyć szyfrowanie dla tego kontaktu?
+[Warning]
+Ostrzeżenie
[Do you want to try to decrypt encrypted message?]
Czy chcesz spróbować odszyfrować zaszyfrowaną wiadomość?
[We're trying to encrypt with untrusted key. Do you want to trust this key permanently?]
@@ -300,22 +222,20 @@ Próbujemy zaszyfrować niezaufanym kluczem. Czy chcesz na stałe zaufać temu k
[Something is wrong, GPG does not understand us, aborting encryption.]
CoÅ› jest nie tak, GPG nas nie rozumie, anulowanie szyfrowania.
;file \plugins\New_GPG\src\options.cpp
-[Services]
-Usługi
-[Main]
-Ogólne
-[GnuPG Variables]
-Zmienne GnuPG
-[Messages]
-Wiadomości
-[Advanced]
-Zaawansowane
[Contact]
Kontakt
[Key ID]
ID klucza
+[Name]
+Nazwa
+[Email]
+E-mail
[Protocol]
Protokół
+[Default private key ID]
+Domyślny prywatny ID klucza
+[not set]
+nie ustawiono
[This key is not used by any contact. Do you want to remove it from public keyring?]
Ten klucz nie jest używany przez żaden kontakt. Czy chcesz usunąć go z breloka publicznego?
[Key info]
@@ -332,6 +252,14 @@ Czy chcesz usunąć klucz z metakontaktu (wszystkie subkontakty)?
Eksportuj klucz publiczny
[.asc pubkey file]
plik klucza publicznego .asc
+[Failed to allocate memory]
+Nie udało się przydzielić pamięci
+[Error]
+Błąd
+[Failed to lock memory with error %d]
+Nie udało się zablokować pamięci z błędem %d
+[Failed write to clipboard with error %d]
+Nie udało się zapisać w schowku z błędem %d
[Failed to open clipboard with error %d]
Nie udało się otworzyć schowka z błędem %d
[Set log file]
@@ -340,6 +268,8 @@ Ustaw plik dziennika
Pliki LOG
[Choose gpg.exe]
Wybierz gpg.exe
+[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+To nie jest plik binarny GnuPG !\nZalecana wersja to v1.x.x.
[Set home directory]
Ustaw folder domowy
[Load Public GPG Key for ]
@@ -356,12 +286,83 @@ Wczytaj klucz publiczny GPG (ID klucza:\s
To nie jest prywatny, ani publiczny klucz
[Key already in secret keyring.]
Klucz znajduje się już w tajnym breloku.
+[Info]
+Info
[Set file containing GPG public key]
Ustaw plik zawierajÄ…cy publiczny klucz GPG
[GPG public key file]
Publiczny klucz GPG
+[Failed to open file]
+Błąd otwierania pliku
[There is no public or private key.]
Nie ma żadnych kluczy prywatnych, ani publicznych.
+[Services]
+Usługi
+[Main]
+Ogólne
+[GnuPG Variables]
+Zmienne GnuPG
+[Messages]
+Wiadomości
+[Advanced]
+Zaawansowane
+;file \plugins\New_GPG\src\ui.cpp
+[New passwords do not match]
+Nowe hasła nie zgadzają się
+[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+Stare hasło nie zgadza się, możesz kontynuować, ale GPG odrzuci błędne hasło.\nCzy chcesz kontynuować?
+[Creation date]
+Data utworzenia
+[Expire date]
+Data wygaśnięcia
+[Key length]
+Długość klucza
+[Accounts]
+Konta
+[Default]
+Domyślny
+[key ID]
+ID klucza
+[Generating new random key, please wait]
+Generuj nowy losowy klucz, proszę czekać
+[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
+Znaleziono plik binarny GPG w folderze Mirandy, ale angielskie ustawienia regionalne nie istnieją.\nWysoce zaleca się umieszczenie \\gnupg.nls\\en@quot.mo w folderze GnuPG w głównym folderze Mirandy.\nBez tego pliku możesz doświadczyć wielu problemów z wyjściem GPG w systemach innych niż angielski,\na wtyczka może w ogóle nie działać.\nZostałeś ostrzeżony.
+[Wrong GPG binary location found in system.\nPlease choose another location]
+Znaleziono niepoprawną lokalizację pliku binarnego GPG w systemie.\nProszę wybrać inną lokalizację
+[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+Znaleziono niewspieraną wersję GnuPG. Używasz na własną odpowiedzialność!\nZaleca się używania gnupg v1.x.x w połączeniu z tą wtyczką.
+["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
+Znaleziono katalog "GPG" w folderze Mirandy.\nZakładam, że jest to katalog domowy "GPG".\nUstawiono katalog domowy GPG.
+[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
+Twoja wersja GPG jest wspierana. Znaleziono plik językowy.\nWtyczka GPG powinna działać poprawnie.\nNaciśnij OK, aby kontynuować.
+[There is existing key for contact, would you like to replace it with new key?]
+Istnieje już klucz dla tego kontaktu. Czy chcesz zastąpić go nowym?
+[New public key was received, do you want to import it?]
+Otrzymano nowy klucz publiczny. Czy chcesz go zaimportować?
+[Replace]
+ZastÄ…p
+[Accept]
+Akceptuj
+[Received key from %s]
+Otrzymano klucz od %s
+[You must set encryption algorithm first]
+Musisz najpierw ustawić algorytm szyfrujący
+[Key length must be of length from 1024 to 4096 bits]
+Długość klucza musi mieć od 1024 do 4096 bitów
+[Invalid date]
+Niepoprawna data
+[Name must contain at least 5 characters]
+Nazwa musi zawierać co najmniej 5 znaków
+[Name cannot contain '(' or ')']
+Nazwa nie może zawierać "(", ani ")"
+[Invalid Email]
+Niepoprawny adres e-mail
+[Generating new key, please wait...]
+Generuj nowy klucz, proszę czekać...
+[Expiration date]
+
+[Failed to export public key.]
+Błąd eksportu kluczu publicznego.
;file \plugins\New_GPG\src\utilities.cpp
[Do you want to toggle encryption for all subcontacts?]
Czy chcesz przełączyć szyfrowanie dla wszystkich subkontaktów?
@@ -393,7 +394,10 @@ Pomyślnie przetworzono %d kluczy publicznych i ileś kluczy prywatnych.
Pomyślnie przetworzono %d kluczy publicznych.
[Keys import result]
Wynik importu kluczy
-[New passwords do not match]
-Nowe hasła nie zgadzają się
-[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
-Stare hasło nie zgadza się, możesz kontynuować, ale GPG odrzuci błędne hasło.\nCzy chcesz kontynuować?
+[GPG binary does not exist.\nPlease choose another location]
+Plik binarny gpg nie istnieje.\nProszę wybrać inną lokalizację.
+[Please choose GPG binary location]
+Proszę wybrać lokalizację pliku binarnego GPG
+[Please set keyring's home directory]
+Proszę ustawić katalog domowy breloka
+;file \plugins\New_GPG\src\utilities.h
diff --git a/langpacks/polish/Plugins/SimpleStatusMsg.txt b/langpacks/polish/Plugins/SimpleStatusMsg.txt
index 606b460d78..d1d8ab8454 100644
--- a/langpacks/polish/Plugins/SimpleStatusMsg.txt
+++ b/langpacks/polish/Plugins/SimpleStatusMsg.txt
@@ -3,7 +3,7 @@
; File: SimpleStatusMsg.dll
; Plugin: Simple status message
; Version: 1.9.0.6
-; Authors: Bartosz 'Dezeath' Bialek, Harven
+; Authors: Bartosz 'Dezeath' Białek, Harven
;============================================================
[Provides a simple way to set status and away messages.]
Umożliwia zmianę statusu i opisów w prosty sposób.
diff --git a/langpacks/polish/Plugins/SmileyAdd.txt b/langpacks/polish/Plugins/SmileyAdd.txt
index ba57b07bbc..6c39f6ab22 100644
--- a/langpacks/polish/Plugins/SmileyAdd.txt
+++ b/langpacks/polish/Plugins/SmileyAdd.txt
@@ -2,7 +2,7 @@
;============================================================
; File: SmileyAdd.dll
; Plugin: SmileyAdd
-; Version: 0.2.4.2
+; Version: 0.3.0.1
; Authors: Peacow, nightwish, bid, borkra
;============================================================
[Smiley support for Miranda NG.]
@@ -98,16 +98,14 @@ Specyficzne dla protokołu
;file \plugins\SmileyAdd\src\smileys.cpp
[Smiley pack %s for category "%s" not found.\nSelect correct smiley pack in the Options -> Customize -> Smileys.]
Nie znaleziono paczki emotikon %s dla kategorii "%s".\nWybierz właściwą paczkę w Opcje -> Personalizacja -> Emotikony.
-[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
-Wystąpiły problemy z wczytaniem paczki emotikon (powinny już działać).\nPo szczegóły zajrzyj do dziennika.
[Smiley #%u in file %s for smiley pack %s not found.]
Nie znaleziono uśmieszku #%u w pliku %s dla paczki uśmieszków %s.
+[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
+Wystąpiły problemy z wczytaniem paczki emotikon (powinny już działać).\nPo szczegóły zajrzyj do dziennika.
[%s global smiley pack]
Globalna paczka emotikon %s
[Standard]
Standardowe
-[Regular expression "%s" in smiley pack "%s" could produce "empty matches".]
-Wyrażenie regularne "%s" w paczce %s może spowodować puste dopasowania.
[Regular expression "%s" in smiley pack "%s" malformed.]
Wyrażenie regularne "%s" w paczce %s zniekształcone.
;file \plugins\SmileyAdd\src\smltool.cpp
diff --git a/langpacks/polish/Plugins/SplashScreen.txt b/langpacks/polish/Plugins/SplashScreen.txt
index 65da5640b0..989b8e2138 100644
--- a/langpacks/polish/Plugins/SplashScreen.txt
+++ b/langpacks/polish/Plugins/SplashScreen.txt
@@ -38,6 +38,8 @@ Przygasanie końcowe:
Nie znaleziono wtyczki AdvaImg.. Pobierz ją z https://miranda-ng.org/p/AdvaImg/, aby móc używać obrazków.
[Preview...]
PodglÄ…d...
+[Download more splash screens]
+
;file \plugins\SplashScreen\src\options.cpp
[Graphic files]
Pliki graficzne
diff --git a/langpacks/polish/Plugins/StatusManager.txt b/langpacks/polish/Plugins/StatusManager.txt
index adbfe59e6d..c9296b42f7 100644
--- a/langpacks/polish/Plugins/StatusManager.txt
+++ b/langpacks/polish/Plugins/StatusManager.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StatusManager.dll
; Plugin: Status manager
-; Version: 0.11.2.3
+; Version: 1.0.1.1
; Authors: P Boon
;============================================================
[A connection checker and auto away module. Also allows you to define the status Miranda should set on startup, configurable per protocol.]
diff --git a/langpacks/polish/Plugins/Steam.txt b/langpacks/polish/Plugins/Steam.txt
index 344ca95118..41c4d529ad 100644
--- a/langpacks/polish/Plugins/Steam.txt
+++ b/langpacks/polish/Plugins/Steam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Steam.dll
; Plugin: Steam protocol
-; Version: 0.11.6.1
+; Version: 0.11.6.3
; Authors: Miranda NG Team, Robert Pösel
;============================================================
[Steam protocol support for Miranda NG.]
diff --git a/langpacks/polish/Plugins/StopSpam.txt b/langpacks/polish/Plugins/StopSpam.txt
index b51b3b85a1..799142dd93 100644
--- a/langpacks/polish/Plugins/StopSpam.txt
+++ b/langpacks/polish/Plugins/StopSpam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpam.dll
; Plugin: StopSpam+
-; Version: 0.0.1.5
+; Version: 0.1.0.1
; Authors: Roman Miklashevsky, A. Petkevich, Kosh&chka, persei
;============================================================
[Anti-spam plugin for Miranda NG.]
@@ -43,6 +43,9 @@ Dziennik spamu w historii systemowej
;file \plugins\StopSpamPlus\src\events.cpp
[StopSpam automatic message:\r\n]
Automatyczna odpowiedź StopSpam:\r\n
+;file \plugins\StopSpamPlus\src\options.cpp
+[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
+Nigdy więcej spamu! Roboty się nie przedrą! Tylko ludzie przejdą zabezpieczenie!\r\n\r\nWtyczka działa bardzo prosto:\r\nWiadomości od użytkowników z listy kontaktów zostaną dostarczone, ponieważ nie ma żadnego oprogramowania anty-spamowego, wiadomości od nieznanych użytkowników nie będą dostarczane. Ale też nie są one ignorowane, wtyczka zadaje proste pytanie, a jeśli użytkownik poda poprawną odpowiedź, plugin doda go do twojej listy kontaktów aby mógł się z tobą skontaktować.
[Message sessions]
Okno rozmowy
[General]
@@ -51,21 +54,18 @@ Ogólne
Wiadomości
[Accounts]
Konta
-;file \plugins\StopSpamPlus\src\options.cpp
-[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
-Nigdy więcej spamu! Roboty się nie przedrą! Tylko ludzie przejdą zabezpieczenie!\r\n\r\nWtyczka działa bardzo prosto:\r\nWiadomości od użytkowników z listy kontaktów zostaną dostarczone, ponieważ nie ma żadnego oprogramowania anty-spamowego, wiadomości od nieznanych użytkowników nie będą dostarczane. Ale też nie są one ignorowane, wtyczka zadaje proste pytanie, a jeśli użytkownik poda poprawną odpowiedź, plugin doda go do twojej listy kontaktów aby mógł się z tobą skontaktować.
;file \plugins\StopSpamPlus\src\services.cpp
[Not In List]
Z Poza Listy
[Complete]
Zakończony
-;file \plugins\StopSpamPlus\src\settings.h
+;file \plugins\StopSpamPlus\src\settings.cpp
[Spammers made me to install small anti-spam system you are now speaking with. Please reply "nospam" without quotes and spaces if you want to contact me.]
Spamerzy sprawili, że musiałem zainstalować drobny system antyspamowy, z którym teraz rozmawiasz. Odpowiedz wiadomością o treści "niespam" bez cudzysłowu i spacji, jeśli chcesz ze mną porozmawiać.
-[Congratulations! You just passed human/robot test. Now you can write me a message.]
-Gratulacje! Przeszedłeś test. Teraz możesz napisać do mnie wiadomość.
[StopSpam: send a message and reply to an anti-spam bot question.]
StopSpam: wyślij wiadomość i odpowiedz na pytania bota.
+[Congratulations! You just passed human/robot test. Now you can write me a message.]
+Gratulacje! Przeszedłeś test. Teraz możesz napisać do mnie wiadomość.
;file \plugins\StopSpamPlus\src\stdafx.h
[StopSpam]
StopSpam
diff --git a/langpacks/polish/Plugins/StopSpamMod.txt b/langpacks/polish/Plugins/StopSpamMod.txt
index febe161138..237cc9700c 100644
--- a/langpacks/polish/Plugins/StopSpamMod.txt
+++ b/langpacks/polish/Plugins/StopSpamMod.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpamMod.dll
; Plugin: StopSpam mod
-; Version: 0.0.2.1
+; Version: 0.0.2.2
; Authors: Roman Miklashevsky, sss, Elzor
;============================================================
[Anti-spam plugin for Miranda NG.]
diff --git a/langpacks/polish/Plugins/TabSRMM.txt b/langpacks/polish/Plugins/TabSRMM.txt
index 5e8b98f0a9..8b6989c4e2 100644
--- a/langpacks/polish/Plugins/TabSRMM.txt
+++ b/langpacks/polish/Plugins/TabSRMM.txt
@@ -516,6 +516,8 @@ Można eksportować i importować wszystkie ustawienia kolorów i czcionek tutaj
Eksportuj do pliku...
[Import from a file...]
Importuj z pliku...
+[Download more skins]
+Pobierz więcej skórek
[Icons]
Ikony
[Event type icons in the message log]
diff --git a/langpacks/polish/Plugins/Tox.txt b/langpacks/polish/Plugins/Tox.txt
index 5401678d61..a49482747e 100644
--- a/langpacks/polish/Plugins/Tox.txt
+++ b/langpacks/polish/Plugins/Tox.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Tox.dll
; Plugin: Tox protocol
-; Version: 0.11.1.25
+; Version: 0.11.1.26
; Authors: Miranda NG Team
;============================================================
[Tox protocol support for Miranda NG.]
diff --git a/langpacks/polish/Plugins/mRadio.txt b/langpacks/polish/Plugins/mRadio.txt
index 228ae344c1..8d20a3773d 100644
--- a/langpacks/polish/Plugins/mRadio.txt
+++ b/langpacks/polish/Plugins/mRadio.txt
@@ -101,8 +101,8 @@ Ciągłe nagrywanie
Kamieniołom
[Sorry!]
Przepraszamy!
-[BASS.DLL not found!]
-BASS.dll nie odnaleziony!
+[bass.dll not found!]
+bass.dll nie odnaleziony!
[Station]
Stacja
[Custom INI file]
@@ -199,3 +199,5 @@ Equalizer
Nowy
[Quick Open]
Szybkie Otwieranie
+[bass.dll not found! Choose bass.dll path manually]
+
diff --git a/langpacks/polish/Untranslated/GmailNotifier.txt b/langpacks/polish/Untranslated/GmailNotifier.txt
new file mode 100644
index 0000000000..fe2bc3771c
--- /dev/null
+++ b/langpacks/polish/Untranslated/GmailNotifier.txt
@@ -0,0 +1 @@
+[Gmail Notifier connection]
diff --git a/langpacks/polish/Untranslated/IEView.txt b/langpacks/polish/Untranslated/IEView.txt
index 1ee743fce8..f312c8569f 100644
--- a/langpacks/polish/Untranslated/IEView.txt
+++ b/langpacks/polish/Untranslated/IEView.txt
@@ -1,3 +1,4 @@
+[Download more templates]
[RTL On]
[RTL Off]
[Group On]
diff --git a/langpacks/polish/Untranslated/New_GPG.txt b/langpacks/polish/Untranslated/New_GPG.txt
new file mode 100644
index 0000000000..8c633b12eb
--- /dev/null
+++ b/langpacks/polish/Untranslated/New_GPG.txt
@@ -0,0 +1 @@
+[Expiration date]
diff --git a/langpacks/polish/Untranslated/SplashScreen.txt b/langpacks/polish/Untranslated/SplashScreen.txt
new file mode 100644
index 0000000000..0add885a64
--- /dev/null
+++ b/langpacks/polish/Untranslated/SplashScreen.txt
@@ -0,0 +1 @@
+[Download more splash screens]
diff --git a/langpacks/polish/Untranslated/mRadio.txt b/langpacks/polish/Untranslated/mRadio.txt
new file mode 100644
index 0000000000..8de4f1d381
--- /dev/null
+++ b/langpacks/polish/Untranslated/mRadio.txt
@@ -0,0 +1 @@
+[bass.dll not found! Choose bass.dll path manually]
diff --git a/langpacks/russian/=CORE=.txt b/langpacks/russian/=CORE=.txt
index 9610f62c40..0979fdf215 100644
--- a/langpacks/russian/=CORE=.txt
+++ b/langpacks/russian/=CORE=.txt
@@ -3,28 +3,6 @@
; Module: Miranda Core
; Version: 0.95.8
;============================================================
-[Authorization request]
-Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸
-[&Authorize]
-&Разрешить
-[&Deny]
-&Запретить
-[Decide &later]
-Решить &позже
-[User &details]
-&ИнформациÑ
-[Reason:]
-Причина:
-[Denial reason:]
-Причина отказа:
-[Add to contact list if authorized]
-Добавить в ÑпиÑок контактов поÑле авторизации
-[You were added]
-Ð’Ð°Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ð»Ð¸
-[&Close]
-&Закрыть
-[&Add]
-&Добавить
[%s message for %s]
%s Ñообщение Ð´Ð»Ñ %s
[&Cancel]
@@ -287,6 +265,8 @@
ОпиÑание:
[&User menu]
Меню &пользователÑ
+[User &details]
+&ИнформациÑ
[&History]
&ИÑториÑ
[Incoming file transfer]
@@ -303,6 +283,8 @@
Файлы:
[Save to:]
СохранÑть в:
+[&Add]
+&Добавить
[&Open...]
&Открыть...
[Open &folder]
@@ -391,10 +373,6 @@
ДопиÑать " (1)" и Ñ‚.д.
[You will always be asked about files from people not on your contact list]
Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð²Ñегда будет показан, еÑли человек не в ÑпиÑке контактов
-[About Miranda NG]
-О программе
-[Credits >]
-БлагодарноÑти >
[Become idle if the following is left unattended:]
Перейти в режим ожиданиÑ, еÑли неактивны:
[Become idle if the screen saver is active]
@@ -713,6 +691,8 @@
Заданное имÑ:
[Group:]
Группа:
+[Authorization request]
+Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸
[&Yes]
&Да
[&No]
@@ -989,6 +969,8 @@
Ð’Ñтавить вложенное меню
[Insert separator]
Ð’Ñтавить разделитель
+[Module:]
+Модуль:
[Service:]
Cлужба:
[Default]
@@ -1123,6 +1105,26 @@ UIN, E-mail и т.д.
Промежуток кнопок:
[Hide if there isn't enough space]
Скрывать, еÑли недоÑтаточно меÑта
+[&Authorize]
+&Разрешить
+[&Deny]
+&Запретить
+[Decide &later]
+Решить &позже
+[Reason:]
+Причина:
+[Denial reason:]
+Причина отказа:
+[Add to contact list if authorized]
+Добавить в ÑпиÑок контактов поÑле авторизации
+[You were added]
+Ð’Ð°Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ð»Ð¸
+[&Close]
+&Закрыть
+[About Miranda NG]
+О программе
+[Credits >]
+БлагодарноÑти >
[Tray]
Трей
[&Hide/Show]
@@ -1183,40 +1185,6 @@ UIN, E-mail и т.д.
Google Карты
[Google Translate]
Переводчик Google
-[%s requests authorization]
-%s запрашивает авторизацию
-[%u requests authorization]
-%u запрашивает авторизацию
-[%s added you to their contact list]
-%s добавил Ð²Ð°Ñ Ð² Ñвой ÑпиÑок контактов
-[%u added you to their contact list]
-%u добавил Ð²Ð°Ñ Ð² Ñвой ÑпиÑок контактов
-[Alerts]
-УведомлениÑ
-[Added event]
-Событие добавлениÑ
-[View user's details]
-Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ пользователе
-[Add contact permanently to list]
-Добавить в ÑпиÑок контактов
-[<Unknown>]
-<ÐеизвеÑтно>
-[%s added you to the contact list\n%u (%s) on %s]
-%s добавил Ð²Ð°Ñ Ð² Ñвой ÑпиÑок контактов\n%u (%s) в %s
-[%s added you to the contact list\n%u on %s]
-%s добавил Ð²Ð°Ñ Ð² Ñвой ÑпиÑок контактов\n%u в %s
-[%s added you to the contact list\n%s on %s]
-%s добавил Ð²Ð°Ñ Ð² Ñвой ÑпиÑок контактов\n%s в %s
-[(Unknown)]
-(ÐеизвеÑтный)
-[%s requested authorization\n%u (%s) on %s]
-%s запроÑил(а) авторизацию\n%u (%s) в %s
-[%s requested authorization\n%u on %s]
-%s запроÑил(а) авторизацию\n%u в %s
-[%s requested authorization\n%s on %s]
-%s запроÑил(а) авторизацию\n%s в %s
-[Feature is not supported by protocol]
-Ðе поддерживаетÑÑ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»Ð¾Ð¼
[Re&ad %s message]
&Прочитать Ñообщение "%s"
[Re&ad status message]
@@ -1325,6 +1293,10 @@ Google Карты
Выбрать папку
[My received files]
ПринÑтые файлы
+[Add contact permanently to list]
+Добавить в ÑпиÑок контактов
+[View user's details]
+Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ пользователе
[View user's history]
ИÑÑ‚Ð¾Ñ€Ð¸Ñ Ñообщений
[User menu]
@@ -1389,18 +1361,6 @@ Google Карты
Передача и проверка на вируÑÑ‹ завершены
[Outgoing]
ИÑходÑщие
-[< Copyright]
-< ÐвторÑкие права
-[&Help]
-&Справка
-[&About...]
-&О программе...
-[&Support]
-&Поддержка
-[&Miranda NG homepage]
-О&фициальный Ñайт Miranda NG
-[&Report bug]
-Сооб&щить об ошибке
[Idle]
Ожидание
[Chat module]
@@ -1859,10 +1819,40 @@ Miranda не Ñмогла загрузить вÑтроенную ÑиÑтему
Личные &данные...
[%s is online]
%s в Ñети
+[Alerts]
+УведомлениÑ
[Add %s]
Добавить %s
[Please authorize my request and add me to your contact list.]
ПожалуйÑта, разрешите добавить Ð²Ð°Ñ Ð² мой ÑпиÑок контактов.
+[%s requests authorization]
+%s запрашивает авторизацию
+[%u requests authorization]
+%u запрашивает авторизацию
+[%s added you to their contact list]
+%s добавил Ð²Ð°Ñ Ð² Ñвой ÑпиÑок контактов
+[%u added you to their contact list]
+%u добавил Ð²Ð°Ñ Ð² Ñвой ÑпиÑок контактов
+[Added event]
+Событие добавлениÑ
+[<Unknown>]
+<ÐеизвеÑтно>
+[%s added you to the contact list\n%u (%s) on %s]
+%s добавил Ð²Ð°Ñ Ð² Ñвой ÑпиÑок контактов\n%u (%s) в %s
+[%s added you to the contact list\n%u on %s]
+%s добавил Ð²Ð°Ñ Ð² Ñвой ÑпиÑок контактов\n%u в %s
+[%s added you to the contact list\n%s on %s]
+%s добавил Ð²Ð°Ñ Ð² Ñвой ÑпиÑок контактов\n%s в %s
+[(Unknown)]
+(ÐеизвеÑтный)
+[%s requested authorization\n%u (%s) on %s]
+%s запроÑил(а) авторизацию\n%u (%s) в %s
+[%s requested authorization\n%u on %s]
+%s запроÑил(а) авторизацию\n%u в %s
+[%s requested authorization\n%s on %s]
+%s запроÑил(а) авторизацию\n%s в %s
+[Feature is not supported by protocol]
+Ðе поддерживаетÑÑ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»Ð¾Ð¼
[&Join chat]
Войти в чат
[&Open chat window]
@@ -2131,6 +2121,18 @@ Ctrl+ИÑкать добавлÑет контакт
ОÑновной текÑÑ‚
[Small text]
Дополнительный текÑÑ‚
+[< Copyright]
+< ÐвторÑкие права
+[&Help]
+&Справка
+[&About...]
+&О программе...
+[&Support]
+&Поддержка
+[&Miranda NG homepage]
+О&фициальный Ñайт Miranda NG
+[&Report bug]
+Сооб&щить об ошибке
[Browser: Back]
Браузер: Ðазад
[Browser: Forward]
diff --git a/langpacks/russian/=HEAD=.txt b/langpacks/russian/=HEAD=.txt
index 7f7bd22f62..0eef0062a4 100644
--- a/langpacks/russian/=HEAD=.txt
+++ b/langpacks/russian/=HEAD=.txt
@@ -1,6 +1,6 @@
Miranda Language Pack Version 1
Locale: 0419
-Last-Modified-Using: 0.95.7
+Last-Modified-Using: 0.95.8
Authors: Homeric (founder), BasiL (maintainer),
Authors: `arag0rn`, +eRRikon, Abyss, al.dexter, Alexander, Alexander Logvinov, Alexander S. Kiselev, apollo2k4,
Authors: ALeXey, Alexey Yakovlev, Andrey A. Chernov, Bergelmir, Bravo123, Buser!, CriS,
diff --git a/langpacks/russian/Plugins/AIM.txt b/langpacks/russian/Deprecated/AIM.txt
index 33dba3e4be..33dba3e4be 100644
--- a/langpacks/russian/Plugins/AIM.txt
+++ b/langpacks/russian/Deprecated/AIM.txt
diff --git a/langpacks/russian/Plugins/AddContactPlus.txt b/langpacks/russian/Plugins/AddContactPlus.txt
index 6ad64ab14e..99929cb7dc 100644
--- a/langpacks/russian/Plugins/AddContactPlus.txt
+++ b/langpacks/russian/Plugins/AddContactPlus.txt
@@ -3,7 +3,7 @@
; File: AddContactPlus.dll
; Plugin: Add contact+
; Version: 0.9.9.2
-; Authors: Bartosz 'Dezeath' Bialek
+; Authors: Bartosz 'Dezeath' Białek
;============================================================
[Provides the ability to quickly add new contacts.]
ПредоÑтавлÑет возможноÑть быÑтро добавить контакт.
diff --git a/langpacks/russian/Plugins/AssocMgr.txt b/langpacks/russian/Plugins/AssocMgr.txt
index c57a5d89cc..2289e2f3e7 100644
--- a/langpacks/russian/Plugins/AssocMgr.txt
+++ b/langpacks/russian/Plugins/AssocMgr.txt
@@ -5,8 +5,8 @@
; Version: 0.2.1.0
; Authors: H. Herkenrath
;============================================================
-[Handles file type associations and URLs like aim, gg, mirpu, tlen, wpmsg, xmpp, ymsgr.]
-ÐÑÑÐ¾Ñ†Ð¸Ð°Ñ†Ð¸Ñ Ñ€Ð°Ñширений файлов и URL-ÑÑылок Ñ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»Ð°Ð¼Ð¸: AIM, Gadu-Gadu, Jabber, MSN, PluginUpdater, Tlen, Yahoo.
+[Handles file type associations and URLs like aim, gg, mirpu, wpmsg, xmpp, ymsgr.]
+ÐÑÑÐ¾Ñ†Ð¸Ð°Ñ†Ð¸Ñ Ñ€Ð°Ñширений файлов и URL-ÑÑылок Ñ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»Ð°Ð¼Ð¸: AIM, Gadu-Gadu, Jabber, MSN, PluginUpdater, Yahoo.
[Registered associations for Miranda NG:]
ЗарегиÑтрированные аÑÑоциации Ð´Ð»Ñ Miranda NG:
[Miscellaneous]
diff --git a/langpacks/russian/Plugins/BASS_interface.txt b/langpacks/russian/Plugins/BASS_interface.txt
index b648007549..23518fdd78 100644
--- a/langpacks/russian/Plugins/BASS_interface.txt
+++ b/langpacks/russian/Plugins/BASS_interface.txt
@@ -1,19 +1,19 @@
#muuid {2f07ea05-05b5-4ff0-875d-c590da2ddac1}
;============================================================
; File: BASS_interface.dll
-; Plugin: BASS interface
+; Plugin: BASS Interface
; Version: 0.0.0.14
; Authors: tico-tico
;============================================================
-[un4seen's BASS interface Miranda NG plugin.]
+[Un4seen's BASS interface Miranda NG plugin.]
Поддержка библиотеки BASS Ð´Ð»Ñ Miranda NG.
-[un4seen's bass interface]
+[Un4seen's BASS interface]
Поддержка библиотеки BASS
[bass.dll loading error]
Ошибка загрузки библиотеки bass.dll
[Current bass.dll path:]
Текущий путь к bass.dll:
-[Maximum number of bass internal channels:]
+[Maximum number of BASS internal channels:]
МакÑимальное количеÑтво каналов:
[Output device:]
УÑтройÑтво вывода:
@@ -21,8 +21,8 @@
Уровень громкоÑти:
[Quiet time:]
Тихий чаÑ:
-[download bass library]
-загрузить библиотеку bass
+[download BASS library]
+загрузить библиотеку BASS
[Play only if]
Играть, еÑли
[Offline]
@@ -47,7 +47,7 @@
Обедаю
[Preview]
ТеÑÑ‚
-[un4seen's bass version: %d.%d.%d.%d]
+[Un4seen's BASS version: %d.%d.%d.%d]
ВерÑÐ¸Ñ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ¸ BASS: %d.%d.%d.%d
[--default device--]
--уÑтройÑтво по умолчанию--
@@ -59,10 +59,12 @@
Включить звуки
[Frame background]
Фон фрейма
+[BASS Interface]
+Библиотека BASS
[Bass Interface]
Библиотека BASS
[Bass library]
-Библиотека Bass
+Библиотека BASS
[Sounds enabled]
Звуки включены
[Sounds disabled]
diff --git a/langpacks/russian/Plugins/BasicHistory.txt b/langpacks/russian/Plugins/BasicHistory.txt
index cc0a839858..9300c0617a 100644
--- a/langpacks/russian/Plugins/BasicHistory.txt
+++ b/langpacks/russian/Plugins/BasicHistory.txt
@@ -7,7 +7,7 @@
;============================================================
[History viewer for Miranda NG.]
ПроÑмотрщик иÑтории Ð´Ð»Ñ Miranda NG.
-[Message History]
+[Message history]
ИÑÑ‚Ð¾Ñ€Ð¸Ñ Ñообщений
[Settings]
ÐаÑтройки
@@ -15,9 +15,9 @@
Ð’Ñегда показывать ÑпиÑок контактов
[Show groups in contact list]
Показывать группы в ÑпиÑке контактов
-[Do not show Find control border]
+[Do not show find control border]
Ðе показывать рамку Ñтроки поиÑка
-[Default Event Filter]
+[Default event filter]
Фильтр Ñобытий
[Custom filters]
Свои фильтры
@@ -55,31 +55,31 @@
Показывать дату
[Show seconds in timestamps]
Показывать Ñекунды
-[Enable Smileys]
+[Enable smileys]
Включить Ñмайлы
[Search forward in list group]
ИÑкать дальше в группе
[Search forward in message window]
ИÑкать дальше в окне Ñообщений
-[Match Case]
+[Match case]
Учитывать региÑтр
-[Match Whole Word]
+[Match whole word]
Слово целиком
-[Only Incoming Messages]
+[Only incoming messages]
Только входÑщие ÑообщениÑ
-[Only Outgoing Messages]
+[Only outgoing messages]
Только иÑходÑщие ÑообщениÑ
-[Only Selected Group]
+[Only selected group]
Только Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð°Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð°
-[All Contacts]
+[All contacts]
Ð’Ñе контакты
-[Export To Txt]
+[Export to txt]
ЭкÑпорт в текÑÑ‚
[File encoding*]
Кодировка файла*
-[Export To Plain Html]
+[Export to plain HTML]
ЭкÑпорт в чиÑтый HTML
-[Export To Rich Html]
+[Export to rich HTML]
ЭкÑпорт в полноценный HTML
[External CSS file]
Внешний файл CSS
@@ -139,9 +139,9 @@
Отмена
[Open History]
Открыть иÑторию
-[View &History]
+[View &history]
&ИÑториÑ
-[Delete All User History]
+[Delete all user history]
Удалить вÑÑŽ иÑторию пользователÑ
[Execute history task]
Выполнить задачу
@@ -151,13 +151,13 @@
ИÑходÑщее Ñообщение
[Status change]
Смена ÑтатуÑа
-[Show Contacts]
+[Show contacts]
Показать контакты
-[Hide Contacts]
+[Hide contacts]
Скрыть контакты
-[Find Next]
+[Find next]
Ðайти дальше
-[Find Previous]
+[Find previous]
Ðайти предыдущее
[Plus in export]
ÐŸÐ»ÑŽÑ Ð² ÑкÑпорте
@@ -175,9 +175,9 @@
СиÑтема
[Me]
Я
-[Invalid Message]
+[Invalid message]
Сообщение повреждено
-[%s Files (*.%s)]
+[%s files (*.%s)]
Файлы %s (*.%s)
[Import]
Импорт
@@ -189,7 +189,7 @@
Файл повреждён
[This operation will PERMANENTLY REMOVE all history for this contact.\nAre you sure you want to do this?]
Эта Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð¿Ð¾Ð»Ð½Ð¾Ñтью удалит иÑторию Ñтого контакта.\nÐ’Ñ‹ уверены?
-[Are You sure?]
+[Are you sure?]
Вы уверены?
[Do you want to delete all imported messages for this contact?\nNote that next scheduler task import this messages again.]
Хотите удалить вÑе импортированные ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñтого контакта?\nУчтите, что Ñледующее задание планировщика Ñнова импортирует Ñти ÑообщениÑ.
@@ -203,11 +203,11 @@
Копировать
[Delete]
Удалить
-[Send Message]
+[Send message]
Отправить
-[Reply &Quoted]
+[Reply &quoted]
Ответить Ñ &цитатой
-[Delete Group]
+[Delete group]
Удаление группы
[Options]
ÐаÑтройки
@@ -219,9 +219,9 @@
Значки
[Hotkeys]
ГорÑчие клавиши
-[Rich Html]
+[Rich HTML]
Полноценный HTML
-[Plain Html]
+[Plain HTML]
ЧиÑтый HTML
[Txt]
ТекÑтовый документ
@@ -295,28 +295,28 @@ Dat (плагин mContacts)
Открыть глобальную иÑторию
[Find]
Ðайти
-[Switch Match Case]
+[Switch match case]
Учитывать региÑтр
-[Switch Match Whole Word]
+[Switch match whole word]
Слово целиком
-[Show/Hide Contacts]
+[Show/hide contacts]
Показать/Ñкрыть контакты
-[Switch Only Incoming Messages]
+[Switch only incoming messages]
Только входÑщие ÑообщениÑ
-[Switch Only Outgoing Messages]
+[Switch only outgoing messages]
Только иÑходÑщие ÑообщениÑ
-[Switch Only Selected Group]
+[Switch only selected group]
Только выбранные группы
-[Switch All Contacts]
+[Switch all contacts]
Ð’Ñе контакты
-[Export To Binary]
+[Export to binary]
ЭкÑпорт в двоичный файл
-[Import From Binary]
+[Import from binary]
Импорт из двоичного файла
-[Export To Dat (mContacts)]
-ЭкÑпорт в Dat (плагин mContacts)
-[Import From Dat (mContacts)]
-Импорт из Dat (плагин mContacts)
+[Export to dat (mContacts)]
+ЭкÑпорт в dat (плагин mContacts)
+[Import from dat (mContacts)]
+Импорт из dat (плагин mContacts)
[Invalid event number]
ÐедопуÑтимый номер ÑобытиÑ
[Incoming events]
@@ -327,7 +327,7 @@ Dat (плагин mContacts)
Файл отÑутÑтвует. Введите верный путь к файлу.
[Invalid file]
Ðеверный файл
-[All Files (*.*)]
+[All files (*.*)]
Ð’Ñе файлы (*.*)
[Enter filter name]
Введите Ð¸Ð¼Ñ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°
@@ -345,17 +345,17 @@ Dat (плагин mContacts)
ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ ÐºÐ¾Ð´Ð¾Ð²Ð°Ñ Ñтраница
[Browse CSS file]
Указать CSS
-[Export and Delete]
+[Export and delete]
ЭкÑпортировать и удалить
-[Import and Merge]
+[Import and merge]
Импортировать и Ñлить
[Minute]
Минуты
[Hour]
ЧаÑÑ‹
-[At Start]
+[At start]
При запуÑке
-[At Finish]
+[At finish]
При выходе
[Daily]
Ежедневно
@@ -399,7 +399,7 @@ Dat (плагин mContacts)
Импорт из:
[** Use <date> to insert date, <ext> to insert extension, <contact> to insert contact name]
** <date> - вÑтавлÑет дату, <ext> - раÑширение, <contact> - Ð¸Ð¼Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð°
-[History Log]
+[History log]
ПроÑмотр иÑтории
[Filter:]
Фильтр
diff --git a/langpacks/russian/Plugins/Clist_modern.txt b/langpacks/russian/Plugins/Clist_modern.txt
index e3f50305d8..6573066fee 100644
--- a/langpacks/russian/Plugins/Clist_modern.txt
+++ b/langpacks/russian/Plugins/Clist_modern.txt
@@ -49,6 +49,8 @@
* Ð”Ð»Ñ Ð²ÑÑ‚ÑƒÐ¿Ð»ÐµÐ½Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹ в Ñилу нужен перезапуÑк
[Skin folder]
Папка Ñкинов
+[Download more skins]
+Скачать Ñкины
[Available view modes]
ДоÑтупные режимы вида
[Include protocols]
diff --git a/langpacks/russian/Plugins/Clist_nicer.txt b/langpacks/russian/Plugins/Clist_nicer.txt
index 23fc2b3e6d..bfaee663af 100644
--- a/langpacks/russian/Plugins/Clist_nicer.txt
+++ b/langpacks/russian/Plugins/Clist_nicer.txt
@@ -375,6 +375,8 @@
Ð’Ñ‹Ñота Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ Ñ„Ñ€ÐµÐ¹Ð¼Ð°
[Ignore selection for groups]
Игнорировать выделение Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿
+[Download more skins]
+Скачать Ñкины
[Load from skin file]
Загрузить из файла
[Export to skin file]
diff --git a/langpacks/russian/Plugins/CloudFile.txt b/langpacks/russian/Plugins/CloudFile.txt
index 3251200d86..772f35f800 100644
--- a/langpacks/russian/Plugins/CloudFile.txt
+++ b/langpacks/russian/Plugins/CloudFile.txt
@@ -2,7 +2,7 @@
;============================================================
; File: CloudFile.dll
; Plugin: CloudFile
-; Version: 0.11.0.2
+; Version: 0.11.0.3
; Authors: Miranda NG Team
;============================================================
[Allows you to transfer files via cloud services.]
diff --git a/langpacks/russian/Plugins/DbEditorPP.txt b/langpacks/russian/Plugins/DbEditorPP.txt
index 72b2a02553..9ce7cb9e7f 100644
--- a/langpacks/russian/Plugins/DbEditorPP.txt
+++ b/langpacks/russian/Plugins/DbEditorPP.txt
@@ -2,7 +2,7 @@
;============================================================
; File: DbEditorPP.dll
; Plugin: Database editor++
-; Version: 4.0.1.1
+; Version: 4.0.1.2
; Authors: Bio, Jonathan Gordon
;============================================================
[Advanced Database Editor.]
diff --git a/langpacks/russian/Plugins/Fingerprint.txt b/langpacks/russian/Plugins/Fingerprint.txt
index 31aea793d6..40f1fee80a 100644
--- a/langpacks/russian/Plugins/Fingerprint.txt
+++ b/langpacks/russian/Plugins/Fingerprint.txt
@@ -45,8 +45,6 @@ Fingerprint NG отображает значки клиентов, иÑпольÐ
Клиенты QQ
[RSS clients]
Клиенты RSS
-[Tlen clients]
-Клиенты Tlen
[Weather clients]
Клиенты погоды
[Yahoo clients]
@@ -103,8 +101,6 @@ Mail.Ru (неизвеÑтный клиент)
TM 2008 и выше
[Gadu-Gadu client]
Gadu-Gadu клиент
-[Tlen.pl client]
-Tlen.pl клиент
[Python-based clients]
Клиенты на оÑнове Python
[Jabber client]
@@ -135,8 +131,6 @@ XMPP клиент
Оверлей MSN
[QQ overlay]
Оверлей QQ
-[Tlen.pl overlay]
-Оверлей Tlen.pl
[Yahoo overlay]
Оверлей Yahoo
[Mail.Ru Agent overlay]
@@ -171,12 +165,6 @@ Gadu-Gadu v10 клиент
Gadu-Gadu v9 клиент
[Gadu-Gadu v8 client]
Gadu-Gadu v8 клиент
-[Tlen 7.x overlay]
-Tlen 7.x оверлей
-[Tlen 6.x overlay]
-Tlen 6.x оверлей
-[Tlen 5.x overlay]
-Tlen 5.x оверлей
[TM/QQ 2012 overlay]
TM/QQ 2012 оверлей
[TM/QQ 2011 overlay]
diff --git a/langpacks/russian/Plugins/GmailNotifier.txt b/langpacks/russian/Plugins/GmailNotifier.txt
index 0dd2046d90..b53b2be3db 100644
--- a/langpacks/russian/Plugins/GmailNotifier.txt
+++ b/langpacks/russian/Plugins/GmailNotifier.txt
@@ -2,7 +2,7 @@
;============================================================
; File: GmailNotifier.dll
; Plugin: Gmail Multiple Notifier
-; Version: 0.3.1.1
+; Version: 1.0.1.1
; Authors: Mixwind
;============================================================
[Check your Gmail inboxes locally.]
@@ -55,16 +55,12 @@
ЗапиÑывать непрочтённое в базу (включает Ñохранение иÑтории)
[Checking...]
Проверка...
-[Can't open Internet!]
-Ðе могу войти в Интернет!
-[Can't reach server!]
-Ðе могу ÑвÑзатьÑÑ Ñ Ñервером!
[Can't send account data!]
Ðе могу отправить данные учётной запиÑи!
-[Can't get RSS feed!]
-Ðе могу прочитать RSS-ленту!
[Wrong name or password!]
Ðеправильное Ð¸Ð¼Ñ Ð¸Ð»Ð¸ пароль!
+[Can't get RSS feed!]
+Ðе могу прочитать RSS-ленту!
[Other]
Другое
[Gmail: New thread(s)]
diff --git a/langpacks/russian/Plugins/IEView.txt b/langpacks/russian/Plugins/IEView.txt
index 9dd91fb94b..b66fce34d9 100644
--- a/langpacks/russian/Plugins/IEView.txt
+++ b/langpacks/russian/Plugins/IEView.txt
@@ -7,6 +7,8 @@
;============================================================
[IE Based Chat Log.]
Журнал на движке IE.
+[Download more templates]
+Скачать шаблоны
[Copy]
Копировать
[Copy Link]
diff --git a/langpacks/russian/Plugins/MSN.txt b/langpacks/russian/Plugins/MSN.txt
index fe3f4b6299..72e619d61f 100644
--- a/langpacks/russian/Plugins/MSN.txt
+++ b/langpacks/russian/Plugins/MSN.txt
@@ -2,7 +2,7 @@
;============================================================
; File: MSN.dll
; Plugin: MSN protocol
-; Version: 0.14.0.1
+; Version: 0.14.0.2
; Authors: Boris Krasnovskiy, George Hazan, Richard Hughes, leecher
;============================================================
[Microsoft Network (MSN) protocol support for Miranda NG.]
diff --git a/langpacks/russian/Plugins/New_GPG.txt b/langpacks/russian/Plugins/New_GPG.txt
index 6f9e761cf9..8c75f05c2f 100644
--- a/langpacks/russian/Plugins/New_GPG.txt
+++ b/langpacks/russian/Plugins/New_GPG.txt
@@ -171,84 +171,6 @@ ID ключа:
Импортировать публичные GPG ключи
[GPG encryption status]
Ð¡Ñ‚Ð°Ñ‚ÑƒÑ ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ GPG
-[Email]
-Почта
-[Name]
-ИмÑ
-[Creation date]
-Дата ÑозданиÑ
-[Expire date]
-Срок дейÑтвиÑ
-[Key length]
-Длина ключа
-[Accounts]
-Учётные запиÑи
-[Default]
-По умолчанию
-[key ID]
-Ключ
-[not set]
-Ðе уÑтановлено
-[Default private key ID]
-ОÑновной приватный ключ
-[Failed to open file]
-Ðевозможно открыть файл
-[Error]
-Ошибка
-[Generating new random key, please wait]
-ГенерируетÑÑ Ð½Ð¾Ð²Ñ‹Ð¹ Ñлучайный ключ, пожалуйÑта, подождите
-[Failed to allocate memory]
-Ðе удалоÑÑŒ выделить памÑть
-[Failed to lock memory with error %d]
-Ошибка блокировки памÑти Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ¾Ð¹ %d
-[Failed write to clipboard with error %d]
-Ошибка запиÑи в буфер обмена Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ¾Ð¹ %d
-[Warning]
-Предупреждение
-[Wrong GPG binary location found in system.\nPlease choose another location]
-ИÑполнÑемый файл GPG не найден в ÑиÑтеме.\nПожалуйÑта, укажите другое путь
-[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-Выбранный вами exe не GnuPG!\nС Ñтим плагином рекомендуетÑÑ Ð¸Ñпользовать GnuPG v1.x.x.
-[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-Ваша верÑÐ¸Ñ GnuPG не поддерживаетÑÑ Ð¸ может работать неправильно!\nС Ñтим плагином рекомендуетÑÑ Ð¸Ñпользовать GnuPG v1.x.x.
-["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
-Каталог "GPG" найден в папке Миранды.\nЕÑли предположить, что Ñто домашний каталог GPG.\nДомашний каталог GPG выбран.
-[Info]
-Инфо
-[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
-Ваша верÑÐ¸Ñ GPG поддерживаетÑÑ. Языковые файлы найдены.\nПлагин должен работать нормально.\nÐажмите ОК.
-[GPG binary does not exist.\nPlease choose another location]
-ИÑполнÑемый файл GPG не найден .\nПожалуйÑта, укажите другой путь
-[Please choose GPG binary location]
-Выберите директорию c GnuPG
-[Please set keyring's home directory]
-Выберите директорию Ñ ÐºÐ»ÑŽÑ‡Ð°Ð¼Ð¸ GnuPG
-[There is existing key for contact, would you like to replace it with new key?]
-Получен ключ, но у контакта уже еÑть ключ. Ð’Ñ‹ хотите его заменить новым?
-[New public key was received, do you want to import it?]
-Получен новый отрытый ключ. Ð’Ñ‹ хотите его принÑть?
-[Replace]
-Заменить
-[Accept]
-ПринÑть
-[Received key from %s]
-Получен ключ от %s
-[You must set encryption algorithm first]
-Сначала необходимо задать алгоритм шифрованиÑ
-[Key length must be of length from 1024 to 4096 bits]
-Длина ключа должна быть от 1024 до 4096 бит
-[Invalid date]
-ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ Ð´Ð°Ñ‚Ð°
-[Name must contain at least 5 characters]
-Ð˜Ð¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ð¾ Ñодержать не менее 5 Ñимволов
-[Name cannot contain '(' or ')']
-Ð˜Ð¼Ñ Ð½Ðµ может Ñодержать '(' или ')'
-[Invalid Email]
-Ðеверный e-mail
-[Generating new key, please wait...]
-Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ ключа, пожалуйÑта подождите...
-[Failed to export public key.]
-Ðе удалоÑÑŒ ÑкÑпортировать открытый ключ.
[GPG binary is set and valid (this is good).\n]
ИÑполнÑемый файл GPG указан и работоÑпоÑобен (Ñто хорошо).\n
[GPG binary unset or invalid (plugin will not work).\n]
@@ -279,26 +201,26 @@ ID ключа:
Загрузить ключ Ð´Ð»Ñ Ð²Ñех Ñубконтактов?
[Metacontact detected]
Обнаружен метаконтакт
+[Warning]
+Предупреждение
[We're trying to encrypt with untrusted key. Do you want to trust this key permanently?]
ПытаемÑÑ Ð·Ð°ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ñ‚ÑŒ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ недоверенного ключа. Ð’Ñ‹ хотите доверÑть Ñтому ключу поÑтоÑнно?
[Something is wrong, GPG does not understand us, aborting encryption.]
Что-то не так, GPG не понимает наÑ, прерываю шифрование.
-[Services]
-Службы
-[Main]
-Главный
-[GnuPG Variables]
-Пути к GPG
-[Messages]
-СообщениÑ
-[Advanced]
-Дополнительно
[Contact]
Контакт
[Key ID]
Ключ
+[Name]
+ИмÑ
+[Email]
+Почта
[Protocol]
Протокол
+[Default private key ID]
+ОÑновной приватный ключ
+[not set]
+Ðе уÑтановлено
[This key is not used by any contact. Do you want to remove it from public keyring?]
Этот ключ не иÑпользуетÑÑ Ð½Ð¸ одним контактом. Ð’Ñ‹ дейÑтвительно хотите удалить его из открытых ключей?
[Key info]
@@ -315,6 +237,14 @@ ID ключа:
ЭкÑпорт открытого ключа
[.asc pubkey file]
Файл публичного ключа (.asc )
+[Failed to allocate memory]
+Ðе удалоÑÑŒ выделить памÑть
+[Error]
+Ошибка
+[Failed to lock memory with error %d]
+Ошибка блокировки памÑти Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ¾Ð¹ %d
+[Failed write to clipboard with error %d]
+Ошибка запиÑи в буфер обмена Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ¾Ð¹ %d
[Failed to open clipboard with error %d]
Ðе удалоÑÑŒ открыть буфер обмена Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ¾Ð¹ %d
[Set log file]
@@ -323,6 +253,8 @@ ID ключа:
Файлы журнала
[Choose gpg.exe]
Выберите gpg.exe
+[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+Выбранный вами exe не GnuPG!\nС Ñтим плагином рекомендуетÑÑ Ð¸Ñпользовать GnuPG v1.x.x.
[Set home directory]
Выбор домашней папки
[Load Public GPG Key for ]
@@ -333,12 +265,78 @@ ID ключа:
Это не публичный или приватный ключ
[Key already in secret keyring.]
Ключ уже в векретном брелоке.
+[Info]
+Инфо
[Set file containing GPG public key]
Задать файл, Ñодержащий открытый ключ GPG
[GPG public key file]
Файл открытого ключа GPG
+[Failed to open file]
+Ðевозможно открыть файл
[There is no public or private key.]
Это не файл открытого или закрытого ключа.
+[Services]
+Службы
+[Main]
+Главный
+[GnuPG Variables]
+Пути к GPG
+[Messages]
+СообщениÑ
+[Advanced]
+Дополнительно
+[New passwords do not match]
+Ðовые пароли не Ñовпадают
+[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+Старый пароль не Ñовпадает, вы можете продолжить, но GPG не примет неверный пароль.\nПродолжить?
+[Creation date]
+Дата ÑозданиÑ
+[Expire date]
+Срок дейÑтвиÑ
+[Key length]
+Длина ключа
+[Accounts]
+Учётные запиÑи
+[Default]
+По умолчанию
+[key ID]
+Ключ
+[Generating new random key, please wait]
+ГенерируетÑÑ Ð½Ð¾Ð²Ñ‹Ð¹ Ñлучайный ключ, пожалуйÑта, подождите
+[Wrong GPG binary location found in system.\nPlease choose another location]
+ИÑполнÑемый файл GPG не найден в ÑиÑтеме.\nПожалуйÑта, укажите другое путь
+[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+Ваша верÑÐ¸Ñ GnuPG не поддерживаетÑÑ Ð¸ может работать неправильно!\nС Ñтим плагином рекомендуетÑÑ Ð¸Ñпользовать GnuPG v1.x.x.
+["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
+Каталог "GPG" найден в папке Миранды.\nЕÑли предположить, что Ñто домашний каталог GPG.\nДомашний каталог GPG выбран.
+[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
+Ваша верÑÐ¸Ñ GPG поддерживаетÑÑ. Языковые файлы найдены.\nПлагин должен работать нормально.\nÐажмите ОК.
+[There is existing key for contact, would you like to replace it with new key?]
+Получен ключ, но у контакта уже еÑть ключ. Ð’Ñ‹ хотите его заменить новым?
+[New public key was received, do you want to import it?]
+Получен новый отрытый ключ. Ð’Ñ‹ хотите его принÑть?
+[Replace]
+Заменить
+[Accept]
+ПринÑть
+[Received key from %s]
+Получен ключ от %s
+[You must set encryption algorithm first]
+Сначала необходимо задать алгоритм шифрованиÑ
+[Key length must be of length from 1024 to 4096 bits]
+Длина ключа должна быть от 1024 до 4096 бит
+[Invalid date]
+ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ Ð´Ð°Ñ‚Ð°
+[Name must contain at least 5 characters]
+Ð˜Ð¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ð¾ Ñодержать не менее 5 Ñимволов
+[Name cannot contain '(' or ')']
+Ð˜Ð¼Ñ Ð½Ðµ может Ñодержать '(' или ')'
+[Invalid Email]
+Ðеверный e-mail
+[Generating new key, please wait...]
+Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ ключа, пожалуйÑта подождите...
+[Failed to export public key.]
+Ðе удалоÑÑŒ ÑкÑпортировать открытый ключ.
[Turn off GPG encryption]
Выключить шифрование GPG
[Turn on GPG encryption]
@@ -355,7 +353,9 @@ ID ключа:
Результат ÑкÑпорта ключей
[Keys import result]
Результат импорта ключей
-[New passwords do not match]
-Ðовые пароли не Ñовпадают
-[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
-Старый пароль не Ñовпадает, вы можете продолжить, но GPG не примет неверный пароль.\nПродолжить?
+[GPG binary does not exist.\nPlease choose another location]
+ИÑполнÑемый файл GPG не найден .\nПожалуйÑта, укажите другой путь
+[Please choose GPG binary location]
+Выберите директорию c GnuPG
+[Please set keyring's home directory]
+Выберите директорию Ñ ÐºÐ»ÑŽÑ‡Ð°Ð¼Ð¸ GnuPG
diff --git a/langpacks/russian/Plugins/SimpleStatusMsg.txt b/langpacks/russian/Plugins/SimpleStatusMsg.txt
index fce5dcf095..9bd883b68c 100644
--- a/langpacks/russian/Plugins/SimpleStatusMsg.txt
+++ b/langpacks/russian/Plugins/SimpleStatusMsg.txt
@@ -3,7 +3,7 @@
; File: SimpleStatusMsg.dll
; Plugin: Simple status message
; Version: 1.9.0.6
-; Authors: Bartosz 'Dezeath' Bialek, Harven
+; Authors: Bartosz 'Dezeath' Białek, Harven
;============================================================
[Provides a simple way to set status and away messages.]
БыÑÑ‚Ñ€Ð°Ñ Ñмена ÑтатуÑов и предуÑтановленных Ñообщений ÑтатуÑа.
diff --git a/langpacks/russian/Plugins/SmileyAdd.txt b/langpacks/russian/Plugins/SmileyAdd.txt
index 0cdc8adf31..2c04dbb68e 100644
--- a/langpacks/russian/Plugins/SmileyAdd.txt
+++ b/langpacks/russian/Plugins/SmileyAdd.txt
@@ -2,7 +2,7 @@
;============================================================
; File: SmileyAdd.dll
; Plugin: SmileyAdd
-; Version: 0.2.4.2
+; Version: 0.3.0.1
; Authors: Peacow, nightwish, bid, borkra
;============================================================
[Smiley support for Miranda NG.]
@@ -91,16 +91,14 @@ HTTP-Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ SmileyAdd
Ð’ ÑоответÑтвии Ñ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»Ð¾Ð¼
[Smiley pack %s for category "%s" not found.\nSelect correct smiley pack in the Options -> Customize -> Smileys.]
Ðе найден набор Ñмайлов %s Ð´Ð»Ñ ÐºÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ð¸Ð¸ "%s".\nВыберите набор Ñмайлов в разделе "ÐаÑтройки -> Ð¢Ð¾Ð½ÐºÐ°Ñ Ð½Ð°Ñтройка -> Смайлы".
-[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
-Проблемы Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¾Ð¹ набора Ñмайлов (необходимо иÑправить).\nПодробноÑти в Ñетевом логе.
[Smiley #%u in file %s for smiley pack %s not found.]
Смайл #%u в файле %s Ð´Ð»Ñ Ð½Ð°Ð±Ð¾Ñ€Ð° Ñмайлов %s не найден.
+[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
+Проблемы Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¾Ð¹ набора Ñмайлов (необходимо иÑправить).\nПодробноÑти в Ñетевом логе.
[%s global smiley pack]
%s глобальный набор Ñмайлов
[Standard]
Стандартные
-[Regular expression "%s" in smiley pack "%s" could produce "empty matches".]
-РегулÑрное выражение "%s" в наборе Ñмайлов "%s" может выводить "пуÑтые значениÑ".
[Regular expression "%s" in smiley pack "%s" malformed.]
Ошибочное регулÑрное выражение "%s" в наборе Ñмайлов "%s".
[d'Oh!]
diff --git a/langpacks/russian/Plugins/SplashScreen.txt b/langpacks/russian/Plugins/SplashScreen.txt
index adcd8cea6c..09b1bece6e 100644
--- a/langpacks/russian/Plugins/SplashScreen.txt
+++ b/langpacks/russian/Plugins/SplashScreen.txt
@@ -37,6 +37,8 @@
Ðе найден плагин AdvaImg. Скачайте его по адреÑу https://miranda-ng.org/p/AdvaImg/, чтобы иÑпользовать изображениÑ.
[Preview...]
ПроÑмотр...
+[Download more splash screens]
+Скачать вÑплывающие окна
[Graphic files]
ГрафичеÑкие файлы
[Sound Files]
diff --git a/langpacks/russian/Plugins/StatusManager.txt b/langpacks/russian/Plugins/StatusManager.txt
index 01d30f3601..5ac0fb9b6e 100644
--- a/langpacks/russian/Plugins/StatusManager.txt
+++ b/langpacks/russian/Plugins/StatusManager.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StatusManager.dll
; Plugin: Status manager
-; Version: 0.11.2.3
+; Version: 1.0.1.1
; Authors: P Boon
;============================================================
[A connection checker and auto away module. Also allows you to define the status Miranda should set on startup, configurable per protocol.]
diff --git a/langpacks/russian/Plugins/Steam.txt b/langpacks/russian/Plugins/Steam.txt
index 8580b84653..48ec494876 100644
--- a/langpacks/russian/Plugins/Steam.txt
+++ b/langpacks/russian/Plugins/Steam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Steam.dll
; Plugin: Steam protocol
-; Version: 0.11.6.1
+; Version: 0.11.6.3
; Authors: Miranda NG Team, Robert Pösel
;============================================================
[Steam protocol support for Miranda NG.]
diff --git a/langpacks/russian/Plugins/StopSpam.txt b/langpacks/russian/Plugins/StopSpam.txt
index ae25157b31..37a53bf341 100644
--- a/langpacks/russian/Plugins/StopSpam.txt
+++ b/langpacks/russian/Plugins/StopSpam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpam.dll
; Plugin: StopSpam+
-; Version: 0.0.1.5
+; Version: 0.1.0.1
; Authors: Roman Miklashevsky, A. Petkevich, Kosh&chka, persei
;============================================================
[Anti-spam plugin for Miranda NG.]
@@ -41,6 +41,8 @@
ЗапиÑывать Ñпамеров в ÑиÑтемную иÑторию
[StopSpam automatic message:\r\n]
Сообщение антиÑпама:\r\n
+[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
+Ðет больше Ñпама! Роботы отдыхают!\r\n\r\nЭтот плагин работает проÑто:\r\nÐ¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ñ‚ пользователей из вашего ÑпиÑка контактов приходÑÑ‚ без проверки на Ñпам, ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ñ‚ неизвеÑтных пользователей вам не доÑтавлÑÑŽÑ‚ÑÑ. Ðо они не игнорируютÑÑ: плагин отвечает проÑтым вопроÑом и, еÑли пользователь даёт правильный ответ, добавлÑет его в ÑпиÑок контактов, чтобы он мог ÑвÑзатьÑÑ Ñ Ð²Ð°Ð¼Ð¸.
[Message sessions]
БеÑеды
[General]
@@ -49,8 +51,6 @@
СообщениÑ
[Accounts]
Учётные запиÑи
-[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
-Ðет больше Ñпама! Роботы отдыхают!\r\n\r\nЭтот плагин работает проÑто:\r\nÐ¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ñ‚ пользователей из вашего ÑпиÑка контактов приходÑÑ‚ без проверки на Ñпам, ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ñ‚ неизвеÑтных пользователей вам не доÑтавлÑÑŽÑ‚ÑÑ. Ðо они не игнорируютÑÑ: плагин отвечает проÑтым вопроÑом и, еÑли пользователь даёт правильный ответ, добавлÑет его в ÑпиÑок контактов, чтобы он мог ÑвÑзатьÑÑ Ñ Ð²Ð°Ð¼Ð¸.
[Not In List]
Ðе в ÑпиÑке
[Complete]
diff --git a/langpacks/russian/Plugins/StopSpamMod.txt b/langpacks/russian/Plugins/StopSpamMod.txt
index 1192f773a8..ecd1168b70 100644
--- a/langpacks/russian/Plugins/StopSpamMod.txt
+++ b/langpacks/russian/Plugins/StopSpamMod.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpamMod.dll
; Plugin: StopSpam mod
-; Version: 0.0.2.1
+; Version: 0.0.2.2
; Authors: Roman Miklashevsky, sss, Elzor
;============================================================
[Anti-spam plugin for Miranda NG.]
@@ -79,10 +79,10 @@
Ðет больше Ñпама! Роботы отдыхают!\r\n\r\nЭтот плагин работает проÑто:\r\nÐ¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ñ‚ пользователей из вашего ÑпиÑка контактов приходÑÑ‚ без проверки на Ñпам, ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ñ‚ неизвеÑтных пользователей вам не доÑтавлÑÑŽÑ‚ÑÑ. Ðо они не игнорируютÑÑ: плагин отвечает проÑтым вопроÑом и, еÑли пользователь даёт правильный ответ, добавлÑет его в ÑпиÑок контактов, чтобы он мог ÑвÑзатьÑÑ Ñ Ð²Ð°Ð¼Ð¸.
[Spammers made me to install small anti-spam system you are now speaking with. Please reply "nospam" without quotes and spaces if you want to contact me.]
ЗдравÑтвуйте! Ð’Ñ‹ говорите Ñ Ð°Ð½Ñ‚Ð¸Ñпам-ботом. ПожалуйÑта, напишите Ñлово "nospam" без кавычек, чтобы пройти проверку на Ñпам.\r\nSpammers made me to install small anti-spam system you are now speaking with. Please reply "nospam" without quotes and spaces if you want to contact me.
-[StopSpam: send a message and reply to an anti-spam bot question.]
-StopSpam: отправьте Ñообщение и ответьте на Ð²Ð¾Ð¿Ñ€Ð¾Ñ Ð°Ð½Ñ‚Ð¸Ñпам-бота.\r\nStopSpam: send a message and reply to an anti-spam bot question.
[Congratulations! You just passed human/robot test. Now you can write me a message.]
ПоздравлÑем! Ð’Ñ‹ прошли теÑÑ‚, теперь можете отправлÑть ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŽ.\r\nCongratulations! You just passed human/robot test. Now you can write me a message.
+[StopSpam: send a message and reply to an anti-spam bot question.]
+StopSpam: отправьте Ñообщение и ответьте на Ð²Ð¾Ð¿Ñ€Ð¾Ñ Ð°Ð½Ñ‚Ð¸Ñпам-бота.\r\nStopSpam: send a message and reply to an anti-spam bot question.
[If math expression is turned on, you can use following expression in message text:\nXX+XX-X/X*X\neach X will be replaced by one random number and answer will be expression result.\nMessage must contain only one expression without spaces.]
ЕÑли включены математичеÑкие выражениÑ, то их можно иÑпользовать в текÑте вопроÑа:\nXX+XX-X/X*X\nкаждый X будет заменён Ñлучайным чиÑлом и ответом будет решение выражениÑ.\nÐ’Ð¾Ð¿Ñ€Ð¾Ñ Ð¼Ð¾Ð¶ÐµÑ‚ включать только одно математичеÑкое выражение, запиÑанное без пробелов.
[Info]
diff --git a/langpacks/russian/Plugins/TabSRMM.txt b/langpacks/russian/Plugins/TabSRMM.txt
index 700eb9f2bc..a9e9a0062f 100644
--- a/langpacks/russian/Plugins/TabSRMM.txt
+++ b/langpacks/russian/Plugins/TabSRMM.txt
@@ -513,6 +513,8 @@ CтатуÑÑ‹ Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑкого ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð²ÐºÐ»Ð°Ð´Ð
ЭкÑпортировать...
[Import from a file...]
Импортировать...
+[Download more skins]
+Скачать Ñкины
[Icons]
Значки
[Event type icons in the message log]
diff --git a/langpacks/russian/Plugins/Tox.txt b/langpacks/russian/Plugins/Tox.txt
index 151b25d7fa..e801b6e04e 100644
--- a/langpacks/russian/Plugins/Tox.txt
+++ b/langpacks/russian/Plugins/Tox.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Tox.dll
; Plugin: Tox protocol
-; Version: 0.11.1.25
+; Version: 0.11.1.26
; Authors: Miranda NG Team
;============================================================
[Tox protocol support for Miranda NG.]
diff --git a/langpacks/russian/Plugins/VKontakte.txt b/langpacks/russian/Plugins/VKontakte.txt
index 5d5ee10857..90ff9a5e6c 100644
--- a/langpacks/russian/Plugins/VKontakte.txt
+++ b/langpacks/russian/Plugins/VKontakte.txt
@@ -390,7 +390,7 @@ E-mail или номер телефона:
[Remove %s from your friend list]
Удалить %s из ÑпиÑка друзей
[Clear server history with %s]
-УдалиÑÑŒ иÑторию перепиÑки Ñ %s на Ñервере
+Удалить иÑторию перепиÑки Ñ %s на Ñервере
[Deleting %s from contact list]
Удаление %s из ÑпиÑка контактов
[New news]
diff --git a/langpacks/russian/Plugins/mRadio.txt b/langpacks/russian/Plugins/mRadio.txt
index 508bfb277b..4f96218dbb 100644
--- a/langpacks/russian/Plugins/mRadio.txt
+++ b/langpacks/russian/Plugins/mRadio.txt
@@ -101,8 +101,10 @@
Карьер
[Sorry!]
Извините!
-[BASS.DLL not found!]
-BASS.DLL не найден!
+[bass.dll not found!]
+bass.dll не найден!
+[bass.dll not found! Choose bass.dll path manually]
+bass.dll не найден! Укажите путь к нему
[Station]
СтанциÑ
[Custom INI file]
diff --git a/langpacks/russian/Untranslated/AIM.txt b/langpacks/russian/Untranslated/AIM.txt
deleted file mode 100644
index 3a8a600ed2..0000000000
--- a/langpacks/russian/Untranslated/AIM.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-[This allows access to user defined chat rooms. To access predefined chat rooms use web links]
-[Server rate limit exceeded.]
-[Client rate limit exceeded]
-[Recipient is not logged in.]
-[Requested service is unavailable.]
-[Requested service is not defined.]
-[Reply too big.]
-[Response lost.]
-[Request denied.]
-[Insufficient rights.]
-[Recipient blocked.]
-[Sender too evil.]
-[Receiver too evil.]
-[List overflow.]
-[Request ambiguous.]
-[Server queue full.]
-[Not while on AOL.]
-[Invalid registration preference.]
-[Read only field.]
-[Write only field.]
-[No database access.]
-[Invalid database fields.]
-[Bad database status.]
-[Migration cancel.]
-[There is already a pending request for this screen name.]
-[Not DT status.]
-[Outstanding confirmation.]
-[No email address.]
-[Over limit.]
-[Email host fail.]
-[Open mail account?]
-[Contact tried to open an audio/video conference (not currently supported)]
-[Item you want to delete not found in list.]
-[Failed to add buddy to list: Item already exist.]
-[Error adding buddy (invalid ID or already in list?)]
-[Cannot add buddy. Limit for this type of item exceeded.]
-[Item you want to modify not found in list.]
-[You've got mail! Checked at]
-[Hiptop]
-[Join me in this buddy chat!]
diff --git a/langpacks/russian/Untranslated/GmailNotifier.txt b/langpacks/russian/Untranslated/GmailNotifier.txt
new file mode 100644
index 0000000000..fe2bc3771c
--- /dev/null
+++ b/langpacks/russian/Untranslated/GmailNotifier.txt
@@ -0,0 +1 @@
+[Gmail Notifier connection]
diff --git a/langpacks/russian/Untranslated/New_GPG.txt b/langpacks/russian/Untranslated/New_GPG.txt
index e5d32c1d97..9ab55621c3 100644
--- a/langpacks/russian/Untranslated/New_GPG.txt
+++ b/langpacks/russian/Untranslated/New_GPG.txt
@@ -1,5 +1,4 @@
[Toggle GPG encryption]
-[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
[Your secret key with ID: ]
[ expired and will not work.\nDo you want to set another key?]
[We received encrypted message from contact with encryption turned off.\nDo you want to turn on encryption for this contact?]
@@ -7,6 +6,8 @@
[ found in presence, and exists in keyring.)]
[Load Public GPG Key (Key ID: ]
[ found in presence.)]
+[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
+[Expiration date]
[Do you want to toggle encryption for all subcontacts?]
[Capability to decrypt file not found on other side.\nRecipient may be unable to decrypt file(s).\nDo you want to encrypt file(s) anyway?]
[Unable to check encryption support on other side.\nRecipient may be unable to decrypt file(s).\nCurrently capability check supported only for ICQ and Jabber protocols.\nIt will work for any other proto if Miranda with New_GPG is used on other side.\nDo you want to encrypt file(s) anyway?]
diff --git a/langpacks/serbian/=CORE=.txt b/langpacks/serbian/=CORE=.txt
index ac49f94dfc..2be05e7907 100644
--- a/langpacks/serbian/=CORE=.txt
+++ b/langpacks/serbian/=CORE=.txt
@@ -3,29 +3,6 @@
; Module: Miranda Core
; Version: 0.95.8
;============================================================
-;file \src\core\stdauth\res\resource.rc
-[Authorization request]
-Zahtev za autorizaciju.
-[&Authorize]
-&Potvrdi autorizaciju
-[&Deny]
-&Odbij autorizaciju
-[Decide &later]
-OdluÄi &kasnije
-[User &details]
-Detalji &korisnika
-[Reason:]
-Razlog:
-[Denial reason:]
-Razlog odbijanja:
-[Add to contact list if authorized]
-Ubaciti na spisak kontakata po autorizaciji
-[You were added]
-Vaš kontakt je dodat
-[&Close]
-&Zatvori
-[&Add]
-&Dodati
;file \src\core\stdaway\res\resource.rc
[%s message for %s]
%s poruka za %s
@@ -291,6 +268,8 @@ Ukupna veliÄina
Opis:
[&User menu]
&KorisniÄki meni
+[User &details]
+Detalji &korisnika
[&History]
&Istorija
[Incoming file transfer]
@@ -307,6 +286,8 @@ Datum:
Datoteke:
[Save to:]
SaÄuvaj u:
+[&Add]
+&Dodati
[&Open...]
&Otvori...
[Open &folder]
@@ -395,11 +376,6 @@ Pitaj me
Preimenuj (dodaj " (1)", itd)
[You will always be asked about files from people not on your contact list]
Pitanje će uvek biti postavljeno ako je datoteka stigla od nepoznatog kontakta
-;file \src\core\stdhelp\res\resource.rc
-[About Miranda NG]
-O programu
-[Credits >]
-Autori >
;file \src\core\stdidle\res\resource.rc
[Become idle if the following is left unattended:]
Pasivni režim usled navedenih događaja:
@@ -723,6 +699,8 @@ Razgovor s kontaktom u prozoru
Izmenjeno ime:
[Group:]
Grupa:
+[Authorization request]
+Zahtev za autorizaciju.
[&Yes]
&Da
[&No]
@@ -999,6 +977,8 @@ Upozorenje!\r\nNavedeni objekat u meniju ne podržava zadatu opciju.
[Insert separator]
Ubaci razdelnik
+[Module:]
+
[Service:]
Služi za:
[Default]
@@ -1133,6 +1113,26 @@ Preuzimanje jeziÄkih paketa
[Hide if there isn't enough space]
+[&Authorize]
+&Potvrdi autorizaciju
+[&Deny]
+&Odbij autorizaciju
+[Decide &later]
+OdluÄi &kasnije
+[Reason:]
+Razlog:
+[Denial reason:]
+Razlog odbijanja:
+[Add to contact list if authorized]
+Ubaciti na spisak kontakata po autorizaciji
+[You were added]
+Vaš kontakt je dodat
+[&Close]
+&Zatvori
+[About Miranda NG]
+O programu
+[Credits >]
+Autori >
[Tray]
Tray
[&Hide/Show]
@@ -1193,42 +1193,6 @@ PronaÄ‘i reÄ
[Google Translate]
-;file \src\core\stdauth\src\auth.cpp
-[%s requests authorization]
-&s zahteva autorizaciju
-[%u requests authorization]
-%u zahteva autorizaciju
-[%s added you to their contact list]
-%s dodaje vaš kontakt na spisak
-[%u added you to their contact list]
-%u dodaje vaš kontakt na spisak
-[Alerts]
-Upozorenja
-[Added event]
-Dodat događaj
-;file \src\core\stdauth\src\authdialogs.cpp
-[View user's details]
-Pregled detalja o korisniku
-[Add contact permanently to list]
-Zapamtiti kontakt na spisku
-[<Unknown>]
-<Nepoznato>
-[%s added you to the contact list\n%u (%s) on %s]
-%s dodaje vaš konatkt na spisak\n%u (%s) na %s
-[%s added you to the contact list\n%u on %s]
-%s dodaje vaš konatkt na spisak\n%u na %s
-[%s added you to the contact list\n%s on %s]
-%s dodaje vaš konatkt na spisak\n%s na %s
-[(Unknown)]
-(Nepoznato)
-[%s requested authorization\n%u (%s) on %s]
-%s šalje zahtev za autorizaciju\n%u (%s) na %s
-[%s requested authorization\n%u on %s]
-%s šalje zahtev za autorizaciju\n%u na %s
-[%s requested authorization\n%s on %s]
-%s šalje zahtev za autorizaciju\n%s na %s
-[Feature is not supported by protocol]
-Protokol ne podržava zahtevanu opciju
;file \src\core\stdaway\src\awaymsg.cpp
[Re&ad %s message]
ÄŒitaj &poruku od: "%s"
@@ -1351,6 +1315,10 @@ Događaji
Izbor foldera
[My received files]
Pristigle datoteke (lokalno)
+[Add contact permanently to list]
+Zapamtiti kontakt na spisku
+[View user's details]
+Pregled detalja o korisniku
[View user's history]
Vidi istoriju korisnika
[User menu]
@@ -1418,20 +1386,6 @@ Prenos podataka i provera virusa dovršeni
;file \src\core\stdfile\src\ftmanager.cpp
[Outgoing]
Odlazni
-;file \src\core\stdhelp\src\about.cpp
-[< Copyright]
-< Zaštita prava
-;file \src\core\stdhelp\src\help.cpp
-[&Help]
-&Pomoć
-[&About...]
-&O programu...
-[&Support]
-&KorisniÄka podrÅ¡ka
-[&Miranda NG homepage]
-&Sajt Miranda NG
-[&Report bug]
-Prijavi &grešku
;file \src\core\stdidle\src\idle.cpp
[Idle]
Pasivni režim
@@ -1907,11 +1861,43 @@ Pregledaj/menjaj &detalje...
;file \src\core\stduseronline\src\useronline.cpp
[%s is online]
%s je prisutan
+[Alerts]
+Upozorenja
;file \src\mir_app\src\addcontact.cpp
[Add %s]
Dodaj %s
[Please authorize my request and add me to your contact list.]
Dodaj me na spisak i daj mi autorizaciju, molim.
+;file \src\mir_app\src\auth.cpp
+[%s requests authorization]
+&s zahteva autorizaciju
+[%u requests authorization]
+%u zahteva autorizaciju
+[%s added you to their contact list]
+%s dodaje vaš kontakt na spisak
+[%u added you to their contact list]
+%u dodaje vaš kontakt na spisak
+[Added event]
+Dodat događaj
+;file \src\mir_app\src\authdialogs.cpp
+[<Unknown>]
+<Nepoznato>
+[%s added you to the contact list\n%u (%s) on %s]
+%s dodaje vaš konatkt na spisak\n%u (%s) na %s
+[%s added you to the contact list\n%u on %s]
+%s dodaje vaš konatkt na spisak\n%u na %s
+[%s added you to the contact list\n%s on %s]
+%s dodaje vaš konatkt na spisak\n%s na %s
+[(Unknown)]
+(Nepoznato)
+[%s requested authorization\n%u (%s) on %s]
+%s šalje zahtev za autorizaciju\n%u (%s) na %s
+[%s requested authorization\n%u on %s]
+%s šalje zahtev za autorizaciju\n%u na %s
+[%s requested authorization\n%s on %s]
+%s šalje zahtev za autorizaciju\n%s na %s
+[Feature is not supported by protocol]
+Protokol ne podržava zahtevanu opciju
;file \src\mir_app\src\chat_clist.cpp
[&Join chat]
&PoÄni razgovor
@@ -2200,6 +2186,19 @@ Zaglavlja
BaziÄni tekst
[Small text]
Dodatni tekst
+;file \src\mir_app\src\help.cpp
+[< Copyright]
+< Zaštita prava
+[&Help]
+&Pomoć
+[&About...]
+&O programu...
+[&Support]
+&KorisniÄka podrÅ¡ka
+[&Miranda NG homepage]
+&Sajt Miranda NG
+[&Report bug]
+Prijavi &grešku
;file \src\mir_app\src\hotkey_opts.cpp
[Browser: Back]
diff --git a/langpacks/serbian/=HEAD=.txt b/langpacks/serbian/=HEAD=.txt
index 93ff4291cf..8ed957b846 100644
--- a/langpacks/serbian/=HEAD=.txt
+++ b/langpacks/serbian/=HEAD=.txt
@@ -3,4 +3,4 @@ Language: Serbian (SR)
Locale: 081A
Authors: vultures
Author-email: okrimnemir@hotmail.com
-Last-Modified-Using: Miranda NG 0.95.7 \ No newline at end of file
+Last-Modified-Using: Miranda NG 0.95.8 \ No newline at end of file
diff --git a/langpacks/serbian/Plugins/AIM.txt b/langpacks/serbian/Plugins/AIM.txt
deleted file mode 100644
index 8de9e0c814..0000000000
--- a/langpacks/serbian/Plugins/AIM.txt
+++ /dev/null
@@ -1,426 +0,0 @@
-#muuid {3750a5a3-bf0d-490e-b65d-41ac4d29aeb3}
-;============================================================
-; File: AIM.dll
-; Plugin: AIM protocol
-; Version: 0.11.0.1
-; Authors: Boris Krasnovskiy, Aaron Myles Landwehr
-;============================================================
-[AOL Instant Messenger (AIM) protocol support for Miranda NG.]
-
-;file \protocols\AimOscar\res\aim.rc
-[AIM user details]
-
-[Screen name:]
-
-[Display name:]
-
-[Password:]
-Å ifra
-[AIM options]
-
-[Message delivery confirmation]
-
-[Do not autoreply when away]
-
-[Convert incoming messages to BBCode]
-
-[Convert outgoing messages to HTML]
-
-[Disable avatars]
-
-[Disable account type icons]
-
-[Disable extended status icons]
-
-[Notify about new mail]
-
-[Manage server groups]
-
-[Advanced options]
-
-[Instant idle on login]
-
-[Force proxy file transfers]
-
-[Masquerade as a Sidekick/Hiptop user]
-
-[Connection]
-
-[Login server:]
-
-[Port:]
-Port:
-[Reset]
-Reset
-[Disable SSL]
-
-[Force single client]
-
-[Use "clientlogin" (recommended)]
-
-[* Some changes will take effect the next time you connect to the AIM network]
-
-[Save profile]
-
-[Create a new AIM account]
-
-[AIM instant idler]
-
-[Number of hours:]
-
-[Number of minutes:]
-
-[Set idle]
-
-[Unset idle]
-
-[Users who can contact me:]
-
-[Allow all users]
-
-[Allow only users on contact list]
-
-[Allow only users below]
-
-[Block all users]
-
-[Block only users below]
-
-[Add]
-Dodaj
-[Remove]
-Ukloni
-[Idle]
-Pasivni režim
-[Allow contacts to be notified of:]
-
-[Join chat room]
-
-[Chat room]
-
-[&Join]
-
-[&Cancel]
-&Otkazivanje
-[This allows access to user defined chat rooms. To access predefined chat rooms use web links]
-
-[Change password]
-
-[Original]
-
-[New]
-
-[Repeat]
-
-[*Passwords don't match.]
-
-[Screen name]
-
-[E-mail]
-E-mail
-[Confirm account]
-
-[*Applied upon reconnect]
-
-[Save changes]
-
-[Invite buddy to chat room]
-
-[&Invite]
-
-[Invitation reason]
-
-[Chat room invitation request]
-
-[&Deny]
-&Odbij autorizaciju
-[Message]
-Poruka
-[Room]
-
-;file \protocols\AimOscar\src\chat.cpp
-[Me]
-Ja
-[Others]
-
-[&Invite user...]
-
-[&Leave chat session]
-
-[User &details]
-Detalji &korisnika
-[User &history]
-
-;file \protocols\AimOscar\src\error.cpp
-[Invalid screen name or password.]
-
-[Mismatched screen name or password.]
-
-[You are connecting too frequently. Try waiting 10 minutes to reconnect.]
-
-[Unknown error occurred when attempting to connect.]
-
-[Invalid SNAC header.]
-
-[Server rate limit exceeded.]
-
-[Client rate limit exceeded]
-
-[Recipient is not logged in.]
-
-[Requested service is unavailable.]
-
-[Requested service is not defined.]
-
-[You sent obsolete SNAC.]
-
-[Not supported by server.]
-
-[Not supported by the client.]
-
-[Refused by client.]
-
-[Reply too big.]
-
-[Response lost.]
-
-[Request denied.]
-
-[Incorrect SNAC format.]
-
-[Insufficient rights.]
-
-[Recipient blocked.]
-
-[Sender too evil.]
-
-[Receiver too evil.]
-
-[User temporarily unavailable.]
-
-[No match.]
-
-[List overflow.]
-
-[Request ambiguous.]
-
-[Server queue full.]
-
-[Not while on AOL.]
-
-[Check your screen name.]
-
-[Check your password.]
-
-[Check your email address.]
-
-[Service temporarily unavailable.]
-
-[Field change temporarily unavailable.]
-
-[Invalid screen name.]
-
-[Invalid password.]
-
-[Invalid email.]
-
-[Invalid registration preference.]
-
-[Invalid old password.]
-
-[Invalid screen name Length.]
-
-[Invalid password length.]
-
-[Invalid email length.]
-
-[Invalid old password length.]
-
-[Need old password.]
-
-[Read only field.]
-
-[Write only field.]
-
-[Unsupported type.]
-
-[An error has occurred.]
-
-[Invalid account.]
-
-[Deleted account.]
-
-[Expired account.]
-
-[No database access.]
-
-[Invalid database fields.]
-
-[Bad database status.]
-
-[Migration cancel.]
-
-[Internal error.]
-
-[There is already a pending request for this screen name.]
-
-[Not DT status.]
-
-[Outstanding confirmation.]
-
-[No email address.]
-
-[Over limit.]
-
-[Email host fail.]
-
-[DNS fail.]
-
-;file \protocols\AimOscar\src\file.cpp
-[Failed to open file: %s : %s]
-
-;file \protocols\AimOscar\src\links.cpp
-[AIM link protocol]
-
-;file \protocols\AimOscar\src\popup.cpp
-[%s protocol]
-
-[Open mail account?]
-
-;file \protocols\AimOscar\src\proto.cpp
-[%s server connection]
-
-[%s client-to-client connections]
-
-;file \protocols\AimOscar\src\server.cpp
-[[Auto-response]:]
-
-[Contact tried to open an audio/video conference (not currently supported)]
-
-[No information has been provided by the server.]
-
-[Item you want to delete not found in list.]
-
-[Failed to add buddy to list: Item already exist.]
-
-[Error adding buddy (invalid ID or already in list?)]
-
-[Cannot add buddy. Limit for this type of item exceeded.]
-
-[Error? Attempting to add ICQ contact to an AIM list.]
-
-[Cannot add this buddy because it requires authorization.]
-
-[Unknown error when adding buddy to list. Error code %#x]
-
-[Item you want to modify not found in list.]
-
-[Unknown error when attempting to modify a group. Error code %#x]
-
-[You've got mail! Checked at]
-
-[Error uploading avatar. (Too small)]
-
-[Error uploading avatar. (Too big)]
-
-[Error uploading avatar. (Wrong type)]
-
-[Error uploading avatar. (Is banned)]
-
-[Error uploading avatar. (Unknown error)]
-
-[A confirmation message has been sent to the new email address. Please follow its instructions.]
-
-[A confirmation message has been sent to your email address. Please follow its instructions.]
-
-[Unable to confirm at this time. Please try again later.]
-
-[Your account has already been confirmed.]
-
-[Can't start the confirmation procedure.]
-
-;file \protocols\AimOscar\src\theme.cpp
-[Block]
-
-[Profile]
-Profil
-[AOL mail]
-
-[AIM icon]
-
-[Hiptop]
-
-[AOL bot]
-
-[Admin]
-
-[Confirmed]
-
-[Not confirmed]
-
-[Blocked list]
-
-[Foreground color]
-
-[Background color]
-Boja pozadine
-[Bold]
-Podebljano
-[Not bold]
-
-[Italic]
-
-[Not italic]
-
-[Underline]
-
-[Not underline]
-
-[Subscript]
-
-[Not subscript]
-
-[Superscript]
-
-[Not superscript]
-
-[Normal script]
-
-[Not normal script]
-
-[Profile editor]
-
-[AIM account type]
-
-[AIM extended status]
-
-[&Block]
-
-[&Unblock]
-
-[Manage account]
-
-[Instant idle]
-
-[Read &HTML away message]
-
-[Read profile]
-
-[Add to server list]
-
-;file \protocols\AimOscar\src\ui.cpp
-[Network]
-Mreža
-[Basic]
-
-[Privacy]
-
-[Join me in this buddy chat!]
-
-;file \protocols\AimOscar\src\utility.cpp
-[Please, enter a user name in the options dialog.]
-
-[Please, enter a password in the options dialog.]
-
-[Failed to open file: %s %s]
-
diff --git a/langpacks/serbian/Plugins/AddContactPlus.txt b/langpacks/serbian/Plugins/AddContactPlus.txt
index 289a648e2d..3a1d3e4fac 100644
--- a/langpacks/serbian/Plugins/AddContactPlus.txt
+++ b/langpacks/serbian/Plugins/AddContactPlus.txt
@@ -3,7 +3,7 @@
; File: AddContactPlus.dll
; Plugin: Add contact+
; Version: 0.9.9.2
-; Authors: Bartosz 'Dezeath' Bialek
+; Authors: Bartosz 'Dezeath' Białek
;============================================================
[Provides the ability to quickly add new contacts.]
diff --git a/langpacks/serbian/Plugins/AssocMgr.txt b/langpacks/serbian/Plugins/AssocMgr.txt
index cc5083e523..8e54f52378 100644
--- a/langpacks/serbian/Plugins/AssocMgr.txt
+++ b/langpacks/serbian/Plugins/AssocMgr.txt
@@ -5,7 +5,7 @@
; Version: 0.2.1.0
; Authors: H. Herkenrath
;============================================================
-[Handles file type associations and URLs like aim, gg, mirpu, tlen, wpmsg, xmpp, ymsgr.]
+[Handles file type associations and URLs like aim, gg, mirpu, wpmsg, xmpp, ymsgr.]
;file \plugins\AssocMgr\res\resource.rc
[Registered associations for Miranda NG:]
diff --git a/langpacks/serbian/Plugins/BASS_interface.txt b/langpacks/serbian/Plugins/BASS_interface.txt
index 07e9605d8e..3eff2adac8 100644
--- a/langpacks/serbian/Plugins/BASS_interface.txt
+++ b/langpacks/serbian/Plugins/BASS_interface.txt
@@ -1,20 +1,20 @@
#muuid {2f07ea05-05b5-4ff0-875d-c590da2ddac1}
;============================================================
; File: BASS_interface.dll
-; Plugin: BASS interface
+; Plugin: BASS Interface
; Version: 0.0.0.14
; Authors: tico-tico
;============================================================
-[un4seen's BASS interface Miranda NG plugin.]
+[Un4seen's BASS interface Miranda NG plugin.]
;file \plugins\BASS_interface\res\Bass.rc
-[un4seen's bass interface]
+[Un4seen's BASS interface]
[bass.dll loading error]
[Current bass.dll path:]
-[Maximum number of bass internal channels:]
+[Maximum number of BASS internal channels:]
[Output device:]
@@ -22,7 +22,7 @@
[Quiet time:]
-[download bass library]
+[download BASS library]
[Play only if]
@@ -49,7 +49,7 @@ Na ruÄku
[Preview]
;file \plugins\BASS_interface\src\Main.cpp
-[un4seen's bass version: %d.%d.%d.%d]
+[Un4seen's BASS version: %d.%d.%d.%d]
[--default device--]
@@ -61,6 +61,8 @@ Zvukovi
[Frame background]
+[BASS Interface]
+
[Bass Interface]
[Bass library]
diff --git a/langpacks/serbian/Plugins/BasicHistory.txt b/langpacks/serbian/Plugins/BasicHistory.txt
index 65d7ae0607..181c58dbd1 100644
--- a/langpacks/serbian/Plugins/BasicHistory.txt
+++ b/langpacks/serbian/Plugins/BasicHistory.txt
@@ -8,7 +8,7 @@
[History viewer for Miranda NG.]
;file \plugins\BasicHistory\res\BasicHistory.rc
-[Message History]
+[Message history]
Ranije poruke
[Settings]
@@ -16,9 +16,9 @@ Ranije poruke
[Show groups in contact list]
-[Do not show Find control border]
+[Do not show find control border]
-[Default Event Filter]
+[Default event filter]
[Custom filters]
@@ -56,31 +56,31 @@ Prikaži poruke
[Show seconds in timestamps]
-[Enable Smileys]
+[Enable smileys]
[Search forward in list group]
[Search forward in message window]
-[Match Case]
+[Match case]
-[Match Whole Word]
+[Match whole word]
-[Only Incoming Messages]
+[Only incoming messages]
-[Only Outgoing Messages]
+[Only outgoing messages]
-[Only Selected Group]
+[Only selected group]
-[All Contacts]
+[All contacts]
-[Export To Txt]
+[Export to txt]
[File encoding*]
-[Export To Plain Html]
+[Export to plain HTML]
-[Export To Rich Html]
+[Export to rich HTML]
[External CSS file]
@@ -141,9 +141,9 @@ Otkazivanje
;file \plugins\BasicHistory\src\BasicHistory.cpp
[Open History]
-[View &History]
+[View &history]
Pregledaj %istoriju
-[Delete All User History]
+[Delete all user history]
[Execute history task]
@@ -153,13 +153,13 @@ Dolazna poruka
Odlazna poruka
[Status change]
-[Show Contacts]
+[Show contacts]
-[Hide Contacts]
+[Hide contacts]
-[Find Next]
+[Find next]
-[Find Previous]
+[Find previous]
[Plus in export]
@@ -178,10 +178,10 @@ Istorija korisnika: %s
Sistem
[Me]
Ja
-[Invalid Message]
+[Invalid message]
Neodgovarajuća poruka
;file \plugins\BasicHistory\src\ExportManager.cpp
-[%s Files (*.%s)]
+[%s files (*.%s)]
[Import]
@@ -194,7 +194,7 @@ Neodgovarajuća poruka
;file \plugins\BasicHistory\src\HistoryWindow.cpp
[This operation will PERMANENTLY REMOVE all history for this contact.\nAre you sure you want to do this?]
-[Are You sure?]
+[Are you sure?]
Potpuno ste sigurni?
[Do you want to delete all imported messages for this contact?\nNote that next scheduler task import this messages again.]
@@ -208,11 +208,11 @@ Kopiraj li&nk
Kopiranje
[Delete]
Briši
-[Send Message]
+[Send message]
-[Reply &Quoted]
+[Reply &quoted]
-[Delete Group]
+[Delete group]
Briši grupu
[Options]
Podešavanja
@@ -224,9 +224,9 @@ Fontovi i boje
Ikonice
[Hotkeys]
Dostupne skraćenice
-[Rich Html]
+[Rich HTML]
-[Plain Html]
+[Plain HTML]
[Txt]
@@ -301,27 +301,27 @@ Pozadina spiska kontakata
[Find]
Pronađi
-[Switch Match Case]
+[Switch match case]
-[Switch Match Whole Word]
+[Switch match whole word]
-[Show/Hide Contacts]
+[Show/hide contacts]
-[Switch Only Incoming Messages]
+[Switch only incoming messages]
-[Switch Only Outgoing Messages]
+[Switch only outgoing messages]
-[Switch Only Selected Group]
+[Switch only selected group]
-[Switch All Contacts]
+[Switch all contacts]
-[Export To Binary]
+[Export to binary]
-[Import From Binary]
+[Import from binary]
-[Export To Dat (mContacts)]
+[Export to dat (mContacts)]
-[Import From Dat (mContacts)]
+[Import from dat (mContacts)]
[Invalid event number]
@@ -333,7 +333,7 @@ Pronađi
[Invalid file]
-[All Files (*.*)]
+[All files (*.*)]
[Enter filter name]
@@ -351,17 +351,17 @@ Pronađi
[Browse CSS file]
-[Export and Delete]
+[Export and delete]
-[Import and Merge]
+[Import and merge]
[Minute]
[Hour]
-[At Start]
+[At start]
-[At Finish]
+[At finish]
[Daily]
@@ -407,7 +407,7 @@ Pronađi
;file \plugins\BasicHistory\src\Options.h
;file \plugins\BasicHistory\src\PlainHtmlExport.cpp
-[History Log]
+[History log]
[Filter:]
diff --git a/langpacks/serbian/Plugins/Clist_modern.txt b/langpacks/serbian/Plugins/Clist_modern.txt
index 0ef2ba3a1d..edb0d24d57 100644
--- a/langpacks/serbian/Plugins/Clist_modern.txt
+++ b/langpacks/serbian/Plugins/Clist_modern.txt
@@ -50,6 +50,8 @@ Primeni
[Skin folder]
+[Download more skins]
+
[Available view modes]
[Include protocols]
diff --git a/langpacks/serbian/Plugins/Clist_nicer.txt b/langpacks/serbian/Plugins/Clist_nicer.txt
index 374c3ef181..bc4fa611e1 100644
--- a/langpacks/serbian/Plugins/Clist_nicer.txt
+++ b/langpacks/serbian/Plugins/Clist_nicer.txt
@@ -380,6 +380,8 @@ Grupa
[Ignore selection for groups]
+[Download more skins]
+
[Load from skin file]
[Export to skin file]
diff --git a/langpacks/serbian/Plugins/CloudFile.txt b/langpacks/serbian/Plugins/CloudFile.txt
index 3b2c7032b8..7e0445be52 100644
--- a/langpacks/serbian/Plugins/CloudFile.txt
+++ b/langpacks/serbian/Plugins/CloudFile.txt
@@ -2,7 +2,7 @@
;============================================================
; File: CloudFile.dll
; Plugin: CloudFile
-; Version: 0.11.0.2
+; Version: 0.11.0.3
; Authors: Miranda NG Team
;============================================================
[Allows you to transfer files via cloud services.]
diff --git a/langpacks/serbian/Plugins/DbEditorPP.txt b/langpacks/serbian/Plugins/DbEditorPP.txt
index 5e87116a95..e02316720d 100644
--- a/langpacks/serbian/Plugins/DbEditorPP.txt
+++ b/langpacks/serbian/Plugins/DbEditorPP.txt
@@ -2,7 +2,7 @@
;============================================================
; File: DbEditorPP.dll
; Plugin: Database editor++
-; Version: 4.0.1.1
+; Version: 4.0.1.2
; Authors: Bio, Jonathan Gordon
;============================================================
[Advanced Database Editor.]
diff --git a/langpacks/serbian/Plugins/Fingerprint.txt b/langpacks/serbian/Plugins/Fingerprint.txt
index 30623379f2..f3b1fe029d 100644
--- a/langpacks/serbian/Plugins/Fingerprint.txt
+++ b/langpacks/serbian/Plugins/Fingerprint.txt
@@ -46,8 +46,6 @@
[RSS clients]
-[Tlen clients]
-
[Weather clients]
[Yahoo clients]
@@ -107,8 +105,6 @@ Protokol
[Gadu-Gadu client]
-[Tlen.pl client]
-
[Python-based clients]
[Jabber client]
@@ -139,8 +135,6 @@ Protokol
[QQ overlay]
-[Tlen.pl overlay]
-
[Yahoo overlay]
[Mail.Ru Agent overlay]
@@ -175,12 +169,6 @@ Protokol
[Gadu-Gadu v8 client]
-[Tlen 7.x overlay]
-
-[Tlen 6.x overlay]
-
-[Tlen 5.x overlay]
-
[TM/QQ 2012 overlay]
[TM/QQ 2011 overlay]
diff --git a/langpacks/serbian/Plugins/GmailNotifier.txt b/langpacks/serbian/Plugins/GmailNotifier.txt
index 1b21718c01..e41b925935 100644
--- a/langpacks/serbian/Plugins/GmailNotifier.txt
+++ b/langpacks/serbian/Plugins/GmailNotifier.txt
@@ -2,7 +2,7 @@
;============================================================
; File: GmailNotifier.dll
; Plugin: Gmail Multiple Notifier
-; Version: 0.3.1.1
+; Version: 1.0.1.1
; Authors: Mixwind
;============================================================
[Check your Gmail inboxes locally.]
@@ -57,21 +57,19 @@ sekundi
;file \plugins\GmailNotifier\src\check.cpp
[Checking...]
-[Can't open Internet!]
-
-[Can't reach server!]
-
[Can't send account data!]
-[Can't get RSS feed!]
-
[Wrong name or password!]
+[Can't get RSS feed!]
+
;file \plugins\GmailNotifier\src\main.cpp
[Other]
Ostalo
[Gmail: New thread(s)]
+[Gmail Notifier connection]
+
[&Check all Gmail inboxes]
[&Check Gmail inbox]
diff --git a/langpacks/serbian/Plugins/IEView.txt b/langpacks/serbian/Plugins/IEView.txt
index 7436df8231..c58627db8c 100644
--- a/langpacks/serbian/Plugins/IEView.txt
+++ b/langpacks/serbian/Plugins/IEView.txt
@@ -66,6 +66,8 @@ Prikaži sekunde
[Use relative timestamp]
+[Download more templates]
+
;file \plugins\IEView\src\HistoryHTMLBuilder.cpp
[Outgoing File Transfer]
diff --git a/langpacks/serbian/Plugins/MSN.txt b/langpacks/serbian/Plugins/MSN.txt
index 1e4eaea88b..88d37fd60e 100644
--- a/langpacks/serbian/Plugins/MSN.txt
+++ b/langpacks/serbian/Plugins/MSN.txt
@@ -2,7 +2,7 @@
;============================================================
; File: MSN.dll
; Plugin: MSN protocol
-; Version: 0.14.0.1
+; Version: 0.14.0.2
; Authors: Boris Krasnovskiy, George Hazan, Richard Hughes, leecher
;============================================================
[Microsoft Network (MSN) protocol support for Miranda NG.]
diff --git a/langpacks/serbian/Plugins/New_GPG.txt b/langpacks/serbian/Plugins/New_GPG.txt
index 9607316c55..6012646c2d 100644
--- a/langpacks/serbian/Plugins/New_GPG.txt
+++ b/langpacks/serbian/Plugins/New_GPG.txt
@@ -176,86 +176,6 @@ Otkazivanje
[GPG encryption status]
;file \plugins\New_GPG\src\main.cpp
-[Email]
-
-[Name]
-Naziv
-[Creation date]
-
-[Expire date]
-
-[Key length]
-
-[Accounts]
-Nalozi
-[Default]
-Standardno
-[key ID]
-
-[not set]
-
-[Default private key ID]
-
-[Failed to open file]
-
-[Error]
-Greška
-[Generating new random key, please wait]
-
-[Failed to allocate memory]
-
-[Failed to lock memory with error %d]
-
-[Failed write to clipboard with error %d]
-
-[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
-
-[Warning]
-Upozorenje
-[Wrong GPG binary location found in system.\nPlease choose another location]
-
-[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-
-[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-
-["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
-
-[Info]
-
-[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
-
-[GPG binary does not exist.\nPlease choose another location]
-
-[Please choose GPG binary location]
-
-[Please set keyring's home directory]
-
-[There is existing key for contact, would you like to replace it with new key?]
-
-[New public key was received, do you want to import it?]
-
-[Replace]
-
-[Accept]
-
-[Received key from %s]
-
-[You must set encryption algorithm first]
-
-[Key length must be of length from 1024 to 4096 bits]
-
-[Invalid date]
-
-[Name must contain at least 5 characters]
-
-[Name cannot contain '(' or ')']
-
-[Invalid Email]
-
-[Generating new key, please wait...]
-
-[Failed to export public key.]
-
[GPG binary is set and valid (this is good).\n]
[GPG binary unset or invalid (plugin will not work).\n]
@@ -293,6 +213,8 @@ Upozorenje
;file \plugins\New_GPG\src\messages.cpp
[We received encrypted message from contact with encryption turned off.\nDo you want to turn on encryption for this contact?]
+[Warning]
+Upozorenje
[Do you want to try to decrypt encrypted message?]
[We're trying to encrypt with untrusted key. Do you want to trust this key permanently?]
@@ -300,22 +222,20 @@ Upozorenje
[Something is wrong, GPG does not understand us, aborting encryption.]
;file \plugins\New_GPG\src\options.cpp
-[Services]
-
-[Main]
-
-[GnuPG Variables]
-
-[Messages]
-Poruke
-[Advanced]
-Napredno
[Contact]
Kontakt
[Key ID]
+[Name]
+Naziv
+[Email]
+
[Protocol]
Protokol
+[Default private key ID]
+
+[not set]
+
[This key is not used by any contact. Do you want to remove it from public keyring?]
[Key info]
@@ -332,6 +252,14 @@ Protokol
[.asc pubkey file]
+[Failed to allocate memory]
+
+[Error]
+Greška
+[Failed to lock memory with error %d]
+
+[Failed write to clipboard with error %d]
+
[Failed to open clipboard with error %d]
[Set log file]
@@ -340,6 +268,8 @@ Protokol
[Choose gpg.exe]
+[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+
[Set home directory]
[Load Public GPG Key for ]
@@ -356,12 +286,83 @@ Protokol
[Key already in secret keyring.]
+[Info]
+
[Set file containing GPG public key]
[GPG public key file]
+[Failed to open file]
+
[There is no public or private key.]
+[Services]
+
+[Main]
+
+[GnuPG Variables]
+
+[Messages]
+Poruke
+[Advanced]
+Napredno
+;file \plugins\New_GPG\src\ui.cpp
+[New passwords do not match]
+
+[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+
+[Creation date]
+
+[Expire date]
+
+[Key length]
+
+[Accounts]
+Nalozi
+[Default]
+Standardno
+[key ID]
+
+[Generating new random key, please wait]
+
+[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
+
+[Wrong GPG binary location found in system.\nPlease choose another location]
+
+[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+
+["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
+
+[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
+
+[There is existing key for contact, would you like to replace it with new key?]
+
+[New public key was received, do you want to import it?]
+
+[Replace]
+
+[Accept]
+
+[Received key from %s]
+
+[You must set encryption algorithm first]
+
+[Key length must be of length from 1024 to 4096 bits]
+
+[Invalid date]
+
+[Name must contain at least 5 characters]
+
+[Name cannot contain '(' or ')']
+
+[Invalid Email]
+
+[Generating new key, please wait...]
+
+[Expiration date]
+
+[Failed to export public key.]
+
;file \plugins\New_GPG\src\utilities.cpp
[Do you want to toggle encryption for all subcontacts?]
@@ -393,7 +394,10 @@ Protokol
[Keys import result]
-[New passwords do not match]
+[GPG binary does not exist.\nPlease choose another location]
-[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[Please choose GPG binary location]
+
+[Please set keyring's home directory]
+;file \plugins\New_GPG\src\utilities.h
diff --git a/langpacks/serbian/Plugins/SimpleStatusMsg.txt b/langpacks/serbian/Plugins/SimpleStatusMsg.txt
index 17a66267cc..19c7844ce3 100644
--- a/langpacks/serbian/Plugins/SimpleStatusMsg.txt
+++ b/langpacks/serbian/Plugins/SimpleStatusMsg.txt
@@ -3,7 +3,7 @@
; File: SimpleStatusMsg.dll
; Plugin: Simple status message
; Version: 1.9.0.6
-; Authors: Bartosz 'Dezeath' Bialek, Harven
+; Authors: Bartosz 'Dezeath' Białek, Harven
;============================================================
[Provides a simple way to set status and away messages.]
diff --git a/langpacks/serbian/Plugins/SmileyAdd.txt b/langpacks/serbian/Plugins/SmileyAdd.txt
index cc714cb47f..eba79e6ba2 100644
--- a/langpacks/serbian/Plugins/SmileyAdd.txt
+++ b/langpacks/serbian/Plugins/SmileyAdd.txt
@@ -2,7 +2,7 @@
;============================================================
; File: SmileyAdd.dll
; Plugin: SmileyAdd
-; Version: 0.2.4.2
+; Version: 0.3.0.1
; Authors: Peacow, nightwish, bid, borkra
;============================================================
[Smiley support for Miranda NG.]
@@ -98,16 +98,14 @@ Podešavanja
;file \plugins\SmileyAdd\src\smileys.cpp
[Smiley pack %s for category "%s" not found.\nSelect correct smiley pack in the Options -> Customize -> Smileys.]
-[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
-
[Smiley #%u in file %s for smiley pack %s not found.]
+[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
+
[%s global smiley pack]
[Standard]
-[Regular expression "%s" in smiley pack "%s" could produce "empty matches".]
-
[Regular expression "%s" in smiley pack "%s" malformed.]
;file \plugins\SmileyAdd\src\smltool.cpp
diff --git a/langpacks/serbian/Plugins/SplashScreen.txt b/langpacks/serbian/Plugins/SplashScreen.txt
index 58b331fd88..e260fa1113 100644
--- a/langpacks/serbian/Plugins/SplashScreen.txt
+++ b/langpacks/serbian/Plugins/SplashScreen.txt
@@ -38,6 +38,8 @@
[Preview...]
+[Download more splash screens]
+
;file \plugins\SplashScreen\src\options.cpp
[Graphic files]
diff --git a/langpacks/serbian/Plugins/StatusManager.txt b/langpacks/serbian/Plugins/StatusManager.txt
index 643f069851..c27f41b859 100644
--- a/langpacks/serbian/Plugins/StatusManager.txt
+++ b/langpacks/serbian/Plugins/StatusManager.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StatusManager.dll
; Plugin: Status manager
-; Version: 0.11.2.3
+; Version: 1.0.1.1
; Authors: P Boon
;============================================================
[A connection checker and auto away module. Also allows you to define the status Miranda should set on startup, configurable per protocol.]
diff --git a/langpacks/serbian/Plugins/Steam.txt b/langpacks/serbian/Plugins/Steam.txt
index df7ca345b8..e8940d67f8 100644
--- a/langpacks/serbian/Plugins/Steam.txt
+++ b/langpacks/serbian/Plugins/Steam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Steam.dll
; Plugin: Steam protocol
-; Version: 0.11.6.1
+; Version: 0.11.6.3
; Authors: Miranda NG Team, Robert Pösel
;============================================================
[Steam protocol support for Miranda NG.]
diff --git a/langpacks/serbian/Plugins/StopSpam.txt b/langpacks/serbian/Plugins/StopSpam.txt
index e0cf3bd687..b7ecc2a0b6 100644
--- a/langpacks/serbian/Plugins/StopSpam.txt
+++ b/langpacks/serbian/Plugins/StopSpam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpam.dll
; Plugin: StopSpam+
-; Version: 0.0.1.5
+; Version: 0.1.0.1
; Authors: Roman Miklashevsky, A. Petkevich, Kosh&chka, persei
;============================================================
[Anti-spam plugin for Miranda NG.]
@@ -43,6 +43,9 @@
;file \plugins\StopSpamPlus\src\events.cpp
[StopSpam automatic message:\r\n]
+;file \plugins\StopSpamPlus\src\options.cpp
+[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
+
[Message sessions]
Celi razgovori
[General]
@@ -51,15 +54,12 @@ Uopšteno
Poruke
[Accounts]
Nalozi
-;file \plugins\StopSpamPlus\src\options.cpp
-[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
-
;file \plugins\StopSpamPlus\src\services.cpp
[Not In List]
[Complete]
Dovršene
-;file \plugins\StopSpamPlus\src\settings.h
+;file \plugins\StopSpamPlus\src\settings.cpp
[Spammers made me to install small anti-spam system you are now speaking with. Please reply "nospam" without quotes and spaces if you want to contact me.]
[StopSpam: send a message and reply to an anti-spam bot question.]
diff --git a/langpacks/serbian/Plugins/StopSpamMod.txt b/langpacks/serbian/Plugins/StopSpamMod.txt
index aadb5482de..b4f99ce871 100644
--- a/langpacks/serbian/Plugins/StopSpamMod.txt
+++ b/langpacks/serbian/Plugins/StopSpamMod.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpamMod.dll
; Plugin: StopSpam mod
-; Version: 0.0.2.1
+; Version: 0.0.2.2
; Authors: Roman Miklashevsky, sss, Elzor
;============================================================
[Anti-spam plugin for Miranda NG.]
diff --git a/langpacks/serbian/Plugins/TabSRMM.txt b/langpacks/serbian/Plugins/TabSRMM.txt
index 80b9a09388..d877601b0f 100644
--- a/langpacks/serbian/Plugins/TabSRMM.txt
+++ b/langpacks/serbian/Plugins/TabSRMM.txt
@@ -516,6 +516,8 @@ Zatvori
[Import from a file...]
+[Download more skins]
+
[Icons]
Ikonice
[Event type icons in the message log]
diff --git a/langpacks/serbian/Plugins/Tox.txt b/langpacks/serbian/Plugins/Tox.txt
index 195be34e72..5e8956edb6 100644
--- a/langpacks/serbian/Plugins/Tox.txt
+++ b/langpacks/serbian/Plugins/Tox.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Tox.dll
; Plugin: Tox protocol
-; Version: 0.11.1.25
+; Version: 0.11.1.26
; Authors: Miranda NG Team
;============================================================
[Tox protocol support for Miranda NG.]
diff --git a/langpacks/serbian/Plugins/mRadio.txt b/langpacks/serbian/Plugins/mRadio.txt
index e34122bdf2..0016ea600e 100644
--- a/langpacks/serbian/Plugins/mRadio.txt
+++ b/langpacks/serbian/Plugins/mRadio.txt
@@ -101,7 +101,7 @@
[Sorry!]
-[BASS.DLL not found!]
+[bass.dll not found!]
[Station]
@@ -199,3 +199,5 @@ Isklj.
[Quick Open]
+[bass.dll not found! Choose bass.dll path manually]
+
diff --git a/langpacks/serbian/Untranslated/=CORE=.txt b/langpacks/serbian/Untranslated/=CORE=.txt
index acb990daa5..fec4199d8c 100644
--- a/langpacks/serbian/Untranslated/=CORE=.txt
+++ b/langpacks/serbian/Untranslated/=CORE=.txt
@@ -1,5 +1,6 @@
[These changes will take effect the next time you connect to the network.]
[Insert submenu]
+[Module:]
[Enable icons]
[Show in IM chats]
[Show in chat rooms]
diff --git a/langpacks/serbian/Untranslated/AIM.txt b/langpacks/serbian/Untranslated/AIM.txt
deleted file mode 100644
index e742b7c030..0000000000
--- a/langpacks/serbian/Untranslated/AIM.txt
+++ /dev/null
@@ -1,188 +0,0 @@
-[AOL Instant Messenger (AIM) protocol support for Miranda NG.]
-[AIM user details]
-[Screen name:]
-[Display name:]
-[AIM options]
-[Message delivery confirmation]
-[Do not autoreply when away]
-[Convert incoming messages to BBCode]
-[Convert outgoing messages to HTML]
-[Disable avatars]
-[Disable account type icons]
-[Disable extended status icons]
-[Notify about new mail]
-[Manage server groups]
-[Advanced options]
-[Instant idle on login]
-[Force proxy file transfers]
-[Masquerade as a Sidekick/Hiptop user]
-[Connection]
-[Login server:]
-[Disable SSL]
-[Force single client]
-[Use "clientlogin" (recommended)]
-[* Some changes will take effect the next time you connect to the AIM network]
-[Save profile]
-[Create a new AIM account]
-[AIM instant idler]
-[Number of hours:]
-[Number of minutes:]
-[Set idle]
-[Unset idle]
-[Users who can contact me:]
-[Allow all users]
-[Allow only users on contact list]
-[Allow only users below]
-[Block all users]
-[Block only users below]
-[Allow contacts to be notified of:]
-[Join chat room]
-[Chat room]
-[&Join]
-[This allows access to user defined chat rooms. To access predefined chat rooms use web links]
-[Change password]
-[Original]
-[New]
-[Repeat]
-[*Passwords don't match.]
-[Screen name]
-[Confirm account]
-[*Applied upon reconnect]
-[Save changes]
-[Invite buddy to chat room]
-[&Invite]
-[Invitation reason]
-[Chat room invitation request]
-[Room]
-[Others]
-[&Invite user...]
-[&Leave chat session]
-[User &history]
-[Invalid screen name or password.]
-[Mismatched screen name or password.]
-[You are connecting too frequently. Try waiting 10 minutes to reconnect.]
-[Unknown error occurred when attempting to connect.]
-[Invalid SNAC header.]
-[Server rate limit exceeded.]
-[Client rate limit exceeded]
-[Recipient is not logged in.]
-[Requested service is unavailable.]
-[Requested service is not defined.]
-[You sent obsolete SNAC.]
-[Not supported by server.]
-[Not supported by the client.]
-[Refused by client.]
-[Reply too big.]
-[Response lost.]
-[Request denied.]
-[Incorrect SNAC format.]
-[Insufficient rights.]
-[Recipient blocked.]
-[Sender too evil.]
-[Receiver too evil.]
-[User temporarily unavailable.]
-[No match.]
-[List overflow.]
-[Request ambiguous.]
-[Server queue full.]
-[Not while on AOL.]
-[Check your screen name.]
-[Check your password.]
-[Check your email address.]
-[Service temporarily unavailable.]
-[Field change temporarily unavailable.]
-[Invalid screen name.]
-[Invalid password.]
-[Invalid email.]
-[Invalid registration preference.]
-[Invalid old password.]
-[Invalid screen name Length.]
-[Invalid password length.]
-[Invalid email length.]
-[Invalid old password length.]
-[Need old password.]
-[Read only field.]
-[Write only field.]
-[Unsupported type.]
-[An error has occurred.]
-[Invalid account.]
-[Deleted account.]
-[Expired account.]
-[No database access.]
-[Invalid database fields.]
-[Bad database status.]
-[Migration cancel.]
-[Internal error.]
-[There is already a pending request for this screen name.]
-[Not DT status.]
-[Outstanding confirmation.]
-[No email address.]
-[Over limit.]
-[Email host fail.]
-[DNS fail.]
-[Failed to open file: %s : %s]
-[AIM link protocol]
-[%s protocol]
-[Open mail account?]
-[%s server connection]
-[%s client-to-client connections]
-[[Auto-response]:]
-[Contact tried to open an audio/video conference (not currently supported)]
-[No information has been provided by the server.]
-[Item you want to delete not found in list.]
-[Failed to add buddy to list: Item already exist.]
-[Error adding buddy (invalid ID or already in list?)]
-[Cannot add buddy. Limit for this type of item exceeded.]
-[Error? Attempting to add ICQ contact to an AIM list.]
-[Cannot add this buddy because it requires authorization.]
-[Unknown error when adding buddy to list. Error code %#x]
-[Item you want to modify not found in list.]
-[Unknown error when attempting to modify a group. Error code %#x]
-[You've got mail! Checked at]
-[Error uploading avatar. (Too small)]
-[Error uploading avatar. (Too big)]
-[Error uploading avatar. (Wrong type)]
-[Error uploading avatar. (Is banned)]
-[Error uploading avatar. (Unknown error)]
-[A confirmation message has been sent to the new email address. Please follow its instructions.]
-[A confirmation message has been sent to your email address. Please follow its instructions.]
-[Unable to confirm at this time. Please try again later.]
-[Your account has already been confirmed.]
-[Can't start the confirmation procedure.]
-[Block]
-[AOL mail]
-[AIM icon]
-[Hiptop]
-[AOL bot]
-[Admin]
-[Confirmed]
-[Not confirmed]
-[Blocked list]
-[Foreground color]
-[Not bold]
-[Italic]
-[Not italic]
-[Underline]
-[Not underline]
-[Subscript]
-[Not subscript]
-[Superscript]
-[Not superscript]
-[Normal script]
-[Not normal script]
-[Profile editor]
-[AIM account type]
-[AIM extended status]
-[&Block]
-[&Unblock]
-[Manage account]
-[Instant idle]
-[Read &HTML away message]
-[Read profile]
-[Add to server list]
-[Basic]
-[Privacy]
-[Join me in this buddy chat!]
-[Please, enter a user name in the options dialog.]
-[Please, enter a password in the options dialog.]
-[Failed to open file: %s %s]
diff --git a/langpacks/serbian/Untranslated/AssocMgr.txt b/langpacks/serbian/Untranslated/AssocMgr.txt
index 405290dafa..caf7e4ff83 100644
--- a/langpacks/serbian/Untranslated/AssocMgr.txt
+++ b/langpacks/serbian/Untranslated/AssocMgr.txt
@@ -1,4 +1,4 @@
-[Handles file type associations and URLs like aim, gg, mirpu, tlen, wpmsg, xmpp, ymsgr.]
+[Handles file type associations and URLs like aim, gg, mirpu, wpmsg, xmpp, ymsgr.]
[Registered associations for Miranda NG:]
[Miscellaneous]
[&Start Miranda NG automatically when the computer starts (using current profile)]
diff --git a/langpacks/serbian/Untranslated/BASS_interface.txt b/langpacks/serbian/Untranslated/BASS_interface.txt
index a7bb8610ab..05bb2bf520 100644
--- a/langpacks/serbian/Untranslated/BASS_interface.txt
+++ b/langpacks/serbian/Untranslated/BASS_interface.txt
@@ -1,19 +1,20 @@
-[un4seen's BASS interface Miranda NG plugin.]
-[un4seen's bass interface]
+[Un4seen's BASS interface Miranda NG plugin.]
+[Un4seen's BASS interface]
[bass.dll loading error]
[Current bass.dll path:]
-[Maximum number of bass internal channels:]
+[Maximum number of BASS internal channels:]
[Output device:]
[Volume:]
[Quiet time:]
-[download bass library]
+[download BASS library]
[Play only if]
[Preview]
-[un4seen's bass version: %d.%d.%d.%d]
+[Un4seen's BASS version: %d.%d.%d.%d]
[--default device--]
[Disable sounds]
[Enable sounds]
[Frame background]
+[BASS Interface]
[Bass Interface]
[Bass library]
[Sounds enabled]
diff --git a/langpacks/serbian/Untranslated/BasicHistory.txt b/langpacks/serbian/Untranslated/BasicHistory.txt
index 5b5d870d9f..4aa50f2d11 100644
--- a/langpacks/serbian/Untranslated/BasicHistory.txt
+++ b/langpacks/serbian/Untranslated/BasicHistory.txt
@@ -2,8 +2,8 @@
[Settings]
[Always show contact list]
[Show groups in contact list]
-[Do not show Find control border]
-[Default Event Filter]
+[Do not show find control border]
+[Default event filter]
[Custom filters]
[Add filter]
[Delete filter]
@@ -20,19 +20,19 @@
[Limit messages to:]
[Show date in timestamps]
[Show seconds in timestamps]
-[Enable Smileys]
+[Enable smileys]
[Search forward in list group]
[Search forward in message window]
-[Match Case]
-[Match Whole Word]
-[Only Incoming Messages]
-[Only Outgoing Messages]
-[Only Selected Group]
-[All Contacts]
-[Export To Txt]
+[Match case]
+[Match whole word]
+[Only incoming messages]
+[Only outgoing messages]
+[Only selected group]
+[All contacts]
+[Export to txt]
[File encoding*]
-[Export To Plain Html]
-[Export To Rich Html]
+[Export to plain HTML]
+[Export to rich HTML]
[External CSS file]
[* Choose encoding from combo box or enter code page number and name separated by semicolon, name is used in Content-Type header.]
[Add task]
@@ -60,28 +60,28 @@
[* Use negative values to filter younger events]
[Execute task for specified contacts]
[Open History]
-[Delete All User History]
+[Delete all user history]
[Execute history task]
[Status change]
-[Show Contacts]
-[Hide Contacts]
-[Find Next]
-[Find Previous]
+[Show contacts]
+[Hide contacts]
+[Find next]
+[Find previous]
[Plus in export]
[Minus in export]
[Default history events]
-[%s Files (*.%s)]
+[%s files (*.%s)]
[Import]
[Export]
[File does not contain selected contact]
[File is corrupted]
[This operation will PERMANENTLY REMOVE all history for this contact.\nAre you sure you want to do this?]
[Do you want to delete all imported messages for this contact?\nNote that next scheduler task import this messages again.]
-[Send Message]
-[Reply &Quoted]
+[Send message]
+[Reply &quoted]
[Filters]
-[Rich Html]
-[Plain Html]
+[Rich HTML]
+[Plain HTML]
[Txt]
[Binary]
[Dat (mContacts)]
@@ -108,23 +108,23 @@
[Find window background]
[Window background]
[Open global history]
-[Switch Match Case]
-[Switch Match Whole Word]
-[Show/Hide Contacts]
-[Switch Only Incoming Messages]
-[Switch Only Outgoing Messages]
-[Switch Only Selected Group]
-[Switch All Contacts]
-[Export To Binary]
-[Import From Binary]
-[Export To Dat (mContacts)]
-[Import From Dat (mContacts)]
+[Switch match case]
+[Switch match whole word]
+[Show/hide contacts]
+[Switch only incoming messages]
+[Switch only outgoing messages]
+[Switch only selected group]
+[Switch all contacts]
+[Export to binary]
+[Import from binary]
+[Export to dat (mContacts)]
+[Import from dat (mContacts)]
[Invalid event number]
[Incoming events]
[Outgoing events]
[File does not exist. Enter correct file path.]
[Invalid file]
-[All Files (*.*)]
+[All files (*.*)]
[Enter filter name]
[Filter name exists]
[Event already exists]
@@ -133,12 +133,12 @@
[You've entered invalid codepage. Select codepage from combo box or enter correct number.]
[Invalid codepage]
[Browse CSS file]
-[Export and Delete]
-[Import and Merge]
+[Export and delete]
+[Import and merge]
[Minute]
[Hour]
-[At Start]
-[At Finish]
+[At start]
+[At finish]
[Daily]
[Weekly]
[Monthly]
@@ -160,7 +160,7 @@
[Download from FTP (WinSCP requred)]
[Import from]
[** Use <date> to insert date, <ext> to insert extension, <contact> to insert contact name]
-[History Log]
+[History log]
[Filter:]
[Conversation started at %s]
[Menu]
diff --git a/langpacks/serbian/Untranslated/Clist_modern.txt b/langpacks/serbian/Untranslated/Clist_modern.txt
index 51b412b2f4..71a17122c8 100644
--- a/langpacks/serbian/Untranslated/Clist_modern.txt
+++ b/langpacks/serbian/Untranslated/Clist_modern.txt
@@ -12,6 +12,7 @@
[WARNING: \tSkins can modify your current profile. Rollback is not possible. \n\t\tPlease BACKUP your database before applying skin.]
[* Restart may be required for all changes to take effect]
[Skin folder]
+[Download more skins]
[Available view modes]
[Include protocols]
[New]
diff --git a/langpacks/serbian/Untranslated/Clist_nicer.txt b/langpacks/serbian/Untranslated/Clist_nicer.txt
index 223a29ee34..0d466ef909 100644
--- a/langpacks/serbian/Untranslated/Clist_nicer.txt
+++ b/langpacks/serbian/Untranslated/Clist_nicer.txt
@@ -97,6 +97,7 @@
[Group top padding]
[Frame title bar height]
[Ignore selection for groups]
+[Download more skins]
[Load from skin file]
[Export to skin file]
[Dialog]
diff --git a/langpacks/serbian/Untranslated/Fingerprint.txt b/langpacks/serbian/Untranslated/Fingerprint.txt
index 0d0233ab2f..1fd97bc9e8 100644
--- a/langpacks/serbian/Untranslated/Fingerprint.txt
+++ b/langpacks/serbian/Untranslated/Fingerprint.txt
@@ -18,7 +18,6 @@
[MSN clients]
[QQ clients]
[RSS clients]
-[Tlen clients]
[Weather clients]
[Yahoo clients]
[Facebook clients]
@@ -46,7 +45,6 @@
[Mail.Ru (unknown client)]
[TM 2008 and >]
[Gadu-Gadu client]
-[Tlen.pl client]
[Python-based clients]
[Jabber client]
[XMPP client]
@@ -62,7 +60,6 @@
[Jabber overlay]
[MSN overlay]
[QQ overlay]
-[Tlen.pl overlay]
[Yahoo overlay]
[Mail.Ru Agent overlay]
[VK overlay]
@@ -80,9 +77,6 @@
[Gadu-Gadu v10 client]
[Gadu-Gadu v9 client]
[Gadu-Gadu v8 client]
-[Tlen 7.x overlay]
-[Tlen 6.x overlay]
-[Tlen 5.x overlay]
[TM/QQ 2012 overlay]
[TM/QQ 2011 overlay]
[TM/QQ 2010 overlay]
diff --git a/langpacks/serbian/Untranslated/GmailNotifier.txt b/langpacks/serbian/Untranslated/GmailNotifier.txt
index 203532dc6f..0f6e3135cd 100644
--- a/langpacks/serbian/Untranslated/GmailNotifier.txt
+++ b/langpacks/serbian/Untranslated/GmailNotifier.txt
@@ -18,12 +18,11 @@
[This is a shared computer so disable auto login]
[Log unread threads into database (enable history)]
[Checking...]
-[Can't open Internet!]
-[Can't reach server!]
[Can't send account data!]
-[Can't get RSS feed!]
[Wrong name or password!]
+[Can't get RSS feed!]
[Gmail: New thread(s)]
+[Gmail Notifier connection]
[&Check all Gmail inboxes]
[&Check Gmail inbox]
[GmailNotifier]
diff --git a/langpacks/serbian/Untranslated/IEView.txt b/langpacks/serbian/Untranslated/IEView.txt
index 18ef06b918..1435269697 100644
--- a/langpacks/serbian/Untranslated/IEView.txt
+++ b/langpacks/serbian/Untranslated/IEView.txt
@@ -22,6 +22,7 @@
[Show date]
[Use long date format]
[Use relative timestamp]
+[Download more templates]
[Outgoing File Transfer]
[URL sent]
[URL received]
diff --git a/langpacks/serbian/Untranslated/New_GPG.txt b/langpacks/serbian/Untranslated/New_GPG.txt
index e62b913868..81f173a260 100644
--- a/langpacks/serbian/Untranslated/New_GPG.txt
+++ b/langpacks/serbian/Untranslated/New_GPG.txt
@@ -79,41 +79,6 @@
[Export GPG Public keys]
[Import GPG Public keys]
[GPG encryption status]
-[Email]
-[Creation date]
-[Expire date]
-[Key length]
-[key ID]
-[not set]
-[Default private key ID]
-[Failed to open file]
-[Generating new random key, please wait]
-[Failed to allocate memory]
-[Failed to lock memory with error %d]
-[Failed write to clipboard with error %d]
-[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
-[Wrong GPG binary location found in system.\nPlease choose another location]
-[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
-[Info]
-[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
-[GPG binary does not exist.\nPlease choose another location]
-[Please choose GPG binary location]
-[Please set keyring's home directory]
-[There is existing key for contact, would you like to replace it with new key?]
-[New public key was received, do you want to import it?]
-[Replace]
-[Accept]
-[Received key from %s]
-[You must set encryption algorithm first]
-[Key length must be of length from 1024 to 4096 bits]
-[Invalid date]
-[Name must contain at least 5 characters]
-[Name cannot contain '(' or ')']
-[Invalid Email]
-[Generating new key, please wait...]
-[Failed to export public key.]
[GPG binary is set and valid (this is good).\n]
[GPG binary unset or invalid (plugin will not work).\n]
[Home dir write access granted (this is good).\n]
@@ -135,10 +100,10 @@
[Do you want to try to decrypt encrypted message?]
[We're trying to encrypt with untrusted key. Do you want to trust this key permanently?]
[Something is wrong, GPG does not understand us, aborting encryption.]
-[Services]
-[Main]
-[GnuPG Variables]
[Key ID]
+[Email]
+[Default private key ID]
+[not set]
[This key is not used by any contact. Do you want to remove it from public keyring?]
[Key info]
[we have secret key for this public key, do not removing from GPG keyring]
@@ -147,10 +112,14 @@
[Do you want to remove key from entire metacontact (all subcontacts)?]
[Export public key]
[.asc pubkey file]
+[Failed to allocate memory]
+[Failed to lock memory with error %d]
+[Failed write to clipboard with error %d]
[Failed to open clipboard with error %d]
[Set log file]
[LOG files]
[Choose gpg.exe]
+[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
[Set home directory]
[Load Public GPG Key for ]
[Turn off encryption]
@@ -159,9 +128,40 @@
[ found in presence.)]
[This is not public or private key]
[Key already in secret keyring.]
+[Info]
[Set file containing GPG public key]
[GPG public key file]
+[Failed to open file]
[There is no public or private key.]
+[Services]
+[Main]
+[GnuPG Variables]
+[New passwords do not match]
+[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[Creation date]
+[Expire date]
+[Key length]
+[key ID]
+[Generating new random key, please wait]
+[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
+[Wrong GPG binary location found in system.\nPlease choose another location]
+[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
+[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
+[There is existing key for contact, would you like to replace it with new key?]
+[New public key was received, do you want to import it?]
+[Replace]
+[Accept]
+[Received key from %s]
+[You must set encryption algorithm first]
+[Key length must be of length from 1024 to 4096 bits]
+[Invalid date]
+[Name must contain at least 5 characters]
+[Name cannot contain '(' or ')']
+[Invalid Email]
+[Generating new key, please wait...]
+[Expiration date]
+[Failed to export public key.]
[Do you want to toggle encryption for all subcontacts?]
[Turn off GPG encryption]
[Turn on GPG encryption]
@@ -177,5 +177,6 @@
[We have successfully processed %d public keys and some private keys.]
[We have successfully processed %d public keys.]
[Keys import result]
-[New passwords do not match]
-[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[GPG binary does not exist.\nPlease choose another location]
+[Please choose GPG binary location]
+[Please set keyring's home directory]
diff --git a/langpacks/serbian/Untranslated/SmileyAdd.txt b/langpacks/serbian/Untranslated/SmileyAdd.txt
index 50de773f19..087605f28b 100644
--- a/langpacks/serbian/Untranslated/SmileyAdd.txt
+++ b/langpacks/serbian/Untranslated/SmileyAdd.txt
@@ -35,10 +35,9 @@
[Smileys]
[Protocol specific]
[Smiley pack %s for category "%s" not found.\nSelect correct smiley pack in the Options -> Customize -> Smileys.]
-[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
[Smiley #%u in file %s for smiley pack %s not found.]
+[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
[%s global smiley pack]
[Standard]
-[Regular expression "%s" in smiley pack "%s" could produce "empty matches".]
[Regular expression "%s" in smiley pack "%s" malformed.]
[d'Oh!]
diff --git a/langpacks/serbian/Untranslated/SplashScreen.txt b/langpacks/serbian/Untranslated/SplashScreen.txt
index 58cb20735e..7d3dc195ab 100644
--- a/langpacks/serbian/Untranslated/SplashScreen.txt
+++ b/langpacks/serbian/Untranslated/SplashScreen.txt
@@ -14,6 +14,7 @@
[Fade out:]
[AdvaImg plugin not found. Please get it from https://miranda-ng.org/p/AdvaImg/ to be able to use images.]
[Preview...]
+[Download more splash screens]
[Graphic files]
[Skins]
[Splash Screen]
diff --git a/langpacks/serbian/Untranslated/TabSRMM.txt b/langpacks/serbian/Untranslated/TabSRMM.txt
index 9da80344c5..f295ab7c3d 100644
--- a/langpacks/serbian/Untranslated/TabSRMM.txt
+++ b/langpacks/serbian/Untranslated/TabSRMM.txt
@@ -209,6 +209,7 @@
[You can export and import all your color and font settings here. This allows you to create a Theme file which can be shared between different profiles or with your buddies.]
[Export to a file...]
[Import from a file...]
+[Download more skins]
[Event type icons in the message log]
[Text symbols as event markers]
[Use different icons to mark incoming and outgoing messages]
diff --git a/langpacks/serbian/Untranslated/mRadio.txt b/langpacks/serbian/Untranslated/mRadio.txt
index 6d04ac77e4..336033e59f 100644
--- a/langpacks/serbian/Untranslated/mRadio.txt
+++ b/langpacks/serbian/Untranslated/mRadio.txt
@@ -46,7 +46,7 @@
[Continuous record]
[Quarry]
[Sorry!]
-[BASS.DLL not found!]
+[bass.dll not found!]
[Station]
[Custom INI file]
[Radio station URL]
@@ -92,3 +92,4 @@
[Equalizer]
[New]
[Quick Open]
+[bass.dll not found! Choose bass.dll path manually]
diff --git a/langpacks/spanish/=CORE=.txt b/langpacks/spanish/=CORE=.txt
index ee4368648d..3595a0514a 100644
--- a/langpacks/spanish/=CORE=.txt
+++ b/langpacks/spanish/=CORE=.txt
@@ -3,28 +3,6 @@
; Module: Miranda Core
; Version: 0.95.8
;============================================================
-[Authorization request]
-Solicitud de autorización
-[&Authorize]
-&Autorizar
-[&Deny]
-&Denegar
-[Decide &later]
-&Decidir más &tarde
-[User &details]
-&Detalles del usuario
-[Reason:]
-Razón:
-[Denial reason:]
-Razón de rechazo:
-[Add to contact list if authorized]
-Añadir a la lista de contactos si está autorizado
-[You were added]
-Usted fue añadido
-[&Close]
-&Cerrar
-[&Add]
-&Añadir
[%s message for %s]
%s Mensaje(S) para %s
[&Cancel]
@@ -287,6 +265,8 @@ Tamaño total:
Detalles:
[&User menu]
Menú de usuario
+[User &details]
+&Detalles del usuario
[&History]
&Historial
[Incoming file transfer]
@@ -303,6 +283,8 @@ Fecha:
Archivos:
[Save to:]
Guardar a:
+[&Add]
+&Añadir
[&Open...]
&Abrir...
[Open &folder]
@@ -391,10 +373,6 @@ Preguntarme
Renombrar (añadir " (1)", etc.)
[You will always be asked about files from people not on your contact list]
Siempre que se pregunte sobre archivos de personas que no están en la lista
-[About Miranda NG]
-Acerca de Miranda NG
-[Credits >]
-Créditos >
[Become idle if the following is left unattended:]
Pasar a reposo, si el siguiente queda desatendido:
[Become idle if the screen saver is active]
@@ -713,6 +691,8 @@ Abrir ventana de conversación del contacto
Nombre personalizado:
[Group:]
Grupo:
+[Authorization request]
+Solicitud de autorización
[&Yes]
&Sí
[&No]
@@ -1067,6 +1047,26 @@ Local
Recargar langpack
[Download more language packs]
Descargar más paquetes de idioma
+[&Authorize]
+&Autorizar
+[&Deny]
+&Denegar
+[Decide &later]
+&Decidir más &tarde
+[Reason:]
+Razón:
+[Denial reason:]
+Razón de rechazo:
+[Add to contact list if authorized]
+Añadir a la lista de contactos si está autorizado
+[You were added]
+Usted fue añadido
+[&Close]
+&Cerrar
+[About Miranda NG]
+Acerca de Miranda NG
+[Credits >]
+Créditos >
[Tray]
Bandeja
[&Hide/Show]
@@ -1119,40 +1119,6 @@ Lista
Limpiar re&gistro
[Word lookup]
Palabra de búsqueda
-[%s requests authorization]
-%s solicita autorización
-[%u requests authorization]
-%u olicita autorización
-[%s added you to their contact list]
-%s te ha añadido a su lista de contactos
-[%u added you to their contact list]
-%u te ha añadido a su lista de contactos
-[Alerts]
-Alertas
-[Added event]
-Evento añadido
-[View user's details]
-Ver detalles del usuario
-[Add contact permanently to list]
-Añadir contacto permanentemente a la lista
-[<Unknown>]
-<Desconocido>
-[%s added you to the contact list\n%u (%s) on %s]
-%s te agregó a la lista de contactos\n%u (%s) en %s
-[%s added you to the contact list\n%u on %s]
-%s te agregó a la lista de contactos\n%u en %s
-[%s added you to the contact list\n%s on %s]
-%s te agregó a la lista de contactos\n%s en %s
-[(Unknown)]
-(Desconocido)
-[%s requested authorization\n%u (%s) on %s]
-%s autorización solicitada\n%u (%s) en %s
-[%s requested authorization\n%u on %s]
-%s autorización solicitada\n%u en %s
-[%s requested authorization\n%s on %s]
-%s autorización solicitada\n%s on %s
-[Feature is not supported by protocol]
-La función no está soportada por el protocolo
[Re&ad %s message]
Leer %s mensaje(s)
[Re&ad status message]
@@ -1263,6 +1229,10 @@ Eventos
Seleccionar carpeta
[My received files]
Mis archivos recibidos
+[Add contact permanently to list]
+Añadir contacto permanentemente a la lista
+[View user's details]
+Ver detalles del usuario
[View user's history]
Ver historial del usuario
[User menu]
@@ -1325,18 +1295,6 @@ Análisis en busca de virus...
Transferencia y Análisis en busca de virus finalizado
[Outgoing]
Saliendo
-[< Copyright]
-< Copyright
-[&Help]
-A&yuda
-[&About...]
-&Acerca de...
-[&Support]
-&Soporte
-[&Miranda NG homepage]
-&Miranda NG página principal
-[&Report bug]
-&Reportar error
[Idle]
Inactivo
[Chat module]
@@ -1771,10 +1729,40 @@ Propietario
Ver/cambiar mis &datos...
[%s is online]
%s está en línea
+[Alerts]
+Alertas
[Add %s]
Añadir %s
[Please authorize my request and add me to your contact list.]
Por favor autorice mi petición y añadame a su lista de contactos.
+[%s requests authorization]
+%s solicita autorización
+[%u requests authorization]
+%u olicita autorización
+[%s added you to their contact list]
+%s te ha añadido a su lista de contactos
+[%u added you to their contact list]
+%u te ha añadido a su lista de contactos
+[Added event]
+Evento añadido
+[<Unknown>]
+<Desconocido>
+[%s added you to the contact list\n%u (%s) on %s]
+%s te agregó a la lista de contactos\n%u (%s) en %s
+[%s added you to the contact list\n%u on %s]
+%s te agregó a la lista de contactos\n%u en %s
+[%s added you to the contact list\n%s on %s]
+%s te agregó a la lista de contactos\n%s en %s
+[(Unknown)]
+(Desconocido)
+[%s requested authorization\n%u (%s) on %s]
+%s autorización solicitada\n%u (%s) en %s
+[%s requested authorization\n%u on %s]
+%s autorización solicitada\n%u en %s
+[%s requested authorization\n%s on %s]
+%s autorización solicitada\n%s on %s
+[Feature is not supported by protocol]
+La función no está soportada por el protocolo
[&Join chat]
&Entrar
[%s has joined]
@@ -2021,6 +2009,18 @@ Cabeceras
Texto genérico
[Small text]
Texto pequeño
+[< Copyright]
+< Copyright
+[&Help]
+A&yuda
+[&About...]
+&Acerca de...
+[&Support]
+&Soporte
+[&Miranda NG homepage]
+&Miranda NG página principal
+[&Report bug]
+&Reportar error
[Ctrl + ]
Ctrl +\s
[Alt + ]
diff --git a/langpacks/spanish/=HEAD=.txt b/langpacks/spanish/=HEAD=.txt
index 36e24aac76..9098823bf1 100644
--- a/langpacks/spanish/=HEAD=.txt
+++ b/langpacks/spanish/=HEAD=.txt
@@ -3,7 +3,7 @@ Language: Spanish (ES)
Locale: 0c0a
Authors: Carlos Sánchez (c-sanchez)
Author-email: carlos1994sanchez@gmail.com
-Last-Modified-Using: Miranda NG v0.95.7
+Last-Modified-Using: Miranda NG v0.95.8
; Una nueva traducción al Español para Miranda NG realizada desde cero.
diff --git a/langpacks/spanish/Plugins/AIM.txt b/langpacks/spanish/Plugins/AIM.txt
deleted file mode 100644
index f79cb98305..0000000000
--- a/langpacks/spanish/Plugins/AIM.txt
+++ /dev/null
@@ -1,53 +0,0 @@
-#muuid {3750a5a3-bf0d-490e-b65d-41ac4d29aeb3}
-;============================================================
-; File: AIM.dll
-; Plugin: AIM protocol
-; Version: 0.11.0.1
-; Authors: Boris Krasnovskiy, Aaron Myles Landwehr
-;============================================================
-[Password:]
-Contraseña:
-[Connection]
-Conexión
-[Port:]
-Puerto:
-[Reset]
-Reiniciar
-[Add]
-Añadir
-[Remove]
-Eliminar
-[Idle]
-Inactivo
-[&Join]
-&Entrar
-[&Cancel]
-&Cancelar
-[Change password]
-Cambiar contraseña
-[New]
-Nuevo
-[E-mail]
-E-mail
-[&Deny]
-&Denegar
-[Message]
-Mensaje
-[&Invite user...]
-&Invitar usuario...
-[&Leave chat session]
-&Abandonar sesión de charla
-[User &details]
-&Detalles del usuario
-[User &history]
-&Historial del usuario
-[%s server connection]
-%s conexión al servidor
-[Profile]
-Perfil
-[Background color]
-Color de fondo
-[Bold]
-Negrita
-[Network]
-Red
diff --git a/langpacks/spanish/Plugins/AddContactPlus.txt b/langpacks/spanish/Plugins/AddContactPlus.txt
index ee28f2d923..247afa282f 100644
--- a/langpacks/spanish/Plugins/AddContactPlus.txt
+++ b/langpacks/spanish/Plugins/AddContactPlus.txt
@@ -3,7 +3,7 @@
; File: AddContactPlus.dll
; Plugin: Add contact+
; Version: 0.9.9.2
-; Authors: Bartosz 'Dezeath' Bialek
+; Authors: Bartosz 'Dezeath' Białek
;============================================================
[Provides the ability to quickly add new contacts.]
Ofrece la posibilidad de añadir rápidamente nuevos contactos.
diff --git a/langpacks/spanish/Plugins/BASS_interface.txt b/langpacks/spanish/Plugins/BASS_interface.txt
index ca262a01ea..8a8226a7eb 100644
--- a/langpacks/spanish/Plugins/BASS_interface.txt
+++ b/langpacks/spanish/Plugins/BASS_interface.txt
@@ -1,19 +1,19 @@
#muuid {2f07ea05-05b5-4ff0-875d-c590da2ddac1}
;============================================================
; File: BASS_interface.dll
-; Plugin: BASS interface
+; Plugin: BASS Interface
; Version: 0.0.0.14
; Authors: tico-tico
;============================================================
-[un4seen's BASS interface Miranda NG plugin.]
-interfaz para el plugin un4seen's BASS de Miranda NG.
-[un4seen's bass interface]
-un4seen's bass interfaz
+[Un4seen's BASS interface Miranda NG plugin.]
+Interfaz para el plugin Un4seen's BASS de Miranda NG.
+[Un4seen's BASS interface]
+Un4seen's BASS interfaz
[bass.dll loading error]
Error cargando bass.dll
[Current bass.dll path:]
Ruta de bass.dll actual:
-[Maximum number of bass internal channels:]
+[Maximum number of BASS internal channels:]
Número máximo de canales bajos internos:
[Output device:]
Dispositivo de salida
@@ -21,8 +21,8 @@ Dispositivo de salida
Volumen:
[Quiet time:]
Tiempo de silencio:
-[download bass library]
-Descargar biblioteca bass
+[download BASS library]
+Descargar biblioteca BASS
[Play only if]
Reproducir sólo si
[Offline]
@@ -47,8 +47,8 @@ En el teléfono
Salí a comer
[Preview]
Previsualizar
-[un4seen's bass version: %d.%d.%d.%d]
-Versión de un4seen's bass: %d.%d.%d.%d
+[Un4seen's BASS version: %d.%d.%d.%d]
+Versión de Un4seen's BASS: %d.%d.%d.%d
[--default device--]
--dispositivo por defecto--
[Sounds]
@@ -59,10 +59,12 @@ Desabilitar sonidos
Habilitar sonidos
[Frame background]
Marco de fondo
+[BASS Interface]
+BASS interfaz
[Bass Interface]
-Bass interfaz
+BASS interfaz
[Bass library]
-Biblioteca Bass
+Biblioteca BASS
[Sounds enabled]
Sonidos habilitados
[Sounds disabled]
diff --git a/langpacks/spanish/Plugins/BasicHistory.txt b/langpacks/spanish/Plugins/BasicHistory.txt
index f772f85372..ca69b0d4d9 100644
--- a/langpacks/spanish/Plugins/BasicHistory.txt
+++ b/langpacks/spanish/Plugins/BasicHistory.txt
@@ -5,7 +5,7 @@
; Version: 1.0.1.10
; Authors: Krzysztof Kral
;============================================================
-[Message History]
+[Message history]
Historial de mensajes
[Settings]
Ajustes
@@ -15,7 +15,7 @@ Mostrar nombres
Mostrar mensajes
[hours]
horas
-[All Contacts]
+[All contacts]
Todos los contactos
[Name]
Nombre
@@ -23,7 +23,7 @@ Nombre
Contraseña
[Cancel]
Cancelar
-[View &History]
+[View &history]
Ver &historial
[Incoming message]
Mensaje entrante
@@ -39,7 +39,7 @@ Todos los eventos
Historial de %s
[System]
Sistema
-[Invalid Message]
+[Invalid message]
Mensaje no válido
[This operation will PERMANENTLY REMOVE all history for this contact.\nAre you sure you want to do this?]
Esta operación va a ELIMINAR DE FORMA PERMANENTE todo historial de este contacto.\n¿Está seguro de que quiere hacer esto?
@@ -53,9 +53,9 @@ Copiar enlace
Copiar
[Delete]
Eliminar
-[Send Message]
+[Send message]
Enviar mensaje
-[Delete Group]
+[Delete group]
Eliminar grupo
[Options]
Opciones
diff --git a/langpacks/spanish/Plugins/CloudFile.txt b/langpacks/spanish/Plugins/CloudFile.txt
index 36d7d16a57..0124e46b5f 100644
--- a/langpacks/spanish/Plugins/CloudFile.txt
+++ b/langpacks/spanish/Plugins/CloudFile.txt
@@ -2,12 +2,20 @@
;============================================================
; File: CloudFile.dll
; Plugin: CloudFile
-; Version: 0.11.0.2
+; Version: 0.11.0.3
; Authors: Miranda NG Team
;============================================================
[General]
General
+[Do nothing]
+No hacer nada
+[Authorization]
+Autorización
[Cancel]
Cancelar
+[Upload]
+Subir
[None]
Ninguno
+[Services]
+Servicios
diff --git a/langpacks/spanish/Plugins/DbEditorPP.txt b/langpacks/spanish/Plugins/DbEditorPP.txt
index 1c1297efbd..708e2bfc36 100644
--- a/langpacks/spanish/Plugins/DbEditorPP.txt
+++ b/langpacks/spanish/Plugins/DbEditorPP.txt
@@ -2,7 +2,7 @@
;============================================================
; File: DbEditorPP.dll
; Plugin: Database editor++
-; Version: 4.0.1.1
+; Version: 4.0.1.2
; Authors: Bio, Jonathan Gordon
;============================================================
[&Search]
diff --git a/langpacks/spanish/Plugins/GmailNotifier.txt b/langpacks/spanish/Plugins/GmailNotifier.txt
index 093943b751..f6fe8efa61 100644
--- a/langpacks/spanish/Plugins/GmailNotifier.txt
+++ b/langpacks/spanish/Plugins/GmailNotifier.txt
@@ -2,7 +2,7 @@
;============================================================
; File: GmailNotifier.dll
; Plugin: Gmail Multiple Notifier
-; Version: 0.3.1.1
+; Version: 1.0.1.1
; Authors: Mixwind
;============================================================
[Name:]
diff --git a/langpacks/spanish/Plugins/MRA.txt b/langpacks/spanish/Plugins/MRA.txt
index 7d7e587c80..6e3b2a9bf8 100644
--- a/langpacks/spanish/Plugins/MRA.txt
+++ b/langpacks/spanish/Plugins/MRA.txt
@@ -65,6 +65,8 @@ Femenino
Solicitar autorización
[Grant authorization]
Conceder autorización
+[Main icon]
+Icono principal
[Protocols]
Protocolos
[Main Menu]
@@ -99,3 +101,7 @@ Avatares
Inicio
[On the phone]
En el teléfono
+[Angry]
+Me enoja
+[Love]
+Me encanta
diff --git a/langpacks/spanish/Plugins/MSN.txt b/langpacks/spanish/Plugins/MSN.txt
index 8cb5fef971..21e5f79920 100644
--- a/langpacks/spanish/Plugins/MSN.txt
+++ b/langpacks/spanish/Plugins/MSN.txt
@@ -2,7 +2,7 @@
;============================================================
; File: MSN.dll
; Plugin: MSN protocol
-; Version: 0.14.0.1
+; Version: 0.14.0.2
; Authors: Boris Krasnovskiy, George Hazan, Richard Hughes, leecher
;============================================================
[Password:]
diff --git a/langpacks/spanish/Plugins/New_GPG.txt b/langpacks/spanish/Plugins/New_GPG.txt
index 7290cb306b..f9acbcef1a 100644
--- a/langpacks/spanish/Plugins/New_GPG.txt
+++ b/langpacks/spanish/Plugins/New_GPG.txt
@@ -17,18 +17,20 @@ Ignorar
Cancelar
[Password:]
Contraseña:
+[Warning]
+Advertencia
+[Contact]
+Contacto
[Name]
Nombre
-[Accounts]
-Cuentas
-[Default]
-Por defecto
+[Protocol]
+Protocolo
[not set]
no establecido
+[info]
+info
[Error]
Error
-[Warning]
-Advertencia
[Info]
Info
[Services]
@@ -39,9 +41,7 @@ Principal
Mensajes
[Advanced]
Avanzado
-[Contact]
-Contacto
-[Protocol]
-Protocolo
-[info]
-info
+[Accounts]
+Cuentas
+[Default]
+Por defecto
diff --git a/langpacks/spanish/Plugins/SimpleStatusMsg.txt b/langpacks/spanish/Plugins/SimpleStatusMsg.txt
index 3f008306d9..8529c1e007 100644
--- a/langpacks/spanish/Plugins/SimpleStatusMsg.txt
+++ b/langpacks/spanish/Plugins/SimpleStatusMsg.txt
@@ -3,7 +3,7 @@
; File: SimpleStatusMsg.dll
; Plugin: Simple status message
; Version: 1.9.0.6
-; Authors: Bartosz 'Dezeath' Bialek, Harven
+; Authors: Bartosz 'Dezeath' Białek, Harven
;============================================================
[%s message for %s]
%s Mensaje(S) para %s
diff --git a/langpacks/spanish/Plugins/SmileyAdd.txt b/langpacks/spanish/Plugins/SmileyAdd.txt
index 44f78de9b8..41bcb492f1 100644
--- a/langpacks/spanish/Plugins/SmileyAdd.txt
+++ b/langpacks/spanish/Plugins/SmileyAdd.txt
@@ -2,7 +2,7 @@
;============================================================
; File: SmileyAdd.dll
; Plugin: SmileyAdd
-; Version: 0.2.4.2
+; Version: 0.3.0.1
; Authors: Peacow, nightwish, bid, borkra
;============================================================
[Name:]
diff --git a/langpacks/spanish/Plugins/StatusManager.txt b/langpacks/spanish/Plugins/StatusManager.txt
index cc41cfc17d..dea91eb083 100644
--- a/langpacks/spanish/Plugins/StatusManager.txt
+++ b/langpacks/spanish/Plugins/StatusManager.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StatusManager.dll
; Plugin: Status manager
-; Version: 0.11.2.3
+; Version: 1.0.1.1
; Authors: P Boon
;============================================================
[Allows you to define the status Miranda should set on startup, configurable per account.]
diff --git a/langpacks/spanish/Plugins/Steam.txt b/langpacks/spanish/Plugins/Steam.txt
index 56d1561b74..5edd5028ee 100644
--- a/langpacks/spanish/Plugins/Steam.txt
+++ b/langpacks/spanish/Plugins/Steam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Steam.dll
; Plugin: Steam protocol
-; Version: 0.11.6.1
+; Version: 0.11.6.3
; Authors: Miranda NG Team, Robert Pösel
;============================================================
[Username:]
diff --git a/langpacks/spanish/Plugins/StopSpam.txt b/langpacks/spanish/Plugins/StopSpam.txt
index 1b9ad2f913..64c0ceb4a2 100644
--- a/langpacks/spanish/Plugins/StopSpam.txt
+++ b/langpacks/spanish/Plugins/StopSpam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpam.dll
; Plugin: StopSpam+
-; Version: 0.0.1.5
+; Version: 0.1.0.1
; Authors: Roman Miklashevsky, A. Petkevich, Kosh&chka, persei
;============================================================
[Divider:]
diff --git a/langpacks/spanish/Plugins/StopSpamMod.txt b/langpacks/spanish/Plugins/StopSpamMod.txt
index 0f310ea281..468905b231 100644
--- a/langpacks/spanish/Plugins/StopSpamMod.txt
+++ b/langpacks/spanish/Plugins/StopSpamMod.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpamMod.dll
; Plugin: StopSpam mod
-; Version: 0.0.2.1
+; Version: 0.0.2.2
; Authors: Roman Miklashevsky, sss, Elzor
;============================================================
[Info]
diff --git a/langpacks/spanish/Plugins/Tox.txt b/langpacks/spanish/Plugins/Tox.txt
index d710d3026c..48f6f72e0b 100644
--- a/langpacks/spanish/Plugins/Tox.txt
+++ b/langpacks/spanish/Plugins/Tox.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Tox.dll
; Plugin: Tox protocol
-; Version: 0.11.1.25
+; Version: 0.11.1.26
; Authors: Miranda NG Team
;============================================================
[Name:]
diff --git a/langpacks/spanish/Untranslated/=CORE=.txt b/langpacks/spanish/Untranslated/=CORE=.txt
index dabb6a237f..0a2dc58045 100644
--- a/langpacks/spanish/Untranslated/=CORE=.txt
+++ b/langpacks/spanish/Untranslated/=CORE=.txt
@@ -1,5 +1,6 @@
[These changes will take effect the next time you connect to the network.]
[Insert submenu]
+[Module:]
[Enable icons]
[Add to existing metacontact]
[Please select a metacontact:]
diff --git a/langpacks/spanish/Untranslated/AIM.txt b/langpacks/spanish/Untranslated/AIM.txt
deleted file mode 100644
index f88ffbaec3..0000000000
--- a/langpacks/spanish/Untranslated/AIM.txt
+++ /dev/null
@@ -1,181 +0,0 @@
-[AOL Instant Messenger (AIM) protocol support for Miranda NG.]
-[AIM user details]
-[Screen name:]
-[Display name:]
-[AIM options]
-[Message delivery confirmation]
-[Do not autoreply when away]
-[Convert incoming messages to BBCode]
-[Convert outgoing messages to HTML]
-[Disable avatars]
-[Disable account type icons]
-[Disable extended status icons]
-[Notify about new mail]
-[Manage server groups]
-[Advanced options]
-[Instant idle on login]
-[Force proxy file transfers]
-[Masquerade as a Sidekick/Hiptop user]
-[Login server:]
-[Disable SSL]
-[Force single client]
-[Use "clientlogin" (recommended)]
-[* Some changes will take effect the next time you connect to the AIM network]
-[Save profile]
-[Create a new AIM account]
-[AIM instant idler]
-[Number of hours:]
-[Number of minutes:]
-[Set idle]
-[Unset idle]
-[Users who can contact me:]
-[Allow all users]
-[Allow only users on contact list]
-[Allow only users below]
-[Block all users]
-[Block only users below]
-[Allow contacts to be notified of:]
-[Join chat room]
-[Chat room]
-[This allows access to user defined chat rooms. To access predefined chat rooms use web links]
-[Original]
-[Repeat]
-[*Passwords don't match.]
-[Screen name]
-[Confirm account]
-[*Applied upon reconnect]
-[Save changes]
-[Invite buddy to chat room]
-[&Invite]
-[Invitation reason]
-[Chat room invitation request]
-[Room]
-[Me]
-[Others]
-[Invalid screen name or password.]
-[Mismatched screen name or password.]
-[You are connecting too frequently. Try waiting 10 minutes to reconnect.]
-[Unknown error occurred when attempting to connect.]
-[Invalid SNAC header.]
-[Server rate limit exceeded.]
-[Client rate limit exceeded]
-[Recipient is not logged in.]
-[Requested service is unavailable.]
-[Requested service is not defined.]
-[You sent obsolete SNAC.]
-[Not supported by server.]
-[Not supported by the client.]
-[Refused by client.]
-[Reply too big.]
-[Response lost.]
-[Request denied.]
-[Incorrect SNAC format.]
-[Insufficient rights.]
-[Recipient blocked.]
-[Sender too evil.]
-[Receiver too evil.]
-[User temporarily unavailable.]
-[No match.]
-[List overflow.]
-[Request ambiguous.]
-[Server queue full.]
-[Not while on AOL.]
-[Check your screen name.]
-[Check your password.]
-[Check your email address.]
-[Service temporarily unavailable.]
-[Field change temporarily unavailable.]
-[Invalid screen name.]
-[Invalid password.]
-[Invalid email.]
-[Invalid registration preference.]
-[Invalid old password.]
-[Invalid screen name Length.]
-[Invalid password length.]
-[Invalid email length.]
-[Invalid old password length.]
-[Need old password.]
-[Read only field.]
-[Write only field.]
-[Unsupported type.]
-[An error has occurred.]
-[Invalid account.]
-[Deleted account.]
-[Expired account.]
-[No database access.]
-[Invalid database fields.]
-[Bad database status.]
-[Migration cancel.]
-[Internal error.]
-[There is already a pending request for this screen name.]
-[Not DT status.]
-[Outstanding confirmation.]
-[No email address.]
-[Over limit.]
-[Email host fail.]
-[DNS fail.]
-[Failed to open file: %s : %s]
-[AIM link protocol]
-[%s protocol]
-[Open mail account?]
-[%s client-to-client connections]
-[[Auto-response]:]
-[Contact tried to open an audio/video conference (not currently supported)]
-[No information has been provided by the server.]
-[Item you want to delete not found in list.]
-[Failed to add buddy to list: Item already exist.]
-[Error adding buddy (invalid ID or already in list?)]
-[Cannot add buddy. Limit for this type of item exceeded.]
-[Error? Attempting to add ICQ contact to an AIM list.]
-[Cannot add this buddy because it requires authorization.]
-[Unknown error when adding buddy to list. Error code %#x]
-[Item you want to modify not found in list.]
-[Unknown error when attempting to modify a group. Error code %#x]
-[You've got mail! Checked at]
-[Error uploading avatar. (Too small)]
-[Error uploading avatar. (Too big)]
-[Error uploading avatar. (Wrong type)]
-[Error uploading avatar. (Is banned)]
-[Error uploading avatar. (Unknown error)]
-[A confirmation message has been sent to the new email address. Please follow its instructions.]
-[A confirmation message has been sent to your email address. Please follow its instructions.]
-[Unable to confirm at this time. Please try again later.]
-[Your account has already been confirmed.]
-[Can't start the confirmation procedure.]
-[Block]
-[AOL mail]
-[AIM icon]
-[Hiptop]
-[AOL bot]
-[Admin]
-[Confirmed]
-[Not confirmed]
-[Blocked list]
-[Foreground color]
-[Not bold]
-[Italic]
-[Not italic]
-[Underline]
-[Not underline]
-[Subscript]
-[Not subscript]
-[Superscript]
-[Not superscript]
-[Normal script]
-[Not normal script]
-[Profile editor]
-[AIM account type]
-[AIM extended status]
-[&Block]
-[&Unblock]
-[Manage account]
-[Instant idle]
-[Read &HTML away message]
-[Read profile]
-[Add to server list]
-[Basic]
-[Privacy]
-[Join me in this buddy chat!]
-[Please, enter a user name in the options dialog.]
-[Please, enter a password in the options dialog.]
-[Failed to open file: %s %s]
diff --git a/langpacks/spanish/Untranslated/AssocMgr.txt b/langpacks/spanish/Untranslated/AssocMgr.txt
index 9365bcea03..67d7a8d33b 100644
--- a/langpacks/spanish/Untranslated/AssocMgr.txt
+++ b/langpacks/spanish/Untranslated/AssocMgr.txt
@@ -1,4 +1,4 @@
-[Handles file type associations and URLs like aim, gg, mirpu, tlen, wpmsg, xmpp, ymsgr.]
+[Handles file type associations and URLs like aim, gg, mirpu, wpmsg, xmpp, ymsgr.]
[Registered associations for Miranda NG:]
[&Start Miranda NG automatically when the computer starts (using current profile)]
[Only associate with Miranda NG while it is &running]
diff --git a/langpacks/spanish/Untranslated/BasicHistory.txt b/langpacks/spanish/Untranslated/BasicHistory.txt
index 1f1f74513c..94653a8be2 100644
--- a/langpacks/spanish/Untranslated/BasicHistory.txt
+++ b/langpacks/spanish/Untranslated/BasicHistory.txt
@@ -1,8 +1,8 @@
[History viewer for Miranda NG.]
[Always show contact list]
[Show groups in contact list]
-[Do not show Find control border]
-[Default Event Filter]
+[Do not show find control border]
+[Default event filter]
[Custom filters]
[Add filter]
[Delete filter]
@@ -18,18 +18,18 @@
[Limit messages to:]
[Show date in timestamps]
[Show seconds in timestamps]
-[Enable Smileys]
+[Enable smileys]
[Search forward in list group]
[Search forward in message window]
-[Match Case]
-[Match Whole Word]
-[Only Incoming Messages]
-[Only Outgoing Messages]
-[Only Selected Group]
-[Export To Txt]
+[Match case]
+[Match whole word]
+[Only incoming messages]
+[Only outgoing messages]
+[Only selected group]
+[Export to txt]
[File encoding*]
-[Export To Plain Html]
-[Export To Rich Html]
+[Export to plain HTML]
+[Export to rich HTML]
[External CSS file]
[* Choose encoding from combo box or enter code page number and name separated by semicolon, name is used in Content-Type header.]
[Add task]
@@ -56,27 +56,27 @@
[* Use negative values to filter younger events]
[Execute task for specified contacts]
[Open History]
-[Delete All User History]
+[Delete all user history]
[Execute history task]
-[Show Contacts]
-[Hide Contacts]
-[Find Next]
-[Find Previous]
+[Show contacts]
+[Hide contacts]
+[Find next]
+[Find previous]
[Plus in export]
[Minus in export]
[Default history events]
[Me]
-[%s Files (*.%s)]
+[%s files (*.%s)]
[Import]
[Export]
[File does not contain selected contact]
[File is corrupted]
-[Are You sure?]
+[Are you sure?]
[Do you want to delete all imported messages for this contact?\nNote that next scheduler task import this messages again.]
-[Reply &Quoted]
+[Reply &quoted]
[Filters]
-[Rich Html]
-[Plain Html]
+[Rich HTML]
+[Plain HTML]
[Txt]
[Binary]
[Dat (mContacts)]
@@ -102,23 +102,23 @@
[Find window background]
[Window background]
[Open global history]
-[Switch Match Case]
-[Switch Match Whole Word]
-[Show/Hide Contacts]
-[Switch Only Incoming Messages]
-[Switch Only Outgoing Messages]
-[Switch Only Selected Group]
-[Switch All Contacts]
-[Export To Binary]
-[Import From Binary]
-[Export To Dat (mContacts)]
-[Import From Dat (mContacts)]
+[Switch match case]
+[Switch match whole word]
+[Show/hide contacts]
+[Switch only incoming messages]
+[Switch only outgoing messages]
+[Switch only selected group]
+[Switch all contacts]
+[Export to binary]
+[Import from binary]
+[Export to dat (mContacts)]
+[Import from dat (mContacts)]
[Invalid event number]
[Incoming events]
[Outgoing events]
[File does not exist. Enter correct file path.]
[Invalid file]
-[All Files (*.*)]
+[All files (*.*)]
[Enter filter name]
[Filter name exists]
[Event already exists]
@@ -127,12 +127,12 @@
[You've entered invalid codepage. Select codepage from combo box or enter correct number.]
[Invalid codepage]
[Browse CSS file]
-[Export and Delete]
-[Import and Merge]
+[Export and delete]
+[Import and merge]
[Minute]
[Hour]
-[At Start]
-[At Finish]
+[At start]
+[At finish]
[Daily]
[Weekly]
[Monthly]
@@ -154,7 +154,7 @@
[Download from FTP (WinSCP requred)]
[Import from]
[** Use <date> to insert date, <ext> to insert extension, <contact> to insert contact name]
-[History Log]
+[History log]
[Filter:]
[Conversation started at %s]
[Menu]
diff --git a/langpacks/spanish/Untranslated/Clist_modern.txt b/langpacks/spanish/Untranslated/Clist_modern.txt
index 57599b55dc..a2c25092c4 100644
--- a/langpacks/spanish/Untranslated/Clist_modern.txt
+++ b/langpacks/spanish/Untranslated/Clist_modern.txt
@@ -1,4 +1,5 @@
[Skin folder]
+[Download more skins]
[Use xStatus icon]
[Icon mode]
[For similar statuses]
diff --git a/langpacks/spanish/Untranslated/Clist_nicer.txt b/langpacks/spanish/Untranslated/Clist_nicer.txt
index 90a8199349..85a091a4d5 100644
--- a/langpacks/spanish/Untranslated/Clist_nicer.txt
+++ b/langpacks/spanish/Untranslated/Clist_nicer.txt
@@ -80,6 +80,7 @@
[Group top padding]
[Frame title bar height]
[Ignore selection for groups]
+[Download more skins]
[Load from skin file]
[Export to skin file]
[Ignore these events]
diff --git a/langpacks/spanish/Untranslated/CloudFile.txt b/langpacks/spanish/Untranslated/CloudFile.txt
index 18f82567e1..397d4143e5 100644
--- a/langpacks/spanish/Untranslated/CloudFile.txt
+++ b/langpacks/spanish/Untranslated/CloudFile.txt
@@ -4,11 +4,9 @@
[Paste download link into message input area]
[Copy download link to clipboard]
[Download link]
-[Do nothing]
[Try to rename]
[Try to replace]
[On conflict when upload]
-[Authorization]
[Enter authorization code:]
[Allow access to team]
[Go to this link]
@@ -18,6 +16,4 @@
[OneDrive]
[Yandex.Disk]
[Upload to...]
-[Upload]
-[Services]
[Upload files to...]
diff --git a/langpacks/spanish/Untranslated/Fingerprint.txt b/langpacks/spanish/Untranslated/Fingerprint.txt
index 0d0233ab2f..1fd97bc9e8 100644
--- a/langpacks/spanish/Untranslated/Fingerprint.txt
+++ b/langpacks/spanish/Untranslated/Fingerprint.txt
@@ -18,7 +18,6 @@
[MSN clients]
[QQ clients]
[RSS clients]
-[Tlen clients]
[Weather clients]
[Yahoo clients]
[Facebook clients]
@@ -46,7 +45,6 @@
[Mail.Ru (unknown client)]
[TM 2008 and >]
[Gadu-Gadu client]
-[Tlen.pl client]
[Python-based clients]
[Jabber client]
[XMPP client]
@@ -62,7 +60,6 @@
[Jabber overlay]
[MSN overlay]
[QQ overlay]
-[Tlen.pl overlay]
[Yahoo overlay]
[Mail.Ru Agent overlay]
[VK overlay]
@@ -80,9 +77,6 @@
[Gadu-Gadu v10 client]
[Gadu-Gadu v9 client]
[Gadu-Gadu v8 client]
-[Tlen 7.x overlay]
-[Tlen 6.x overlay]
-[Tlen 5.x overlay]
[TM/QQ 2012 overlay]
[TM/QQ 2011 overlay]
[TM/QQ 2010 overlay]
diff --git a/langpacks/spanish/Untranslated/GmailNotifier.txt b/langpacks/spanish/Untranslated/GmailNotifier.txt
index 060dcb806c..20cdcd4dae 100644
--- a/langpacks/spanish/Untranslated/GmailNotifier.txt
+++ b/langpacks/spanish/Untranslated/GmailNotifier.txt
@@ -16,12 +16,11 @@
[This is a shared computer so disable auto login]
[Log unread threads into database (enable history)]
[Checking...]
-[Can't open Internet!]
-[Can't reach server!]
[Can't send account data!]
-[Can't get RSS feed!]
[Wrong name or password!]
+[Can't get RSS feed!]
[Gmail: New thread(s)]
+[Gmail Notifier connection]
[&Check all Gmail inboxes]
[&Check Gmail inbox]
[GmailNotifier]
diff --git a/langpacks/spanish/Untranslated/IEView.txt b/langpacks/spanish/Untranslated/IEView.txt
index 33d9e7474f..bcaf4a0f9b 100644
--- a/langpacks/spanish/Untranslated/IEView.txt
+++ b/langpacks/spanish/Untranslated/IEView.txt
@@ -22,6 +22,7 @@
[Show date]
[Use long date format]
[Use relative timestamp]
+[Download more templates]
[Outgoing File Transfer]
[URL sent]
[URL received]
diff --git a/langpacks/spanish/Untranslated/MRA.txt b/langpacks/spanish/Untranslated/MRA.txt
index 3c583bd588..cb82777181 100644
--- a/langpacks/spanish/Untranslated/MRA.txt
+++ b/langpacks/spanish/Untranslated/MRA.txt
@@ -113,7 +113,6 @@
[Receive files: request for file %s not sent, error]
[Send files: can't open file %s, error]
[Send files: requested file: %S - not found in send files list.]
-[Main icon]
[MRA]
[Extra status]
[Debug]
@@ -175,10 +174,8 @@
[Disappointed]
[Almost crying]
[Fearful]
-[Angry]
[Vampire]
[Ass]
-[Love]
[Sleeping]
[Cool!]
[Peace!]
diff --git a/langpacks/spanish/Untranslated/New_GPG.txt b/langpacks/spanish/Untranslated/New_GPG.txt
index e88c9a7004..c8aa1b830c 100644
--- a/langpacks/spanish/Untranslated/New_GPG.txt
+++ b/langpacks/spanish/Untranslated/New_GPG.txt
@@ -76,39 +76,6 @@
[Export GPG Public keys]
[Import GPG Public keys]
[GPG encryption status]
-[Email]
-[Creation date]
-[Expire date]
-[Key length]
-[key ID]
-[Default private key ID]
-[Failed to open file]
-[Generating new random key, please wait]
-[Failed to allocate memory]
-[Failed to lock memory with error %d]
-[Failed write to clipboard with error %d]
-[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
-[Wrong GPG binary location found in system.\nPlease choose another location]
-[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
-[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
-[GPG binary does not exist.\nPlease choose another location]
-[Please choose GPG binary location]
-[Please set keyring's home directory]
-[There is existing key for contact, would you like to replace it with new key?]
-[New public key was received, do you want to import it?]
-[Replace]
-[Accept]
-[Received key from %s]
-[You must set encryption algorithm first]
-[Key length must be of length from 1024 to 4096 bits]
-[Invalid date]
-[Name must contain at least 5 characters]
-[Name cannot contain '(' or ')']
-[Invalid Email]
-[Generating new key, please wait...]
-[Failed to export public key.]
[GPG binary is set and valid (this is good).\n]
[GPG binary unset or invalid (plugin will not work).\n]
[Home dir write access granted (this is good).\n]
@@ -130,8 +97,9 @@
[Do you want to try to decrypt encrypted message?]
[We're trying to encrypt with untrusted key. Do you want to trust this key permanently?]
[Something is wrong, GPG does not understand us, aborting encryption.]
-[GnuPG Variables]
[Key ID]
+[Email]
+[Default private key ID]
[This key is not used by any contact. Do you want to remove it from public keyring?]
[Key info]
[we have secret key for this public key, do not removing from GPG keyring]
@@ -139,10 +107,14 @@
[Do you want to remove key from entire metacontact (all subcontacts)?]
[Export public key]
[.asc pubkey file]
+[Failed to allocate memory]
+[Failed to lock memory with error %d]
+[Failed write to clipboard with error %d]
[Failed to open clipboard with error %d]
[Set log file]
[LOG files]
[Choose gpg.exe]
+[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
[Set home directory]
[Load Public GPG Key for ]
[Turn off encryption]
@@ -153,7 +125,35 @@
[Key already in secret keyring.]
[Set file containing GPG public key]
[GPG public key file]
+[Failed to open file]
[There is no public or private key.]
+[GnuPG Variables]
+[New passwords do not match]
+[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[Creation date]
+[Expire date]
+[Key length]
+[key ID]
+[Generating new random key, please wait]
+[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
+[Wrong GPG binary location found in system.\nPlease choose another location]
+[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
+[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
+[There is existing key for contact, would you like to replace it with new key?]
+[New public key was received, do you want to import it?]
+[Replace]
+[Accept]
+[Received key from %s]
+[You must set encryption algorithm first]
+[Key length must be of length from 1024 to 4096 bits]
+[Invalid date]
+[Name must contain at least 5 characters]
+[Name cannot contain '(' or ')']
+[Invalid Email]
+[Generating new key, please wait...]
+[Expiration date]
+[Failed to export public key.]
[Do you want to toggle encryption for all subcontacts?]
[Turn off GPG encryption]
[Turn on GPG encryption]
@@ -169,5 +169,6 @@
[We have successfully processed %d public keys and some private keys.]
[We have successfully processed %d public keys.]
[Keys import result]
-[New passwords do not match]
-[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+[GPG binary does not exist.\nPlease choose another location]
+[Please choose GPG binary location]
+[Please set keyring's home directory]
diff --git a/langpacks/spanish/Untranslated/SmileyAdd.txt b/langpacks/spanish/Untranslated/SmileyAdd.txt
index b4d0a87c38..9bd8cec2d3 100644
--- a/langpacks/spanish/Untranslated/SmileyAdd.txt
+++ b/langpacks/spanish/Untranslated/SmileyAdd.txt
@@ -32,10 +32,9 @@
[Smileys]
[Protocol specific]
[Smiley pack %s for category "%s" not found.\nSelect correct smiley pack in the Options -> Customize -> Smileys.]
-[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
[Smiley #%u in file %s for smiley pack %s not found.]
+[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
[%s global smiley pack]
[Standard]
-[Regular expression "%s" in smiley pack "%s" could produce "empty matches".]
[Regular expression "%s" in smiley pack "%s" malformed.]
[d'Oh!]
diff --git a/langpacks/spanish/Untranslated/SplashScreen.txt b/langpacks/spanish/Untranslated/SplashScreen.txt
new file mode 100644
index 0000000000..0add885a64
--- /dev/null
+++ b/langpacks/spanish/Untranslated/SplashScreen.txt
@@ -0,0 +1 @@
+[Download more splash screens]
diff --git a/langpacks/spanish/Untranslated/TabSRMM.txt b/langpacks/spanish/Untranslated/TabSRMM.txt
index f51ef34d0d..62a7961408 100644
--- a/langpacks/spanish/Untranslated/TabSRMM.txt
+++ b/langpacks/spanish/Untranslated/TabSRMM.txt
@@ -201,6 +201,7 @@
[You can export and import all your color and font settings here. This allows you to create a Theme file which can be shared between different profiles or with your buddies.]
[Export to a file...]
[Import from a file...]
+[Download more skins]
[Event type icons in the message log]
[Text symbols as event markers]
[Use different icons to mark incoming and outgoing messages]
diff --git a/langpacks/spanish/Untranslated/mRadio.txt b/langpacks/spanish/Untranslated/mRadio.txt
index 53a6a234ef..65e9a23606 100644
--- a/langpacks/spanish/Untranslated/mRadio.txt
+++ b/langpacks/spanish/Untranslated/mRadio.txt
@@ -46,7 +46,7 @@
[Continuous record]
[Quarry]
[Sorry!]
-[BASS.DLL not found!]
+[bass.dll not found!]
[Station]
[Custom INI file]
[Radio station URL]
@@ -90,3 +90,4 @@
[Device list]
[Equalizer]
[Quick Open]
+[bass.dll not found! Choose bass.dll path manually]
diff --git a/langpacks/ukrainian/=CORE=.txt b/langpacks/ukrainian/=CORE=.txt
index 96ad027c07..fbc6904e43 100644
--- a/langpacks/ukrainian/=CORE=.txt
+++ b/langpacks/ukrainian/=CORE=.txt
@@ -3,32 +3,12 @@
; Module: Miranda Core
; Version: 0.95.8
;============================================================
-[Authorization request]
-Запит авторизації
-[&Authorize]
-Дозволити
-[&Deny]
-&Відмовити
-[Decide &later]
-Вирішити &пізніше
-[User &details]
-&Про кориÑтувача
-[Reason:]
-Причина:
-[Denial reason:]
-Причина відмови:
-[Add to contact list if authorized]
-Додавати до ÑпиÑку контактів піÑÐ»Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ñ–Ñ—
-[You were added]
-Ð’Ð°Ñ Ð´Ð¾Ð´Ð°Ð»Ð¸
-[&Close]
-Закрити
-[&Add]
-&Додати
[%s message for %s]
%s (%s)
[&Cancel]
&СкаÑувати
+[Module:]
+Модуль:
[Retrieving %s message...]
Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ "%s"...
[Status messages]
@@ -287,6 +267,8 @@
ОпиÑ:
[&User menu]
&Меню кориÑтувача
+[User &details]
+&Про кориÑтувача
[&History]
&ІÑторіÑ
[Incoming file transfer]
@@ -303,6 +285,8 @@
Файли:
[Save to:]
Зберегти до:
+[&Add]
+&Додати
[&Open...]
&Відкрити...
[Open &folder]
@@ -391,10 +375,6 @@
Перейменувати: додати "(1)"
[You will always be asked about files from people not on your contact list]
Запит буде показано завжди, Ñкщо відправник поза ÑпиÑком контактів
-[About Miranda NG]
-Про Miranda NG
-[Credits >]
-Ðвтори >
[Become idle if the following is left unattended:]
Перейти до режиму очікуваннÑ, Ñкщо неактивні:
[Become idle if the screen saver is active]
@@ -713,6 +693,8 @@
Вказане ім'Ñ:
[Group:]
Група:
+[Authorization request]
+Запит авторизації
[&Yes]
&Так
[&No]
@@ -1121,6 +1103,26 @@ UIN, E-mail тощо
Проміжок кнопок:
[Hide if there isn't enough space]
Ховати, Ñкщо недоÑтатньо міÑцÑ
+[&Authorize]
+Дозволити
+[&Deny]
+&Відмовити
+[Decide &later]
+Вирішити &пізніше
+[Reason:]
+Причина:
+[Denial reason:]
+Причина відмови:
+[Add to contact list if authorized]
+Додавати до ÑпиÑку контактів піÑÐ»Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ñ–Ñ—
+[You were added]
+Ð’Ð°Ñ Ð´Ð¾Ð´Ð°Ð»Ð¸
+[&Close]
+Закрити
+[About Miranda NG]
+Про Miranda NG
+[Credits >]
+Ðвтори >
[Tray]
Трей
[&Hide/Show]
@@ -1179,40 +1181,6 @@ UIN, E-mail тощо
Мапи Google
[Google Translate]
Перекладач Google
-[%s requests authorization]
-%s запитує авторизацію
-[%u requests authorization]
-%u запитує авторизацію
-[%s added you to their contact list]
-%s додав Ð²Ð°Ñ Ð´Ð¾ Ñвого ÑпиÑку контактів
-[%u added you to their contact list]
-%u додав Ð²Ð°Ñ Ð´Ð¾ Ñвого ÑпиÑку контактів
-[Alerts]
-СповіщеннÑ
-[Added event]
-ÐŸÐ¾Ð´Ñ–Ñ "Ð’Ð°Ñ Ð´Ð¾Ð´Ð°Ð»Ð¸"
-[View user's details]
-Про кориÑтувача
-[Add contact permanently to list]
-Додати до ÑпиÑку
-[<Unknown>]
-<невідомо>
-[%s added you to the contact list\n%u (%s) on %s]
-%s додав Ð²Ð°Ñ Ð´Ð¾ Ñвого ÑпиÑку контактів\n%u (%s) о %s
-[%s added you to the contact list\n%u on %s]
-%s додав Ð²Ð°Ñ Ð´Ð¾ Ñвого ÑпиÑку контактів\n%u о %s
-[%s added you to the contact list\n%s on %s]
-%s додав Ð²Ð°Ñ Ð´Ð¾ Ñвого ÑпиÑку контактів\n%s о %s
-[(Unknown)]
-(невідомий)
-[%s requested authorization\n%u (%s) on %s]
-%s запитав(ла) авторизацію\n%u (%s) о %s
-[%s requested authorization\n%u on %s]
-%s запитав(ла) авторизацію\n%u о %s
-[%s requested authorization\n%s on %s]
-%s запитав(ла) авторизацію\n%s о %s
-[Feature is not supported by protocol]
-Ðе підтримуєтьÑÑ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»Ð¾Ð¼
[Re&ad %s message]
Читати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ "%s"
[Re&ad status message]
@@ -1323,6 +1291,10 @@ UIN, E-mail тощо
Вибрати папку
[My received files]
Отримані файли
+[Add contact permanently to list]
+Додати до ÑпиÑку
+[View user's details]
+Про кориÑтувача
[View user's history]
ІÑторіÑ
[User menu]
@@ -1387,18 +1359,6 @@ UIN, E-mail тощо
Передачу та перевірку на віруÑи завершено
[Outgoing]
Вихідні
-[< Copyright]
-< Права
-[&Help]
-Довідка
-[&About...]
-Про Miranda NG
-[&Support]
-П&ідтримка кориÑтувачів
-[&Miranda NG homepage]
-Сайт Miranda NG
-[&Report bug]
-Повідомити про помилку
[Idle]
ОчікуваннÑ
[Chat module]
@@ -1855,10 +1815,40 @@ UIN, E-mail тощо
ОÑобиÑті дані...
[%s is online]
%s в мережі
+[Alerts]
+СповіщеннÑ
[Add %s]
Додати %s
[Please authorize my request and add me to your contact list.]
Будь лаÑка, авторизуйте мене Ñ– внеÑіть до Ñвого ÑпиÑку контактів.
+[%s requests authorization]
+%s запитує авторизацію
+[%u requests authorization]
+%u запитує авторизацію
+[%s added you to their contact list]
+%s додав Ð²Ð°Ñ Ð´Ð¾ Ñвого ÑпиÑку контактів
+[%u added you to their contact list]
+%u додав Ð²Ð°Ñ Ð´Ð¾ Ñвого ÑпиÑку контактів
+[Added event]
+ÐŸÐ¾Ð´Ñ–Ñ "Ð’Ð°Ñ Ð´Ð¾Ð´Ð°Ð»Ð¸"
+[<Unknown>]
+<невідомо>
+[%s added you to the contact list\n%u (%s) on %s]
+%s додав Ð²Ð°Ñ Ð´Ð¾ Ñвого ÑпиÑку контактів\n%u (%s) о %s
+[%s added you to the contact list\n%u on %s]
+%s додав Ð²Ð°Ñ Ð´Ð¾ Ñвого ÑпиÑку контактів\n%u о %s
+[%s added you to the contact list\n%s on %s]
+%s додав Ð²Ð°Ñ Ð´Ð¾ Ñвого ÑпиÑку контактів\n%s о %s
+[(Unknown)]
+(невідомий)
+[%s requested authorization\n%u (%s) on %s]
+%s запитав(ла) авторизацію\n%u (%s) о %s
+[%s requested authorization\n%u on %s]
+%s запитав(ла) авторизацію\n%u о %s
+[%s requested authorization\n%s on %s]
+%s запитав(ла) авторизацію\n%s о %s
+[Feature is not supported by protocol]
+Ðе підтримуєтьÑÑ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»Ð¾Ð¼
[&Join chat]
&Увійти до чату
[&Open chat window]
@@ -2123,6 +2113,18 @@ Ctrl+Знайти додає контакт
Звичайний текÑÑ‚
[Small text]
Дрібний текÑÑ‚
+[< Copyright]
+< Права
+[&Help]
+Довідка
+[&About...]
+Про Miranda NG
+[&Support]
+П&ідтримка кориÑтувачів
+[&Miranda NG homepage]
+Сайт Miranda NG
+[&Report bug]
+Повідомити про помилку
[Remove shortcut]
Видалити
[Add another shortcut]
diff --git a/langpacks/ukrainian/=HEAD=.txt b/langpacks/ukrainian/=HEAD=.txt
index 3073f8581a..83864e2a7c 100644
--- a/langpacks/ukrainian/=HEAD=.txt
+++ b/langpacks/ukrainian/=HEAD=.txt
@@ -1,6 +1,6 @@
Miranda Language Pack Version 1
Locale: 0422
-Last-Modified-Using: Miranda NG 0.95.7
+Last-Modified-Using: Miranda NG 0.95.8
Authors: apollo2k4, RMN
Author-email:
diff --git a/langpacks/ukrainian/Plugins/AIM.txt b/langpacks/ukrainian/Deprecated/AIM.txt
index 777846156a..777846156a 100644
--- a/langpacks/ukrainian/Plugins/AIM.txt
+++ b/langpacks/ukrainian/Deprecated/AIM.txt
diff --git a/langpacks/ukrainian/Plugins/AddContactPlus.txt b/langpacks/ukrainian/Plugins/AddContactPlus.txt
index cf4f45bbc5..85af5c3ec2 100644
--- a/langpacks/ukrainian/Plugins/AddContactPlus.txt
+++ b/langpacks/ukrainian/Plugins/AddContactPlus.txt
@@ -3,7 +3,7 @@
; File: AddContactPlus.dll
; Plugin: Add contact+
; Version: 0.9.9.2
-; Authors: Bartosz 'Dezeath' Bialek
+; Authors: Bartosz 'Dezeath' Białek
;============================================================
[Provides the ability to quickly add new contacts.]
Ðадає можливіÑть швидко додати контакт.
diff --git a/langpacks/ukrainian/Plugins/AssocMgr.txt b/langpacks/ukrainian/Plugins/AssocMgr.txt
index efcb562be7..8a6ed06653 100644
--- a/langpacks/ukrainian/Plugins/AssocMgr.txt
+++ b/langpacks/ukrainian/Plugins/AssocMgr.txt
@@ -5,8 +5,8 @@
; Version: 0.2.1.0
; Authors: H. Herkenrath
;============================================================
-[Handles file type associations and URLs like aim, gg, mirpu, tlen, wpmsg, xmpp, ymsgr.]
-ÐÑÐ¾Ñ†Ñ–Ð°Ñ†Ñ–Ñ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½ÑŒ файлів Ñ– URL-поÑилань з протоколами: AIM, Gadu-Gadu, Jabber, MSN, PluginUpdater, Tlen, Yahoo.
+[Handles file type associations and URLs like aim, gg, mirpu, wpmsg, xmpp, ymsgr.]
+ÐÑÐ¾Ñ†Ñ–Ð°Ñ†Ñ–Ñ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½ÑŒ файлів Ñ– URL-поÑилань з протоколами: AIM, Gadu-Gadu, Jabber, MSN, PluginUpdater, Yahoo.
[Registered associations for Miranda NG:]
ЗареєÑтровані аÑоціації Ð´Ð»Ñ Miranda NG:
[Miscellaneous]
diff --git a/langpacks/ukrainian/Plugins/BASS_interface.txt b/langpacks/ukrainian/Plugins/BASS_interface.txt
index 667014867a..1c3edc9686 100644
--- a/langpacks/ukrainian/Plugins/BASS_interface.txt
+++ b/langpacks/ukrainian/Plugins/BASS_interface.txt
@@ -1,19 +1,19 @@
#muuid {2f07ea05-05b5-4ff0-875d-c590da2ddac1}
;============================================================
; File: BASS_interface.dll
-; Plugin: BASS interface
+; Plugin: BASS Interface
; Version: 0.0.0.14
; Authors: tico-tico
;============================================================
-[un4seen's BASS interface Miranda NG plugin.]
+[Un4seen's BASS interface Miranda NG plugin.]
Підтримка бібліотеки BASS Ð´Ð»Ñ Miranda NG.
-[un4seen's bass interface]
+[Un4seen's BASS interface]
Підтримка бібліотеки BASS
[bass.dll loading error]
Помилка Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð±Ñ–Ð±Ð»Ñ–Ð¾Ñ‚ÐµÐºÐ¸ bass.dll
[Current bass.dll path:]
Поточний шлÑÑ… до bass.dll:
-[Maximum number of bass internal channels:]
+[Maximum number of BASS internal channels:]
МакÑимальна кількіÑть каналів:
[Output device:]
ПриÑтрій виводу:
@@ -21,7 +21,7 @@
Рівень гучноÑті:
[Quiet time:]
Тиха година:
-[download bass library]
+[download BASS library]
завантажити бібліотеку BASS
[Play only if]
Грати, Ñкщо
@@ -47,7 +47,7 @@
Обідаю
[Preview]
ТеÑÑ‚
-[un4seen's bass version: %d.%d.%d.%d]
+[Un4seen's BASS version: %d.%d.%d.%d]
ВерÑÑ–Ñ Ð±Ñ–Ð±Ð»Ñ–Ð¾Ñ‚ÐµÐºÐ¸ BASS: %d.%d.%d.%d
[--default device--]
--типовий прилад--
@@ -59,6 +59,8 @@
Увімкнути звуки
[Frame background]
Фон
+[BASS Interface]
+Бібліотека BASS
[Bass Interface]
Бібліотека BASS
[Bass library]
diff --git a/langpacks/ukrainian/Plugins/BasicHistory.txt b/langpacks/ukrainian/Plugins/BasicHistory.txt
index 3be8f30888..81dcc9659e 100644
--- a/langpacks/ukrainian/Plugins/BasicHistory.txt
+++ b/langpacks/ukrainian/Plugins/BasicHistory.txt
@@ -7,7 +7,7 @@
;============================================================
[History viewer for Miranda NG.]
ПереглÑдач Ñ–Ñторії Ð´Ð»Ñ Miranda NG.
-[Message History]
+[Message history]
ІÑÑ‚Ð¾Ñ€Ñ–Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ
[Settings]
ÐалаштуваннÑ
@@ -15,9 +15,9 @@
Завжди показувати ÑпиÑок контактів
[Show groups in contact list]
Показувати групи в ÑпиÑку контактів
-[Do not show Find control border]
+[Do not show find control border]
Ðе показувати рамку Ñ€Ñдка пошуку
-[Default Event Filter]
+[Default event filter]
Фільтр подій
[Custom filters]
Свої фільтри
@@ -55,31 +55,31 @@
Показувати дату
[Show seconds in timestamps]
Показувати Ñекунди
-[Enable Smileys]
+[Enable smileys]
Увімкнути Ñмайли
[Search forward in list group]
Шукати далі в групі
[Search forward in message window]
Шукати далі у вікні повідомлень
-[Match Case]
+[Match case]
Враховувати регіÑтр
-[Match Whole Word]
+[Match whole word]
Слово цілком
-[Only Incoming Messages]
+[Only incoming messages]
Тільки вхідні повідомленнÑ
-[Only Outgoing Messages]
+[Only outgoing messages]
Тільки вихідні повідомленнÑ
-[Only Selected Group]
+[Only selected group]
Тільки вибрана група
-[All Contacts]
+[All contacts]
УÑÑ– контакти
-[Export To Txt]
+[Export to txt]
ЕкÑпорт в текÑÑ‚
[File encoding*]
ÐšÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ*
-[Export To Plain Html]
+[Export to plain HTML]
ЕкÑпорт у чиÑтий HTML
-[Export To Rich Html]
+[Export to rich HTML]
ЕкÑпорт в повноцінний HTML
[External CSS file]
Зовнішній файл CSS
@@ -139,9 +139,9 @@
СкаÑувати
[Open History]
Відкрити Ñ–Ñторію
-[View &History]
+[View &history]
&ІÑторіÑ
-[Delete All User History]
+[Delete all user history]
Видалити вÑÑŽ Ñ–Ñторію кориÑтувача
[Execute history task]
Виконати задачу
@@ -151,13 +151,13 @@
Вихідне повідомленнÑ
[Status change]
Зміна ÑтатуÑу
-[Show Contacts]
+[Show contacts]
Показати контакти
-[Hide Contacts]
+[Hide contacts]
Сховати контакти
-[Find Next]
+[Find next]
Знайти далі
-[Find Previous]
+[Find previous]
Знайте попереднє
[Plus in export]
ÐŸÐ»ÑŽÑ Ð² екÑпорті
@@ -175,9 +175,9 @@
СиÑтема
[Me]
Я
-[Invalid Message]
+[Invalid message]
Пошкоджене повідомленнÑ
-[%s Files (*.%s)]
+[%s files (*.%s)]
Файли %s (*.%s)
[Import]
Імпорт
@@ -189,7 +189,7 @@
Файл пошкоджений
[This operation will PERMANENTLY REMOVE all history for this contact.\nAre you sure you want to do this?]
Ð¦Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð¿Ð¾Ð²Ð½Ñ–Ñтю видалить Ñ–Ñторію цього контакту.\nВи впевнені?
-[Are You sure?]
+[Are you sure?]
Ви впевнені?
[Do you want to delete all imported messages for this contact?\nNote that next scheduler task import this messages again.]
Ви дійÑно хочете видалити вÑÑ– імпортовані Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ контакту?\nПримітка: наÑтупне Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð¿Ð»Ð°Ð½ÑƒÐ²Ð°Ñ‡Ð° імпортує ці Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð·Ð½Ð¾Ð²Ñƒ.
@@ -203,11 +203,11 @@
Копіювати
[Delete]
Видалити
-[Send Message]
+[Send message]
Відправити
-[Reply &Quoted]
+[Reply &quoted]
ВідповіÑти з &цитатою
-[Delete Group]
+[Delete group]
Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð³Ñ€ÑƒÐ¿Ð¸
[Options]
ÐалаштуваннÑ
@@ -219,9 +219,9 @@
Значки
[Hotkeys]
ГарÑчі клавіші
-[Rich Html]
+[Rich HTML]
Повноцінний HTML
-[Plain Html]
+[Plain HTML]
ЧиÑтий HTML
[Txt]
ТекÑÑ‚
@@ -295,27 +295,27 @@ dat (плагін mContacts)
Відкрити глобальну Ñ–Ñторію
[Find]
Знайти
-[Switch Match Case]
+[Switch match case]
Враховувати регіÑтр
-[Switch Match Whole Word]
+[Switch match whole word]
Слово цілком
-[Show/Hide Contacts]
+[Show/hide contacts]
Показати/Ñховати контакти
-[Switch Only Incoming Messages]
+[Switch only incoming messages]
Тільки вхідні повідомленнÑ
-[Switch Only Outgoing Messages]
+[Switch only outgoing messages]
Тільки вихідні повідомленнÑ
-[Switch Only Selected Group]
+[Switch only selected group]
Тільки вибрані групи
-[Switch All Contacts]
+[Switch all contacts]
УÑÑ– контакти
-[Export To Binary]
+[Export to binary]
ЕкÑпорт у двійковий файл
-[Import From Binary]
+[Import from binary]
Імпорт з двійкового файлу
-[Export To Dat (mContacts)]
+[Export to dat (mContacts)]
ЕкÑпорт у dat (плагін mContacts)
-[Import From Dat (mContacts)]
+[Import from dat (mContacts)]
Імпорт з dat (плагін mContacts)
[Invalid event number]
Ðеправильний номер події
@@ -327,7 +327,7 @@ dat (плагін mContacts)
Файл відÑутній. Вкажіть правильний шлÑÑ… до файлу.
[Invalid file]
Ðеправильний файл
-[All Files (*.*)]
+[All files (*.*)]
УÑÑ– файли (*.*)
[Enter filter name]
Введіть назву фільтра
@@ -345,17 +345,17 @@ dat (плагін mContacts)
Ðеправильна кодова Ñторінка
[Browse CSS file]
Вибрати CSS файл
-[Export and Delete]
+[Export and delete]
ЕкÑпортувати та видалити
-[Import and Merge]
+[Import and merge]
Імпорт Ñ– злиттÑ
[Minute]
Хвилини
[Hour]
Години
-[At Start]
+[At start]
Ðа Ñтарті
-[At Finish]
+[At finish]
Ðа виході
[Daily]
ЩоднÑ
@@ -399,7 +399,7 @@ dat (плагін mContacts)
Імпорт з:
[** Use <date> to insert date, <ext> to insert extension, <contact> to insert contact name]
** <date> вÑтавлÑÑ” дату, <ext> - розширеннÑ, <contact> - ім'Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ñƒ
-[History Log]
+[History log]
ПереглÑд Ñ–Ñторії
[Filter:]
Фільтр:
diff --git a/langpacks/ukrainian/Plugins/Clist_modern.txt b/langpacks/ukrainian/Plugins/Clist_modern.txt
index 73a67714b7..5684379352 100644
--- a/langpacks/ukrainian/Plugins/Clist_modern.txt
+++ b/langpacks/ukrainian/Plugins/Clist_modern.txt
@@ -63,6 +63,8 @@
Включити ÑтатуÑи
[Cancel]
СкаÑувати
+[Download more skins]
+Завантажити Ñкіни
[Sticky contacts]
Закріплені контакти
[Clear all]
diff --git a/langpacks/ukrainian/Plugins/Clist_nicer.txt b/langpacks/ukrainian/Plugins/Clist_nicer.txt
index 8318a35be4..cdd4b0ea59 100644
--- a/langpacks/ukrainian/Plugins/Clist_nicer.txt
+++ b/langpacks/ukrainian/Plugins/Clist_nicer.txt
@@ -59,6 +59,8 @@
Завжди показувати ÑÑ‚Ð°Ñ‚ÑƒÑ Ñƒ підказці
[ms]
мÑ
+[Download more skins]
+Завантажити Ñкіни
[Event area]
ОблаÑть подій
[Set base visibility on the frames menu]
diff --git a/langpacks/ukrainian/Plugins/CloudFile.txt b/langpacks/ukrainian/Plugins/CloudFile.txt
index e4cdd42985..18e0768ab6 100644
--- a/langpacks/ukrainian/Plugins/CloudFile.txt
+++ b/langpacks/ukrainian/Plugins/CloudFile.txt
@@ -2,7 +2,7 @@
;============================================================
; File: CloudFile.dll
; Plugin: CloudFile
-; Version: 0.11.0.2
+; Version: 0.11.0.3
; Authors: Miranda NG Team
;============================================================
[General]
diff --git a/langpacks/ukrainian/Plugins/DbEditorPP.txt b/langpacks/ukrainian/Plugins/DbEditorPP.txt
index 4e83a3a342..968f14b5f2 100644
--- a/langpacks/ukrainian/Plugins/DbEditorPP.txt
+++ b/langpacks/ukrainian/Plugins/DbEditorPP.txt
@@ -2,7 +2,7 @@
;============================================================
; File: DbEditorPP.dll
; Plugin: Database editor++
-; Version: 4.0.1.1
+; Version: 4.0.1.2
; Authors: Bio, Jonathan Gordon
;============================================================
[Advanced Database Editor.]
diff --git a/langpacks/ukrainian/Plugins/Fingerprint.txt b/langpacks/ukrainian/Plugins/Fingerprint.txt
index 20f78367db..7db81c3c02 100644
--- a/langpacks/ukrainian/Plugins/Fingerprint.txt
+++ b/langpacks/ukrainian/Plugins/Fingerprint.txt
@@ -45,8 +45,6 @@
Клієнти QQ
[RSS clients]
Клієнти RSS
-[Tlen clients]
-Клієнти Tlen
[Weather clients]
Клієнти погоди
[Yahoo clients]
@@ -103,8 +101,6 @@ Mail.Ru (невідомий клієнт)
TM 2008 і вище
[Gadu-Gadu client]
Клієнт Gadu-Gadu
-[Tlen.pl client]
-Клієнт Tlen.pl
[Python-based clients]
Клієнти на оÑнові Python
[Jabber client]
@@ -135,8 +131,6 @@ TM 2008 і вище
Оверлей MSN
[QQ overlay]
Оверлей QQ
-[Tlen.pl overlay]
-Оверлей Tlen.pl
[Yahoo overlay]
Оверлей Yahoo
[Mail.Ru Agent overlay]
@@ -171,12 +165,6 @@ Gadu-Gadu v10 клієнт
Gadu-Gadu v9 клієнт
[Gadu-Gadu v8 client]
Gadu-Gadu v8 клієнт
-[Tlen 7.x overlay]
-Оверлей Tlen 7.x
-[Tlen 6.x overlay]
-Оверлей Tlen 6.x
-[Tlen 5.x overlay]
-Оверлей Tlen 5.x
[TM/QQ 2012 overlay]
Оверлей TM/QQ 2012
[TM/QQ 2011 overlay]
diff --git a/langpacks/ukrainian/Plugins/GmailNotifier.txt b/langpacks/ukrainian/Plugins/GmailNotifier.txt
index bec09f17a7..e45da8907c 100644
--- a/langpacks/ukrainian/Plugins/GmailNotifier.txt
+++ b/langpacks/ukrainian/Plugins/GmailNotifier.txt
@@ -2,7 +2,7 @@
;============================================================
; File: GmailNotifier.dll
; Plugin: Gmail Multiple Notifier
-; Version: 0.3.1.1
+; Version: 1.0.1.1
; Authors: Mixwind
;============================================================
[Check your Gmail inboxes locally.]
@@ -55,16 +55,12 @@
ЗапиÑувати непрочитане в базу (вмикає Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ñ–Ñторії)
[Checking...]
Перевірка...
-[Can't open Internet!]
-Ðе можу ввійти в Інтернет!
-[Can't reach server!]
-Ðе можу зв'ÑзатиÑÑ Ð· Ñервером!
[Can't send account data!]
Ðе можу відправити дані облікового запиÑу!
-[Can't get RSS feed!]
-Ðе можу прочитати Ñтрічку RSS!
[Wrong name or password!]
Ðеправильне ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача або пароль!
+[Can't get RSS feed!]
+Ðе можу прочитати Ñтрічку RSS!
[Other]
Інше
[Gmail: New thread(s)]
diff --git a/langpacks/ukrainian/Plugins/MSN.txt b/langpacks/ukrainian/Plugins/MSN.txt
index 93a23fdc8a..ebccd6e6f1 100644
--- a/langpacks/ukrainian/Plugins/MSN.txt
+++ b/langpacks/ukrainian/Plugins/MSN.txt
@@ -2,7 +2,7 @@
;============================================================
; File: MSN.dll
; Plugin: MSN protocol
-; Version: 0.14.0.1
+; Version: 0.14.0.2
; Authors: Boris Krasnovskiy, George Hazan, Richard Hughes, leecher
;============================================================
[Microsoft Network (MSN) protocol support for Miranda NG.]
diff --git a/langpacks/ukrainian/Plugins/New_GPG.txt b/langpacks/ukrainian/Plugins/New_GPG.txt
index 098aed079c..382b56322e 100644
--- a/langpacks/ukrainian/Plugins/New_GPG.txt
+++ b/langpacks/ukrainian/Plugins/New_GPG.txt
@@ -155,60 +155,6 @@ ID ключа:
Імпортувати публічні ключі GPG
[GPG encryption status]
Ð¡Ñ‚Ð°Ñ‚ÑƒÑ ÑˆÐ¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ GPG
-[Email]
-Пошта
-[Name]
-Ім'Ñ
-[Creation date]
-Дата ÑтвореннÑ
-[Key length]
-Довжина ключа
-[Accounts]
-Облікові запиÑи
-[Default]
-За замовчаннÑм
-[key ID]
-Ключ
-[not set]
-Ðе вÑтановлено
-[Default private key ID]
-ОÑновний приватний ключ
-[Failed to open file]
-Ðеможливо відкрити файл
-[Error]
-Помилка
-[Warning]
-ПопередженнÑ
-[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-Вибраний вами exe не GnuPG!\nРекомендуємо викориÑтовувати GnuPG v1.x.x з цим плагіном.
-[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
-Ваша верÑÑ–Ñ GnuPG не підтримуєтьÑÑ Ñ– може працювати неправильно!\nРекомендуємо викориÑтовувати GnuPG v1.x.x з цим плагіном.
-[Info]
-Інфо
-[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
-Ваша верÑÑ–Ñ GPG підтримуєтьÑÑ. Мовні файли знайдені.\nПлагін повинен працювати нормально.\nÐатиÑніть ОК.
-[Please choose GPG binary location]
-Виберіть директорію з GnuPG
-[Please set keyring's home directory]
-Виберіть директорію з ключами GnuPG
-[There is existing key for contact, would you like to replace it with new key?]
-Отримано ключ, але в контакту вже є ключ. Ви хочете його замінити новим?
-[New public key was received, do you want to import it?]
-Отримано новий відкритий ключ. Ви хочете його прийнÑти?
-[Replace]
-Замінити
-[Accept]
-ПрийнÑти
-[Received key from %s]
-Отримано ключ від %s
-[Key length must be of length from 1024 to 4096 bits]
-Довжина ключа має бути від 1024 до 4096 біт
-[Name must contain at least 5 characters]
-Ім'Ñ Ð¼Ð°Ñ” міÑтити щонайменше 5 Ñимволів
-[Name cannot contain '(' or ')']
-Ім'Ñ Ð½Ðµ може міÑтити '(' чи ')'
-[Invalid Email]
-Ðеправильний E-mail
[GPG binary is set and valid (this is good).\n]
Виконуваний файл GPG вказаний і є придатним (Це добре).\n
[GPG binary unset or invalid (plugin will not work).\n]
@@ -233,22 +179,22 @@ ID ключа:
Завантажити ключ Ð´Ð»Ñ Ð²ÑÑ–Ñ… Ñубконтактів?
[Metacontact detected]
ВиÑвлено метаконтакт
-[Services]
-Служби
-[Main]
-Головний
-[GnuPG Variables]
-ШлÑÑ… до GPG
-[Messages]
-ПовідомленнÑ
-[Advanced]
-Додатково
+[Warning]
+ПопередженнÑ
[Contact]
Контакт
[Key ID]
Ключ
+[Name]
+Ім'Ñ
+[Email]
+Пошта
[Protocol]
Протокол
+[Default private key ID]
+ОÑновний приватний ключ
+[not set]
+Ðе вÑтановлено
[info]
Інфо
[Do you want to remove key from entire metacontact (all subcontacts)?]
@@ -257,10 +203,64 @@ ID ключа:
ЕкÑпорт відкритого ключа
[.asc pubkey file]
Файл публічного ключа (.asc)
+[Error]
+Помилка
[LOG files]
Файли журналу
+[This is not GnuPG binary!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+Вибраний вами exe не GnuPG!\nРекомендуємо викориÑтовувати GnuPG v1.x.x з цим плагіном.
[Turn off encryption]
Вимкнути шифруваннÑ
+[Info]
+Інфо
+[Failed to open file]
+Ðеможливо відкрити файл
+[Services]
+Служби
+[Main]
+Головний
+[GnuPG Variables]
+ШлÑÑ… до GPG
+[Messages]
+ПовідомленнÑ
+[Advanced]
+Додатково
+[New passwords do not match]
+Ðові паролі не збігаютьÑÑ
+[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
+Старий пароль не збігаєтьÑÑ, ви можете продовжити, але GPG не прийме неправильний пароль.\nПродовжити?
+[Creation date]
+Дата ÑтвореннÑ
+[Key length]
+Довжина ключа
+[Accounts]
+Облікові запиÑи
+[Default]
+За замовчаннÑм
+[key ID]
+Ключ
+[Unsupported GnuPG version found, use at you own risk!\nIt is recommended that you use GnuPG v1.x.x with this plugin.]
+Ваша верÑÑ–Ñ GnuPG не підтримуєтьÑÑ Ñ– може працювати неправильно!\nРекомендуємо викориÑтовувати GnuPG v1.x.x з цим плагіном.
+[Your GPG version is supported. The language file was found.\nGPG plugin should work fine.\nPress OK to continue.]
+Ваша верÑÑ–Ñ GPG підтримуєтьÑÑ. Мовні файли знайдені.\nПлагін повинен працювати нормально.\nÐатиÑніть ОК.
+[There is existing key for contact, would you like to replace it with new key?]
+Отримано ключ, але в контакту вже є ключ. Ви хочете його замінити новим?
+[New public key was received, do you want to import it?]
+Отримано новий відкритий ключ. Ви хочете його прийнÑти?
+[Replace]
+Замінити
+[Accept]
+ПрийнÑти
+[Received key from %s]
+Отримано ключ від %s
+[Key length must be of length from 1024 to 4096 bits]
+Довжина ключа має бути від 1024 до 4096 біт
+[Name must contain at least 5 characters]
+Ім'Ñ Ð¼Ð°Ñ” міÑтити щонайменше 5 Ñимволів
+[Name cannot contain '(' or ')']
+Ім'Ñ Ð½Ðµ може міÑтити '(' чи ')'
+[Invalid Email]
+Ðеправильний E-mail
[Turn off GPG encryption]
Вимкнути ÑˆÐ¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ GPG
[Turn on GPG encryption]
@@ -269,7 +269,7 @@ ID ключа:
Результат екÑпорту ключів
[Keys import result]
Результат імпорту ключів
-[New passwords do not match]
-Ðові паролі не збігаютьÑÑ
-[Old password does not match, you can continue, but GPG will reject wrong password.\nDo you want to continue?]
-Старий пароль не збігаєтьÑÑ, ви можете продовжити, але GPG не прийме неправильний пароль.\nПродовжити?
+[Please choose GPG binary location]
+Виберіть директорію з GnuPG
+[Please set keyring's home directory]
+Виберіть директорію з ключами GnuPG
diff --git a/langpacks/ukrainian/Plugins/QuickSearch.txt b/langpacks/ukrainian/Plugins/QuickSearch.txt
index 1bd242a514..b263e9540a 100644
--- a/langpacks/ukrainian/Plugins/QuickSearch.txt
+++ b/langpacks/ukrainian/Plugins/QuickSearch.txt
@@ -1,7 +1,7 @@
#muuid {e4058506-6494-4d60-9cf4-40bf545f78bd}
;============================================================
; File: QuickSearch.dll
-; Module: Quick Search
+; Plugin: Quick Search
; Version: 1.4.2.0
; Authors: Awkward
;============================================================
diff --git a/langpacks/ukrainian/Plugins/SimpleStatusMsg.txt b/langpacks/ukrainian/Plugins/SimpleStatusMsg.txt
index aa8971c4a7..0279a1872f 100644
--- a/langpacks/ukrainian/Plugins/SimpleStatusMsg.txt
+++ b/langpacks/ukrainian/Plugins/SimpleStatusMsg.txt
@@ -3,7 +3,7 @@
; File: SimpleStatusMsg.dll
; Plugin: Simple status message
; Version: 1.9.0.6
-; Authors: Bartosz 'Dezeath' Bialek, Harven
+; Authors: Bartosz 'Dezeath' Białek, Harven
;============================================================
[Provides a simple way to set status and away messages.]
Швидка зміна ÑтатуÑів Ñ– вÑтановлених повідомлень ÑтатуÑу.
diff --git a/langpacks/ukrainian/Plugins/SmileyAdd.txt b/langpacks/ukrainian/Plugins/SmileyAdd.txt
index 1cd8d47606..46e5dde890 100644
--- a/langpacks/ukrainian/Plugins/SmileyAdd.txt
+++ b/langpacks/ukrainian/Plugins/SmileyAdd.txt
@@ -2,7 +2,7 @@
;============================================================
; File: SmileyAdd.dll
; Plugin: SmileyAdd
-; Version: 0.2.4.2
+; Version: 0.3.0.1
; Authors: Peacow, nightwish, bid, borkra
;============================================================
[Smiley support for Miranda NG.]
@@ -91,15 +91,13 @@ HTTP-з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ SmileyAdd
Згідно з протоколом
[Smiley pack %s for category "%s" not found.\nSelect correct smiley pack in the Options -> Customize -> Smileys.]
Ðабір Ñмайлів %s Ð´Ð»Ñ ÐºÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ñ–Ñ— "%s" не знайдено.\nВиберіть набір Ñмайлів: ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ -> Тонке Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ -> Смайли.
-[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
-Проблеми з завантаженнÑм набору Ñмайлів (необхідно виправити).\nПодробиці дивітьÑÑ Ð² мережевому журналі.
[Smiley #%u in file %s for smiley pack %s not found.]
Смайл #%u у файлі %s Ð´Ð»Ñ Ð½Ð°Ð±Ð¾Ñ€Ñƒ Ñмайлів %s не знайдено.
+[There were problems loading smiley pack (it should be corrected).\nSee network log for details.]
+Проблеми з завантаженнÑм набору Ñмайлів (необхідно виправити).\nПодробиці дивітьÑÑ Ð² мережевому журналі.
[%s global smiley pack]
%s глобальний набір Ñмайлів
[Standard]
Стандартні
-[Regular expression "%s" in smiley pack "%s" could produce "empty matches".]
-РегулÑрний вираз "%s" в наборі Ñмайлів "%s" може виводити "порожнє значеннÑ".
[Regular expression "%s" in smiley pack "%s" malformed.]
Помилковий регулÑрний вираз "%s" в наборі Ñмайлів "%s".
diff --git a/langpacks/ukrainian/Plugins/StatusManager.txt b/langpacks/ukrainian/Plugins/StatusManager.txt
index d5658d5aea..cddc4b32cd 100644
--- a/langpacks/ukrainian/Plugins/StatusManager.txt
+++ b/langpacks/ukrainian/Plugins/StatusManager.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StatusManager.dll
; Plugin: Status manager
-; Version: 0.11.2.3
+; Version: 1.0.1.1
; Authors: P Boon
;============================================================
[A connection checker and auto away module. Also allows you to define the status Miranda should set on startup, configurable per protocol.]
diff --git a/langpacks/ukrainian/Plugins/Steam.txt b/langpacks/ukrainian/Plugins/Steam.txt
index eab553a21f..e03cb3a181 100644
--- a/langpacks/ukrainian/Plugins/Steam.txt
+++ b/langpacks/ukrainian/Plugins/Steam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Steam.dll
; Plugin: Steam protocol
-; Version: 0.11.6.1
+; Version: 0.11.6.3
; Authors: Miranda NG Team, Robert Pösel
;============================================================
[Steam protocol support for Miranda NG.]
diff --git a/langpacks/ukrainian/Plugins/StopSpam.txt b/langpacks/ukrainian/Plugins/StopSpam.txt
index ee4ca07169..2dd13ce984 100644
--- a/langpacks/ukrainian/Plugins/StopSpam.txt
+++ b/langpacks/ukrainian/Plugins/StopSpam.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpam.dll
; Plugin: StopSpam+
-; Version: 0.0.1.5
+; Version: 0.1.0.1
; Authors: Roman Miklashevsky, A. Petkevich, Kosh&chka, persei
;============================================================
[Anti-spam plugin for Miranda NG.]
@@ -39,6 +39,8 @@
ЗапиÑувати Ñпамерів в ÑиÑтемну Ñ–Ñторію
[StopSpam automatic message:\r\n]
ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð°Ð½Ñ‚Ð¸Ñпаму:\r\n
+[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
+Ðемає більше Ñпаму! Роботи відпочивають!\r\n\r\nЦей плагін працює проÑто:\r\nÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ кориÑтувачів з вашого ÑпиÑку контактів приходÑть без перевірки на Ñпам, а Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ невідомих кориÑтувачів вам не доÑтавлÑютьÑÑ. Ðле вони не ігноруютьÑÑ: плагін відповідає проÑтим питаннÑм Ñ–, Ñкщо кориÑтувач відповідає правильно, додає його до ÑпиÑку контактів, щоб він міг зв'ÑзатиÑÑ Ð· вами.
[Message sessions]
БеÑіди
[General]
@@ -47,8 +49,6 @@
ПовідомленнÑ
[Accounts]
Облікові запиÑи
-[No more spam! Robots can't go! Only human beings invited!\r\n\r\nThis plugin works pretty simple:\r\nWhile messages from users on your contact list go as there is no any anti-spam software, messages from unknown users are not delivered to you. But also they are not ignored, this plugin replies with a simple question, and if user gives the right answer, plugin adds him to your contact list so that he can contact you.]
-Ðемає більше Ñпаму! Роботи відпочивають!\r\n\r\nЦей плагін працює проÑто:\r\nÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ кориÑтувачів з вашого ÑпиÑку контактів приходÑть без перевірки на Ñпам, а Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ невідомих кориÑтувачів вам не доÑтавлÑютьÑÑ. Ðле вони не ігноруютьÑÑ: плагін відповідає проÑтим питаннÑм Ñ–, Ñкщо кориÑтувач відповідає правильно, додає його до ÑпиÑку контактів, щоб він міг зв'ÑзатиÑÑ Ð· вами.
[Not In List]
Ðе в ÑпиÑку
[Complete]
diff --git a/langpacks/ukrainian/Plugins/StopSpamMod.txt b/langpacks/ukrainian/Plugins/StopSpamMod.txt
index 0bdc1fe280..5015db842c 100644
--- a/langpacks/ukrainian/Plugins/StopSpamMod.txt
+++ b/langpacks/ukrainian/Plugins/StopSpamMod.txt
@@ -2,7 +2,7 @@
;============================================================
; File: StopSpamMod.dll
; Plugin: StopSpam mod
-; Version: 0.0.2.1
+; Version: 0.0.2.2
; Authors: Roman Miklashevsky, sss, Elzor
;============================================================
[Anti-spam plugin for Miranda NG.]
diff --git a/langpacks/ukrainian/Plugins/TabSRMM.txt b/langpacks/ukrainian/Plugins/TabSRMM.txt
index 93dc77ab2a..9eb2c2c1e8 100644
--- a/langpacks/ukrainian/Plugins/TabSRMM.txt
+++ b/langpacks/ukrainian/Plugins/TabSRMM.txt
@@ -35,6 +35,8 @@
Сплив. вікно
[Tray]
Трей
+[Download more skins]
+Завантажити Ñкіни
[Options]
ÐалаштуваннÑ
[Add new rooms to group:]
diff --git a/langpacks/ukrainian/Plugins/Tox.txt b/langpacks/ukrainian/Plugins/Tox.txt
index 99dbc9a912..24ecd4ac79 100644
--- a/langpacks/ukrainian/Plugins/Tox.txt
+++ b/langpacks/ukrainian/Plugins/Tox.txt
@@ -2,7 +2,7 @@
;============================================================
; File: Tox.dll
; Plugin: Tox protocol
-; Version: 0.11.1.25
+; Version: 0.11.1.26
; Authors: Miranda NG Team
;============================================================
[Tox protocol support for Miranda NG.]
diff --git a/langpacks/ukrainian/Plugins/mRadio.txt b/langpacks/ukrainian/Plugins/mRadio.txt
index bf12864338..876a9201b6 100644
--- a/langpacks/ukrainian/Plugins/mRadio.txt
+++ b/langpacks/ukrainian/Plugins/mRadio.txt
@@ -101,8 +101,8 @@
Кар'єр
[Sorry!]
Вибачте!
-[BASS.DLL not found!]
-BASS.DLL не знайдено!
+[bass.dll not found!]
+bass.dll не знайдено!
[Station]
СтанціÑ
[Custom INI file]
diff --git a/langpacks/ukrainian/Untranslated/AIM.txt b/langpacks/ukrainian/Untranslated/AIM.txt
deleted file mode 100644
index b99689096d..0000000000
--- a/langpacks/ukrainian/Untranslated/AIM.txt
+++ /dev/null
@@ -1,53 +0,0 @@
-[Use "clientlogin" (recommended)]
-[This allows access to user defined chat rooms. To access predefined chat rooms use web links]
-[Invalid screen name or password.]
-[Invalid SNAC header.]
-[Server rate limit exceeded.]
-[Client rate limit exceeded]
-[Recipient is not logged in.]
-[Requested service is unavailable.]
-[Requested service is not defined.]
-[You sent obsolete SNAC.]
-[Reply too big.]
-[Response lost.]
-[Request denied.]
-[Insufficient rights.]
-[Recipient blocked.]
-[Sender too evil.]
-[Receiver too evil.]
-[List overflow.]
-[Request ambiguous.]
-[Server queue full.]
-[Not while on AOL.]
-[Field change temporarily unavailable.]
-[Invalid registration preference.]
-[Read only field.]
-[Write only field.]
-[Invalid account.]
-[Deleted account.]
-[Expired account.]
-[No database access.]
-[Invalid database fields.]
-[Bad database status.]
-[Migration cancel.]
-[There is already a pending request for this screen name.]
-[Not DT status.]
-[Outstanding confirmation.]
-[No email address.]
-[Over limit.]
-[Email host fail.]
-[Open mail account?]
-[Contact tried to open an audio/video conference (not currently supported)]
-[Item you want to delete not found in list.]
-[Failed to add buddy to list: Item already exist.]
-[Error adding buddy (invalid ID or already in list?)]
-[Cannot add buddy. Limit for this type of item exceeded.]
-[Error? Attempting to add ICQ contact to an AIM list.]
-[Cannot add this buddy because it requires authorization.]
-[Item you want to modify not found in list.]
-[You've got mail! Checked at]
-[Unable to confirm at this time. Please try again later.]
-[Your account has already been confirmed.]
-[Can't start the confirmation procedure.]
-[Hiptop]
-[Join me in this buddy chat!]
diff --git a/langpacks/ukrainian/Untranslated/GmailNotifier.txt b/langpacks/ukrainian/Untranslated/GmailNotifier.txt
new file mode 100644
index 0000000000..fe2bc3771c
--- /dev/null
+++ b/langpacks/ukrainian/Untranslated/GmailNotifier.txt
@@ -0,0 +1 @@
+[Gmail Notifier connection]
diff --git a/langpacks/ukrainian/Untranslated/IEView.txt b/langpacks/ukrainian/Untranslated/IEView.txt
index f0d09680ad..d9423226fd 100644
--- a/langpacks/ukrainian/Untranslated/IEView.txt
+++ b/langpacks/ukrainian/Untranslated/IEView.txt
@@ -1,3 +1,4 @@
+[Download more templates]
[IID_IOleObject failed.]
[IID_IOleInPlaceObject failed.]
[Failed to Advise]
diff --git a/langpacks/ukrainian/Untranslated/New_GPG.txt b/langpacks/ukrainian/Untranslated/New_GPG.txt
index aaa54bc67e..db252c9536 100644
--- a/langpacks/ukrainian/Untranslated/New_GPG.txt
+++ b/langpacks/ukrainian/Untranslated/New_GPG.txt
@@ -7,19 +7,6 @@
[GPG Turn off encryption]
[GPG Turn on encryption]
[Toggle GPG encryption]
-[Expire date]
-[Generating new random key, please wait]
-[Failed to allocate memory]
-[Failed to lock memory with error %d]
-[Failed write to clipboard with error %d]
-[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
-[Wrong GPG binary location found in system.\nPlease choose another location]
-["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
-[GPG binary does not exist.\nPlease choose another location]
-[You must set encryption algorithm first]
-[Invalid date]
-[Generating new key, please wait...]
-[Failed to export public key.]
[Your secret key with ID: ]
[ for account ]
[ deleted from GPG secret keyring.\nDo you want to set another key?]
@@ -33,6 +20,9 @@
[Key info]
[we have secret key for this public key, do not removing from GPG keyring]
[Key removed from GPG keyring]
+[Failed to allocate memory]
+[Failed to lock memory with error %d]
+[Failed write to clipboard with error %d]
[Failed to open clipboard with error %d]
[Set log file]
[Choose gpg.exe]
@@ -46,6 +36,16 @@
[Set file containing GPG public key]
[GPG public key file]
[There is no public or private key.]
+[Expire date]
+[Generating new random key, please wait]
+[GPG binary found in Miranda folder, but English locale does not exist.\nIt's highly recommended that you place \\gnupg.nls\\en@quot.mo in GnuPG folder under Miranda root.\nWithout this file you may experience many problems with GPG output on non-English systems\nand plugin may completely not work.\nYou have been warned.]
+[Wrong GPG binary location found in system.\nPlease choose another location]
+["GPG" directory found in Miranda root.\nAssuming it's GPG home directory.\nGPG home directory set.]
+[You must set encryption algorithm first]
+[Invalid date]
+[Generating new key, please wait...]
+[Expiration date]
+[Failed to export public key.]
[Do you want to toggle encryption for all subcontacts?]
[Target file exists, do you want to replace it?]
[Capability to decrypt file not found on other side.\nRecipient may be unable to decrypt file(s).\nDo you want to encrypt file(s) anyway?]
@@ -57,3 +57,4 @@
[We have successfully exported %d public keys.]
[We have successfully processed %d public keys and some private keys.]
[We have successfully processed %d public keys.]
+[GPG binary does not exist.\nPlease choose another location]
diff --git a/langpacks/ukrainian/Untranslated/SplashScreen.txt b/langpacks/ukrainian/Untranslated/SplashScreen.txt
new file mode 100644
index 0000000000..0add885a64
--- /dev/null
+++ b/langpacks/ukrainian/Untranslated/SplashScreen.txt
@@ -0,0 +1 @@
+[Download more splash screens]
diff --git a/langpacks/ukrainian/Untranslated/mRadio.txt b/langpacks/ukrainian/Untranslated/mRadio.txt
new file mode 100644
index 0000000000..8de4f1d381
--- /dev/null
+++ b/langpacks/ukrainian/Untranslated/mRadio.txt
@@ -0,0 +1 @@
+[bass.dll not found! Choose bass.dll path manually]
diff --git a/langpacks/ukrainian/Weather/Intellicast.txt b/langpacks/ukrainian/Weather/Intellicast.txt
index 3b5177a584..7323db384a 100644
--- a/langpacks/ukrainian/Weather/Intellicast.txt
+++ b/langpacks/ukrainian/Weather/Intellicast.txt
@@ -1,6 +1,6 @@
;============================================================
; File: Intellicast.ini
-; Module: weather
+; Plugin: Weather
;============================================================
[Ceiling]
ВиÑота хмар
diff --git a/langpacks/ukrainian/Weather/weatherxml.txt b/langpacks/ukrainian/Weather/weatherxml.txt
index b32b8a8fb1..1279f93f72 100644
--- a/langpacks/ukrainian/Weather/weatherxml.txt
+++ b/langpacks/ukrainian/Weather/weatherxml.txt
@@ -1,6 +1,6 @@
;============================================================
; File: weatherxml.ini
-; Module: weather
+; Plugin: Weather
;============================================================
[AM Rain]
Дощ у першій половині днÑ
diff --git a/langpacks/ukrainian/Weather/wundergrnd_intl.txt b/langpacks/ukrainian/Weather/wundergrnd_intl.txt
index f606acc6f5..1c19f0854d 100644
--- a/langpacks/ukrainian/Weather/wundergrnd_intl.txt
+++ b/langpacks/ukrainian/Weather/wundergrnd_intl.txt
@@ -1,6 +1,6 @@
;============================================================
; File: wundergrnd_intl.ini
-; Module: weather
+; Plugin: Weather
;============================================================
[Alert]
ПопередженнÑ
diff --git a/langpacks/ukrainian/Weather/yweather.txt b/langpacks/ukrainian/Weather/yweather.txt
index 040318b72d..5712a3dc9f 100644
--- a/langpacks/ukrainian/Weather/yweather.txt
+++ b/langpacks/ukrainian/Weather/yweather.txt
@@ -1,6 +1,6 @@
;============================================================
; File: yweather.ini
-; Module: weather
+; Plugin: Weather
;============================================================
[ENE]
С-Пн-С
diff --git a/libs/libjson/src/libjson.def b/libs/libjson/src/libjson.def
index 9d8b63ec49..027b0fd092 100644
--- a/libs/libjson/src/libjson.def
+++ b/libs/libjson/src/libjson.def
@@ -194,3 +194,10 @@ json_write @190
json_write_formatted @191
??6JSONNode@@QAEAAV0@ABV0@@Z @192 NONAME
??4JSONWorker@@QAEAAV0@$$QAV0@@Z @193 NONAME
+??6@YGAAVJSONNode@@AAV0@ABUBOOL_PARAM@@@Z @194 NONAME
+??6@YGAAVJSONNode@@AAV0@ABUCHAR_PARAM@@@Z @195 NONAME
+??6@YGAAVJSONNode@@AAV0@ABUINT64_PARAM@@@Z @196 NONAME
+??6@YGAAVJSONNode@@AAV0@ABUINT_PARAM@@@Z @197 NONAME
+??6@YGAAVJSONNode@@AAV0@ABUWCHAR_PARAM@@@Z @198 NONAME
+??6@YGAAVJSONNode@@AAV0@ABUJSON_PARAM@@@Z @199 NONAME
+??6@YGAAVJSONNode@@AAV0@ABUNULL_PARAM@@@Z @200 NONAME
diff --git a/libs/libjson/src/libjson64.def b/libs/libjson/src/libjson64.def
index 1e501cba21..e22d9f62ac 100644
--- a/libs/libjson/src/libjson64.def
+++ b/libs/libjson/src/libjson64.def
@@ -194,3 +194,10 @@ json_write @190
json_write_formatted @191
??6JSONNode@@QEAAAEAV0@AEBV0@@Z @192 NONAME
??4JSONWorker@@QEAAAEAV0@$$QEAV0@@Z @193 NONAME
+??6@YAAEAVJSONNode@@AEAV0@AEBUBOOL_PARAM@@@Z @194 NONAME
+??6@YAAEAVJSONNode@@AEAV0@AEBUCHAR_PARAM@@@Z @195 NONAME
+??6@YAAEAVJSONNode@@AEAV0@AEBUINT64_PARAM@@@Z @196 NONAME
+??6@YAAEAVJSONNode@@AEAV0@AEBUINT_PARAM@@@Z @197 NONAME
+??6@YAAEAVJSONNode@@AEAV0@AEBUWCHAR_PARAM@@@Z @198 NONAME
+??6@YAAEAVJSONNode@@AEAV0@AEBUJSON_PARAM@@@Z @199 NONAME
+??6@YAAEAVJSONNode@@AEAV0@AEBUNULL_PARAM@@@Z @200 NONAME
diff --git a/libs/libjson/src/stdafx.cxx b/libs/libjson/src/stdafx.cxx
index 6f97ed9a4e..b16af99abd 100644
--- a/libs/libjson/src/stdafx.cxx
+++ b/libs/libjson/src/stdafx.cxx
@@ -16,4 +16,50 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "stdafx.h" \ No newline at end of file
+#include "stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+LIBJSON_DLL(JSONNode&) operator<<(JSONNode &json, const INT_PARAM &param)
+{
+ json.push_back(JSONNode(param.szName, param.iValue));
+ return json;
+}
+
+LIBJSON_DLL(JSONNode&) operator<<(JSONNode &json, const INT64_PARAM &param)
+{
+ char tmp[100];
+ _i64toa_s(param.iValue, tmp, _countof(tmp), 10);
+ json.push_back(JSONNode(param.szName, tmp));
+ return json;
+}
+
+LIBJSON_DLL(JSONNode&) operator<<(JSONNode &json, const BOOL_PARAM &param)
+{
+ json.push_back(JSONNode(param.szName, param.bValue));
+ return json;
+}
+
+LIBJSON_DLL(JSONNode&) operator<<(JSONNode &json, const CHAR_PARAM &param)
+{
+ json.push_back(JSONNode(param.szName, param.szValue));
+ return json;
+}
+
+LIBJSON_DLL(JSONNode&) operator<<(JSONNode &json, const WCHAR_PARAM &param)
+{
+ json.push_back(JSONNode(param.szName, ptrA(mir_utf8encodeW(param.wszValue)).get()));
+ return json;
+}
+
+LIBJSON_DLL(JSONNode&) operator<<(JSONNode &json, const NULL_PARAM &param)
+{
+ json.push_back(JSONNode(param.szName, nullptr));
+ return json;
+}
+
+LIBJSON_DLL(JSONNode&) operator<<(JSONNode &json, const JSON_PARAM &param)
+{
+ json.push_back(JSONNode(param.szName, param.node));
+ return json;
+}
diff --git a/libs/libsodium/docs/AUTHORS b/libs/libsodium/docs/AUTHORS
new file mode 100644
index 0000000000..39e55f6288
--- /dev/null
+++ b/libs/libsodium/docs/AUTHORS
@@ -0,0 +1,135 @@
+
+Designers
+=========
+
+argon2 Alex Biryukov
+ Daniel Dinu
+ Dmitry Khovratovich
+
+blake2 Jean-Philippe Aumasson
+ Christian Winnerlein
+ Samuel Neves
+ Zooko Wilcox-O'Hearn
+
+chacha20 Daniel J. Bernstein
+
+chacha20poly1305 Adam Langley
+ Yoav Nir
+
+curve25519 Daniel J. Bernstein
+
+curve25519xsalsa20poly1305 Daniel J. Bernstein
+
+ed25519 Daniel J. Bernstein
+ Bo-Yin Yang
+ Niels Duif
+ Peter Schwabe
+ Tanja Lange
+
+poly1305 Daniel J. Bernstein
+
+salsa20 Daniel J. Bernstein
+
+scrypt Colin Percival
+
+siphash Jean-Philippe Aumasson
+ Daniel J. Bernstein
+
+Implementors
+============
+
+crypto_aead/aes256gcm/aesni Romain Dolbeau
+ Frank Denis
+
+crypto_aead/chacha20poly1305 Frank Denis
+
+crypto_aead/xchacha20poly1305 Frank Denis
+ Jason A. Donenfeld
+
+crypto_auth/hmacsha256 Colin Percival
+crypto_auth/hmacsha512
+crypto_auth/hmacsha512256
+
+crypto_box/curve25519xsalsa20poly1305 Daniel J. Bernstein
+
+crypto_box/curve25519xchacha20poly1305 Frank Denis
+
+crypto_core/ed25519 Daniel J. Bernstein
+ Adam Langley
+
+crypto_core/hchacha20 Frank Denis
+
+crypto_core/hsalsa20 Daniel J. Bernstein
+crypto_core/salsa
+
+crypto_generichash/blake2b Jean-Philippe Aumasson
+ Christian Winnerlein
+ Samuel Neves
+ Zooko Wilcox-O'Hearn
+
+crypto_hash/sha256 Colin Percival
+crypto_hash/sha512
+crypto_hash/sha512256
+
+crypto_kdf Frank Denis
+
+crypto_kx Frank Denis
+
+crypto_onetimeauth/poly1305/donna Andrew "floodyberry" Moon
+crypto_onetimeauth/poly1305/sse2
+
+crypto_pwhash/argon2 Samuel Neves
+ Dmitry Khovratovich
+ Jean-Philippe Aumasson
+ Daniel Dinu
+ Thomas Pornin
+
+crypto_pwhash/scryptsalsa208sha256 Colin Percival
+ Alexander Peslyak
+
+crypto_scalarmult/curve25519/ref10 Daniel J. Bernstein
+
+crypto_scalarmult/curve25519/sandy2x Tung Chou
+
+crypto_scalarmult/ed25519 Frank Denis
+
+crypto_secretbox/xsalsa20poly1305 Daniel J. Bernstein
+
+crypto_secretbox/xchacha20poly1305 Frank Denis
+
+crypto_secretstream/xchacha20poly1305 Frank Denis
+
+crypto_shorthash/siphash24 Jean-Philippe Aumasson
+ Daniel J. Bernstein
+
+crypto_sign/ed25519 Peter Schwabe
+ Daniel J. Bernstein
+ Niels Duif
+ Tanja Lange
+ Bo-Yin Yang
+
+crypto_stream/chacha20/ref Daniel J. Bernstein
+
+crypto_stream/chacha20/dolbeau Romain Dolbeau
+ Daniel J. Bernstein
+
+crypto_stream/salsa20/ref Daniel J. Bernstein
+crypto_stream/salsa20/xmm6
+
+crypto_stream/salsa20/xmm6int Romain Dolbeau
+ Daniel J. Bernstein
+
+crypto_stream/salsa2012/ref Daniel J. Bernstein
+crypto_stream/salsa2008/ref
+
+crypto_stream/xchacha20 Frank Denis
+
+crypto_verify Frank Denis
+
+sodium/codecs.c Frank Denis
+ Thomas Pornin
+ Christian Winnerlein
+
+sodium/core.c Frank Denis
+sodium/runtime.h
+sodium/utils.c
diff --git a/libs/libsodium/docs/ChangeLog b/libs/libsodium/docs/ChangeLog
new file mode 100644
index 0000000000..2c6f7f1777
--- /dev/null
+++ b/libs/libsodium/docs/ChangeLog
@@ -0,0 +1,505 @@
+
+* Version 1.0.16
+ - Signatures computations and verifications are now way faster on
+64-bit platforms with compilers supporting 128-bit arithmetic (gcc,
+clang, icc). This includes the WebAssembly target.
+ - New low-level APIs for computations over edwards25519:
+`crypto_scalarmult_ed25519()`, `crypto_scalarmult_ed25519_base()`,
+`crypto_core_ed25519_is_valid_point()`, `crypto_core_ed25519_add()`,
+`crypto_core_ed25519_sub()` and `crypto_core_ed25519_from_uniform()`
+(elligator representative to point).
+ - `crypto_sign_open()`, `crypto_sign_verify_detached() and
+`crypto_sign_edwards25519sha512batch_open` now reject public keys in
+non-canonical form in addition to low-order points.
+ - The library can be built with `ED25519_NONDETERMINISTIC` defined in
+order to use synthetic nonces for EdDSA. This is disabled by default.
+ - Webassembly: `crypto_pwhash_*()` functions are now included in
+non-sumo builds.
+ - `sodium_stackzero()` was added to wipe content off the stack.
+ - Android: support new SDKs where unified headers have become the
+default.
+ - The Salsa20-based PRNG example is now thread-safe on platforms with
+support for thread-local storage, optionally mixes bits from RDRAND.
+ - CMAKE: static library detection on Unix systems has been improved
+(thanks to @BurningEnlightenment, @nibua-r, @mellery451)
+ - Argon2 and scrypt are slightly faster on Linux.
+
+* Version 1.0.15
+ - The default password hashing algorithm is now Argon2id. The
+`pwhash_str_verify()` function can still verify Argon2i hashes
+without any changes, and `pwhash()` can still compute Argon2i hashes
+as well.
+ - The aes128ctr primitive was removed. It was slow, non-standard, not
+authenticated, and didn't seem to be used by any opensource project.
+ - Argon2id required at least 3 passes like Argon2i, despite a minimum
+of `1` as defined by the `OPSLIMIT_MIN` constant. This has been fixed.
+ - The secretstream construction was slightly changed to be consistent
+with forthcoming variants.
+ - The Javascript and Webassembly versions have been merged, and the
+module now returns a `.ready` promise that will resolve after the
+Webassembly code is loaded and compiled.
+ - Note that due to these incompatible changes, the library version
+major was bumped up.
+
+* Version 1.0.14
+ - iOS binaries should now be compatible with WatchOS and TVOS.
+ - WebAssembly is now officially supported. Special thanks to
+@facekapow and @pepyakin who helped to make it happen.
+ - Internal consistency checks failing and primitives used with
+dangerous/out-of-bounds/invalid parameters used to call abort(3).
+Now, a custom handler *that doesn't return* can be set with the
+`set_sodium_misuse()` function. It still aborts by default or if the
+handler ever returns. This is not a replacement for non-fatal,
+expected runtime errors. This handler will be only called in
+unexpected situations due to potential bugs in the library or in
+language bindings.
+ - `*_MESSAGEBYTES_MAX` macros (and the corresponding
+`_messagebytes_max()` symbols) have been added to represent the
+maximum message size that can be safely handled by a primitive.
+Language bindings are encouraged to check user inputs against these
+maximum lengths.
+ - The test suite has been extended to cover more edge cases.
+ - crypto_sign_ed25519_pk_to_curve25519() now rejects points that are
+not on the curve, or not in the main subgroup.
+ - Further changes have been made to ensure that smart compilers will
+not optimize out code that we don't want to be optimized.
+ - Visual Studio solutions are now included in distribution tarballs.
+ - The `sodium_runtime_has_*` symbols for CPU features detection are
+now defined as weak symbols, i.e. they can be replaced with an
+application-defined implementation. This can be useful to disable
+AVX* when temperature/power consumption is a concern.
+ - `crypto_kx_*()` now aborts if called with no non-NULL pointers to
+store keys to.
+ - SSE2 implementations of `crypto_verify_*()` have been added.
+ - Passwords can be hashed using a specific algorithm with the new
+`crypto_pwhash_str_alg()` function.
+ - Due to popular demand, base64 encoding (`sodium_bin2base64()`) and
+decoding (`sodium_base642bin()`) have been implemented.
+ - A new `crypto_secretstream_*()` API was added to safely encrypt files
+and multi-part messages.
+ - The `sodium_pad()` and `sodium_unpad()` helper functions have been
+added in order to add & remove padding.
+ - An AVX512 optimized implementation of Argon2 has been added (written
+by Ondrej MosnáÄek, thanks!)
+ - The `crypto_pwhash_str_needs_rehash()` function was added to check if
+a password hash string matches the given parameters, or if it needs an
+update.
+ - The library can now be compiled with recent versions of
+emscripten/binaryen that don't allow multiple variables declarations
+using a single `var` statement.
+
+* Version 1.0.13
+ - Javascript: the sumo builds now include all symbols. They were
+previously limited to symbols defined in minimal builds.
+ - The public `crypto_pwhash_argon2i_MEMLIMIT_MAX` constant was
+incorrectly defined on 32-bit platforms. This has been fixed.
+ - Version 1.0.12 didn't compile on OpenBSD/i386 using the base gcc
+compiler. This has been fixed.
+ - The Android compilation scripts have been updated for NDK r14b.
+ - armv7s-optimized code was re-added to iOS builds.
+ - An AVX2 optimized implementation of the Argon2 round function was
+added.
+ - The Argon2id variant of Argon2 has been implemented. The
+high-level `crypto_pwhash_str_verify()` function automatically detects
+the algorithm and can verify both Argon2i and Argon2id hashed passwords.
+The default algorithm for newly hashed passwords remains Argon2i in
+this version to avoid breaking compatibility with verifiers running
+libsodium <= 1.0.12.
+ - A `crypto_box_curve25519xchacha20poly1305_seal*()` function set was
+implemented.
+ - scrypt was removed from minimal builds.
+ - libsodium is now available on NuGet.
+
+* Version 1.0.12
+ - Ed25519ph was implemented, adding a multi-part signature API
+(`crypto_sign_init()`, `crypto_sign_update()`, `crypto_sign_final_*()`).
+ - New constants and related accessors have been added for Scrypt and
+Argon2.
+ - XChaCha20 has been implemented. Like XSalsa20, this construction
+extends the ChaCha20 cipher to accept a 192-bit nonce. This makes it safe
+to use ChaCha20 with random nonces.
+ - `crypto_secretbox`, `crypto_box` and `crypto_aead` now offer
+variants leveraging XChaCha20.
+ - SHA-2 is about 20% faster, which also gives a speed boost to
+signature and signature verification.
+ - AVX2 implementations of Salsa20 and ChaCha20 have been added. They
+are twice as fast as the SSE2 implementations. The speed gain is
+even more significant on Windows, that previously didn't use
+vectorized implementations.
+ - New high-level API: `crypto_kdf`, to easily derive one or more
+subkeys from a master key.
+ - Siphash with a 128-bit output has been implemented, and is
+available as `crypto_shorthash_siphashx_*`.
+ - New `*_keygen()` helpers functions have been added to create secret
+keys for all constructions. This improves code clarity and can prevent keys
+from being partially initialized.
+ - A new `randombytes_buf_deterministic()` function was added to
+deterministically fill a memory region with pseudorandom data. This
+function can especially be useful to write reproducible tests.
+ - A preliminary `crypto_kx_*()` API was added to compute shared session
+keys.
+ - AVX2 detection is more reliable.
+ - The pthreads library is not required any more when using MingW.
+ - `contrib/Findsodium.cmake` was added as an example to include
+libsodium in a project using cmake.
+ - Compatibility with gcc 2.x has been restored.
+ - Minimal builds can be checked using `sodium_library_minimal()`.
+ - The `--enable-opt` compilation switch has become compatible with more
+platforms.
+ - Android builds are now using clang on platforms where it is
+available.
+
+* Version 1.0.11
+ - `sodium_init()` is now thread-safe, and can be safely called multiple
+times.
+ - Android binaries now properly support 64-bit Android, targeting
+platform 24, but without breaking compatibility with platforms 16 and
+21.
+ - Better support for old gcc versions.
+ - On FreeBSD, core dumps are disabled on regions allocated with
+sodium allocation functions.
+ - AVX2 detection was fixed, resulting in faster Blake2b hashing on
+platforms where it was not properly detected.
+ - The Sandy2x Curve25519 implementation was not as fast as expected
+on some platforms. This has been fixed.
+ - The NativeClient target was improved. Most notably, it now supports
+optimized implementations, and uses pepper_49 by default.
+ - The library can be compiled with recent Emscripten versions.
+Changes have been made to produce smaller code, and the default heap
+size was reduced in the standard version.
+ - The code can now be compiled on SLES11 service pack 4.
+ - Decryption functions can now accept a NULL pointer for the output.
+This checks the MAC without writing the decrypted message.
+ - crypto_generichash_final() now returns -1 if called twice.
+ - Support for Visual Studio 2008 was improved.
+
+* Version 1.0.10
+ - This release only fixes a compilation issue reported with some older
+gcc versions. There are no functional changes over the previous release.
+
+* Version 1.0.9
+ - The Javascript target now includes a `--sumo` option to include all
+the symbols of the original C library.
+ - A detached API was added to the ChaCha20-Poly1305 and AES256-GCM
+implementations.
+ - The Argon2i password hashing function was added, and is accessible
+directly and through a new, high-level `crypto_pwhash` API. The scrypt
+function remains available as well.
+ - A speed-record AVX2 implementation of BLAKE2b was added (thanks to
+Samuel Neves).
+ - The library can now be compiled using C++Builder (thanks to @jcolli44)
+ - Countermeasures for Ed25519 signatures malleability have been added
+to match the irtf-cfrg-eddsa draft (note that malleability is irrelevant to
+the standard definition of signature security). Signatures with a small-order
+`R` point are now also rejected.
+ - Some implementations are now slightly faster when using the Clang
+compiler.
+ - The HChaCha20 core function was implemented (`crypto_core_hchacha20()`).
+ - No-op stubs were added for all AES256-GCM public functions even when
+compiled on non-Intel platforms.
+ - `crypt_generichash_blake2b_statebytes()` was added.
+ - New macros were added for the IETF variant of the ChaCha20-Poly1305
+construction.
+ - The library can now be compiled on Minix.
+ - HEASLR is now enabled on MinGW builds.
+
+* Version 1.0.8
+ - Handle the case where the CPU supports AVX, but we are running
+on an hypervisor with AVX disabled/not supported.
+ - Faster (2x) scalarmult_base() when using the ref10 implementation.
+
+* Version 1.0.7
+ - More functions whose return value should be checked have been
+tagged with `__attribute__ ((warn_unused_result))`: `crypto_box_easy()`,
+`crypto_box_detached()`, `crypto_box_beforenm()`, `crypto_box()`, and
+`crypto_scalarmult()`.
+ - Sandy2x, the fastest Curve25519 implementation ever, has been
+merged in, and is automatically used on CPUs supporting the AVX
+instructions set.
+ - An SSE2 optimized implementation of Poly1305 was added, and is
+twice as fast as the portable one.
+ - An SSSE3 optimized implementation of ChaCha20 was added, and is
+twice as fast as the portable one.
+ - Faster `sodium_increment()` for common nonce sizes.
+ - New helper functions have been added: `sodium_is_zero()` and
+ `sodium_add()`.
+ - `sodium_runtime_has_aesni()` now properly detects the CPU flag when
+ compiled using Visual Studio.
+
+* Version 1.0.6
+ - Optimized implementations of Blake2 have been added for modern
+Intel platforms. `crypto_generichash()` is now faster than MD5 and SHA1
+implementations while being far more secure.
+ - Functions for which the return value should be checked have been
+tagged with `__attribute__ ((warn_unused_result))`. This will
+intentionally break code compiled with `-Werror` that didn't bother
+checking critical return values.
+ - The `crypto_sign_edwards25519sha512batch_*()` functions have been
+tagged as deprecated.
+ - Undocumented symbols that were exported, but were only useful for
+internal purposes have been removed or made private:
+`sodium_runtime_get_cpu_features()`, the implementation-specific
+`crypto_onetimeauth_poly1305_donna()` symbols,
+`crypto_onetimeauth_poly1305_set_implementation()`,
+`crypto_onetimeauth_poly1305_implementation_name()` and
+`crypto_onetimeauth_pick_best_implementation()`.
+ - `sodium_compare()` now works as documented, and compares numbers
+in little-endian format instead of behaving like `memcmp()`.
+ - The previous changes should not break actual applications, but to be
+safe, the library version major was incremented.
+ - `sodium_runtime_has_ssse3()` and `sodium_runtime_has_sse41()` have
+been added.
+ - The library can now be compiled with the CompCert compiler.
+
+* Version 1.0.5
+ - Compilation issues on some platforms were fixed: missing alignment
+directives were added (required at least on RHEL-6/i386), a workaround
+for a VRP bug on gcc/armv7 was added, and the library can now be compiled
+with the SunPro compiler.
+ - Javascript target: io.js is not supported any more. Use nodejs.
+
+* Version 1.0.4
+ - Support for AES256-GCM has been added. This requires
+a CPU with the aesni and pclmul extensions, and is accessible via the
+crypto_aead_aes256gcm_*() functions.
+ - The Javascript target doesn't use eval() any more, so that the
+library can be used in Chrome packaged applications.
+ - QNX and CloudABI are now supported.
+ - Support for NaCl has finally been added.
+ - ChaCha20 with an extended (96 bit) nonce and a 32-bit counter has
+been implemented as crypto_stream_chacha20_ietf(),
+crypto_stream_chacha20_ietf_xor() and crypto_stream_chacha20_ietf_xor_ic().
+An IETF-compatible version of ChaCha20Poly1305 is available as
+crypto_aead_chacha20poly1305_ietf_npubbytes(),
+crypto_aead_chacha20poly1305_ietf_encrypt() and
+crypto_aead_chacha20poly1305_ietf_decrypt().
+ - The sodium_increment() helper function has been added, to increment
+an arbitrary large number (such as a nonce).
+ - The sodium_compare() helper function has been added, to compare
+arbitrary large numbers (such as nonces, in order to prevent replay
+attacks).
+
+* Version 1.0.3
+ - In addition to sodium_bin2hex(), sodium_hex2bin() is now a
+constant-time function.
+ - crypto_stream_xsalsa20_ic() has been added.
+ - crypto_generichash_statebytes(), crypto_auth_*_statebytes() and
+crypto_hash_*_statebytes() have been added in order to retrieve the
+size of structures keeping states from foreign languages.
+ - The JavaScript target doesn't require /dev/urandom or an external
+randombytes() implementation any more. Other minor Emscripten-related
+improvements have been made in order to support libsodium.js
+ - Custom randombytes implementations do not need to provide their own
+implementation of randombytes_uniform() any more. randombytes_stir()
+and randombytes_close() can also be NULL pointers if they are not
+required.
+ - On Linux, getrandom(2) is being used instead of directly accessing
+/dev/urandom, if the kernel supports this system call.
+ - crypto_box_seal() and crypto_box_seal_open() have been added.
+ - Visual Studio 2015 is now supported.
+
+* Version 1.0.2
+ - The _easy and _detached APIs now support precalculated keys;
+crypto_box_easy_afternm(), crypto_box_open_easy_afternm(),
+crypto_box_detached_afternm() and crypto_box_open_detached_afternm()
+have been added as an alternative to the NaCl interface.
+ - Memory allocation functions can now be used on operating systems with
+no memory protection.
+ - crypto_sign_open() and crypto_sign_edwards25519sha512batch_open()
+now accept a NULL pointer instead of a pointer to the message size, if
+storing this information is not required.
+ - The close-on-exec flag is now set on the descriptor returned when
+opening /dev/urandom.
+ - A libsodium-uninstalled.pc file to use pkg-config even when
+libsodium is not installed, has been added.
+ - The iOS target now includes armv7s and arm64 optimized code, as well
+as i386 and x86_64 code for the iOS simulator.
+ - sodium_free() can now be called on regions with PROT_NONE protection.
+ - The Javascript tests can run on Ubuntu, where the node binary was
+renamed nodejs. io.js can also be used instead of node.
+
+* Version 1.0.1
+ - DLL_EXPORT was renamed SODIUM_DLL_EXPORT in order to avoid
+collisions with similar macros defined by other libraries.
+ - sodium_bin2hex() is now constant-time.
+ - crypto_secretbox_detached() now supports overlapping input and output
+regions.
+ - NaCl's donna_c64 implementation of curve25519 was reading an extra byte
+past the end of the buffer containing the base point. This has been
+fixed.
+
+* Version 1.0.0
+ - The API and ABI are now stable. New features will be added, but
+backward-compatibility is guaranteed through all the 1.x.y releases.
+ - crypto_sign() properly works with overlapping regions again. Thanks
+to @pysiak for reporting this regression introduced in version 0.6.1.
+ - The test suite has been extended.
+
+* Version 0.7.1 (1.0 RC2)
+ - This is the second release candidate of Sodium 1.0. Minor
+compilation, readability and portability changes have been made and the
+test suite was improved, but the API is the same as the previous release
+candidate.
+
+* Version 0.7.0 (1.0 RC1)
+ - Allocating memory to store sensitive data can now be done using
+sodium_malloc() and sodium_allocarray(). These functions add guard
+pages around the protected data to make it less likely to be
+accessible in a heartbleed-like scenario. In addition, the protection
+for memory regions allocated that way can be changed using
+sodium_mprotect_noaccess(), sodium_mprotect_readonly() and
+sodium_mprotect_readwrite().
+ - ed25519 keys can be converted to curve25519 keys with
+crypto_sign_ed25519_pk_to_curve25519() and
+crypto_sign_ed25519_sk_to_curve25519(). This allows using the same
+keys for signature and encryption.
+ - The seed and the public key can be extracted from an ed25519 key
+using crypto_sign_ed25519_sk_to_seed() and crypto_sign_ed25519_sk_to_pk().
+ - aes256 was removed. A timing-attack resistant implementation might
+be added later, but not before version 1.0 is tagged.
+ - The crypto_pwhash_scryptxsalsa208sha256_* compatibility layer was
+removed. Use crypto_pwhash_scryptsalsa208sha256_*.
+ - The compatibility layer for implementation-specific functions was
+removed.
+ - Compilation issues with Mingw64 on MSYS (not MSYS2) were fixed.
+ - crypto_pwhash_scryptsalsa208sha256_STRPREFIX was added: it contains
+the prefix produced by crypto_pwhash_scryptsalsa208sha256_str()
+
+* Version 0.6.1
+ - Important bug fix: when crypto_sign_open() was given a signed
+message too short to even contain a signature, it was putting an
+unlimited amount of zeros into the target buffer instead of
+immediately returning -1. The bug was introduced in version 0.5.0.
+ - New API: crypto_sign_detached() and crypto_sign_verify_detached()
+to produce and verify ed25519 signatures without having to duplicate
+the message.
+ - New ./configure switch: --enable-minimal, to create a smaller
+library, with only the functions required for the high-level API.
+Mainly useful for the JavaScript target and embedded systems.
+ - All the symbols are now exported by the Emscripten build script.
+ - The pkg-config .pc file is now always installed even if the
+pkg-config tool is not available during the installation.
+
+* Version 0.6.0
+ - The ChaCha20 stream cipher has been added, as crypto_stream_chacha20_*
+ - The ChaCha20Poly1305 AEAD construction has been implemented, as
+crypto_aead_chacha20poly1305_*
+ - The _easy API does not require any heap allocations any more and
+does not have any overhead over the NaCl API. With the password
+hashing function being an obvious exception, the library doesn't
+allocate and will not allocate heap memory ever.
+ - crypto_box and crypto_secretbox have a new _detached API to store
+the authentication tag and the encrypted message separately.
+ - crypto_pwhash_scryptxsalsa208sha256*() functions have been renamed
+crypto_pwhash_scryptsalsa208sha256*().
+ - The low-level crypto_pwhash_scryptsalsa208sha256_ll() function
+allows setting individual parameters of the scrypt function.
+ - New macros and functions for recommended crypto_pwhash_* parameters
+have been added.
+ - Similarly to crypto_sign_seed_keypair(), crypto_box_seed_keypair()
+has been introduced to deterministically generate a key pair from a seed.
+ - crypto_onetimeauth() now provides a streaming interface.
+ - crypto_stream_chacha20_xor_ic() and crypto_stream_salsa20_xor_ic()
+have been added to use a non-zero initial block counter.
+ - On Windows, CryptGenRandom() was replaced by RtlGenRandom(), which
+doesn't require the Crypt API.
+ - The high bit in curve25519 is masked instead of processing the key as
+a 256-bit value.
+ - The curve25519 ref implementation was replaced by the latest ref10
+implementation from Supercop.
+ - sodium_mlock() now prevents memory from being included in coredumps
+on Linux 3.4+
+
+* Version 0.5.0
+ - sodium_mlock()/sodium_munlock() have been introduced to lock pages
+in memory before storing sensitive data, and to zero them before
+unlocking them.
+ - High-level wrappers for crypto_box and crypto_secretbox
+(crypto_box_easy and crypto_secretbox_easy) can be used to avoid
+dealing with the specific memory layout regular functions depend on.
+ - crypto_pwhash_scryptsalsa208sha256* functions have been added
+to derive a key from a password, and for password storage.
+ - Salsa20 and ed25519 implementations now support overlapping
+inputs/keys/outputs (changes imported from supercop-20140505).
+ - New build scripts for Visual Studio, Emscripten, different Android
+architectures and msys2 are available.
+ - The poly1305-53 implementation has been replaced with Floodyberry's
+poly1305-donna32 and poly1305-donna64 implementations.
+ - sodium_hex2bin() has been added to complement sodium_bin2hex().
+ - On OpenBSD and Bitrig, arc4random() is used instead of reading
+/dev/urandom.
+ - crypto_auth_hmac_sha512() has been implemented.
+ - sha256 and sha512 now have a streaming interface.
+ - hmacsha256, hmacsha512 and hmacsha512256 now support keys of
+arbitrary length, and have a streaming interface.
+ - crypto_verify_64() has been implemented.
+ - first-class Visual Studio build system, thanks to @evoskuil
+ - CPU features are now detected at runtime.
+
+* Version 0.4.5
+ - Restore compatibility with OSX <= 10.6
+
+* Version 0.4.4
+ - Visual Studio is officially supported (VC 2010 & VC 2013)
+ - mingw64 is now supported
+ - big-endian architectures are now supported as well
+ - The donna_c64 implementation of curve25519_donna_c64 now handles
+non-canonical points like the ref implementation
+ - Missing scalarmult_curve25519 and stream_salsa20 constants are now exported
+ - A crypto_onetimeauth_poly1305_ref() wrapper has been added
+
+* Version 0.4.3
+ - crypto_sign_seedbytes() and crypto_sign_SEEDBYTES were added.
+ - crypto_onetimeauth_poly1305_implementation_name() was added.
+ - poly1305-ref has been replaced by a faster implementation,
+Floodyberry's poly1305-donna-unrolled.
+ - Stackmarkings have been added to assembly code, for Hardened Gentoo.
+ - pkg-config can now be used in order to retrieve compilations flags for
+using libsodium.
+ - crypto_stream_aes256estream_*() can now deal with unaligned input
+on platforms that require word alignment.
+ - portability improvements.
+
+* Version 0.4.2
+ - All NaCl constants are now also exposed as functions.
+ - The Android and iOS cross-compilation script have been improved.
+ - libsodium can now be cross-compiled to Windows from Linux.
+ - libsodium can now be compiled with emscripten.
+ - New convenience function (prototyped in utils.h): sodium_bin2hex().
+
+* Version 0.4.1
+ - sodium_version_*() functions were not exported in version 0.4. They
+are now visible as intended.
+ - sodium_init() now calls randombytes_stir().
+ - optimized assembly version of salsa20 is now used on amd64.
+ - further cleanups and enhanced compatibility with non-C99 compilers.
+
+* Version 0.4
+ - Most constants and operations are now available as actual functions
+instead of macros, making it easier to use from other languages.
+ - New operation: crypto_generichash, featuring a variable key size, a
+variable output size, and a streaming API. Currently implemented using
+Blake2b.
+ - The package can be compiled in a separate directory.
+ - aes128ctr functions are exported.
+ - Optimized versions of curve25519 (curve25519_donna_c64), poly1305
+(poly1305_53) and ed25519 (ed25519_ref10) are available. Optionally calling
+sodium_init() once before using the library makes it pick the fastest
+implementation.
+ - New convenience function: sodium_memzero() in order to securely
+wipe a memory area.
+ - A whole bunch of cleanups and portability enhancements.
+ - On Windows, a .REF file is generated along with the shared library,
+for use with Visual Studio. The installation path for these has become
+$prefix/bin as expected by MingW.
+
+* Version 0.3
+ - The crypto_shorthash operation has been added, implemented using
+SipHash-2-4.
+
+* Version 0.2
+ - crypto_sign_seed_keypair() has been added
+
+* Version 0.1
+ - Initial release.
+
diff --git a/libs/libsodium/docs/LICENSE b/libs/libsodium/docs/LICENSE
new file mode 100644
index 0000000000..2489a68143
--- /dev/null
+++ b/libs/libsodium/docs/LICENSE
@@ -0,0 +1,18 @@
+/*
+ * ISC License
+ *
+ * Copyright (c) 2013-2017
+ * Frank Denis <j at pureftpd dot org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
diff --git a/libs/libsodium/docs/README.markdown b/libs/libsodium/docs/README.markdown
new file mode 100644
index 0000000000..815240abea
--- /dev/null
+++ b/libs/libsodium/docs/README.markdown
@@ -0,0 +1,46 @@
+[![Build Status](https://travis-ci.org/jedisct1/libsodium.svg?branch=master)](https://travis-ci.org/jedisct1/libsodium?branch=master)
+[![Windows build status](https://ci.appveyor.com/api/projects/status/fu8s2elx25il98hj?svg=true)](https://ci.appveyor.com/project/jedisct1/libsodium)
+[![Coverity Scan Build Status](https://scan.coverity.com/projects/2397/badge.svg)](https://scan.coverity.com/projects/2397)
+
+![libsodium](https://raw.github.com/jedisct1/libsodium/master/logo.png)
+============
+
+Sodium is a new, easy-to-use software library for encryption,
+decryption, signatures, password hashing and more.
+
+It is a portable, cross-compilable, installable, packageable
+fork of [NaCl](http://nacl.cr.yp.to/), with a compatible API, and an
+extended API to improve usability even further.
+
+Its goal is to provide all of the core operations needed to build
+higher-level cryptographic tools.
+
+Sodium supports a variety of compilers and operating systems,
+including Windows (with MingW or Visual Studio, x86 and x64), iOS, Android,
+as well as Javascript and Webassembly.
+
+## Documentation
+
+The documentation is available on Gitbook:
+
+* [libsodium documentation](https://download.libsodium.org/doc/) -
+online, requires Javascript.
+* [offline documentation](https://www.gitbook.com/book/jedisct1/libsodium/details)
+in PDF, MOBI and ePUB formats.
+
+## Integrity Checking
+
+The integrity checking instructions (including the signing key for libsodium)
+are available in the [installation](https://download.libsodium.org/doc/installation/index.html#integrity-checking)
+section of the documentation.
+
+## Community
+
+A mailing-list is available to discuss libsodium.
+
+In order to join, just send a random mail to `sodium-subscribe` {at}
+`pureftpd` {dot} `org`.
+
+## License
+
+[ISC license](https://en.wikipedia.org/wiki/ISC_license).
diff --git a/libs/libsodium/docs/THANKS b/libs/libsodium/docs/THANKS
new file mode 100644
index 0000000000..0d0da788f3
--- /dev/null
+++ b/libs/libsodium/docs/THANKS
@@ -0,0 +1,91 @@
+Special thanks to people, companies and organizations having written
+libsodium bindings for their favorite programming languages:
+
+@alethia7
+@artemisc
+@carblue
+@dnaq
+@ektrah
+@graxrabble
+@harleqin
+@joshjdevl
+@jrmarino
+@jshahbazi
+@lvh
+@neheb
+
+Adam Caudill (@adamcaudill)
+Alexander Morris (@alexpmorris)
+Amit Murthy (@amitmurthy)
+Andrew Bennett (@potatosalad)
+Andrew Lambert (@charonn0)
+Bruce Mitchener (@waywardmonkeys)
+Bruno Oliveira (@abstractj)
+Caolan McMahon (@caolan)
+Chris Rebert (@cvrebert)
+Christian Hermann (@bitbeans)
+Christian Wiese (@morfoh)
+Christian Wiese (@morfoh)
+Colm MacCárthaigh (@colmmacc)
+David Parrish (@dmp1ce)
+Donald Stufft (@dstufft)
+Douglas Campos (@qmx)
+Drew Crawford (@drewcrawford)
+Emil Bay (@emilbayes)
+Eric Dong (@quantum1423)
+Eric Voskuil (@evoskuil)
+Farid Hajji (@fhajji)
+Frank Siebenlist (@franks42)
+Gabriel Handford (@gabriel)
+Geo Carncross (@geocar)
+Henrik Gassmann (BurningEnlightenment)
+Jachym Holecek (@freza)
+Jack Wink (@jackwink)
+James Ruan (@jamesruan)
+Jan de Muijnck-Hughes (@jfdm)
+Jason McCampbell (@jasonmccampbell)
+Jeroen Habraken (@VeXocide)
+Jeroen Ooms (@jeroen)
+Jesper Louis Andersen (@jlouis)
+Joe Eli McIlvain (@jemc)
+Jonathan Stowe (@jonathanstowe)
+Joseph Abrahamson (@tel)
+Julien Kauffmann (@ereOn)
+Kenneth Ballenegger (@kballenegger)
+Loic Maury (@loicmaury)
+Michael Gorlick (@mgorlick)
+Michael Gregorowicz (@mgregoro)
+Michał Zieliński (@zielmicha)
+Omar Ayub (@electricFeel)
+Pedro Paixao (@paixaop)
+Project ArteMisc (@artemisc)
+Rich FitzJohn (@richfitz)
+Ruben De Visscher (@rubendv)
+Rudolf Von Krugstein (@rudolfvonkrugstein)
+Samuel Neves (@sneves)
+Scott Arciszewski (@paragonie-scott)
+Stanislav Ovsiannikov (@naphaso)
+Stefan Marsiske (@stef)
+Stephan Touset (@stouset)
+Stephen Chavez (@redragonx)
+Steve Gibson (@sggrc)
+Tony Arcieri (@bascule)
+Tony Garnock-Jones (@tonyg)
+Y. T. Chung (@zonyitoo)
+
+Bytecurry Software
+Cryptotronix
+Facebook
+FSF France
+MaidSafe
+Paragonie Initiative Enterprises
+Python Cryptographic Authority
+
+(this list may not be complete, if you don't see your name, please
+submit a pull request!)
+
+Also thanks to:
+
+- Coverity, Inc. to provide static analysis.
+- FSF France for providing access to their compilation servers.
+- Private Internet Access for having sponsored a complete security audit.
diff --git a/libs/libsodium/libsodium.vcxproj b/libs/libsodium/libsodium.vcxproj
new file mode 100644
index 0000000000..182ac4184b
--- /dev/null
+++ b/libs/libsodium/libsodium.vcxproj
@@ -0,0 +1,493 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{A185B162-6CB6-4502-B03F-B56F7699A8D9}</ProjectGuid>
+ <ProjectName>libsodium</ProjectName>
+ <RootNamespace>libsodium</RootNamespace>
+ </PropertyGroup>
+ <PropertyGroup>
+ <GenerateManifest>false</GenerateManifest>
+ <EmbedManifest>false</EmbedManifest>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <OutDir Condition="'$(Platform)'=='Win32'">$(SolutionDir)$(Configuration)\Libs\</OutDir>
+ <OutDir Condition="'$(Platform)'=='x64'">$(SolutionDir)$(Configuration)64\Libs\</OutDir>
+ </PropertyGroup>
+ <Import Project="$(ProjectDir)..\..\build\vc.common\common.props"/>
+ <PropertyGroup>
+ <TargetExt>.mir</TargetExt>
+ <TargetPath>$(OutDir)$(TargetName)$(TargetExt)</TargetPath>
+ </PropertyGroup>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <PreprocessorDefinitions>SODIUM_DLL_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <DisableSpecificWarnings>4244;4310;4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <AdditionalIncludeDirectories>$(ProjectDir)src\include;$(ProjectDir)src\include\sodium;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="src\crypto_generichash\crypto_generichash.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_generichash\blake2b\generichash_blake2.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_generichash\blake2b\ref\blake2b-compress-ref.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_generichash\blake2b\ref\blake2b-compress-ssse3.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_generichash\blake2b\ref\blake2b-compress-avx2.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_generichash\blake2b\ref\blake2b-compress-sse41.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_generichash\blake2b\ref\generichash_blake2b.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_generichash\blake2b\ref\blake2b-ref.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_kx\crypto_kx.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_sign\crypto_sign.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_sign\ed25519\sign_ed25519.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_sign\ed25519\ref10\obsolete.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_sign\ed25519\ref10\sign.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_sign\ed25519\ref10\keypair.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_sign\ed25519\ref10\open.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_secretbox\crypto_secretbox.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_secretbox\crypto_secretbox_easy.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_secretbox\xsalsa20poly1305\secretbox_xsalsa20poly1305.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_secretbox\xchacha20poly1305\secretbox_xchacha20poly1305.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_pwhash\crypto_pwhash.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_pwhash\argon2\blake2b-long.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_pwhash\argon2\argon2-core.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_pwhash\argon2\argon2-fill-block-avx512f.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_pwhash\argon2\argon2-fill-block-ref.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_pwhash\argon2\argon2-fill-block-ssse3.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_pwhash\argon2\pwhash_argon2i.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_pwhash\argon2\pwhash_argon2id.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_pwhash\argon2\argon2.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_pwhash\argon2\argon2-fill-block-avx2.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_pwhash\argon2\argon2-encoding.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_pwhash\scryptsalsa208sha256\scrypt_platform.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_pwhash\scryptsalsa208sha256\crypto_scrypt-common.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_pwhash\scryptsalsa208sha256\pwhash_scryptsalsa208sha256.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_pwhash\scryptsalsa208sha256\pbkdf2-sha256.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_pwhash\scryptsalsa208sha256\nosse\pwhash_scryptsalsa208sha256_nosse.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_pwhash\scryptsalsa208sha256\sse\pwhash_scryptsalsa208sha256_sse.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_verify\sodium\verify.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_auth\crypto_auth.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_auth\hmacsha512\auth_hmacsha512.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_auth\hmacsha512256\auth_hmacsha512256.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_auth\hmacsha256\auth_hmacsha256.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_kdf\crypto_kdf.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_kdf\blake2b\kdf_blake2b.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_shorthash\crypto_shorthash.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_shorthash\siphash24\shorthash_siphash24.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_shorthash\siphash24\shorthash_siphashx24.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_shorthash\siphash24\ref\shorthash_siphashx24_ref.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_shorthash\siphash24\ref\shorthash_siphash24_ref.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_scalarmult\crypto_scalarmult.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_scalarmult\ed25519\ref10\scalarmult_ed25519_ref10.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_scalarmult\curve25519\scalarmult_curve25519.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_scalarmult\curve25519\sandy2x\curve25519_sandy2x.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_scalarmult\curve25519\sandy2x\fe_frombytes_sandy2x.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_scalarmult\curve25519\sandy2x\fe51_invert.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_scalarmult\curve25519\ref10\x25519_ref10.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_onetimeauth\crypto_onetimeauth.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_onetimeauth\poly1305\onetimeauth_poly1305.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_onetimeauth\poly1305\donna\poly1305_donna.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_onetimeauth\poly1305\sse2\poly1305_sse2.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\randombytes\randombytes.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\randombytes\sysrandom\randombytes_sysrandom.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\randombytes\salsa20\randombytes_salsa20_random.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\randombytes\nativeclient\randombytes_nativeclient.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_box\crypto_box_easy.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_box\crypto_box_seal.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_box\crypto_box.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_box\curve25519xsalsa20poly1305\box_curve25519xsalsa20poly1305.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_box\curve25519xchacha20poly1305\box_curve25519xchacha20poly1305.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_box\curve25519xchacha20poly1305\box_seal_curve25519xchacha20poly1305.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\sodium\codecs.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\sodium\runtime.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\sodium\core.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\sodium\utils.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\sodium\version.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_stream\crypto_stream.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_stream\xchacha20\stream_xchacha20.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_stream\chacha20\stream_chacha20.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_stream\chacha20\ref\chacha20_ref.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_stream\chacha20\dolbeau\chacha20_dolbeau-avx2.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_stream\chacha20\dolbeau\chacha20_dolbeau-ssse3.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_stream\salsa20\stream_salsa20.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_stream\salsa20\ref\salsa20_ref.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_stream\salsa20\xmm6int\salsa20_xmm6int-avx2.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_stream\salsa20\xmm6int\salsa20_xmm6int-sse2.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_stream\salsa20\xmm6\salsa20_xmm6.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_stream\salsa2012\stream_salsa2012.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_stream\salsa2012\ref\stream_salsa2012_ref.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_stream\salsa208\stream_salsa208.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_stream\salsa208\ref\stream_salsa208_ref.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_stream\xsalsa20\stream_xsalsa20.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_hash\crypto_hash.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_hash\sha512\hash_sha512.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_hash\sha512\cp\hash_sha512_cp.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_hash\sha256\hash_sha256.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_hash\sha256\cp\hash_sha256_cp.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_aead\xchacha20poly1305\sodium\aead_xchacha20poly1305.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_aead\aes256gcm\aesni\aead_aes256gcm_aesni.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_aead\chacha20poly1305\sodium\aead_chacha20poly1305.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_secretstream\xchacha20poly1305\secretstream_xchacha20poly1305.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_core\salsa\ref\core_salsa_ref.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_core\hchacha20\core_hchacha20.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_core\hsalsa20\core_hsalsa20.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_core\hsalsa20\ref2\core_hsalsa20_ref2.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_core\ed25519\core_ed25519.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\crypto_core\ed25519\ref10\ed25519_ref10.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\crypto_generichash\blake2b\ref\blake2b-load-sse2.h"/>
+ <ClInclude Include="src\crypto_generichash\blake2b\ref\blake2b-load-avx2.h"/>
+ <ClInclude Include="src\crypto_generichash\blake2b\ref\blake2.h"/>
+ <ClInclude Include="src\crypto_generichash\blake2b\ref\blake2b-compress-ssse3.h"/>
+ <ClInclude Include="src\crypto_generichash\blake2b\ref\blake2b-load-sse41.h"/>
+ <ClInclude Include="src\crypto_generichash\blake2b\ref\blake2b-compress-avx2.h"/>
+ <ClInclude Include="src\crypto_generichash\blake2b\ref\blake2b-compress-sse41.h"/>
+ <ClInclude Include="src\crypto_sign\ed25519\ref10\sign_ed25519_ref10.h"/>
+ <ClInclude Include="src\include\sodium.h"/>
+ <ClInclude Include="src\include\sodium\crypto_stream_salsa2012.h"/>
+ <ClInclude Include="src\include\sodium\crypto_auth.h"/>
+ <ClInclude Include="src\include\sodium\utils.h"/>
+ <ClInclude Include="src\include\sodium\crypto_core_hchacha20.h"/>
+ <ClInclude Include="src\include\sodium\crypto_hash_sha512.h"/>
+ <ClInclude Include="src\include\sodium\core.h"/>
+ <ClInclude Include="src\include\sodium\export.h"/>
+ <ClInclude Include="src\include\sodium\randombytes_salsa20_random.h"/>
+ <ClInclude Include="src\include\sodium\crypto_core_salsa20.h"/>
+ <ClInclude Include="src\include\sodium\crypto_shorthash_siphash24.h"/>
+ <ClInclude Include="src\include\sodium\randombytes.h"/>
+ <ClInclude Include="src\include\sodium\crypto_hash_sha256.h"/>
+ <ClInclude Include="src\include\sodium\crypto_stream.h"/>
+ <ClInclude Include="src\include\sodium\crypto_auth_hmacsha512.h"/>
+ <ClInclude Include="src\include\sodium\crypto_aead_xchacha20poly1305.h"/>
+ <ClInclude Include="src\include\sodium\crypto_stream_salsa20.h"/>
+ <ClInclude Include="src\include\sodium\crypto_onetimeauth_poly1305.h"/>
+ <ClInclude Include="src\include\sodium\crypto_kx.h"/>
+ <ClInclude Include="src\include\sodium\crypto_hash.h"/>
+ <ClInclude Include="src\include\sodium\crypto_sign.h"/>
+ <ClInclude Include="src\include\sodium\crypto_kdf.h"/>
+ <ClInclude Include="src\include\sodium\crypto_auth_hmacsha256.h"/>
+ <ClInclude Include="src\include\sodium\crypto_box.h"/>
+ <ClInclude Include="src\include\sodium\crypto_verify_32.h"/>
+ <ClInclude Include="src\include\sodium\crypto_stream_xchacha20.h"/>
+ <ClInclude Include="src\include\sodium\crypto_core_salsa208.h"/>
+ <ClInclude Include="src\include\sodium\crypto_auth_hmacsha512256.h"/>
+ <ClInclude Include="src\include\sodium\crypto_aead_chacha20poly1305.h"/>
+ <ClInclude Include="src\include\sodium\randombytes_sysrandom.h"/>
+ <ClInclude Include="src\include\sodium\runtime.h"/>
+ <ClInclude Include="src\include\sodium\crypto_stream_salsa208.h"/>
+ <ClInclude Include="src\include\sodium\crypto_aead_aes256gcm.h"/>
+ <ClInclude Include="src\include\sodium\crypto_core_salsa2012.h"/>
+ <ClInclude Include="src\include\sodium\crypto_secretbox_xchacha20poly1305.h"/>
+ <ClInclude Include="src\include\sodium\randombytes_nativeclient.h"/>
+ <ClInclude Include="src\include\sodium\crypto_scalarmult.h"/>
+ <ClInclude Include="src\include\sodium\crypto_pwhash.h"/>
+ <ClInclude Include="src\include\sodium\crypto_verify_16.h"/>
+ <ClInclude Include="src\include\sodium\crypto_stream_chacha20.h"/>
+ <ClInclude Include="src\include\sodium\crypto_stream_xsalsa20.h"/>
+ <ClInclude Include="src\include\sodium\crypto_core_hsalsa20.h"/>
+ <ClInclude Include="src\include\sodium\crypto_kdf_blake2b.h"/>
+ <ClInclude Include="src\include\sodium\crypto_scalarmult_curve25519.h"/>
+ <ClInclude Include="src\include\sodium\crypto_shorthash.h"/>
+ <ClInclude Include="src\include\sodium\crypto_pwhash_argon2id.h"/>
+ <ClInclude Include="src\include\sodium\crypto_secretstream_xchacha20poly1305.h"/>
+ <ClInclude Include="src\include\sodium\crypto_pwhash_scryptsalsa208sha256.h"/>
+ <ClInclude Include="src\include\sodium\crypto_sign_ed25519.h"/>
+ <ClInclude Include="src\include\sodium\crypto_onetimeauth.h"/>
+ <ClInclude Include="src\include\sodium\crypto_verify_64.h"/>
+ <ClInclude Include="src\include\sodium\crypto_box_curve25519xchacha20poly1305.h"/>
+ <ClInclude Include="src\include\sodium\crypto_core_ed25519.h"/>
+ <ClInclude Include="src\include\sodium\crypto_pwhash_argon2i.h"/>
+ <ClInclude Include="src\include\sodium\crypto_generichash.h"/>
+ <ClInclude Include="src\include\sodium\crypto_secretbox_xsalsa20poly1305.h"/>
+ <ClInclude Include="src\include\sodium\crypto_secretbox.h"/>
+ <ClInclude Include="src\include\sodium\crypto_scalarmult_ed25519.h"/>
+ <ClInclude Include="src\include\sodium\crypto_box_curve25519xsalsa20poly1305.h"/>
+ <ClInclude Include="src\include\sodium\crypto_generichash_blake2b.h"/>
+ <ClInclude Include="src\include\sodium\crypto_sign_edwards25519sha512batch.h"/>
+ <ClInclude Include="src\include\sodium\version.h"/>
+ <ClInclude Include="src\include\sodium\private\ed25519_ref10.h"/>
+ <ClInclude Include="src\include\sodium\private\ed25519_ref10_fe_25_5.h"/>
+ <ClInclude Include="src\include\sodium\private\ed25519_ref10_fe_51.h"/>
+ <ClInclude Include="src\include\sodium\private\sse2_64_32.h"/>
+ <ClInclude Include="src\include\sodium\private\common.h"/>
+ <ClInclude Include="src\include\sodium\private\mutex.h"/>
+ <ClInclude Include="src\include\sodium\private\implementations.h"/>
+ <ClInclude Include="src\crypto_pwhash\argon2\blamka-round-ref.h"/>
+ <ClInclude Include="src\crypto_pwhash\argon2\blamka-round-avx2.h"/>
+ <ClInclude Include="src\crypto_pwhash\argon2\argon2.h"/>
+ <ClInclude Include="src\crypto_pwhash\argon2\blamka-round-ssse3.h"/>
+ <ClInclude Include="src\crypto_pwhash\argon2\argon2-encoding.h"/>
+ <ClInclude Include="src\crypto_pwhash\argon2\blake2b-long.h"/>
+ <ClInclude Include="src\crypto_pwhash\argon2\blamka-round-avx512f.h"/>
+ <ClInclude Include="src\crypto_pwhash\argon2\argon2-core.h"/>
+ <ClInclude Include="src\crypto_pwhash\scryptsalsa208sha256\crypto_scrypt.h"/>
+ <ClInclude Include="src\crypto_pwhash\scryptsalsa208sha256\pbkdf2-sha256.h"/>
+ <ClInclude Include="src\crypto_shorthash\siphash24\ref\shorthash_siphash_ref.h"/>
+ <ClInclude Include="src\crypto_scalarmult\curve25519\scalarmult_curve25519.h"/>
+ <ClInclude Include="src\crypto_scalarmult\curve25519\sandy2x\consts_namespace.h"/>
+ <ClInclude Include="src\crypto_scalarmult\curve25519\sandy2x\ladder_namespace.h"/>
+ <ClInclude Include="src\crypto_scalarmult\curve25519\sandy2x\fe.h"/>
+ <ClInclude Include="src\crypto_scalarmult\curve25519\sandy2x\ladder_base_namespace.h"/>
+ <ClInclude Include="src\crypto_scalarmult\curve25519\sandy2x\ladder.h"/>
+ <ClInclude Include="src\crypto_scalarmult\curve25519\sandy2x\fe51.h"/>
+ <ClInclude Include="src\crypto_scalarmult\curve25519\sandy2x\curve25519_sandy2x.h"/>
+ <ClInclude Include="src\crypto_scalarmult\curve25519\sandy2x\fe51_namespace.h"/>
+ <ClInclude Include="src\crypto_scalarmult\curve25519\sandy2x\ladder_base.h"/>
+ <ClInclude Include="src\crypto_scalarmult\curve25519\ref10\x25519_ref10.h"/>
+ <ClInclude Include="src\crypto_onetimeauth\poly1305\onetimeauth_poly1305.h"/>
+ <ClInclude Include="src\crypto_onetimeauth\poly1305\donna\poly1305_donna.h"/>
+ <ClInclude Include="src\crypto_onetimeauth\poly1305\donna\poly1305_donna64.h"/>
+ <ClInclude Include="src\crypto_onetimeauth\poly1305\donna\poly1305_donna32.h"/>
+ <ClInclude Include="src\crypto_onetimeauth\poly1305\sse2\poly1305_sse2.h"/>
+ <ClInclude Include="src\crypto_stream\chacha20\stream_chacha20.h"/>
+ <ClInclude Include="src\crypto_stream\chacha20\ref\chacha20_ref.h"/>
+ <ClInclude Include="src\crypto_stream\chacha20\dolbeau\u4.h"/>
+ <ClInclude Include="src\crypto_stream\chacha20\dolbeau\chacha20_dolbeau-ssse3.h"/>
+ <ClInclude Include="src\crypto_stream\chacha20\dolbeau\u0.h"/>
+ <ClInclude Include="src\crypto_stream\chacha20\dolbeau\u1.h"/>
+ <ClInclude Include="src\crypto_stream\chacha20\dolbeau\chacha20_dolbeau-avx2.h"/>
+ <ClInclude Include="src\crypto_stream\chacha20\dolbeau\u8.h"/>
+ <ClInclude Include="src\crypto_stream\salsa20\stream_salsa20.h"/>
+ <ClInclude Include="src\crypto_stream\salsa20\ref\salsa20_ref.h"/>
+ <ClInclude Include="src\crypto_stream\salsa20\xmm6int\u4.h"/>
+ <ClInclude Include="src\crypto_stream\salsa20\xmm6int\u0.h"/>
+ <ClInclude Include="src\crypto_stream\salsa20\xmm6int\u1.h"/>
+ <ClInclude Include="src\crypto_stream\salsa20\xmm6int\salsa20_xmm6int-avx2.h"/>
+ <ClInclude Include="src\crypto_stream\salsa20\xmm6int\u8.h"/>
+ <ClInclude Include="src\crypto_stream\salsa20\xmm6int\salsa20_xmm6int-sse2.h"/>
+ <ClInclude Include="src\crypto_stream\salsa20\xmm6\salsa20_xmm6.h"/>
+ <ClInclude Include="src\crypto_core\ed25519\ref10\fe_25_5\constants.h"/>
+ <ClInclude Include="src\crypto_core\ed25519\ref10\fe_25_5\fe.h"/>
+ <ClInclude Include="src\crypto_core\ed25519\ref10\fe_25_5\base2.h"/>
+ <ClInclude Include="src\crypto_core\ed25519\ref10\fe_25_5\base.h"/>
+ <ClInclude Include="src\crypto_core\ed25519\ref10\fe_51\constants.h"/>
+ <ClInclude Include="src\crypto_core\ed25519\ref10\fe_51\fe.h"/>
+ <ClInclude Include="src\crypto_core\ed25519\ref10\fe_51\base2.h"/>
+ <ClInclude Include="src\crypto_core\ed25519\ref10\fe_51\base.h"/>
+ </ItemGroup>
+</Project>
diff --git a/protocols/AimOscar/aim.vcxproj.filters b/libs/libsodium/libsodium.vcxproj.filters
index de5ad9f66c..8f90aeb3d5 100644
--- a/protocols/AimOscar/aim.vcxproj.filters
+++ b/libs/libsodium/libsodium.vcxproj.filters
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$(ProjectDir)..\..\build\vc.common\common.filters" />
-</Project> \ No newline at end of file
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(ProjectDir)..\..\build\vc.common\common.filters" />
+</Project>
diff --git a/libs/libsodium/src/crypto_aead/aes256gcm/aesni/aead_aes256gcm_aesni.c b/libs/libsodium/src/crypto_aead/aes256gcm/aesni/aead_aes256gcm_aesni.c
new file mode 100644
index 0000000000..dc54bca76b
--- /dev/null
+++ b/libs/libsodium/src/crypto_aead/aes256gcm/aesni/aead_aes256gcm_aesni.c
@@ -0,0 +1,1079 @@
+
+/*
+ * AES256-GCM, based on the "Intel Carry-Less Multiplication Instruction and its Usage for Computing
+ * the GCM Mode" paper and reference code, using the aggregated reduction method.
+ * Originally adapted by Romain Dolbeau.
+ */
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "core.h"
+#include "crypto_aead_aes256gcm.h"
+#include "export.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+#include "randombytes.h"
+#include "runtime.h"
+#include "utils.h"
+
+#if defined(HAVE_TMMINTRIN_H) && defined(HAVE_WMMINTRIN_H)
+
+# ifdef __GNUC__
+# pragma GCC target("ssse3")
+# pragma GCC target("aes")
+# pragma GCC target("pclmul")
+# endif
+
+#include <tmmintrin.h>
+#include <wmmintrin.h>
+
+#ifndef ENOSYS
+# define ENOSYS ENXIO
+#endif
+
+#if defined(__INTEL_COMPILER) || defined(_bswap64)
+#elif defined(_MSC_VER)
+# define _bswap64(a) _byteswap_uint64(a)
+#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
+# define _bswap64(a) __builtin_bswap64(a)
+#else
+static inline uint64_t
+_bswap64(const uint64_t x)
+{
+ return
+ ((x << 56) & 0xFF00000000000000UL) | ((x << 40) & 0x00FF000000000000UL) |
+ ((x << 24) & 0x0000FF0000000000UL) | ((x << 8) & 0x000000FF00000000UL) |
+ ((x >> 8) & 0x00000000FF000000UL) | ((x >> 24) & 0x0000000000FF0000UL) |
+ ((x >> 40) & 0x000000000000FF00UL) | ((x >> 56) & 0x00000000000000FFUL);
+}
+#endif
+
+typedef struct context {
+ CRYPTO_ALIGN(16) unsigned char H[16];
+ __m128i rkeys[16];
+} context;
+
+static inline void
+aesni_key256_expand(const unsigned char *key, __m128i * const rkeys)
+{
+ __m128i X0, X1, X2, X3;
+ int i = 0;
+
+ X0 = _mm_loadu_si128((const __m128i *) &key[0]);
+ rkeys[i++] = X0;
+
+ X2 = _mm_loadu_si128((const __m128i *) &key[16]);
+ rkeys[i++] = X2;
+
+#define EXPAND_KEY_1(S) do { \
+ X1 = _mm_shuffle_epi32(_mm_aeskeygenassist_si128(X2, (S)), 0xff); \
+ X3 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(X3), _mm_castsi128_ps(X0), 0x10)); \
+ X0 = _mm_xor_si128(X0, X3); \
+ X3 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(X3), _mm_castsi128_ps(X0), 0x8c)); \
+ X0 = _mm_xor_si128(_mm_xor_si128(X0, X3), X1); \
+ rkeys[i++] = X0; \
+} while (0)
+
+#define EXPAND_KEY_2(S) do { \
+ X1 = _mm_shuffle_epi32(_mm_aeskeygenassist_si128(X0, (S)), 0xaa); \
+ X3 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(X3), _mm_castsi128_ps(X2), 0x10)); \
+ X2 = _mm_xor_si128(X2, X3); \
+ X3 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(X3), _mm_castsi128_ps(X2), 0x8c)); \
+ X2 = _mm_xor_si128(_mm_xor_si128(X2, X3), X1); \
+ rkeys[i++] = X2; \
+} while (0)
+
+ X3 = _mm_setzero_si128();
+ EXPAND_KEY_1(0x01); EXPAND_KEY_2(0x01);
+ EXPAND_KEY_1(0x02); EXPAND_KEY_2(0x02);
+ EXPAND_KEY_1(0x04); EXPAND_KEY_2(0x04);
+ EXPAND_KEY_1(0x08); EXPAND_KEY_2(0x08);
+ EXPAND_KEY_1(0x10); EXPAND_KEY_2(0x10);
+ EXPAND_KEY_1(0x20); EXPAND_KEY_2(0x20);
+ EXPAND_KEY_1(0x40);
+}
+
+/** single, by-the-book AES encryption with AES-NI */
+static inline void
+aesni_encrypt1(unsigned char *out, __m128i nv, const __m128i *rkeys)
+{
+ __m128i temp = _mm_xor_si128(nv, rkeys[0]);
+
+ temp = _mm_aesenc_si128(temp, rkeys[1]);
+ temp = _mm_aesenc_si128(temp, rkeys[2]);
+ temp = _mm_aesenc_si128(temp, rkeys[3]);
+ temp = _mm_aesenc_si128(temp, rkeys[4]);
+ temp = _mm_aesenc_si128(temp, rkeys[5]);
+ temp = _mm_aesenc_si128(temp, rkeys[6]);
+ temp = _mm_aesenc_si128(temp, rkeys[7]);
+ temp = _mm_aesenc_si128(temp, rkeys[8]);
+ temp = _mm_aesenc_si128(temp, rkeys[9]);
+ temp = _mm_aesenc_si128(temp, rkeys[10]);
+ temp = _mm_aesenc_si128(temp, rkeys[11]);
+ temp = _mm_aesenc_si128(temp, rkeys[12]);
+ temp = _mm_aesenc_si128(temp, rkeys[13]);
+
+ temp = _mm_aesenclast_si128(temp, rkeys[14]);
+ _mm_storeu_si128((__m128i *) out, temp);
+}
+
+/** multiple-blocks-at-once AES encryption with AES-NI ;
+ on Haswell, aesenc has a latency of 7 and a throughput of 1
+ so the sequence of aesenc should be bubble-free if you
+ have at least 8 blocks. Let's build an arbitratry-sized
+ function */
+/* Step 1 : loading the nonce */
+/* load & increment the n vector (non-vectorized, unused for now) */
+#define NVDECLx(a) \
+ __m128i nv##a
+
+#define NVx(a) \
+ nv##a = _mm_shuffle_epi8(_mm_load_si128((const __m128i *) n), pt); \
+ n[3]++
+
+/* Step 2 : define value in round one (xor with subkey #0, aka key) */
+#define TEMPDECLx(a) \
+ __m128i temp##a
+
+#define TEMPx(a) \
+ temp##a = _mm_xor_si128(nv##a, rkeys[0])
+
+/* Step 3: one round of AES */
+#define AESENCx(a) \
+ temp##a = _mm_aesenc_si128(temp##a, rkeys[roundctr])
+
+/* Step 4: last round of AES */
+#define AESENCLASTx(a) \
+ temp##a = _mm_aesenclast_si128(temp##a, rkeys[14])
+
+/* Step 5: store result */
+#define STOREx(a) \
+ _mm_storeu_si128((__m128i *) (out + (a * 16)), temp##a)
+
+/* all the MAKE* macros are for automatic explicit unrolling */
+#define MAKE4(X) \
+ X(0); \
+ X(1); \
+ X(2); \
+ X(3)
+
+#define MAKE8(X) \
+ X(0); \
+ X(1); \
+ X(2); \
+ X(3); \
+ X(4); \
+ X(5); \
+ X(6); \
+ X(7)
+
+#define COUNTER_INC2(N) (N)[3] += 2
+
+/* create a function of unrolling N ; the MAKEN is the unrolling
+ macro, defined above. The N in MAKEN must match N, obviously. */
+#define FUNC(N, MAKEN) \
+ static inline void aesni_encrypt##N(unsigned char *out, uint32_t *n, const __m128i *rkeys) \
+ { \
+ const __m128i pt = _mm_set_epi8(12, 13, 14, 15, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); \
+ int roundctr; \
+ MAKEN(NVDECLx); \
+ MAKEN(TEMPDECLx); \
+ \
+ MAKEN(NVx); \
+ MAKEN(TEMPx); \
+ for (roundctr = 1; roundctr < 14; roundctr++) { \
+ MAKEN(AESENCx); \
+ } \
+ MAKEN(AESENCLASTx); \
+ MAKEN(STOREx); \
+ }
+
+FUNC(8, MAKE8)
+
+/* all GF(2^128) fnctions are by the book, meaning this one:
+ <https://software.intel.com/sites/default/files/managed/72/cc/clmul-wp-rev-2.02-2014-04-20.pdf>
+*/
+
+static inline void
+addmul(unsigned char *c, const unsigned char *a, unsigned int xlen, const unsigned char *b)
+{
+ const __m128i rev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
+ __m128i A, B, C;
+ __m128i tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9;
+ __m128i tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17, tmp18;
+ __m128i tmp19, tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27;
+ __m128i tmp28, tmp29, tmp30, tmp31, tmp32, tmp33, tmp34, tmp35, tmp36;
+
+ if (xlen >= 16) {
+ A = _mm_loadu_si128((const __m128i *) a);
+ } else {
+ CRYPTO_ALIGN(16) unsigned char padded[16];
+ unsigned int i;
+
+ memset(padded, 0, 16);
+ for (i = 0; i < xlen; i++) {
+ padded[i] = a[i];
+ }
+ A = _mm_load_si128((const __m128i *) padded);
+ }
+ A = _mm_shuffle_epi8(A, rev);
+ B = _mm_loadu_si128((const __m128i *) b);
+ C = _mm_loadu_si128((const __m128i *) c);
+ A = _mm_xor_si128(A, C);
+ tmp3 = _mm_clmulepi64_si128(A, B, 0x00);
+ tmp4 = _mm_clmulepi64_si128(A, B, 0x10);
+ tmp5 = _mm_clmulepi64_si128(A, B, 0x01);
+ tmp6 = _mm_clmulepi64_si128(A, B, 0x11);
+ tmp10 = _mm_xor_si128(tmp4, tmp5);
+ tmp13 = _mm_slli_si128(tmp10, 8);
+ tmp11 = _mm_srli_si128(tmp10, 8);
+ tmp15 = _mm_xor_si128(tmp3, tmp13);
+ tmp17 = _mm_xor_si128(tmp6, tmp11);
+ tmp7 = _mm_srli_epi32(tmp15, 31);
+ tmp8 = _mm_srli_epi32(tmp17, 31);
+ tmp16 = _mm_slli_epi32(tmp15, 1);
+ tmp18 = _mm_slli_epi32(tmp17, 1);
+ tmp9 = _mm_srli_si128(tmp7, 12);
+ tmp22 = _mm_slli_si128(tmp8, 4);
+ tmp25 = _mm_slli_si128(tmp7, 4);
+ tmp29 = _mm_or_si128(tmp16, tmp25);
+ tmp19 = _mm_or_si128(tmp18, tmp22);
+ tmp20 = _mm_or_si128(tmp19, tmp9);
+ tmp26 = _mm_slli_epi32(tmp29, 31);
+ tmp23 = _mm_slli_epi32(tmp29, 30);
+ tmp32 = _mm_slli_epi32(tmp29, 25);
+ tmp27 = _mm_xor_si128(tmp26, tmp23);
+ tmp28 = _mm_xor_si128(tmp27, tmp32);
+ tmp24 = _mm_srli_si128(tmp28, 4);
+ tmp33 = _mm_slli_si128(tmp28, 12);
+ tmp30 = _mm_xor_si128(tmp29, tmp33);
+ tmp2 = _mm_srli_epi32(tmp30, 1);
+ tmp12 = _mm_srli_epi32(tmp30, 2);
+ tmp14 = _mm_srli_epi32(tmp30, 7);
+ tmp34 = _mm_xor_si128(tmp2, tmp12);
+ tmp35 = _mm_xor_si128(tmp34, tmp14);
+ tmp36 = _mm_xor_si128(tmp35, tmp24);
+ tmp31 = _mm_xor_si128(tmp30, tmp36);
+ tmp21 = _mm_xor_si128(tmp20, tmp31);
+ _mm_storeu_si128((__m128i *) c, tmp21);
+}
+
+/* pure multiplication, for pre-computing powers of H */
+static inline __m128i
+mulv(__m128i A, __m128i B)
+{
+ __m128i tmp3 = _mm_clmulepi64_si128(A, B, 0x00);
+ __m128i tmp4 = _mm_clmulepi64_si128(A, B, 0x10);
+ __m128i tmp5 = _mm_clmulepi64_si128(A, B, 0x01);
+ __m128i tmp6 = _mm_clmulepi64_si128(A, B, 0x11);
+ __m128i tmp10 = _mm_xor_si128(tmp4, tmp5);
+ __m128i tmp13 = _mm_slli_si128(tmp10, 8);
+ __m128i tmp11 = _mm_srli_si128(tmp10, 8);
+ __m128i tmp15 = _mm_xor_si128(tmp3, tmp13);
+ __m128i tmp17 = _mm_xor_si128(tmp6, tmp11);
+ __m128i tmp7 = _mm_srli_epi32(tmp15, 31);
+ __m128i tmp8 = _mm_srli_epi32(tmp17, 31);
+ __m128i tmp16 = _mm_slli_epi32(tmp15, 1);
+ __m128i tmp18 = _mm_slli_epi32(tmp17, 1);
+ __m128i tmp9 = _mm_srli_si128(tmp7, 12);
+ __m128i tmp22 = _mm_slli_si128(tmp8, 4);
+ __m128i tmp25 = _mm_slli_si128(tmp7, 4);
+ __m128i tmp29 = _mm_or_si128(tmp16, tmp25);
+ __m128i tmp19 = _mm_or_si128(tmp18, tmp22);
+ __m128i tmp20 = _mm_or_si128(tmp19, tmp9);
+ __m128i tmp26 = _mm_slli_epi32(tmp29, 31);
+ __m128i tmp23 = _mm_slli_epi32(tmp29, 30);
+ __m128i tmp32 = _mm_slli_epi32(tmp29, 25);
+ __m128i tmp27 = _mm_xor_si128(tmp26, tmp23);
+ __m128i tmp28 = _mm_xor_si128(tmp27, tmp32);
+ __m128i tmp24 = _mm_srli_si128(tmp28, 4);
+ __m128i tmp33 = _mm_slli_si128(tmp28, 12);
+ __m128i tmp30 = _mm_xor_si128(tmp29, tmp33);
+ __m128i tmp2 = _mm_srli_epi32(tmp30, 1);
+ __m128i tmp12 = _mm_srli_epi32(tmp30, 2);
+ __m128i tmp14 = _mm_srli_epi32(tmp30, 7);
+ __m128i tmp34 = _mm_xor_si128(tmp2, tmp12);
+ __m128i tmp35 = _mm_xor_si128(tmp34, tmp14);
+ __m128i tmp36 = _mm_xor_si128(tmp35, tmp24);
+ __m128i tmp31 = _mm_xor_si128(tmp30, tmp36);
+ __m128i C = _mm_xor_si128(tmp20, tmp31);
+
+ return C;
+}
+
+/* 4 multiply-accumulate at once; again
+ <https://software.intel.com/sites/default/files/managed/72/cc/clmul-wp-rev-2.02-2014-04-20.pdf>
+ for the Aggregated Reduction Method & sample code.
+ Algorithm by Krzysztof Jankowski, Pierre Laurent - Intel */
+
+#define RED_DECL(a) __m128i H##a##_X##a##_lo, H##a##_X##a##_hi, tmp##a, tmp##a##B
+#define RED_SHUFFLE(a) X##a = _mm_shuffle_epi8(X##a, rev)
+#define RED_MUL_LOW(a) H##a##_X##a##_lo = _mm_clmulepi64_si128(H##a, X##a, 0x00)
+#define RED_MUL_HIGH(a) H##a##_X##a##_hi = _mm_clmulepi64_si128(H##a, X##a, 0x11)
+#define RED_MUL_MID(a) \
+ tmp##a = _mm_shuffle_epi32(H##a, 0x4e); \
+ tmp##a##B = _mm_shuffle_epi32(X##a, 0x4e); \
+ tmp##a = _mm_xor_si128(tmp##a, H##a); \
+ tmp##a##B = _mm_xor_si128(tmp##a##B, X##a); \
+ tmp##a = _mm_clmulepi64_si128(tmp##a, tmp##a##B, 0x00)
+
+#define MULREDUCE4(rev, H0_, H1_, H2_, H3_, X0_, X1_, X2_, X3_, accv) \
+do { \
+ MAKE4(RED_DECL); \
+ __m128i lo, hi; \
+ __m128i tmp8, tmp9; \
+ __m128i H0 = H0_; \
+ __m128i H1 = H1_; \
+ __m128i H2 = H2_; \
+ __m128i H3 = H3_; \
+ __m128i X0 = X0_; \
+ __m128i X1 = X1_; \
+ __m128i X2 = X2_; \
+ __m128i X3 = X3_; \
+\
+/* byte-revert the inputs & xor the first one into the accumulator */ \
+\
+ MAKE4(RED_SHUFFLE); \
+ X3 = _mm_xor_si128(X3, accv); \
+\
+/* 4 low H*X (x0*h0) */ \
+\
+ MAKE4(RED_MUL_LOW); \
+ lo = _mm_xor_si128(H0_X0_lo, H1_X1_lo); \
+ lo = _mm_xor_si128(lo, H2_X2_lo); \
+ lo = _mm_xor_si128(lo, H3_X3_lo); \
+\
+/* 4 high H*X (x1*h1) */ \
+\
+ MAKE4(RED_MUL_HIGH); \
+ hi = _mm_xor_si128(H0_X0_hi, H1_X1_hi); \
+ hi = _mm_xor_si128(hi, H2_X2_hi); \
+ hi = _mm_xor_si128(hi, H3_X3_hi); \
+\
+/* 4 middle H*X, using Karatsuba, i.e. \
+ x1*h0+x0*h1 =(x1+x0)*(h1+h0)-x1*h1-x0*h0 \
+ we already have all x1y1 & x0y0 (accumulated in hi & lo) \
+ (0 is low half and 1 is high half) \
+ */ \
+/* permute the high and low 64 bits in H1 & X1, \
+ so create (h0,h1) from (h1,h0) and (x0,x1) from (x1,x0), \
+ then compute (h0+h1,h1+h0) and (x0+x1,x1+x0), \
+ and finally multiply \
+ */ \
+ MAKE4(RED_MUL_MID); \
+\
+/* substracts x1*h1 and x0*h0 */ \
+ tmp0 = _mm_xor_si128(tmp0, lo); \
+ tmp0 = _mm_xor_si128(tmp0, hi); \
+ tmp0 = _mm_xor_si128(tmp1, tmp0); \
+ tmp0 = _mm_xor_si128(tmp2, tmp0); \
+ tmp0 = _mm_xor_si128(tmp3, tmp0);\
+\
+ /* reduction */ \
+ tmp0B = _mm_slli_si128(tmp0, 8); \
+ tmp0 = _mm_srli_si128(tmp0, 8); \
+ lo = _mm_xor_si128(tmp0B, lo); \
+ hi = _mm_xor_si128(tmp0, hi); \
+ tmp3 = lo; \
+ tmp2B = hi; \
+ tmp3B = _mm_srli_epi32(tmp3, 31); \
+ tmp8 = _mm_srli_epi32(tmp2B, 31); \
+ tmp3 = _mm_slli_epi32(tmp3, 1); \
+ tmp2B = _mm_slli_epi32(tmp2B, 1); \
+ tmp9 = _mm_srli_si128(tmp3B, 12); \
+ tmp8 = _mm_slli_si128(tmp8, 4); \
+ tmp3B = _mm_slli_si128(tmp3B, 4); \
+ tmp3 = _mm_or_si128(tmp3, tmp3B); \
+ tmp2B = _mm_or_si128(tmp2B, tmp8); \
+ tmp2B = _mm_or_si128(tmp2B, tmp9); \
+ tmp3B = _mm_slli_epi32(tmp3, 31); \
+ tmp8 = _mm_slli_epi32(tmp3, 30); \
+ tmp9 = _mm_slli_epi32(tmp3, 25); \
+ tmp3B = _mm_xor_si128(tmp3B, tmp8); \
+ tmp3B = _mm_xor_si128(tmp3B, tmp9); \
+ tmp8 = _mm_srli_si128(tmp3B, 4); \
+ tmp3B = _mm_slli_si128(tmp3B, 12); \
+ tmp3 = _mm_xor_si128(tmp3, tmp3B); \
+ tmp2 = _mm_srli_epi32(tmp3, 1); \
+ tmp0B = _mm_srli_epi32(tmp3, 2); \
+ tmp1B = _mm_srli_epi32(tmp3, 7); \
+ tmp2 = _mm_xor_si128(tmp2, tmp0B); \
+ tmp2 = _mm_xor_si128(tmp2, tmp1B); \
+ tmp2 = _mm_xor_si128(tmp2, tmp8); \
+ tmp3 = _mm_xor_si128(tmp3, tmp2); \
+ tmp2B = _mm_xor_si128(tmp2B, tmp3); \
+\
+ accv = tmp2B; \
+} while(0)
+
+#define XORx(a) \
+ temp##a = _mm_xor_si128(temp##a, \
+ _mm_loadu_si128((const __m128i *) (in + a * 16)))
+
+#define LOADx(a) \
+ __m128i in##a = _mm_loadu_si128((const __m128i *) (in + a * 16))
+
+/* full encrypt & checksum 8 blocks at once */
+#define aesni_encrypt8full(out_, n_, rkeys, in_, accum, hv_, h2v_, h3v_, h4v_, rev) \
+do { \
+ unsigned char *out = out_; \
+ uint32_t *n = n_; \
+ const unsigned char *in = in_; \
+ const __m128i hv = hv_; \
+ const __m128i h2v = h2v_; \
+ const __m128i h3v = h3v_; \
+ const __m128i h4v = h4v_; \
+ const __m128i pt = _mm_set_epi8(12, 13, 14, 15, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); \
+ __m128i accv_; \
+ int roundctr; \
+ \
+ MAKE8(NVDECLx); \
+ MAKE8(TEMPDECLx); \
+ MAKE8(NVx); \
+ MAKE8(TEMPx); \
+ for (roundctr = 1; roundctr < 14; roundctr++) { \
+ MAKE8(AESENCx); \
+ } \
+ MAKE8(AESENCLASTx); \
+ MAKE8(XORx); \
+ MAKE8(STOREx); \
+ accv_ = _mm_load_si128((const __m128i *) accum); \
+ MULREDUCE4(rev, hv, h2v, h3v, h4v, temp3, temp2, temp1, temp0, accv_); \
+ MULREDUCE4(rev, hv, h2v, h3v, h4v, temp7, temp6, temp5, temp4, accv_); \
+ _mm_store_si128((__m128i *) accum, accv_); \
+} while(0)
+
+/* checksum 8 blocks at once */
+#define aesni_addmul8full(in_, accum, hv_, h2v_, h3v_, h4v_, rev) \
+do { \
+ const unsigned char *in = in_; \
+ const __m128i hv = hv_; \
+ const __m128i h2v = h2v_; \
+ const __m128i h3v = h3v_; \
+ const __m128i h4v = h4v_; \
+ __m128i accv_; \
+ \
+ MAKE8(LOADx); \
+ accv_ = _mm_load_si128((const __m128i *) accum); \
+ MULREDUCE4(rev, hv, h2v, h3v, h4v, in3, in2, in1, in0, accv_); \
+ MULREDUCE4(rev, hv, h2v, h3v, h4v, in7, in6, in5, in4, accv_); \
+ _mm_store_si128((__m128i *) accum, accv_); \
+} while(0)
+
+/* decrypt 8 blocks at once */
+#define aesni_decrypt8full(out_, n_, rkeys, in_) \
+do { \
+ unsigned char *out = out_; \
+ uint32_t *n = n_; \
+ const unsigned char *in = in_; \
+ const __m128i pt = _mm_set_epi8(12, 13, 14, 15, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); \
+ int roundctr; \
+\
+ MAKE8(NVDECLx); \
+ MAKE8(TEMPDECLx); \
+ MAKE8(NVx); \
+ MAKE8(TEMPx); \
+ for (roundctr = 1; roundctr < 14; roundctr++) { \
+ MAKE8(AESENCx); \
+ } \
+ MAKE8(AESENCLASTx); \
+ MAKE8(XORx); \
+ MAKE8(STOREx); \
+} while(0)
+
+int
+crypto_aead_aes256gcm_beforenm(crypto_aead_aes256gcm_state *ctx_,
+ const unsigned char *k)
+{
+ context *ctx = (context *) ctx_;
+ __m128i *rkeys = ctx->rkeys;
+ __m128i zero = _mm_setzero_si128();
+ unsigned char *H = ctx->H;
+
+ COMPILER_ASSERT((sizeof *ctx_) >= (sizeof *ctx));
+ aesni_key256_expand(k, rkeys);
+ aesni_encrypt1(H, zero, rkeys);
+
+ return 0;
+}
+
+int
+crypto_aead_aes256gcm_encrypt_detached_afternm(unsigned char *c,
+ unsigned char *mac, unsigned long long *maclen_p,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *ad, unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const crypto_aead_aes256gcm_state *ctx_)
+{
+ const __m128i rev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
+ const context *ctx = (const context *) ctx_;
+ const __m128i *rkeys = ctx->rkeys;
+ __m128i Hv, H2v, H3v, H4v, accv;
+ unsigned long long i, j;
+ unsigned long long adlen_rnd64 = adlen & ~63ULL;
+ unsigned long long mlen_rnd128 = mlen & ~127ULL;
+ CRYPTO_ALIGN(16) uint32_t n2[4];
+ CRYPTO_ALIGN(16) unsigned char H[16];
+ CRYPTO_ALIGN(16) unsigned char T[16];
+ CRYPTO_ALIGN(16) unsigned char accum[16];
+ CRYPTO_ALIGN(16) unsigned char fb[16];
+
+ (void) nsec;
+ memcpy(H, ctx->H, sizeof H);
+ if (mlen > crypto_aead_aes256gcm_MESSAGEBYTES_MAX) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+ memcpy(&n2[0], npub, 3 * 4);
+ n2[3] = 0x01000000;
+ aesni_encrypt1(T, _mm_load_si128((const __m128i *) n2), rkeys);
+ {
+ uint64_t x;
+ x = _bswap64((uint64_t) (8 * adlen));
+ memcpy(&fb[0], &x, sizeof x);
+ x = _bswap64((uint64_t) (8 * mlen));
+ memcpy(&fb[8], &x, sizeof x);
+ }
+ /* we store H (and it's power) byte-reverted once and for all */
+ Hv = _mm_shuffle_epi8(_mm_load_si128((const __m128i *) H), rev);
+ _mm_store_si128((__m128i *) H, Hv);
+ H2v = mulv(Hv, Hv);
+ H3v = mulv(H2v, Hv);
+ H4v = mulv(H3v, Hv);
+
+ accv = _mm_setzero_si128();
+ /* unrolled by 4 GCM (by 8 doesn't improve using MULREDUCE4) */
+ for (i = 0; i < adlen_rnd64; i += 64) {
+ __m128i X4_ = _mm_loadu_si128((const __m128i *) (ad + i + 0));
+ __m128i X3_ = _mm_loadu_si128((const __m128i *) (ad + i + 16));
+ __m128i X2_ = _mm_loadu_si128((const __m128i *) (ad + i + 32));
+ __m128i X1_ = _mm_loadu_si128((const __m128i *) (ad + i + 48));
+ MULREDUCE4(rev, Hv, H2v, H3v, H4v, X1_, X2_, X3_, X4_, accv);
+ }
+ _mm_store_si128((__m128i *) accum, accv);
+
+ /* GCM remainder loop */
+ for (i = adlen_rnd64; i < adlen; i += 16) {
+ unsigned int blocklen = 16;
+
+ if (i + (unsigned long long) blocklen > adlen) {
+ blocklen = (unsigned int) (adlen - i);
+ }
+ addmul(accum, ad + i, blocklen, H);
+ }
+
+/* this only does 8 full blocks, so no fancy bounds checking is necessary*/
+#define LOOPRND128 \
+ do { \
+ const int iter = 8; \
+ const int lb = iter * 16; \
+ \
+ for (i = 0; i < mlen_rnd128; i += lb) { \
+ aesni_encrypt8full(c + i, n2, rkeys, m + i, accum, Hv, H2v, H3v, H4v, rev); \
+ } \
+ } while(0)
+
+/* remainder loop, with the slower GCM update to accommodate partial blocks */
+#define LOOPRMD128 \
+ do { \
+ const int iter = 8; \
+ const int lb = iter * 16; \
+ \
+ for (i = mlen_rnd128; i < mlen; i += lb) { \
+ CRYPTO_ALIGN(16) unsigned char outni[8 * 16]; \
+ unsigned long long mj = lb; \
+ \
+ aesni_encrypt8(outni, n2, rkeys); \
+ if ((i + mj) >= mlen) { \
+ mj = mlen - i; \
+ } \
+ for (j = 0; j < mj; j++) { \
+ c[i + j] = m[i + j] ^ outni[j]; \
+ } \
+ for (j = 0; j < mj; j += 16) { \
+ unsigned int bl = 16; \
+ \
+ if (j + (unsigned long long) bl >= mj) { \
+ bl = (unsigned int) (mj - j); \
+ } \
+ addmul(accum, c + i + j, bl, H); \
+ } \
+ } \
+ } while(0)
+
+ n2[3] &= 0x00ffffff;
+ COUNTER_INC2(n2);
+ LOOPRND128;
+ LOOPRMD128;
+
+ addmul(accum, fb, 16, H);
+
+ for (i = 0; i < 16; ++i) {
+ mac[i] = T[i] ^ accum[15 - i];
+ }
+ if (maclen_p != NULL) {
+ *maclen_p = 16;
+ }
+ return 0;
+}
+
+int
+crypto_aead_aes256gcm_encrypt_afternm(unsigned char *c, unsigned long long *clen_p,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *ad, unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const crypto_aead_aes256gcm_state *ctx_)
+{
+ int ret = crypto_aead_aes256gcm_encrypt_detached_afternm(c,
+ c + mlen, NULL,
+ m, mlen,
+ ad, adlen,
+ nsec, npub, ctx_);
+ if (clen_p != NULL) {
+ *clen_p = mlen + crypto_aead_aes256gcm_ABYTES;
+ }
+ return ret;
+}
+
+int
+crypto_aead_aes256gcm_decrypt_detached_afternm(unsigned char *m, unsigned char *nsec,
+ const unsigned char *c, unsigned long long clen,
+ const unsigned char *mac,
+ const unsigned char *ad, unsigned long long adlen,
+ const unsigned char *npub,
+ const crypto_aead_aes256gcm_state *ctx_)
+{
+ const __m128i rev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
+ const context *ctx = (const context *) ctx_;
+ const __m128i *rkeys = ctx->rkeys;
+ __m128i Hv, H2v, H3v, H4v, accv;
+ unsigned long long i, j;
+ unsigned long long adlen_rnd64 = adlen & ~63ULL;
+ unsigned long long mlen;
+ unsigned long long mlen_rnd128;
+ CRYPTO_ALIGN(16) uint32_t n2[4];
+ CRYPTO_ALIGN(16) unsigned char H[16];
+ CRYPTO_ALIGN(16) unsigned char T[16];
+ CRYPTO_ALIGN(16) unsigned char accum[16];
+ CRYPTO_ALIGN(16) unsigned char fb[16];
+
+ (void) nsec;
+ if (clen > crypto_aead_aes256gcm_MESSAGEBYTES_MAX) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+ mlen = clen;
+
+ memcpy(&n2[0], npub, 3 * 4);
+ n2[3] = 0x01000000;
+ aesni_encrypt1(T, _mm_load_si128((const __m128i *) n2), rkeys);
+
+ {
+ uint64_t x;
+ x = _bswap64((uint64_t)(8 * adlen));
+ memcpy(&fb[0], &x, sizeof x);
+ x = _bswap64((uint64_t)(8 * mlen));
+ memcpy(&fb[8], &x, sizeof x);
+ }
+
+ memcpy(H, ctx->H, sizeof H);
+ Hv = _mm_shuffle_epi8(_mm_load_si128((const __m128i *) H), rev);
+ _mm_store_si128((__m128i *) H, Hv);
+ H2v = mulv(Hv, Hv);
+ H3v = mulv(H2v, Hv);
+ H4v = mulv(H3v, Hv);
+
+ accv = _mm_setzero_si128();
+ for (i = 0; i < adlen_rnd64; i += 64) {
+ __m128i X4_ = _mm_loadu_si128((const __m128i *) (ad + i + 0));
+ __m128i X3_ = _mm_loadu_si128((const __m128i *) (ad + i + 16));
+ __m128i X2_ = _mm_loadu_si128((const __m128i *) (ad + i + 32));
+ __m128i X1_ = _mm_loadu_si128((const __m128i *) (ad + i + 48));
+ MULREDUCE4(rev, Hv, H2v, H3v, H4v, X1_, X2_, X3_, X4_, accv);
+ }
+ _mm_store_si128((__m128i *) accum, accv);
+
+ for (i = adlen_rnd64; i < adlen; i += 16) {
+ unsigned int blocklen = 16;
+ if (i + (unsigned long long) blocklen > adlen) {
+ blocklen = (unsigned int) (adlen - i);
+ }
+ addmul(accum, ad + i, blocklen, H);
+ }
+
+ mlen_rnd128 = mlen & ~127ULL;
+
+#define LOOPACCUMDRND128 \
+ do { \
+ const int iter = 8; \
+ const int lb = iter * 16; \
+ for (i = 0; i < mlen_rnd128; i += lb) { \
+ aesni_addmul8full(c + i, accum, Hv, H2v, H3v, H4v, rev); \
+ } \
+ } while(0)
+
+#define LOOPDRND128 \
+ do { \
+ const int iter = 8; \
+ const int lb = iter * 16; \
+ \
+ for (i = 0; i < mlen_rnd128; i += lb) { \
+ aesni_decrypt8full(m + i, n2, rkeys, c + i); \
+ } \
+ } while(0)
+
+#define LOOPACCUMDRMD128 \
+ do { \
+ const int iter = 8; \
+ const int lb = iter * 16; \
+ \
+ for (i = mlen_rnd128; i < mlen; i += lb) { \
+ unsigned long long mj = lb; \
+ \
+ if ((i + mj) >= mlen) { \
+ mj = mlen - i; \
+ } \
+ for (j = 0; j < mj; j += 16) { \
+ unsigned int bl = 16; \
+ \
+ if (j + (unsigned long long) bl >= mj) { \
+ bl = (unsigned int) (mj - j); \
+ } \
+ addmul(accum, c + i + j, bl, H); \
+ } \
+ } \
+ } while(0)
+
+#define LOOPDRMD128 \
+ do { \
+ const int iter = 8; \
+ const int lb = iter * 16; \
+ \
+ for (i = mlen_rnd128; i < mlen; i += lb) { \
+ CRYPTO_ALIGN(16) unsigned char outni[8 * 16]; \
+ unsigned long long mj = lb; \
+ \
+ if ((i + mj) >= mlen) { \
+ mj = mlen - i; \
+ } \
+ aesni_encrypt8(outni, n2, rkeys); \
+ for (j = 0; j < mj; j++) { \
+ m[i + j] = c[i + j] ^ outni[j]; \
+ } \
+ } \
+ } while(0)
+
+ n2[3] &= 0x00ffffff;
+
+ COUNTER_INC2(n2);
+ LOOPACCUMDRND128;
+ LOOPACCUMDRMD128;
+ addmul(accum, fb, 16, H);
+ {
+ unsigned char d = 0;
+
+ for (i = 0; i < 16; i++) {
+ d |= (mac[i] ^ (T[i] ^ accum[15 - i]));
+ }
+ if (d != 0) {
+ if (m != NULL) {
+ memset(m, 0, mlen);
+ }
+ return -1;
+ }
+ if (m == NULL) {
+ return 0;
+ }
+ }
+ n2[3] = 0U;
+ COUNTER_INC2(n2);
+ LOOPDRND128;
+ LOOPDRMD128;
+
+ return 0;
+}
+
+int
+crypto_aead_aes256gcm_decrypt_afternm(unsigned char *m, unsigned long long *mlen_p,
+ unsigned char *nsec,
+ const unsigned char *c, unsigned long long clen,
+ const unsigned char *ad, unsigned long long adlen,
+ const unsigned char *npub,
+ const crypto_aead_aes256gcm_state *ctx_)
+{
+ unsigned long long mlen = 0ULL;
+ int ret = -1;
+
+ if (clen >= crypto_aead_aes256gcm_ABYTES) {
+ ret = crypto_aead_aes256gcm_decrypt_detached_afternm
+ (m, nsec, c, clen - crypto_aead_aes256gcm_ABYTES,
+ c + clen - crypto_aead_aes256gcm_ABYTES,
+ ad, adlen, npub, ctx_);
+ }
+ if (mlen_p != NULL) {
+ if (ret == 0) {
+ mlen = clen - crypto_aead_aes256gcm_ABYTES;
+ }
+ *mlen_p = mlen;
+ }
+ return ret;
+}
+
+int
+crypto_aead_aes256gcm_encrypt_detached(unsigned char *c,
+ unsigned char *mac,
+ unsigned long long *maclen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ CRYPTO_ALIGN(16) crypto_aead_aes256gcm_state ctx;
+
+ crypto_aead_aes256gcm_beforenm(&ctx, k);
+
+ return crypto_aead_aes256gcm_encrypt_detached_afternm
+ (c, mac, maclen_p, m, mlen, ad, adlen, nsec, npub,
+ (const crypto_aead_aes256gcm_state *) &ctx);
+}
+
+int
+crypto_aead_aes256gcm_encrypt(unsigned char *c,
+ unsigned long long *clen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ CRYPTO_ALIGN(16) crypto_aead_aes256gcm_state ctx;
+ int ret;
+
+ crypto_aead_aes256gcm_beforenm(&ctx, k);
+
+ ret = crypto_aead_aes256gcm_encrypt_afternm
+ (c, clen_p, m, mlen, ad, adlen, nsec, npub,
+ (const crypto_aead_aes256gcm_state *) &ctx);
+ sodium_memzero(ctx, sizeof ctx);
+
+ return ret;
+}
+
+int
+crypto_aead_aes256gcm_decrypt_detached(unsigned char *m,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *mac,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ CRYPTO_ALIGN(16) crypto_aead_aes256gcm_state ctx;
+
+ crypto_aead_aes256gcm_beforenm(&ctx, k);
+
+ return crypto_aead_aes256gcm_decrypt_detached_afternm
+ (m, nsec, c, clen, mac, ad, adlen, npub,
+ (const crypto_aead_aes256gcm_state *) &ctx);
+}
+
+int
+crypto_aead_aes256gcm_decrypt(unsigned char *m,
+ unsigned long long *mlen_p,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ CRYPTO_ALIGN(16) crypto_aead_aes256gcm_state ctx;
+ int ret;
+
+ crypto_aead_aes256gcm_beforenm(&ctx, k);
+
+ ret = crypto_aead_aes256gcm_decrypt_afternm
+ (m, mlen_p, nsec, c, clen, ad, adlen, npub,
+ (const crypto_aead_aes256gcm_state *) &ctx);
+ sodium_memzero(ctx, sizeof ctx);
+
+ return ret;
+}
+
+int
+crypto_aead_aes256gcm_is_available(void)
+{
+ return sodium_runtime_has_pclmul() & sodium_runtime_has_aesni();
+}
+
+#else
+
+int
+crypto_aead_aes256gcm_encrypt_detached(unsigned char *c,
+ unsigned char *mac,
+ unsigned long long *maclen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+crypto_aead_aes256gcm_encrypt(unsigned char *c, unsigned long long *clen_p,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *ad, unsigned long long adlen,
+ const unsigned char *nsec, const unsigned char *npub,
+ const unsigned char *k)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+crypto_aead_aes256gcm_decrypt_detached(unsigned char *m,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *mac,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+crypto_aead_aes256gcm_decrypt(unsigned char *m, unsigned long long *mlen_p,
+ unsigned char *nsec, const unsigned char *c,
+ unsigned long long clen, const unsigned char *ad,
+ unsigned long long adlen, const unsigned char *npub,
+ const unsigned char *k)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+crypto_aead_aes256gcm_beforenm(crypto_aead_aes256gcm_state *ctx_,
+ const unsigned char *k)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+crypto_aead_aes256gcm_encrypt_detached_afternm(unsigned char *c,
+ unsigned char *mac, unsigned long long *maclen_p,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *ad, unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const crypto_aead_aes256gcm_state *ctx_)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+crypto_aead_aes256gcm_encrypt_afternm(unsigned char *c, unsigned long long *clen_p,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *ad, unsigned long long adlen,
+ const unsigned char *nsec, const unsigned char *npub,
+ const crypto_aead_aes256gcm_state *ctx_)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+crypto_aead_aes256gcm_decrypt_detached_afternm(unsigned char *m, unsigned char *nsec,
+ const unsigned char *c, unsigned long long clen,
+ const unsigned char *mac,
+ const unsigned char *ad, unsigned long long adlen,
+ const unsigned char *npub,
+ const crypto_aead_aes256gcm_state *ctx_)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+crypto_aead_aes256gcm_decrypt_afternm(unsigned char *m, unsigned long long *mlen_p,
+ unsigned char *nsec,
+ const unsigned char *c, unsigned long long clen,
+ const unsigned char *ad, unsigned long long adlen,
+ const unsigned char *npub,
+ const crypto_aead_aes256gcm_state *ctx_)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+crypto_aead_aes256gcm_is_available(void)
+{
+ return 0;
+}
+
+#endif
+
+size_t
+crypto_aead_aes256gcm_keybytes(void)
+{
+ return crypto_aead_aes256gcm_KEYBYTES;
+}
+
+size_t
+crypto_aead_aes256gcm_nsecbytes(void)
+{
+ return crypto_aead_aes256gcm_NSECBYTES;
+}
+
+size_t
+crypto_aead_aes256gcm_npubbytes(void)
+{
+ return crypto_aead_aes256gcm_NPUBBYTES;
+}
+
+size_t
+crypto_aead_aes256gcm_abytes(void)
+{
+ return crypto_aead_aes256gcm_ABYTES;
+}
+
+size_t
+crypto_aead_aes256gcm_statebytes(void)
+{
+ return (sizeof(crypto_aead_aes256gcm_state) + (size_t) 15U) & ~(size_t) 15U;
+}
+
+size_t
+crypto_aead_aes256gcm_messagebytes_max(void)
+{
+ return crypto_aead_aes256gcm_MESSAGEBYTES_MAX;
+}
+
+void
+crypto_aead_aes256gcm_keygen(unsigned char k[crypto_aead_aes256gcm_KEYBYTES])
+{
+ randombytes_buf(k, crypto_aead_aes256gcm_KEYBYTES);
+}
diff --git a/libs/libsodium/src/crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c b/libs/libsodium/src/crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c
new file mode 100644
index 0000000000..c79407a185
--- /dev/null
+++ b/libs/libsodium/src/crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c
@@ -0,0 +1,399 @@
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+
+#include "core.h"
+#include "crypto_aead_chacha20poly1305.h"
+#include "crypto_onetimeauth_poly1305.h"
+#include "crypto_stream_chacha20.h"
+#include "crypto_verify_16.h"
+#include "randombytes.h"
+#include "utils.h"
+
+#include "private/common.h"
+
+static const unsigned char _pad0[16] = { 0 };
+
+int
+crypto_aead_chacha20poly1305_encrypt_detached(unsigned char *c,
+ unsigned char *mac,
+ unsigned long long *maclen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ crypto_onetimeauth_poly1305_state state;
+ unsigned char block0[64U];
+ unsigned char slen[8U];
+
+ (void) nsec;
+ crypto_stream_chacha20(block0, sizeof block0, npub, k);
+ crypto_onetimeauth_poly1305_init(&state, block0);
+ sodium_memzero(block0, sizeof block0);
+
+ crypto_onetimeauth_poly1305_update(&state, ad, adlen);
+ STORE64_LE(slen, (uint64_t) adlen);
+ crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+ crypto_stream_chacha20_xor_ic(c, m, mlen, npub, 1U, k);
+
+ crypto_onetimeauth_poly1305_update(&state, c, mlen);
+ STORE64_LE(slen, (uint64_t) mlen);
+ crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+ crypto_onetimeauth_poly1305_final(&state, mac);
+ sodium_memzero(&state, sizeof state);
+
+ if (maclen_p != NULL) {
+ *maclen_p = crypto_aead_chacha20poly1305_ABYTES;
+ }
+ return 0;
+}
+
+int
+crypto_aead_chacha20poly1305_encrypt(unsigned char *c,
+ unsigned long long *clen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ unsigned long long clen = 0ULL;
+ int ret;
+
+ if (mlen > crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX) {
+ sodium_misuse();
+ }
+ ret = crypto_aead_chacha20poly1305_encrypt_detached(c,
+ c + mlen, NULL,
+ m, mlen,
+ ad, adlen,
+ nsec, npub, k);
+ if (clen_p != NULL) {
+ if (ret == 0) {
+ clen = mlen + crypto_aead_chacha20poly1305_ABYTES;
+ }
+ *clen_p = clen;
+ }
+ return ret;
+}
+
+int
+crypto_aead_chacha20poly1305_ietf_encrypt_detached(unsigned char *c,
+ unsigned char *mac,
+ unsigned long long *maclen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ crypto_onetimeauth_poly1305_state state;
+ unsigned char block0[64U];
+ unsigned char slen[8U];
+
+ (void) nsec;
+ crypto_stream_chacha20_ietf(block0, sizeof block0, npub, k);
+ crypto_onetimeauth_poly1305_init(&state, block0);
+ sodium_memzero(block0, sizeof block0);
+
+ crypto_onetimeauth_poly1305_update(&state, ad, adlen);
+ crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf);
+
+ crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, npub, 1U, k);
+
+ crypto_onetimeauth_poly1305_update(&state, c, mlen);
+ crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf);
+
+ STORE64_LE(slen, (uint64_t) adlen);
+ crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+ STORE64_LE(slen, (uint64_t) mlen);
+ crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+ crypto_onetimeauth_poly1305_final(&state, mac);
+ sodium_memzero(&state, sizeof state);
+
+ if (maclen_p != NULL) {
+ *maclen_p = crypto_aead_chacha20poly1305_ietf_ABYTES;
+ }
+ return 0;
+}
+
+int
+crypto_aead_chacha20poly1305_ietf_encrypt(unsigned char *c,
+ unsigned long long *clen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ unsigned long long clen = 0ULL;
+ int ret;
+
+ if (mlen > crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX) {
+ sodium_misuse();
+ }
+ ret = crypto_aead_chacha20poly1305_ietf_encrypt_detached(c,
+ c + mlen, NULL,
+ m, mlen,
+ ad, adlen,
+ nsec, npub, k);
+ if (clen_p != NULL) {
+ if (ret == 0) {
+ clen = mlen + crypto_aead_chacha20poly1305_ietf_ABYTES;
+ }
+ *clen_p = clen;
+ }
+ return ret;
+}
+
+int
+crypto_aead_chacha20poly1305_decrypt_detached(unsigned char *m,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *mac,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ crypto_onetimeauth_poly1305_state state;
+ unsigned char block0[64U];
+ unsigned char slen[8U];
+ unsigned char computed_mac[crypto_aead_chacha20poly1305_ABYTES];
+ unsigned long long mlen;
+ int ret;
+
+ (void) nsec;
+ crypto_stream_chacha20(block0, sizeof block0, npub, k);
+ crypto_onetimeauth_poly1305_init(&state, block0);
+ sodium_memzero(block0, sizeof block0);
+
+ crypto_onetimeauth_poly1305_update(&state, ad, adlen);
+ STORE64_LE(slen, (uint64_t) adlen);
+ crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+ mlen = clen;
+ crypto_onetimeauth_poly1305_update(&state, c, mlen);
+ STORE64_LE(slen, (uint64_t) mlen);
+ crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+ crypto_onetimeauth_poly1305_final(&state, computed_mac);
+ sodium_memzero(&state, sizeof state);
+
+ COMPILER_ASSERT(sizeof computed_mac == 16U);
+ ret = crypto_verify_16(computed_mac, mac);
+ sodium_memzero(computed_mac, sizeof computed_mac);
+ if (m == NULL) {
+ return ret;
+ }
+ if (ret != 0) {
+ memset(m, 0, mlen);
+ return -1;
+ }
+ crypto_stream_chacha20_xor_ic(m, c, mlen, npub, 1U, k);
+
+ return 0;
+}
+
+int
+crypto_aead_chacha20poly1305_decrypt(unsigned char *m,
+ unsigned long long *mlen_p,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ unsigned long long mlen = 0ULL;
+ int ret = -1;
+
+ if (clen >= crypto_aead_chacha20poly1305_ABYTES) {
+ ret = crypto_aead_chacha20poly1305_decrypt_detached
+ (m, nsec,
+ c, clen - crypto_aead_chacha20poly1305_ABYTES,
+ c + clen - crypto_aead_chacha20poly1305_ABYTES,
+ ad, adlen, npub, k);
+ }
+ if (mlen_p != NULL) {
+ if (ret == 0) {
+ mlen = clen - crypto_aead_chacha20poly1305_ABYTES;
+ }
+ *mlen_p = mlen;
+ }
+ return ret;
+}
+
+int
+crypto_aead_chacha20poly1305_ietf_decrypt_detached(unsigned char *m,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *mac,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ crypto_onetimeauth_poly1305_state state;
+ unsigned char block0[64U];
+ unsigned char slen[8U];
+ unsigned char computed_mac[crypto_aead_chacha20poly1305_ietf_ABYTES];
+ unsigned long long mlen;
+ int ret;
+
+ (void) nsec;
+ crypto_stream_chacha20_ietf(block0, sizeof block0, npub, k);
+ crypto_onetimeauth_poly1305_init(&state, block0);
+ sodium_memzero(block0, sizeof block0);
+
+ crypto_onetimeauth_poly1305_update(&state, ad, adlen);
+ crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf);
+
+ mlen = clen;
+ crypto_onetimeauth_poly1305_update(&state, c, mlen);
+ crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf);
+
+ STORE64_LE(slen, (uint64_t) adlen);
+ crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+ STORE64_LE(slen, (uint64_t) mlen);
+ crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
+
+ crypto_onetimeauth_poly1305_final(&state, computed_mac);
+ sodium_memzero(&state, sizeof state);
+
+ COMPILER_ASSERT(sizeof computed_mac == 16U);
+ ret = crypto_verify_16(computed_mac, mac);
+ sodium_memzero(computed_mac, sizeof computed_mac);
+ if (m == NULL) {
+ return ret;
+ }
+ if (ret != 0) {
+ memset(m, 0, mlen);
+ return -1;
+ }
+ crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, npub, 1U, k);
+
+ return 0;
+}
+
+int
+crypto_aead_chacha20poly1305_ietf_decrypt(unsigned char *m,
+ unsigned long long *mlen_p,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ unsigned long long mlen = 0ULL;
+ int ret = -1;
+
+ if (clen >= crypto_aead_chacha20poly1305_ietf_ABYTES) {
+ ret = crypto_aead_chacha20poly1305_ietf_decrypt_detached
+ (m, nsec,
+ c, clen - crypto_aead_chacha20poly1305_ietf_ABYTES,
+ c + clen - crypto_aead_chacha20poly1305_ietf_ABYTES,
+ ad, adlen, npub, k);
+ }
+ if (mlen_p != NULL) {
+ if (ret == 0) {
+ mlen = clen - crypto_aead_chacha20poly1305_ietf_ABYTES;
+ }
+ *mlen_p = mlen;
+ }
+ return ret;
+}
+
+size_t
+crypto_aead_chacha20poly1305_ietf_keybytes(void)
+{
+ return crypto_aead_chacha20poly1305_ietf_KEYBYTES;
+}
+
+size_t
+crypto_aead_chacha20poly1305_ietf_npubbytes(void)
+{
+ return crypto_aead_chacha20poly1305_ietf_NPUBBYTES;
+}
+
+size_t
+crypto_aead_chacha20poly1305_ietf_nsecbytes(void)
+{
+ return crypto_aead_chacha20poly1305_ietf_NSECBYTES;
+}
+
+size_t
+crypto_aead_chacha20poly1305_ietf_abytes(void)
+{
+ return crypto_aead_chacha20poly1305_ietf_ABYTES;
+}
+
+size_t
+crypto_aead_chacha20poly1305_ietf_messagebytes_max(void)
+{
+ return crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX;
+}
+
+void
+crypto_aead_chacha20poly1305_ietf_keygen(unsigned char k[crypto_aead_chacha20poly1305_ietf_KEYBYTES])
+{
+ randombytes_buf(k, crypto_aead_chacha20poly1305_ietf_KEYBYTES);
+}
+
+size_t
+crypto_aead_chacha20poly1305_keybytes(void)
+{
+ return crypto_aead_chacha20poly1305_KEYBYTES;
+}
+
+size_t
+crypto_aead_chacha20poly1305_npubbytes(void)
+{
+ return crypto_aead_chacha20poly1305_NPUBBYTES;
+}
+
+size_t
+crypto_aead_chacha20poly1305_nsecbytes(void)
+{
+ return crypto_aead_chacha20poly1305_NSECBYTES;
+}
+
+size_t
+crypto_aead_chacha20poly1305_abytes(void)
+{
+ return crypto_aead_chacha20poly1305_ABYTES;
+}
+
+size_t
+crypto_aead_chacha20poly1305_messagebytes_max(void)
+{
+ return crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX;
+}
+
+void
+crypto_aead_chacha20poly1305_keygen(unsigned char k[crypto_aead_chacha20poly1305_KEYBYTES])
+{
+ randombytes_buf(k, crypto_aead_chacha20poly1305_KEYBYTES);
+}
diff --git a/libs/libsodium/src/crypto_aead/xchacha20poly1305/sodium/aead_xchacha20poly1305.c b/libs/libsodium/src/crypto_aead/xchacha20poly1305/sodium/aead_xchacha20poly1305.c
new file mode 100644
index 0000000000..c18cdf9458
--- /dev/null
+++ b/libs/libsodium/src/crypto_aead/xchacha20poly1305/sodium/aead_xchacha20poly1305.c
@@ -0,0 +1,160 @@
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+
+#include "core.h"
+#include "crypto_aead_xchacha20poly1305.h"
+#include "crypto_aead_chacha20poly1305.h"
+#include "crypto_core_hchacha20.h"
+#include "randombytes.h"
+#include "utils.h"
+
+#include "private/common.h"
+
+int
+crypto_aead_xchacha20poly1305_ietf_encrypt_detached(unsigned char *c,
+ unsigned char *mac,
+ unsigned long long *maclen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ unsigned char k2[crypto_core_hchacha20_OUTPUTBYTES];
+ unsigned char npub2[crypto_aead_chacha20poly1305_ietf_NPUBBYTES] = { 0 };
+ int ret;
+
+ crypto_core_hchacha20(k2, npub, k, NULL);
+ memcpy(npub2 + 4, npub + crypto_core_hchacha20_INPUTBYTES,
+ crypto_aead_chacha20poly1305_ietf_NPUBBYTES - 4);
+ ret = crypto_aead_chacha20poly1305_ietf_encrypt_detached
+ (c, mac, maclen_p, m, mlen, ad, adlen, nsec, npub2, k2);
+ sodium_memzero(k2, crypto_core_hchacha20_OUTPUTBYTES);
+
+ return ret;
+}
+
+int
+crypto_aead_xchacha20poly1305_ietf_encrypt(unsigned char *c,
+ unsigned long long *clen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ unsigned long long clen = 0ULL;
+ int ret;
+
+ if (mlen > UINT64_MAX - crypto_aead_xchacha20poly1305_ietf_ABYTES) {
+ sodium_misuse();
+ }
+ ret = crypto_aead_xchacha20poly1305_ietf_encrypt_detached
+ (c, c + mlen, NULL, m, mlen, ad, adlen, nsec, npub, k);
+ if (clen_p != NULL) {
+ if (ret == 0) {
+ clen = mlen + crypto_aead_xchacha20poly1305_ietf_ABYTES;
+ }
+ *clen_p = clen;
+ }
+ return ret;
+}
+
+int
+crypto_aead_xchacha20poly1305_ietf_decrypt_detached(unsigned char *m,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *mac,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ unsigned char k2[crypto_core_hchacha20_OUTPUTBYTES];
+ unsigned char npub2[crypto_aead_chacha20poly1305_ietf_NPUBBYTES] = { 0 };
+ int ret;
+
+ crypto_core_hchacha20(k2, npub, k, NULL);
+ memcpy(npub2 + 4, npub + crypto_core_hchacha20_INPUTBYTES,
+ crypto_aead_chacha20poly1305_ietf_NPUBBYTES - 4);
+ ret = crypto_aead_chacha20poly1305_ietf_decrypt_detached
+ (m, nsec, c, clen, mac, ad, adlen, npub2, k2);
+ sodium_memzero(k2, crypto_core_hchacha20_OUTPUTBYTES);
+
+ return ret;
+
+}
+
+int
+crypto_aead_xchacha20poly1305_ietf_decrypt(unsigned char *m,
+ unsigned long long *mlen_p,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const unsigned char *k)
+{
+ unsigned long long mlen = 0ULL;
+ int ret = -1;
+
+ if (clen >= crypto_aead_xchacha20poly1305_ietf_ABYTES) {
+ ret = crypto_aead_xchacha20poly1305_ietf_decrypt_detached
+ (m, nsec,
+ c, clen - crypto_aead_xchacha20poly1305_ietf_ABYTES,
+ c + clen - crypto_aead_xchacha20poly1305_ietf_ABYTES,
+ ad, adlen, npub, k);
+ }
+ if (mlen_p != NULL) {
+ if (ret == 0) {
+ mlen = clen - crypto_aead_xchacha20poly1305_ietf_ABYTES;
+ }
+ *mlen_p = mlen;
+ }
+ return ret;
+}
+
+size_t
+crypto_aead_xchacha20poly1305_ietf_keybytes(void)
+{
+ return crypto_aead_xchacha20poly1305_ietf_KEYBYTES;
+}
+
+size_t
+crypto_aead_xchacha20poly1305_ietf_npubbytes(void)
+{
+ return crypto_aead_xchacha20poly1305_ietf_NPUBBYTES;
+}
+
+size_t
+crypto_aead_xchacha20poly1305_ietf_nsecbytes(void)
+{
+ return crypto_aead_xchacha20poly1305_ietf_NSECBYTES;
+}
+
+size_t
+crypto_aead_xchacha20poly1305_ietf_abytes(void)
+{
+ return crypto_aead_xchacha20poly1305_ietf_ABYTES;
+}
+
+size_t
+crypto_aead_xchacha20poly1305_ietf_messagebytes_max(void)
+{
+ return crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX;
+}
+
+void
+crypto_aead_xchacha20poly1305_ietf_keygen(unsigned char k[crypto_aead_xchacha20poly1305_ietf_KEYBYTES])
+{
+ randombytes_buf(k, crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
+}
diff --git a/libs/libsodium/src/crypto_auth/crypto_auth.c b/libs/libsodium/src/crypto_auth/crypto_auth.c
new file mode 100644
index 0000000000..d061c8c1c5
--- /dev/null
+++ b/libs/libsodium/src/crypto_auth/crypto_auth.c
@@ -0,0 +1,41 @@
+
+#include "crypto_auth.h"
+#include "randombytes.h"
+
+size_t
+crypto_auth_bytes(void)
+{
+ return crypto_auth_BYTES;
+}
+
+size_t
+crypto_auth_keybytes(void)
+{
+ return crypto_auth_KEYBYTES;
+}
+
+const char *
+crypto_auth_primitive(void)
+{
+ return crypto_auth_PRIMITIVE;
+}
+
+int
+crypto_auth(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k)
+{
+ return crypto_auth_hmacsha512256(out, in, inlen, k);
+}
+
+int
+crypto_auth_verify(const unsigned char *h, const unsigned char *in,
+ unsigned long long inlen,const unsigned char *k)
+{
+ return crypto_auth_hmacsha512256_verify(h, in, inlen, k);
+}
+
+void
+crypto_auth_keygen(unsigned char k[crypto_auth_KEYBYTES])
+{
+ randombytes_buf(k, crypto_auth_KEYBYTES);
+}
diff --git a/libs/libsodium/src/crypto_auth/hmacsha256/auth_hmacsha256.c b/libs/libsodium/src/crypto_auth/hmacsha256/auth_hmacsha256.c
new file mode 100644
index 0000000000..a951e932b8
--- /dev/null
+++ b/libs/libsodium/src/crypto_auth/hmacsha256/auth_hmacsha256.c
@@ -0,0 +1,118 @@
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "crypto_auth_hmacsha256.h"
+#include "crypto_hash_sha256.h"
+#include "crypto_verify_32.h"
+#include "randombytes.h"
+#include "utils.h"
+
+size_t
+crypto_auth_hmacsha256_bytes(void)
+{
+ return crypto_auth_hmacsha256_BYTES;
+}
+
+size_t
+crypto_auth_hmacsha256_keybytes(void)
+{
+ return crypto_auth_hmacsha256_KEYBYTES;
+}
+
+size_t
+crypto_auth_hmacsha256_statebytes(void)
+{
+ return sizeof(crypto_auth_hmacsha256_state);
+}
+
+void
+crypto_auth_hmacsha256_keygen(unsigned char k[crypto_auth_hmacsha256_KEYBYTES])
+{
+ randombytes_buf(k, crypto_auth_hmacsha256_KEYBYTES);
+}
+
+int
+crypto_auth_hmacsha256_init(crypto_auth_hmacsha256_state *state,
+ const unsigned char *key, size_t keylen)
+{
+ unsigned char pad[64];
+ unsigned char khash[32];
+ size_t i;
+
+ if (keylen > 64) {
+ crypto_hash_sha256_init(&state->ictx);
+ crypto_hash_sha256_update(&state->ictx, key, keylen);
+ crypto_hash_sha256_final(&state->ictx, khash);
+ key = khash;
+ keylen = 32;
+ }
+ crypto_hash_sha256_init(&state->ictx);
+ memset(pad, 0x36, 64);
+ for (i = 0; i < keylen; i++) {
+ pad[i] ^= key[i];
+ }
+ crypto_hash_sha256_update(&state->ictx, pad, 64);
+
+ crypto_hash_sha256_init(&state->octx);
+ memset(pad, 0x5c, 64);
+ for (i = 0; i < keylen; i++) {
+ pad[i] ^= key[i];
+ }
+ crypto_hash_sha256_update(&state->octx, pad, 64);
+
+ sodium_memzero((void *) pad, sizeof pad);
+ sodium_memzero((void *) khash, sizeof khash);
+
+ return 0;
+}
+
+int
+crypto_auth_hmacsha256_update(crypto_auth_hmacsha256_state *state,
+ const unsigned char *in, unsigned long long inlen)
+{
+ crypto_hash_sha256_update(&state->ictx, in, inlen);
+
+ return 0;
+}
+
+int
+crypto_auth_hmacsha256_final(crypto_auth_hmacsha256_state *state,
+ unsigned char *out)
+{
+ unsigned char ihash[32];
+
+ crypto_hash_sha256_final(&state->ictx, ihash);
+ crypto_hash_sha256_update(&state->octx, ihash, 32);
+ crypto_hash_sha256_final(&state->octx, out);
+
+ sodium_memzero((void *) ihash, sizeof ihash);
+
+ return 0;
+}
+
+int
+crypto_auth_hmacsha256(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k)
+{
+ crypto_auth_hmacsha256_state state;
+
+ crypto_auth_hmacsha256_init(&state, k, crypto_auth_hmacsha256_KEYBYTES);
+ crypto_auth_hmacsha256_update(&state, in, inlen);
+ crypto_auth_hmacsha256_final(&state, out);
+
+ return 0;
+}
+
+int
+crypto_auth_hmacsha256_verify(const unsigned char *h, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k)
+{
+ unsigned char correct[32];
+
+ crypto_auth_hmacsha256(correct, in, inlen, k);
+
+ return crypto_verify_32(h, correct) | (-(h == correct)) |
+ sodium_memcmp(correct, h, 32);
+}
diff --git a/libs/libsodium/src/crypto_auth/hmacsha512/auth_hmacsha512.c b/libs/libsodium/src/crypto_auth/hmacsha512/auth_hmacsha512.c
new file mode 100644
index 0000000000..018d7a4e87
--- /dev/null
+++ b/libs/libsodium/src/crypto_auth/hmacsha512/auth_hmacsha512.c
@@ -0,0 +1,118 @@
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "crypto_auth_hmacsha512.h"
+#include "crypto_hash_sha512.h"
+#include "crypto_verify_64.h"
+#include "randombytes.h"
+#include "utils.h"
+
+size_t
+crypto_auth_hmacsha512_bytes(void)
+{
+ return crypto_auth_hmacsha512_BYTES;
+}
+
+size_t
+crypto_auth_hmacsha512_keybytes(void)
+{
+ return crypto_auth_hmacsha512_KEYBYTES;
+}
+
+size_t
+crypto_auth_hmacsha512_statebytes(void)
+{
+ return sizeof(crypto_auth_hmacsha512_state);
+}
+
+void
+crypto_auth_hmacsha512_keygen(unsigned char k[crypto_auth_hmacsha512_KEYBYTES])
+{
+ randombytes_buf(k, crypto_auth_hmacsha512_KEYBYTES);
+}
+
+int
+crypto_auth_hmacsha512_init(crypto_auth_hmacsha512_state *state,
+ const unsigned char *key, size_t keylen)
+{
+ unsigned char pad[128];
+ unsigned char khash[64];
+ size_t i;
+
+ if (keylen > 128) {
+ crypto_hash_sha512_init(&state->ictx);
+ crypto_hash_sha512_update(&state->ictx, key, keylen);
+ crypto_hash_sha512_final(&state->ictx, khash);
+ key = khash;
+ keylen = 64;
+ }
+ crypto_hash_sha512_init(&state->ictx);
+ memset(pad, 0x36, 128);
+ for (i = 0; i < keylen; i++) {
+ pad[i] ^= key[i];
+ }
+ crypto_hash_sha512_update(&state->ictx, pad, 128);
+
+ crypto_hash_sha512_init(&state->octx);
+ memset(pad, 0x5c, 128);
+ for (i = 0; i < keylen; i++) {
+ pad[i] ^= key[i];
+ }
+ crypto_hash_sha512_update(&state->octx, pad, 128);
+
+ sodium_memzero((void *) pad, sizeof pad);
+ sodium_memzero((void *) khash, sizeof khash);
+
+ return 0;
+}
+
+int
+crypto_auth_hmacsha512_update(crypto_auth_hmacsha512_state *state,
+ const unsigned char *in, unsigned long long inlen)
+{
+ crypto_hash_sha512_update(&state->ictx, in, inlen);
+
+ return 0;
+}
+
+int
+crypto_auth_hmacsha512_final(crypto_auth_hmacsha512_state *state,
+ unsigned char *out)
+{
+ unsigned char ihash[64];
+
+ crypto_hash_sha512_final(&state->ictx, ihash);
+ crypto_hash_sha512_update(&state->octx, ihash, 64);
+ crypto_hash_sha512_final(&state->octx, out);
+
+ sodium_memzero((void *) ihash, sizeof ihash);
+
+ return 0;
+}
+
+int
+crypto_auth_hmacsha512(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k)
+{
+ crypto_auth_hmacsha512_state state;
+
+ crypto_auth_hmacsha512_init(&state, k, crypto_auth_hmacsha512_KEYBYTES);
+ crypto_auth_hmacsha512_update(&state, in, inlen);
+ crypto_auth_hmacsha512_final(&state, out);
+
+ return 0;
+}
+
+int
+crypto_auth_hmacsha512_verify(const unsigned char *h, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k)
+{
+ unsigned char correct[64];
+
+ crypto_auth_hmacsha512(correct, in, inlen, k);
+
+ return crypto_verify_64(h, correct) | (-(h == correct)) |
+ sodium_memcmp(correct, h, 64);
+}
diff --git a/libs/libsodium/src/crypto_auth/hmacsha512256/auth_hmacsha512256.c b/libs/libsodium/src/crypto_auth/hmacsha512256/auth_hmacsha512256.c
new file mode 100644
index 0000000000..432d6dbee5
--- /dev/null
+++ b/libs/libsodium/src/crypto_auth/hmacsha512256/auth_hmacsha512256.c
@@ -0,0 +1,93 @@
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "crypto_auth_hmacsha512.h"
+#include "crypto_auth_hmacsha512256.h"
+#include "crypto_hash_sha512.h"
+#include "crypto_verify_32.h"
+#include "randombytes.h"
+#include "utils.h"
+
+size_t
+crypto_auth_hmacsha512256_bytes(void)
+{
+ return crypto_auth_hmacsha512256_BYTES;
+}
+
+size_t
+crypto_auth_hmacsha512256_keybytes(void)
+{
+ return crypto_auth_hmacsha512256_KEYBYTES;
+}
+
+size_t
+crypto_auth_hmacsha512256_statebytes(void)
+{
+ return sizeof(crypto_auth_hmacsha512256_state);
+}
+
+void
+crypto_auth_hmacsha512256_keygen(
+ unsigned char k[crypto_auth_hmacsha512256_KEYBYTES])
+{
+ randombytes_buf(k, crypto_auth_hmacsha512256_KEYBYTES);
+}
+
+int
+crypto_auth_hmacsha512256_init(crypto_auth_hmacsha512256_state *state,
+ const unsigned char *key, size_t keylen)
+{
+ return crypto_auth_hmacsha512_init((crypto_auth_hmacsha512_state *) state,
+ key, keylen);
+}
+
+int
+crypto_auth_hmacsha512256_update(crypto_auth_hmacsha512256_state *state,
+ const unsigned char *in,
+ unsigned long long inlen)
+{
+ return crypto_auth_hmacsha512_update((crypto_auth_hmacsha512_state *) state,
+ in, inlen);
+}
+
+int
+crypto_auth_hmacsha512256_final(crypto_auth_hmacsha512256_state *state,
+ unsigned char *out)
+{
+ unsigned char out0[64];
+
+ crypto_auth_hmacsha512_final((crypto_auth_hmacsha512_state *) state, out0);
+ memcpy(out, out0, 32);
+
+ return 0;
+}
+
+int
+crypto_auth_hmacsha512256(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k)
+{
+ crypto_auth_hmacsha512256_state state;
+
+ crypto_auth_hmacsha512256_init(&state, k,
+ crypto_auth_hmacsha512256_KEYBYTES);
+ crypto_auth_hmacsha512256_update(&state, in, inlen);
+ crypto_auth_hmacsha512256_final(&state, out);
+
+ return 0;
+}
+
+int
+crypto_auth_hmacsha512256_verify(const unsigned char *h,
+ const unsigned char *in,
+ unsigned long long inlen,
+ const unsigned char *k)
+{
+ unsigned char correct[32];
+
+ crypto_auth_hmacsha512256(correct, in, inlen, k);
+
+ return crypto_verify_32(h, correct) | (-(h == correct)) |
+ sodium_memcmp(correct, h, 32);
+}
diff --git a/libs/libsodium/src/crypto_box/crypto_box.c b/libs/libsodium/src/crypto_box/crypto_box.c
new file mode 100644
index 0000000000..7e4f00bd15
--- /dev/null
+++ b/libs/libsodium/src/crypto_box/crypto_box.c
@@ -0,0 +1,114 @@
+
+#include "crypto_box.h"
+
+size_t
+crypto_box_seedbytes(void)
+{
+ return crypto_box_SEEDBYTES;
+}
+
+size_t
+crypto_box_publickeybytes(void)
+{
+ return crypto_box_PUBLICKEYBYTES;
+}
+
+size_t
+crypto_box_secretkeybytes(void)
+{
+ return crypto_box_SECRETKEYBYTES;
+}
+
+size_t
+crypto_box_beforenmbytes(void)
+{
+ return crypto_box_BEFORENMBYTES;
+}
+
+size_t
+crypto_box_noncebytes(void)
+{
+ return crypto_box_NONCEBYTES;
+}
+
+size_t
+crypto_box_zerobytes(void)
+{
+ return crypto_box_ZEROBYTES;
+}
+
+size_t
+crypto_box_boxzerobytes(void)
+{
+ return crypto_box_BOXZEROBYTES;
+}
+
+size_t
+crypto_box_macbytes(void)
+{
+ return crypto_box_MACBYTES;
+}
+
+size_t
+crypto_box_messagebytes_max(void)
+{
+ return crypto_box_MESSAGEBYTES_MAX;
+}
+
+const char *
+crypto_box_primitive(void)
+{
+ return crypto_box_PRIMITIVE;
+}
+
+int
+crypto_box_seed_keypair(unsigned char *pk, unsigned char *sk,
+ const unsigned char *seed)
+{
+ return crypto_box_curve25519xsalsa20poly1305_seed_keypair(pk, sk, seed);
+}
+
+int
+crypto_box_keypair(unsigned char *pk, unsigned char *sk)
+{
+ return crypto_box_curve25519xsalsa20poly1305_keypair(pk, sk);
+}
+
+int
+crypto_box_beforenm(unsigned char *k, const unsigned char *pk,
+ const unsigned char *sk)
+{
+ return crypto_box_curve25519xsalsa20poly1305_beforenm(k, pk, sk);
+}
+
+int
+crypto_box_afternm(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k)
+{
+ return crypto_box_curve25519xsalsa20poly1305_afternm(c, m, mlen, n, k);
+}
+
+int
+crypto_box_open_afternm(unsigned char *m, const unsigned char *c,
+ unsigned long long clen, const unsigned char *n,
+ const unsigned char *k)
+{
+ return crypto_box_curve25519xsalsa20poly1305_open_afternm(m, c, clen, n, k);
+}
+
+int
+crypto_box(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *pk, const unsigned char *sk)
+{
+ return crypto_box_curve25519xsalsa20poly1305(c, m, mlen, n, pk, sk);
+}
+
+int
+crypto_box_open(unsigned char *m, const unsigned char *c,
+ unsigned long long clen, const unsigned char *n,
+ const unsigned char *pk, const unsigned char *sk)
+{
+ return crypto_box_curve25519xsalsa20poly1305_open(m, c, clen, n, pk, sk);
+}
diff --git a/libs/libsodium/src/crypto_box/crypto_box_easy.c b/libs/libsodium/src/crypto_box/crypto_box_easy.c
new file mode 100644
index 0000000000..deb40b4083
--- /dev/null
+++ b/libs/libsodium/src/crypto_box/crypto_box_easy.c
@@ -0,0 +1,115 @@
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "core.h"
+#include "crypto_box.h"
+#include "crypto_secretbox.h"
+#include "private/common.h"
+#include "utils.h"
+
+int
+crypto_box_detached_afternm(unsigned char *c, unsigned char *mac,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *n, const unsigned char *k)
+{
+ return crypto_secretbox_detached(c, mac, m, mlen, n, k);
+}
+
+int
+crypto_box_detached(unsigned char *c, unsigned char *mac,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *n, const unsigned char *pk,
+ const unsigned char *sk)
+{
+ unsigned char k[crypto_box_BEFORENMBYTES];
+ int ret;
+
+ COMPILER_ASSERT(crypto_box_BEFORENMBYTES >= crypto_secretbox_KEYBYTES);
+ if (crypto_box_beforenm(k, pk, sk) != 0) {
+ return -1;
+ }
+ ret = crypto_box_detached_afternm(c, mac, m, mlen, n, k);
+ sodium_memzero(k, sizeof k);
+
+ return ret;
+}
+
+int
+crypto_box_easy_afternm(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k)
+{
+ if (mlen > crypto_box_MESSAGEBYTES_MAX) {
+ sodium_misuse();
+ }
+ return crypto_box_detached_afternm(c + crypto_box_MACBYTES, c, m, mlen, n,
+ k);
+}
+
+int
+crypto_box_easy(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *pk, const unsigned char *sk)
+{
+ if (mlen > crypto_box_MESSAGEBYTES_MAX) {
+ sodium_misuse();
+ }
+ return crypto_box_detached(c + crypto_box_MACBYTES, c, m, mlen, n,
+ pk, sk);
+}
+
+int
+crypto_box_open_detached_afternm(unsigned char *m, const unsigned char *c,
+ const unsigned char *mac,
+ unsigned long long clen,
+ const unsigned char *n,
+ const unsigned char *k)
+{
+ return crypto_secretbox_open_detached(m, c, mac, clen, n, k);
+}
+
+int
+crypto_box_open_detached(unsigned char *m, const unsigned char *c,
+ const unsigned char *mac,
+ unsigned long long clen, const unsigned char *n,
+ const unsigned char *pk, const unsigned char *sk)
+{
+ unsigned char k[crypto_box_BEFORENMBYTES];
+ int ret;
+
+ if (crypto_box_beforenm(k, pk, sk) != 0) {
+ return -1;
+ }
+ ret = crypto_box_open_detached_afternm(m, c, mac, clen, n, k);
+ sodium_memzero(k, sizeof k);
+
+ return ret;
+}
+
+int
+crypto_box_open_easy_afternm(unsigned char *m, const unsigned char *c,
+ unsigned long long clen, const unsigned char *n,
+ const unsigned char *k)
+{
+ if (clen < crypto_box_MACBYTES) {
+ return -1;
+ }
+ return crypto_box_open_detached_afternm(m, c + crypto_box_MACBYTES, c,
+ clen - crypto_box_MACBYTES,
+ n, k);
+}
+
+int
+crypto_box_open_easy(unsigned char *m, const unsigned char *c,
+ unsigned long long clen, const unsigned char *n,
+ const unsigned char *pk, const unsigned char *sk)
+{
+ if (clen < crypto_box_MACBYTES) {
+ return -1;
+ }
+ return crypto_box_open_detached(m, c + crypto_box_MACBYTES, c,
+ clen - crypto_box_MACBYTES,
+ n, pk, sk);
+}
diff --git a/libs/libsodium/src/crypto_box/crypto_box_seal.c b/libs/libsodium/src/crypto_box/crypto_box_seal.c
new file mode 100644
index 0000000000..7181334578
--- /dev/null
+++ b/libs/libsodium/src/crypto_box/crypto_box_seal.c
@@ -0,0 +1,68 @@
+
+#include <string.h>
+
+#include "crypto_box.h"
+#include "crypto_generichash.h"
+#include "private/common.h"
+#include "utils.h"
+
+static int
+_crypto_box_seal_nonce(unsigned char *nonce,
+ const unsigned char *pk1, const unsigned char *pk2)
+{
+ crypto_generichash_state st;
+
+ crypto_generichash_init(&st, NULL, 0U, crypto_box_NONCEBYTES);
+ crypto_generichash_update(&st, pk1, crypto_box_PUBLICKEYBYTES);
+ crypto_generichash_update(&st, pk2, crypto_box_PUBLICKEYBYTES);
+ crypto_generichash_final(&st, nonce, crypto_box_NONCEBYTES);
+
+ return 0;
+}
+
+int
+crypto_box_seal(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *pk)
+{
+ unsigned char nonce[crypto_box_NONCEBYTES];
+ unsigned char epk[crypto_box_PUBLICKEYBYTES];
+ unsigned char esk[crypto_box_SECRETKEYBYTES];
+ int ret;
+
+ if (crypto_box_keypair(epk, esk) != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ memcpy(c, epk, crypto_box_PUBLICKEYBYTES);
+ _crypto_box_seal_nonce(nonce, epk, pk);
+ ret = crypto_box_easy(c + crypto_box_PUBLICKEYBYTES, m, mlen,
+ nonce, pk, esk);
+ sodium_memzero(esk, sizeof esk);
+ sodium_memzero(epk, sizeof epk);
+ sodium_memzero(nonce, sizeof nonce);
+
+ return ret;
+}
+
+int
+crypto_box_seal_open(unsigned char *m, const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *pk, const unsigned char *sk)
+{
+ unsigned char nonce[crypto_box_NONCEBYTES];
+
+ if (clen < crypto_box_SEALBYTES) {
+ return -1;
+ }
+ _crypto_box_seal_nonce(nonce, c, pk);
+
+ COMPILER_ASSERT(crypto_box_PUBLICKEYBYTES < crypto_box_SEALBYTES);
+ return crypto_box_open_easy(m, c + crypto_box_PUBLICKEYBYTES,
+ clen - crypto_box_PUBLICKEYBYTES,
+ nonce, c, sk);
+}
+
+size_t
+crypto_box_sealbytes(void)
+{
+ return crypto_box_SEALBYTES;
+}
diff --git a/libs/libsodium/src/crypto_box/curve25519xchacha20poly1305/box_curve25519xchacha20poly1305.c b/libs/libsodium/src/crypto_box/curve25519xchacha20poly1305/box_curve25519xchacha20poly1305.c
new file mode 100644
index 0000000000..5e2532eab7
--- /dev/null
+++ b/libs/libsodium/src/crypto_box/curve25519xchacha20poly1305/box_curve25519xchacha20poly1305.c
@@ -0,0 +1,204 @@
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "core.h"
+#include "crypto_box_curve25519xchacha20poly1305.h"
+#include "crypto_core_hchacha20.h"
+#include "crypto_hash_sha512.h"
+#include "crypto_scalarmult_curve25519.h"
+#include "crypto_secretbox_xchacha20poly1305.h"
+#include "private/common.h"
+#include "randombytes.h"
+#include "utils.h"
+
+int
+crypto_box_curve25519xchacha20poly1305_seed_keypair(unsigned char *pk,
+ unsigned char *sk,
+ const unsigned char *seed)
+{
+ unsigned char hash[64];
+
+ crypto_hash_sha512(hash, seed, 32);
+ memcpy(sk, hash, 32);
+ sodium_memzero(hash, sizeof hash);
+
+ return crypto_scalarmult_curve25519_base(pk, sk);
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_keypair(unsigned char *pk,
+ unsigned char *sk)
+{
+ randombytes_buf(sk, 32);
+
+ return crypto_scalarmult_curve25519_base(pk, sk);
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_beforenm(unsigned char *k,
+ const unsigned char *pk,
+ const unsigned char *sk)
+{
+ static const unsigned char zero[16] = { 0 };
+ unsigned char s[32];
+
+ if (crypto_scalarmult_curve25519(s, sk, pk) != 0) {
+ return -1;
+ }
+ return crypto_core_hchacha20(k, zero, s, NULL);
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_detached_afternm(
+ unsigned char *c, unsigned char *mac, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n, const unsigned char *k)
+{
+ return crypto_secretbox_xchacha20poly1305_detached(c, mac, m, mlen, n, k);
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_detached(
+ unsigned char *c, unsigned char *mac, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n, const unsigned char *pk,
+ const unsigned char *sk)
+{
+ unsigned char k[crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES];
+ int ret;
+
+ COMPILER_ASSERT(crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES >=
+ crypto_secretbox_xchacha20poly1305_KEYBYTES);
+ if (crypto_box_curve25519xchacha20poly1305_beforenm(k, pk, sk) != 0) {
+ return -1;
+ }
+ ret = crypto_box_curve25519xchacha20poly1305_detached_afternm(c, mac, m,
+ mlen, n, k);
+ sodium_memzero(k, sizeof k);
+
+ return ret;
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_easy_afternm(unsigned char *c,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n,
+ const unsigned char *k)
+{
+ if (mlen > crypto_box_curve25519xchacha20poly1305_MESSAGEBYTES_MAX) {
+ sodium_misuse();
+ }
+ return crypto_box_curve25519xchacha20poly1305_detached_afternm(
+ c + crypto_box_curve25519xchacha20poly1305_MACBYTES, c, m, mlen, n, k);
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_easy(
+ unsigned char *c, const unsigned char *m, unsigned long long mlen,
+ const unsigned char *n, const unsigned char *pk, const unsigned char *sk)
+{
+ if (mlen > crypto_box_curve25519xchacha20poly1305_MESSAGEBYTES_MAX) {
+ sodium_misuse();
+ }
+ return crypto_box_curve25519xchacha20poly1305_detached(
+ c + crypto_box_curve25519xchacha20poly1305_MACBYTES, c, m, mlen, n, pk,
+ sk);
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_open_detached_afternm(
+ unsigned char *m, const unsigned char *c, const unsigned char *mac,
+ unsigned long long clen, const unsigned char *n, const unsigned char *k)
+{
+ return crypto_secretbox_xchacha20poly1305_open_detached(m, c, mac, clen, n,
+ k);
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_open_detached(
+ unsigned char *m, const unsigned char *c, const unsigned char *mac,
+ unsigned long long clen, const unsigned char *n, const unsigned char *pk,
+ const unsigned char *sk)
+{
+ unsigned char k[crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES];
+ int ret;
+
+ if (crypto_box_curve25519xchacha20poly1305_beforenm(k, pk, sk) != 0) {
+ return -1;
+ }
+ ret = crypto_box_curve25519xchacha20poly1305_open_detached_afternm(
+ m, c, mac, clen, n, k);
+ sodium_memzero(k, sizeof k);
+
+ return ret;
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_open_easy_afternm(
+ unsigned char *m, const unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k)
+{
+ if (clen < crypto_box_curve25519xchacha20poly1305_MACBYTES) {
+ return -1;
+ }
+ return crypto_box_curve25519xchacha20poly1305_open_detached_afternm(
+ m, c + crypto_box_curve25519xchacha20poly1305_MACBYTES, c,
+ clen - crypto_box_curve25519xchacha20poly1305_MACBYTES, n, k);
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_open_easy(
+ unsigned char *m, const unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *pk, const unsigned char *sk)
+{
+ if (clen < crypto_box_curve25519xchacha20poly1305_MACBYTES) {
+ return -1;
+ }
+ return crypto_box_curve25519xchacha20poly1305_open_detached(
+ m, c + crypto_box_curve25519xchacha20poly1305_MACBYTES, c,
+ clen - crypto_box_curve25519xchacha20poly1305_MACBYTES, n, pk, sk);
+}
+
+size_t
+crypto_box_curve25519xchacha20poly1305_seedbytes(void)
+{
+ return crypto_box_curve25519xchacha20poly1305_SEEDBYTES;
+}
+
+size_t
+crypto_box_curve25519xchacha20poly1305_publickeybytes(void)
+{
+ return crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES;
+}
+
+size_t
+crypto_box_curve25519xchacha20poly1305_secretkeybytes(void)
+{
+ return crypto_box_curve25519xchacha20poly1305_SECRETKEYBYTES;
+}
+
+size_t
+crypto_box_curve25519xchacha20poly1305_beforenmbytes(void)
+{
+ return crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES;
+}
+
+size_t
+crypto_box_curve25519xchacha20poly1305_noncebytes(void)
+{
+ return crypto_box_curve25519xchacha20poly1305_NONCEBYTES;
+}
+
+size_t
+crypto_box_curve25519xchacha20poly1305_macbytes(void)
+{
+ return crypto_box_curve25519xchacha20poly1305_MACBYTES;
+}
+
+size_t
+crypto_box_curve25519xchacha20poly1305_messagebytes_max(void)
+{
+ return crypto_box_curve25519xchacha20poly1305_MESSAGEBYTES_MAX;
+}
diff --git a/libs/libsodium/src/crypto_box/curve25519xchacha20poly1305/box_seal_curve25519xchacha20poly1305.c b/libs/libsodium/src/crypto_box/curve25519xchacha20poly1305/box_seal_curve25519xchacha20poly1305.c
new file mode 100644
index 0000000000..9e73a265aa
--- /dev/null
+++ b/libs/libsodium/src/crypto_box/curve25519xchacha20poly1305/box_seal_curve25519xchacha20poly1305.c
@@ -0,0 +1,79 @@
+
+#include <string.h>
+
+#include "crypto_box_curve25519xchacha20poly1305.h"
+#include "crypto_generichash.h"
+#include "private/common.h"
+#include "utils.h"
+
+static int
+_crypto_box_curve25519xchacha20poly1305_seal_nonce(unsigned char *nonce,
+ const unsigned char *pk1,
+ const unsigned char *pk2)
+{
+ crypto_generichash_state st;
+
+ crypto_generichash_init(&st, NULL, 0U,
+ crypto_box_curve25519xchacha20poly1305_NONCEBYTES);
+ crypto_generichash_update(&st, pk1,
+ crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES);
+ crypto_generichash_update(&st, pk2,
+ crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES);
+ crypto_generichash_final(&st, nonce,
+ crypto_box_curve25519xchacha20poly1305_NONCEBYTES);
+
+ return 0;
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_seal(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *pk)
+{
+ unsigned char nonce[crypto_box_curve25519xchacha20poly1305_NONCEBYTES];
+ unsigned char epk[crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES];
+ unsigned char esk[crypto_box_curve25519xchacha20poly1305_SECRETKEYBYTES];
+ int ret;
+
+ if (crypto_box_curve25519xchacha20poly1305_keypair(epk, esk) != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ memcpy(c, epk, crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES);
+ _crypto_box_curve25519xchacha20poly1305_seal_nonce(nonce, epk, pk);
+ ret = crypto_box_curve25519xchacha20poly1305_easy(
+ c + crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES, m, mlen,
+ nonce, pk, esk);
+ sodium_memzero(esk, sizeof esk);
+ sodium_memzero(epk, sizeof epk);
+ sodium_memzero(nonce, sizeof nonce);
+
+ return ret;
+}
+
+int
+crypto_box_curve25519xchacha20poly1305_seal_open(unsigned char *m, const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *pk,
+ const unsigned char *sk)
+{
+ unsigned char nonce[crypto_box_curve25519xchacha20poly1305_NONCEBYTES];
+
+ if (clen < crypto_box_curve25519xchacha20poly1305_SEALBYTES) {
+ return -1;
+ }
+ _crypto_box_curve25519xchacha20poly1305_seal_nonce(nonce, c, pk);
+
+ COMPILER_ASSERT(crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES <
+ crypto_box_curve25519xchacha20poly1305_SEALBYTES);
+
+ return crypto_box_curve25519xchacha20poly1305_open_easy(
+ m, c + crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES,
+ clen - crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES,
+ nonce, c, sk);
+}
+
+size_t
+crypto_box_curve25519xchacha20poly1305_sealbytes(void)
+{
+ return crypto_box_curve25519xchacha20poly1305_SEALBYTES;
+}
diff --git a/libs/libsodium/src/crypto_box/curve25519xsalsa20poly1305/box_curve25519xsalsa20poly1305.c b/libs/libsodium/src/crypto_box/curve25519xsalsa20poly1305/box_curve25519xsalsa20poly1305.c
new file mode 100644
index 0000000000..4c1d62ed43
--- /dev/null
+++ b/libs/libsodium/src/crypto_box/curve25519xsalsa20poly1305/box_curve25519xsalsa20poly1305.c
@@ -0,0 +1,156 @@
+#include <string.h>
+
+#include "crypto_box_curve25519xsalsa20poly1305.h"
+#include "crypto_core_hsalsa20.h"
+#include "crypto_hash_sha512.h"
+#include "crypto_scalarmult_curve25519.h"
+#include "crypto_secretbox_xsalsa20poly1305.h"
+#include "randombytes.h"
+#include "utils.h"
+
+int
+crypto_box_curve25519xsalsa20poly1305_seed_keypair(unsigned char *pk,
+ unsigned char *sk,
+ const unsigned char *seed)
+{
+ unsigned char hash[64];
+
+ crypto_hash_sha512(hash, seed, 32);
+ memcpy(sk, hash, 32);
+ sodium_memzero(hash, sizeof hash);
+
+ return crypto_scalarmult_curve25519_base(pk, sk);
+}
+
+int
+crypto_box_curve25519xsalsa20poly1305_keypair(unsigned char *pk,
+ unsigned char *sk)
+{
+ randombytes_buf(sk, 32);
+
+ return crypto_scalarmult_curve25519_base(pk, sk);
+}
+
+int
+crypto_box_curve25519xsalsa20poly1305_beforenm(unsigned char *k,
+ const unsigned char *pk,
+ const unsigned char *sk)
+{
+ static const unsigned char zero[16] = { 0 };
+ unsigned char s[32];
+
+ if (crypto_scalarmult_curve25519(s, sk, pk) != 0) {
+ return -1;
+ }
+ return crypto_core_hsalsa20(k, zero, s, NULL);
+}
+
+int
+crypto_box_curve25519xsalsa20poly1305_afternm(unsigned char *c,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n,
+ const unsigned char *k)
+{
+ return crypto_secretbox_xsalsa20poly1305(c, m, mlen, n, k);
+}
+
+int
+crypto_box_curve25519xsalsa20poly1305_open_afternm(unsigned char *m,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *n,
+ const unsigned char *k)
+{
+ return crypto_secretbox_xsalsa20poly1305_open(m, c, clen, n, k);
+}
+
+int
+crypto_box_curve25519xsalsa20poly1305(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n,
+ const unsigned char *pk,
+ const unsigned char *sk)
+{
+ unsigned char k[crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES];
+ int ret;
+
+ if (crypto_box_curve25519xsalsa20poly1305_beforenm(k, pk, sk) != 0) {
+ return -1;
+ }
+ ret = crypto_box_curve25519xsalsa20poly1305_afternm(c, m, mlen, n, k);
+ sodium_memzero(k, sizeof k);
+
+ return ret;
+}
+
+int
+crypto_box_curve25519xsalsa20poly1305_open(
+ unsigned char *m, const unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *pk, const unsigned char *sk)
+{
+ unsigned char k[crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES];
+ int ret;
+
+ if (crypto_box_curve25519xsalsa20poly1305_beforenm(k, pk, sk) != 0) {
+ return -1;
+ }
+ ret = crypto_box_curve25519xsalsa20poly1305_open_afternm(m, c, clen, n, k);
+ sodium_memzero(k, sizeof k);
+
+ return ret;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_seedbytes(void)
+{
+ return crypto_box_curve25519xsalsa20poly1305_SEEDBYTES;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_publickeybytes(void)
+{
+ return crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_secretkeybytes(void)
+{
+ return crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_beforenmbytes(void)
+{
+ return crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_noncebytes(void)
+{
+ return crypto_box_curve25519xsalsa20poly1305_NONCEBYTES;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_zerobytes(void)
+{
+ return crypto_box_curve25519xsalsa20poly1305_ZEROBYTES;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_boxzerobytes(void)
+{
+ return crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_macbytes(void)
+{
+ return crypto_box_curve25519xsalsa20poly1305_MACBYTES;
+}
+
+size_t
+crypto_box_curve25519xsalsa20poly1305_messagebytes_max(void)
+{
+ return crypto_box_curve25519xsalsa20poly1305_MESSAGEBYTES_MAX;
+}
diff --git a/libs/libsodium/src/crypto_core/ed25519/core_ed25519.c b/libs/libsodium/src/crypto_core/ed25519/core_ed25519.c
new file mode 100644
index 0000000000..1bcf5022b1
--- /dev/null
+++ b/libs/libsodium/src/crypto_core/ed25519/core_ed25519.c
@@ -0,0 +1,79 @@
+
+#include "crypto_core_ed25519.h"
+#include "private/common.h"
+#include "private/ed25519_ref10.h"
+
+int
+crypto_core_ed25519_is_valid_point(const unsigned char *p)
+{
+ ge25519_p3 p_p3;
+
+ if (ge25519_is_canonical(p) == 0 ||
+ ge25519_has_small_order(p) != 0 ||
+ ge25519_frombytes(&p_p3, p) != 0 ||
+ ge25519_is_on_curve(&p_p3) == 0 ||
+ ge25519_is_on_main_subgroup(&p_p3) == 0) {
+ return 0;
+ }
+ return 1;
+}
+
+int
+crypto_core_ed25519_add(unsigned char *r,
+ const unsigned char *p, const unsigned char *q)
+{
+ ge25519_p3 p_p3, q_p3, r_p3;
+ ge25519_p1p1 r_p1p1;
+ ge25519_cached q_cached;
+
+ if (ge25519_frombytes(&p_p3, p) != 0 || ge25519_is_on_curve(&p_p3) == 0 ||
+ ge25519_frombytes(&q_p3, q) != 0 || ge25519_is_on_curve(&q_p3) == 0) {
+ return -1;
+ }
+ ge25519_p3_to_cached(&q_cached, &q_p3);
+ ge25519_add(&r_p1p1, &p_p3, &q_cached);
+ ge25519_p1p1_to_p3(&r_p3, &r_p1p1);
+ ge25519_p3_tobytes(r, &r_p3);
+
+ return 0;
+}
+
+int
+crypto_core_ed25519_sub(unsigned char *r,
+ const unsigned char *p, const unsigned char *q)
+{
+ ge25519_p3 p_p3, q_p3, r_p3;
+ ge25519_p1p1 r_p1p1;
+ ge25519_cached q_cached;
+
+ if (ge25519_frombytes(&p_p3, p) != 0 || ge25519_is_on_curve(&p_p3) == 0 ||
+ ge25519_frombytes(&q_p3, q) != 0 || ge25519_is_on_curve(&q_p3) == 0) {
+ return -1;
+ }
+ ge25519_p3_to_cached(&q_cached, &q_p3);
+ ge25519_sub(&r_p1p1, &p_p3, &q_cached);
+ ge25519_p1p1_to_p3(&r_p3, &r_p1p1);
+ ge25519_p3_tobytes(r, &r_p3);
+
+ return 0;
+}
+
+int
+crypto_core_ed25519_from_uniform(unsigned char *p, const unsigned char *r)
+{
+ ge25519_from_uniform(p, r);
+
+ return - ge25519_has_small_order(p);
+}
+
+size_t
+crypto_core_ed25519_bytes(void)
+{
+ return crypto_core_ed25519_BYTES;
+}
+
+size_t
+crypto_core_ed25519_uniformbytes(void)
+{
+ return crypto_core_ed25519_UNIFORMBYTES;
+}
diff --git a/libs/libsodium/src/crypto_core/ed25519/ref10/ed25519_ref10.c b/libs/libsodium/src/crypto_core/ed25519/ref10/ed25519_ref10.c
new file mode 100644
index 0000000000..f7b8280685
--- /dev/null
+++ b/libs/libsodium/src/crypto_core/ed25519/ref10/ed25519_ref10.c
@@ -0,0 +1,2031 @@
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "crypto_verify_32.h"
+#include "private/common.h"
+#include "private/ed25519_ref10.h"
+#include "utils.h"
+
+static inline uint64_t
+load_3(const unsigned char *in)
+{
+ uint64_t result;
+
+ result = (uint64_t) in[0];
+ result |= ((uint64_t) in[1]) << 8;
+ result |= ((uint64_t) in[2]) << 16;
+
+ return result;
+}
+
+static inline uint64_t
+load_4(const unsigned char *in)
+{
+ uint64_t result;
+
+ result = (uint64_t) in[0];
+ result |= ((uint64_t) in[1]) << 8;
+ result |= ((uint64_t) in[2]) << 16;
+ result |= ((uint64_t) in[3]) << 24;
+
+ return result;
+}
+
+/*
+ * Field arithmetic:
+ * Use 5*51 bit limbs on 64-bit systems with support for 128 bit arithmetic,
+ * and 10*25.5 bit limbs elsewhere.
+ *
+ * Functions used elsewhere that are candidates for inlining are defined
+ * via "private/curve25519_ref10.h".
+ */
+
+#ifdef HAVE_TI_MODE
+# include "fe_51/constants.h"
+# include "fe_51/fe.h"
+#else
+# include "fe_25_5/constants.h"
+# include "fe_25_5/fe.h"
+#endif
+
+void
+fe25519_invert(fe25519 out, const fe25519 z)
+{
+ fe25519 t0;
+ fe25519 t1;
+ fe25519 t2;
+ fe25519 t3;
+ int i;
+
+ fe25519_sq(t0, z);
+ fe25519_sq(t1, t0);
+ fe25519_sq(t1, t1);
+ fe25519_mul(t1, z, t1);
+ fe25519_mul(t0, t0, t1);
+ fe25519_sq(t2, t0);
+ fe25519_mul(t1, t1, t2);
+ fe25519_sq(t2, t1);
+ for (i = 1; i < 5; ++i) {
+ fe25519_sq(t2, t2);
+ }
+ fe25519_mul(t1, t2, t1);
+ fe25519_sq(t2, t1);
+ for (i = 1; i < 10; ++i) {
+ fe25519_sq(t2, t2);
+ }
+ fe25519_mul(t2, t2, t1);
+ fe25519_sq(t3, t2);
+ for (i = 1; i < 20; ++i) {
+ fe25519_sq(t3, t3);
+ }
+ fe25519_mul(t2, t3, t2);
+ fe25519_sq(t2, t2);
+ for (i = 1; i < 10; ++i) {
+ fe25519_sq(t2, t2);
+ }
+ fe25519_mul(t1, t2, t1);
+ fe25519_sq(t2, t1);
+ for (i = 1; i < 50; ++i) {
+ fe25519_sq(t2, t2);
+ }
+ fe25519_mul(t2, t2, t1);
+ fe25519_sq(t3, t2);
+ for (i = 1; i < 100; ++i) {
+ fe25519_sq(t3, t3);
+ }
+ fe25519_mul(t2, t3, t2);
+ fe25519_sq(t2, t2);
+ for (i = 1; i < 50; ++i) {
+ fe25519_sq(t2, t2);
+ }
+ fe25519_mul(t1, t2, t1);
+ fe25519_sq(t1, t1);
+ for (i = 1; i < 5; ++i) {
+ fe25519_sq(t1, t1);
+ }
+ fe25519_mul(out, t1, t0);
+}
+
+static void
+fe25519_pow22523(fe25519 out, const fe25519 z)
+{
+ fe25519 t0;
+ fe25519 t1;
+ fe25519 t2;
+ int i;
+
+ fe25519_sq(t0, z);
+ fe25519_sq(t1, t0);
+ fe25519_sq(t1, t1);
+ fe25519_mul(t1, z, t1);
+ fe25519_mul(t0, t0, t1);
+ fe25519_sq(t0, t0);
+ fe25519_mul(t0, t1, t0);
+ fe25519_sq(t1, t0);
+ for (i = 1; i < 5; ++i) {
+ fe25519_sq(t1, t1);
+ }
+ fe25519_mul(t0, t1, t0);
+ fe25519_sq(t1, t0);
+ for (i = 1; i < 10; ++i) {
+ fe25519_sq(t1, t1);
+ }
+ fe25519_mul(t1, t1, t0);
+ fe25519_sq(t2, t1);
+ for (i = 1; i < 20; ++i) {
+ fe25519_sq(t2, t2);
+ }
+ fe25519_mul(t1, t2, t1);
+ fe25519_sq(t1, t1);
+ for (i = 1; i < 10; ++i) {
+ fe25519_sq(t1, t1);
+ }
+ fe25519_mul(t0, t1, t0);
+ fe25519_sq(t1, t0);
+ for (i = 1; i < 50; ++i) {
+ fe25519_sq(t1, t1);
+ }
+ fe25519_mul(t1, t1, t0);
+ fe25519_sq(t2, t1);
+ for (i = 1; i < 100; ++i) {
+ fe25519_sq(t2, t2);
+ }
+ fe25519_mul(t1, t2, t1);
+ fe25519_sq(t1, t1);
+ for (i = 1; i < 50; ++i) {
+ fe25519_sq(t1, t1);
+ }
+ fe25519_mul(t0, t1, t0);
+ fe25519_sq(t0, t0);
+ fe25519_sq(t0, t0);
+ fe25519_mul(out, t0, z);
+}
+
+/*
+ r = p + q
+ */
+
+void
+ge25519_add(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_cached *q)
+{
+ fe25519 t0;
+
+ fe25519_add(r->X, p->Y, p->X);
+ fe25519_sub(r->Y, p->Y, p->X);
+ fe25519_mul(r->Z, r->X, q->YplusX);
+ fe25519_mul(r->Y, r->Y, q->YminusX);
+ fe25519_mul(r->T, q->T2d, p->T);
+ fe25519_mul(r->X, p->Z, q->Z);
+ fe25519_add(t0, r->X, r->X);
+ fe25519_sub(r->X, r->Z, r->Y);
+ fe25519_add(r->Y, r->Z, r->Y);
+ fe25519_add(r->Z, t0, r->T);
+ fe25519_sub(r->T, t0, r->T);
+}
+
+static void
+slide_vartime(signed char *r, const unsigned char *a)
+{
+ int i;
+ int b;
+ int k;
+ int ribs;
+ int cmp;
+
+ for (i = 0; i < 256; ++i) {
+ r[i] = 1 & (a[i >> 3] >> (i & 7));
+ }
+ for (i = 0; i < 256; ++i) {
+ if (! r[i]) {
+ continue;
+ }
+ for (b = 1; b <= 6 && i + b < 256; ++b) {
+ if (! r[i + b]) {
+ continue;
+ }
+ ribs = r[i + b] << b;
+ cmp = r[i] + ribs;
+ if (cmp <= 15) {
+ r[i] = cmp;
+ r[i + b] = 0;
+ } else {
+ cmp = r[i] - ribs;
+ if (cmp < -15) {
+ break;
+ }
+ r[i] = cmp;
+ for (k = i + b; k < 256; ++k) {
+ if (! r[k]) {
+ r[k] = 1;
+ break;
+ }
+ r[k] = 0;
+ }
+ }
+ }
+ }
+}
+
+int
+ge25519_frombytes(ge25519_p3 *h, const unsigned char *s)
+{
+ fe25519 u;
+ fe25519 v;
+ fe25519 v3;
+ fe25519 vxx;
+ fe25519 m_root_check, p_root_check;
+ fe25519 negx;
+ fe25519 x_sqrtm1;
+ int has_m_root, has_p_root;
+
+ fe25519_frombytes(h->Y, s);
+ fe25519_1(h->Z);
+ fe25519_sq(u, h->Y);
+ fe25519_mul(v, u, d);
+ fe25519_sub(u, u, h->Z); /* u = y^2-1 */
+ fe25519_add(v, v, h->Z); /* v = dy^2+1 */
+
+ fe25519_sq(v3, v);
+ fe25519_mul(v3, v3, v); /* v3 = v^3 */
+ fe25519_sq(h->X, v3);
+ fe25519_mul(h->X, h->X, v);
+ fe25519_mul(h->X, h->X, u); /* x = uv^7 */
+
+ fe25519_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */
+ fe25519_mul(h->X, h->X, v3);
+ fe25519_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */
+
+ fe25519_sq(vxx, h->X);
+ fe25519_mul(vxx, vxx, v);
+ fe25519_sub(m_root_check, vxx, u); /* vx^2-u */
+ fe25519_add(p_root_check, vxx, u); /* vx^2+u */
+ has_m_root = fe25519_iszero(m_root_check);
+ has_p_root = fe25519_iszero(p_root_check);
+ fe25519_mul(x_sqrtm1, h->X, sqrtm1); /* x*sqrt(-1) */
+ fe25519_cmov(h->X, x_sqrtm1, 1 - has_m_root);
+
+ fe25519_neg(negx, h->X);
+ fe25519_cmov(h->X, negx, fe25519_isnegative(h->X) ^ (s[31] >> 7));
+ fe25519_mul(h->T, h->X, h->Y);
+
+ return (has_m_root | has_p_root) - 1;
+}
+
+int
+ge25519_frombytes_negate_vartime(ge25519_p3 *h, const unsigned char *s)
+{
+ fe25519 u;
+ fe25519 v;
+ fe25519 v3;
+ fe25519 vxx;
+ fe25519 m_root_check, p_root_check;
+
+ fe25519_frombytes(h->Y, s);
+ fe25519_1(h->Z);
+ fe25519_sq(u, h->Y);
+ fe25519_mul(v, u, d);
+ fe25519_sub(u, u, h->Z); /* u = y^2-1 */
+ fe25519_add(v, v, h->Z); /* v = dy^2+1 */
+
+ fe25519_sq(v3, v);
+ fe25519_mul(v3, v3, v); /* v3 = v^3 */
+ fe25519_sq(h->X, v3);
+ fe25519_mul(h->X, h->X, v);
+ fe25519_mul(h->X, h->X, u); /* x = uv^7 */
+
+ fe25519_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */
+ fe25519_mul(h->X, h->X, v3);
+ fe25519_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */
+
+ fe25519_sq(vxx, h->X);
+ fe25519_mul(vxx, vxx, v);
+ fe25519_sub(m_root_check, vxx, u); /* vx^2-u */
+ if (fe25519_iszero(m_root_check) == 0) {
+ fe25519_add(p_root_check, vxx, u); /* vx^2+u */
+ if (fe25519_iszero(p_root_check) == 0) {
+ return -1;
+ }
+ fe25519_mul(h->X, h->X, sqrtm1);
+ }
+
+ if (fe25519_isnegative(h->X) == (s[31] >> 7)) {
+ fe25519_neg(h->X, h->X);
+ }
+ fe25519_mul(h->T, h->X, h->Y);
+
+ return 0;
+}
+
+/*
+ r = p + q
+ */
+
+static void
+ge25519_madd(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_precomp *q)
+{
+ fe25519 t0;
+
+ fe25519_add(r->X, p->Y, p->X);
+ fe25519_sub(r->Y, p->Y, p->X);
+ fe25519_mul(r->Z, r->X, q->yplusx);
+ fe25519_mul(r->Y, r->Y, q->yminusx);
+ fe25519_mul(r->T, q->xy2d, p->T);
+ fe25519_add(t0, p->Z, p->Z);
+ fe25519_sub(r->X, r->Z, r->Y);
+ fe25519_add(r->Y, r->Z, r->Y);
+ fe25519_add(r->Z, t0, r->T);
+ fe25519_sub(r->T, t0, r->T);
+}
+
+/*
+ r = p - q
+ */
+
+static void
+ge25519_msub(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_precomp *q)
+{
+ fe25519 t0;
+
+ fe25519_add(r->X, p->Y, p->X);
+ fe25519_sub(r->Y, p->Y, p->X);
+ fe25519_mul(r->Z, r->X, q->yminusx);
+ fe25519_mul(r->Y, r->Y, q->yplusx);
+ fe25519_mul(r->T, q->xy2d, p->T);
+ fe25519_add(t0, p->Z, p->Z);
+ fe25519_sub(r->X, r->Z, r->Y);
+ fe25519_add(r->Y, r->Z, r->Y);
+ fe25519_sub(r->Z, t0, r->T);
+ fe25519_add(r->T, t0, r->T);
+}
+
+/*
+ r = p
+ */
+
+void
+ge25519_p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p)
+{
+ fe25519_mul(r->X, p->X, p->T);
+ fe25519_mul(r->Y, p->Y, p->Z);
+ fe25519_mul(r->Z, p->Z, p->T);
+}
+
+/*
+ r = p
+ */
+
+void
+ge25519_p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p)
+{
+ fe25519_mul(r->X, p->X, p->T);
+ fe25519_mul(r->Y, p->Y, p->Z);
+ fe25519_mul(r->Z, p->Z, p->T);
+ fe25519_mul(r->T, p->X, p->Y);
+}
+
+static void
+ge25519_p2_0(ge25519_p2 *h)
+{
+ fe25519_0(h->X);
+ fe25519_1(h->Y);
+ fe25519_1(h->Z);
+}
+
+/*
+ r = 2 * p
+ */
+
+static void
+ge25519_p2_dbl(ge25519_p1p1 *r, const ge25519_p2 *p)
+{
+ fe25519 t0;
+
+ fe25519_sq(r->X, p->X);
+ fe25519_sq(r->Z, p->Y);
+ fe25519_sq2(r->T, p->Z);
+ fe25519_add(r->Y, p->X, p->Y);
+ fe25519_sq(t0, r->Y);
+ fe25519_add(r->Y, r->Z, r->X);
+ fe25519_sub(r->Z, r->Z, r->X);
+ fe25519_sub(r->X, t0, r->Y);
+ fe25519_sub(r->T, r->T, r->Z);
+}
+
+static void
+ge25519_p3_0(ge25519_p3 *h)
+{
+ fe25519_0(h->X);
+ fe25519_1(h->Y);
+ fe25519_1(h->Z);
+ fe25519_0(h->T);
+}
+
+static void
+ge25519_cached_0(ge25519_cached *h)
+{
+ fe25519_1(h->YplusX);
+ fe25519_1(h->YminusX);
+ fe25519_1(h->Z);
+ fe25519_0(h->T2d);
+}
+
+/*
+ r = p
+ */
+
+void
+ge25519_p3_to_cached(ge25519_cached *r, const ge25519_p3 *p)
+{
+ fe25519_add(r->YplusX, p->Y, p->X);
+ fe25519_sub(r->YminusX, p->Y, p->X);
+ fe25519_copy(r->Z, p->Z);
+ fe25519_mul(r->T2d, p->T, d2);
+}
+
+static void
+ge25519_p3_to_precomp(ge25519_precomp *pi, const ge25519_p3 *p)
+{
+ fe25519 recip;
+ fe25519 x;
+ fe25519 y;
+ fe25519 xy;
+
+ fe25519_invert(recip, p->Z);
+ fe25519_mul(x, p->X, recip);
+ fe25519_mul(y, p->Y, recip);
+ fe25519_add(pi->yplusx, y, x);
+ fe25519_sub(pi->yminusx, y, x);
+ fe25519_mul(xy, x, y);
+ fe25519_mul(pi->xy2d, xy, d2);
+}
+
+/*
+ r = p
+ */
+
+static void
+ge25519_p3_to_p2(ge25519_p2 *r, const ge25519_p3 *p)
+{
+ fe25519_copy(r->X, p->X);
+ fe25519_copy(r->Y, p->Y);
+ fe25519_copy(r->Z, p->Z);
+}
+
+void
+ge25519_p3_tobytes(unsigned char *s, const ge25519_p3 *h)
+{
+ fe25519 recip;
+ fe25519 x;
+ fe25519 y;
+
+ fe25519_invert(recip, h->Z);
+ fe25519_mul(x, h->X, recip);
+ fe25519_mul(y, h->Y, recip);
+ fe25519_tobytes(s, y);
+ s[31] ^= fe25519_isnegative(x) << 7;
+}
+
+/*
+ r = 2 * p
+ */
+
+static void
+ge25519_p3_dbl(ge25519_p1p1 *r, const ge25519_p3 *p)
+{
+ ge25519_p2 q;
+ ge25519_p3_to_p2(&q, p);
+ ge25519_p2_dbl(r, &q);
+}
+
+static void
+ge25519_precomp_0(ge25519_precomp *h)
+{
+ fe25519_1(h->yplusx);
+ fe25519_1(h->yminusx);
+ fe25519_0(h->xy2d);
+}
+
+static unsigned char
+equal(signed char b, signed char c)
+{
+ unsigned char ub = b;
+ unsigned char uc = c;
+ unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */
+ uint32_t y = x; /* 0: yes; 1..255: no */
+
+ y -= 1; /* 4294967295: yes; 0..254: no */
+ y >>= 31; /* 1: yes; 0: no */
+
+ return y;
+}
+
+static unsigned char
+negative(signed char b)
+{
+ /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
+ uint64_t x = b;
+
+ x >>= 63; /* 1: yes; 0: no */
+
+ return x;
+}
+
+static void
+ge25519_cmov(ge25519_precomp *t, const ge25519_precomp *u, unsigned char b)
+{
+ fe25519_cmov(t->yplusx, u->yplusx, b);
+ fe25519_cmov(t->yminusx, u->yminusx, b);
+ fe25519_cmov(t->xy2d, u->xy2d, b);
+}
+
+static void
+ge25519_cmov_cached(ge25519_cached *t, const ge25519_cached *u, unsigned char b)
+{
+ fe25519_cmov(t->YplusX, u->YplusX, b);
+ fe25519_cmov(t->YminusX, u->YminusX, b);
+ fe25519_cmov(t->Z, u->Z, b);
+ fe25519_cmov(t->T2d, u->T2d, b);
+}
+
+static void
+ge25519_select(ge25519_precomp *t, const ge25519_precomp precomp[8], const signed char b)
+{
+ ge25519_precomp minust;
+ const unsigned char bnegative = negative(b);
+ const unsigned char babs = b - (((-bnegative) & b) * ((signed char) 1 << 1));
+
+ ge25519_precomp_0(t);
+ ge25519_cmov(t, &precomp[0], equal(babs, 1));
+ ge25519_cmov(t, &precomp[1], equal(babs, 2));
+ ge25519_cmov(t, &precomp[2], equal(babs, 3));
+ ge25519_cmov(t, &precomp[3], equal(babs, 4));
+ ge25519_cmov(t, &precomp[4], equal(babs, 5));
+ ge25519_cmov(t, &precomp[5], equal(babs, 6));
+ ge25519_cmov(t, &precomp[6], equal(babs, 7));
+ ge25519_cmov(t, &precomp[7], equal(babs, 8));
+ fe25519_copy(minust.yplusx, t->yminusx);
+ fe25519_copy(minust.yminusx, t->yplusx);
+ fe25519_neg(minust.xy2d, t->xy2d);
+ ge25519_cmov(t, &minust, bnegative);
+}
+
+static void
+ge25519_select_base(ge25519_precomp *t, const int pos, const signed char b)
+{
+ static const ge25519_precomp base[32][8] = { /* base[i][j] = (j+1)*256^i*B */
+#ifdef HAVE_TI_MODE
+# include "fe_51/base.h"
+#else
+# include "fe_25_5/base.h"
+#endif
+ };
+ ge25519_select(t, base[pos], b);
+}
+
+static void
+ge25519_select_cached(ge25519_cached *t, const ge25519_cached cached[8], const signed char b)
+{
+ ge25519_cached minust;
+ const unsigned char bnegative = negative(b);
+ const unsigned char babs = b - (((-bnegative) & b) * ((signed char) 1 << 1));
+
+ ge25519_cached_0(t);
+ ge25519_cmov_cached(t, &cached[0], equal(babs, 1));
+ ge25519_cmov_cached(t, &cached[1], equal(babs, 2));
+ ge25519_cmov_cached(t, &cached[2], equal(babs, 3));
+ ge25519_cmov_cached(t, &cached[3], equal(babs, 4));
+ ge25519_cmov_cached(t, &cached[4], equal(babs, 5));
+ ge25519_cmov_cached(t, &cached[5], equal(babs, 6));
+ ge25519_cmov_cached(t, &cached[6], equal(babs, 7));
+ ge25519_cmov_cached(t, &cached[7], equal(babs, 8));
+ fe25519_copy(minust.YplusX, t->YminusX);
+ fe25519_copy(minust.YminusX, t->YplusX);
+ fe25519_copy(minust.Z, t->Z);
+ fe25519_neg(minust.T2d, t->T2d);
+ ge25519_cmov_cached(t, &minust, bnegative);
+}
+
+/*
+ r = p - q
+ */
+
+void
+ge25519_sub(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_cached *q)
+{
+ fe25519 t0;
+
+ fe25519_add(r->X, p->Y, p->X);
+ fe25519_sub(r->Y, p->Y, p->X);
+ fe25519_mul(r->Z, r->X, q->YminusX);
+ fe25519_mul(r->Y, r->Y, q->YplusX);
+ fe25519_mul(r->T, q->T2d, p->T);
+ fe25519_mul(r->X, p->Z, q->Z);
+ fe25519_add(t0, r->X, r->X);
+ fe25519_sub(r->X, r->Z, r->Y);
+ fe25519_add(r->Y, r->Z, r->Y);
+ fe25519_sub(r->Z, t0, r->T);
+ fe25519_add(r->T, t0, r->T);
+}
+
+void
+ge25519_tobytes(unsigned char *s, const ge25519_p2 *h)
+{
+ fe25519 recip;
+ fe25519 x;
+ fe25519 y;
+
+ fe25519_invert(recip, h->Z);
+ fe25519_mul(x, h->X, recip);
+ fe25519_mul(y, h->Y, recip);
+ fe25519_tobytes(s, y);
+ s[31] ^= fe25519_isnegative(x) << 7;
+}
+
+/*
+ r = a * A + b * B
+ where a = a[0]+256*a[1]+...+256^31 a[31].
+ and b = b[0]+256*b[1]+...+256^31 b[31].
+ B is the Ed25519 base point (x,4/5) with x positive.
+
+ Only used for signatures verification.
+ */
+
+void
+ge25519_double_scalarmult_vartime(ge25519_p2 *r, const unsigned char *a,
+ const ge25519_p3 *A, const unsigned char *b)
+{
+ static const ge25519_precomp Bi[8] = {
+#ifdef HAVE_TI_MODE
+# include "fe_51/base2.h"
+#else
+# include "fe_25_5/base2.h"
+#endif
+ };
+ signed char aslide[256];
+ signed char bslide[256];
+ ge25519_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
+ ge25519_p1p1 t;
+ ge25519_p3 u;
+ ge25519_p3 A2;
+ int i;
+
+ slide_vartime(aslide, a);
+ slide_vartime(bslide, b);
+
+ ge25519_p3_to_cached(&Ai[0], A);
+
+ ge25519_p3_dbl(&t, A);
+ ge25519_p1p1_to_p3(&A2, &t);
+
+ ge25519_add(&t, &A2, &Ai[0]);
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_p3_to_cached(&Ai[1], &u);
+
+ ge25519_add(&t, &A2, &Ai[1]);
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_p3_to_cached(&Ai[2], &u);
+
+ ge25519_add(&t, &A2, &Ai[2]);
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_p3_to_cached(&Ai[3], &u);
+
+ ge25519_add(&t, &A2, &Ai[3]);
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_p3_to_cached(&Ai[4], &u);
+
+ ge25519_add(&t, &A2, &Ai[4]);
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_p3_to_cached(&Ai[5], &u);
+
+ ge25519_add(&t, &A2, &Ai[5]);
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_p3_to_cached(&Ai[6], &u);
+
+ ge25519_add(&t, &A2, &Ai[6]);
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_p3_to_cached(&Ai[7], &u);
+
+ ge25519_p2_0(r);
+
+ for (i = 255; i >= 0; --i) {
+ if (aslide[i] || bslide[i]) {
+ break;
+ }
+ }
+
+ for (; i >= 0; --i) {
+ ge25519_p2_dbl(&t, r);
+
+ if (aslide[i] > 0) {
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_add(&t, &u, &Ai[aslide[i] / 2]);
+ } else if (aslide[i] < 0) {
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
+ }
+
+ if (bslide[i] > 0) {
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_madd(&t, &u, &Bi[bslide[i] / 2]);
+ } else if (bslide[i] < 0) {
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_msub(&t, &u, &Bi[(-bslide[i]) / 2]);
+ }
+
+ ge25519_p1p1_to_p2(r, &t);
+ }
+}
+
+/*
+ h = a * p
+ where a = a[0]+256*a[1]+...+256^31 a[31]
+
+ Preconditions:
+ a[31] <= 127
+
+ p is public
+ */
+
+void
+ge25519_scalarmult(ge25519_p3 *h, const unsigned char *a, const ge25519_p3 *p)
+{
+ signed char e[64];
+ signed char carry;
+ ge25519_p1p1 r;
+ ge25519_p2 s;
+ ge25519_p1p1 t2, t3, t4, t5, t6, t7, t8;
+ ge25519_p3 p2, p3, p4, p5, p6, p7, p8;
+ ge25519_cached pi[8];
+ ge25519_cached t;
+ int i;
+
+ ge25519_p3_to_cached(&pi[1 - 1], p); /* p */
+
+ ge25519_p3_dbl(&t2, p);
+ ge25519_p1p1_to_p3(&p2, &t2);
+ ge25519_p3_to_cached(&pi[2 - 1], &p2); /* 2p = 2*p */
+
+ ge25519_add(&t3, p, &pi[2 - 1]);
+ ge25519_p1p1_to_p3(&p3, &t3);
+ ge25519_p3_to_cached(&pi[3 - 1], &p3); /* 3p = 2p+p */
+
+ ge25519_p3_dbl(&t4, &p2);
+ ge25519_p1p1_to_p3(&p4, &t4);
+ ge25519_p3_to_cached(&pi[4 - 1], &p4); /* 4p = 2*2p */
+
+ ge25519_add(&t5, p, &pi[4 - 1]);
+ ge25519_p1p1_to_p3(&p5, &t5);
+ ge25519_p3_to_cached(&pi[5 - 1], &p5); /* 5p = 4p+p */
+
+ ge25519_p3_dbl(&t6, &p3);
+ ge25519_p1p1_to_p3(&p6, &t6);
+ ge25519_p3_to_cached(&pi[6 - 1], &p6); /* 6p = 2*3p */
+
+ ge25519_add(&t7, p, &pi[6 - 1]);
+ ge25519_p1p1_to_p3(&p7, &t7);
+ ge25519_p3_to_cached(&pi[7 - 1], &p7); /* 7p = 6p+p */
+
+ ge25519_p3_dbl(&t8, &p4);
+ ge25519_p1p1_to_p3(&p8, &t8);
+ ge25519_p3_to_cached(&pi[8 - 1], &p8); /* 8p = 2*4p */
+
+ for (i = 0; i < 32; ++i) {
+ e[2 * i + 0] = (a[i] >> 0) & 15;
+ e[2 * i + 1] = (a[i] >> 4) & 15;
+ }
+ /* each e[i] is between 0 and 15 */
+ /* e[63] is between 0 and 7 */
+
+ carry = 0;
+ for (i = 0; i < 63; ++i) {
+ e[i] += carry;
+ carry = e[i] + 8;
+ carry >>= 4;
+ e[i] -= carry * ((signed char) 1 << 4);
+ }
+ e[63] += carry;
+ /* each e[i] is between -8 and 8 */
+
+ ge25519_p3_0(h);
+
+ for (i = 63; i != 0; i--) {
+ ge25519_select_cached(&t, pi, e[i]);
+ ge25519_add(&r, h, &t);
+
+ ge25519_p1p1_to_p2(&s, &r);
+ ge25519_p2_dbl(&r, &s);
+ ge25519_p1p1_to_p2(&s, &r);
+ ge25519_p2_dbl(&r, &s);
+ ge25519_p1p1_to_p2(&s, &r);
+ ge25519_p2_dbl(&r, &s);
+ ge25519_p1p1_to_p2(&s, &r);
+ ge25519_p2_dbl(&r, &s);
+
+ ge25519_p1p1_to_p3(h, &r); /* *16 */
+ }
+ ge25519_select_cached(&t, pi, e[i]);
+ ge25519_add(&r, h, &t);
+
+ ge25519_p1p1_to_p3(h, &r);
+}
+
+/*
+ h = a * B (with precomputation)
+ where a = a[0]+256*a[1]+...+256^31 a[31]
+ B is the Ed25519 base point (x,4/5) with x positive
+ (as bytes: 0x5866666666666666666666666666666666666666666666666666666666666666)
+
+ Preconditions:
+ a[31] <= 127
+ */
+
+void
+ge25519_scalarmult_base(ge25519_p3 *h, const unsigned char *a)
+{
+ signed char e[64];
+ signed char carry;
+ ge25519_p1p1 r;
+ ge25519_p2 s;
+ ge25519_precomp t;
+ int i;
+
+ for (i = 0; i < 32; ++i) {
+ e[2 * i + 0] = (a[i] >> 0) & 15;
+ e[2 * i + 1] = (a[i] >> 4) & 15;
+ }
+ /* each e[i] is between 0 and 15 */
+ /* e[63] is between 0 and 7 */
+
+ carry = 0;
+ for (i = 0; i < 63; ++i) {
+ e[i] += carry;
+ carry = e[i] + 8;
+ carry >>= 4;
+ e[i] -= carry * ((signed char) 1 << 4);
+ }
+ e[63] += carry;
+ /* each e[i] is between -8 and 8 */
+
+ ge25519_p3_0(h);
+
+ for (i = 1; i < 64; i += 2) {
+ ge25519_select_base(&t, i / 2, e[i]);
+ ge25519_madd(&r, h, &t);
+ ge25519_p1p1_to_p3(h, &r);
+ }
+
+ ge25519_p3_dbl(&r, h);
+ ge25519_p1p1_to_p2(&s, &r);
+ ge25519_p2_dbl(&r, &s);
+ ge25519_p1p1_to_p2(&s, &r);
+ ge25519_p2_dbl(&r, &s);
+ ge25519_p1p1_to_p2(&s, &r);
+ ge25519_p2_dbl(&r, &s);
+ ge25519_p1p1_to_p3(h, &r);
+
+ for (i = 0; i < 64; i += 2) {
+ ge25519_select_base(&t, i / 2, e[i]);
+ ge25519_madd(&r, h, &t);
+ ge25519_p1p1_to_p3(h, &r);
+ }
+}
+
+/* multiply by the order of the main subgroup l = 2^252+27742317777372353535851937790883648493 */
+static void
+ge25519_mul_l(ge25519_p3 *r, const ge25519_p3 *A)
+{
+ static const signed char aslide[253] = {
+ 13, 0, 0, 0, 0, -1, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, -5, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, -13, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 3, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+ };
+ ge25519_cached Ai[8];
+ ge25519_p1p1 t;
+ ge25519_p3 u;
+ ge25519_p3 A2;
+ int i;
+
+ ge25519_p3_to_cached(&Ai[0], A);
+ ge25519_p3_dbl(&t, A);
+ ge25519_p1p1_to_p3(&A2, &t);
+ ge25519_add(&t, &A2, &Ai[0]);
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_p3_to_cached(&Ai[1], &u);
+ ge25519_add(&t, &A2, &Ai[1]);
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_p3_to_cached(&Ai[2], &u);
+ ge25519_add(&t, &A2, &Ai[2]);
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_p3_to_cached(&Ai[3], &u);
+ ge25519_add(&t, &A2, &Ai[3]);
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_p3_to_cached(&Ai[4], &u);
+ ge25519_add(&t, &A2, &Ai[4]);
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_p3_to_cached(&Ai[5], &u);
+ ge25519_add(&t, &A2, &Ai[5]);
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_p3_to_cached(&Ai[6], &u);
+ ge25519_add(&t, &A2, &Ai[6]);
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_p3_to_cached(&Ai[7], &u);
+
+ ge25519_p3_0(r);
+
+ for (i = 252; i >= 0; --i) {
+ ge25519_p3_dbl(&t, r);
+
+ if (aslide[i] > 0) {
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_add(&t, &u, &Ai[aslide[i] / 2]);
+ } else if (aslide[i] < 0) {
+ ge25519_p1p1_to_p3(&u, &t);
+ ge25519_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
+ }
+
+ ge25519_p1p1_to_p3(r, &t);
+ }
+}
+
+int
+ge25519_is_on_curve(const ge25519_p3 *p)
+{
+ fe25519 x2;
+ fe25519 y2;
+ fe25519 z2;
+ fe25519 z4;
+ fe25519 t0;
+ fe25519 t1;
+
+ fe25519_sq(x2, p->X);
+ fe25519_sq(y2, p->Y);
+ fe25519_sq(z2, p->Z);
+ fe25519_sub(t0, y2, x2);
+ fe25519_mul(t0, t0, z2);
+
+ fe25519_mul(t1, x2, y2);
+ fe25519_mul(t1, t1, d);
+ fe25519_sq(z4, z2);
+ fe25519_add(t1, t1, z4);
+ fe25519_sub(t0, t0, t1);
+
+ return fe25519_iszero(t0);
+}
+
+int
+ge25519_is_on_main_subgroup(const ge25519_p3 *p)
+{
+ ge25519_p3 pl;
+
+ ge25519_mul_l(&pl, p);
+
+ return fe25519_iszero(pl.X);
+}
+
+int
+ge25519_is_canonical(const unsigned char *s)
+{
+ unsigned char c;
+ unsigned char d;
+ unsigned int i;
+
+ c = (s[31] & 0x7f) ^ 0x7f;
+ for (i = 30; i > 0; i--) {
+ c |= s[i] ^ 0xff;
+ }
+ c = (((unsigned int) c) - 1U) >> 8;
+ d = (0xed - 1U - (unsigned int) s[0]) >> 8;
+
+ return 1 - (c & d & 1);
+}
+
+int
+ge25519_has_small_order(const unsigned char s[32])
+{
+ CRYPTO_ALIGN(16)
+ static const unsigned char blacklist[][32] = {
+ /* 0 (order 4) */
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ /* 1 (order 1) */
+ { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ /* 2707385501144840649318225287225658788936804267575313519463743609750303402022
+ (order 8) */
+ { 0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4,
+ 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6,
+ 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05 },
+ /* 55188659117513257062467267217118295137698188065244968500265048394206261417927
+ (order 8) */
+ { 0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b,
+ 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39,
+ 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a },
+ /* p-1 (order 2) */
+ { 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
+ /* p (=0, order 4) */
+ { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
+ /* p+1 (=1, order 1) */
+ { 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }
+ };
+ unsigned char c[7] = { 0 };
+ unsigned int k;
+ size_t i, j;
+
+ COMPILER_ASSERT(7 == sizeof blacklist / sizeof blacklist[0]);
+ for (j = 0; j < 31; j++) {
+ for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) {
+ c[i] |= s[j] ^ blacklist[i][j];
+ }
+ }
+ for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) {
+ c[i] |= (s[j] & 0x7f) ^ blacklist[i][j];
+ }
+ k = 0;
+ for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) {
+ k |= (c[i] - 1);
+ }
+ return (int) ((k >> 8) & 1);
+}
+
+/*
+ Input:
+ a[0]+256*a[1]+...+256^31*a[31] = a
+ b[0]+256*b[1]+...+256^31*b[31] = b
+ c[0]+256*c[1]+...+256^31*c[31] = c
+ *
+ Output:
+ s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
+ where l = 2^252 + 27742317777372353535851937790883648493.
+ */
+
+void
+sc25519_muladd(unsigned char *s, const unsigned char *a,
+ const unsigned char *b, const unsigned char *c)
+{
+ int64_t a0 = 2097151 & load_3(a);
+ int64_t a1 = 2097151 & (load_4(a + 2) >> 5);
+ int64_t a2 = 2097151 & (load_3(a + 5) >> 2);
+ int64_t a3 = 2097151 & (load_4(a + 7) >> 7);
+ int64_t a4 = 2097151 & (load_4(a + 10) >> 4);
+ int64_t a5 = 2097151 & (load_3(a + 13) >> 1);
+ int64_t a6 = 2097151 & (load_4(a + 15) >> 6);
+ int64_t a7 = 2097151 & (load_3(a + 18) >> 3);
+ int64_t a8 = 2097151 & load_3(a + 21);
+ int64_t a9 = 2097151 & (load_4(a + 23) >> 5);
+ int64_t a10 = 2097151 & (load_3(a + 26) >> 2);
+ int64_t a11 = (load_4(a + 28) >> 7);
+
+ int64_t b0 = 2097151 & load_3(b);
+ int64_t b1 = 2097151 & (load_4(b + 2) >> 5);
+ int64_t b2 = 2097151 & (load_3(b + 5) >> 2);
+ int64_t b3 = 2097151 & (load_4(b + 7) >> 7);
+ int64_t b4 = 2097151 & (load_4(b + 10) >> 4);
+ int64_t b5 = 2097151 & (load_3(b + 13) >> 1);
+ int64_t b6 = 2097151 & (load_4(b + 15) >> 6);
+ int64_t b7 = 2097151 & (load_3(b + 18) >> 3);
+ int64_t b8 = 2097151 & load_3(b + 21);
+ int64_t b9 = 2097151 & (load_4(b + 23) >> 5);
+ int64_t b10 = 2097151 & (load_3(b + 26) >> 2);
+ int64_t b11 = (load_4(b + 28) >> 7);
+
+ int64_t c0 = 2097151 & load_3(c);
+ int64_t c1 = 2097151 & (load_4(c + 2) >> 5);
+ int64_t c2 = 2097151 & (load_3(c + 5) >> 2);
+ int64_t c3 = 2097151 & (load_4(c + 7) >> 7);
+ int64_t c4 = 2097151 & (load_4(c + 10) >> 4);
+ int64_t c5 = 2097151 & (load_3(c + 13) >> 1);
+ int64_t c6 = 2097151 & (load_4(c + 15) >> 6);
+ int64_t c7 = 2097151 & (load_3(c + 18) >> 3);
+ int64_t c8 = 2097151 & load_3(c + 21);
+ int64_t c9 = 2097151 & (load_4(c + 23) >> 5);
+ int64_t c10 = 2097151 & (load_3(c + 26) >> 2);
+ int64_t c11 = (load_4(c + 28) >> 7);
+
+ int64_t s0;
+ int64_t s1;
+ int64_t s2;
+ int64_t s3;
+ int64_t s4;
+ int64_t s5;
+ int64_t s6;
+ int64_t s7;
+ int64_t s8;
+ int64_t s9;
+ int64_t s10;
+ int64_t s11;
+ int64_t s12;
+ int64_t s13;
+ int64_t s14;
+ int64_t s15;
+ int64_t s16;
+ int64_t s17;
+ int64_t s18;
+ int64_t s19;
+ int64_t s20;
+ int64_t s21;
+ int64_t s22;
+ int64_t s23;
+
+ int64_t carry0;
+ int64_t carry1;
+ int64_t carry2;
+ int64_t carry3;
+ int64_t carry4;
+ int64_t carry5;
+ int64_t carry6;
+ int64_t carry7;
+ int64_t carry8;
+ int64_t carry9;
+ int64_t carry10;
+ int64_t carry11;
+ int64_t carry12;
+ int64_t carry13;
+ int64_t carry14;
+ int64_t carry15;
+ int64_t carry16;
+ int64_t carry17;
+ int64_t carry18;
+ int64_t carry19;
+ int64_t carry20;
+ int64_t carry21;
+ int64_t carry22;
+
+ s0 = c0 + a0 * b0;
+ s1 = c1 + a0 * b1 + a1 * b0;
+ s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0;
+ s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
+ s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0;
+ s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0;
+ s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 +
+ a6 * b0;
+ s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 +
+ a6 * b1 + a7 * b0;
+ s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 +
+ a6 * b2 + a7 * b1 + a8 * b0;
+ s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 +
+ a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0;
+ s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 +
+ a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0;
+ s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 +
+ a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0;
+ s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 +
+ a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1;
+ s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 +
+ a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2;
+ s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 +
+ a9 * b5 + a10 * b4 + a11 * b3;
+ s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 +
+ a10 * b5 + a11 * b4;
+ s16 =
+ a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5;
+ s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6;
+ s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7;
+ s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8;
+ s20 = a9 * b11 + a10 * b10 + a11 * b9;
+ s21 = a10 * b11 + a11 * b10;
+ s22 = a11 * b11;
+ s23 = 0;
+
+ carry0 = (s0 + (int64_t) (1L << 20)) >> 21;
+ s1 += carry0;
+ s0 -= carry0 * ((uint64_t) 1L << 21);
+ carry2 = (s2 + (int64_t) (1L << 20)) >> 21;
+ s3 += carry2;
+ s2 -= carry2 * ((uint64_t) 1L << 21);
+ carry4 = (s4 + (int64_t) (1L << 20)) >> 21;
+ s5 += carry4;
+ s4 -= carry4 * ((uint64_t) 1L << 21);
+ carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
+ s7 += carry6;
+ s6 -= carry6 * ((uint64_t) 1L << 21);
+ carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
+ s9 += carry8;
+ s8 -= carry8 * ((uint64_t) 1L << 21);
+ carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
+ s11 += carry10;
+ s10 -= carry10 * ((uint64_t) 1L << 21);
+ carry12 = (s12 + (int64_t) (1L << 20)) >> 21;
+ s13 += carry12;
+ s12 -= carry12 * ((uint64_t) 1L << 21);
+ carry14 = (s14 + (int64_t) (1L << 20)) >> 21;
+ s15 += carry14;
+ s14 -= carry14 * ((uint64_t) 1L << 21);
+ carry16 = (s16 + (int64_t) (1L << 20)) >> 21;
+ s17 += carry16;
+ s16 -= carry16 * ((uint64_t) 1L << 21);
+ carry18 = (s18 + (int64_t) (1L << 20)) >> 21;
+ s19 += carry18;
+ s18 -= carry18 * ((uint64_t) 1L << 21);
+ carry20 = (s20 + (int64_t) (1L << 20)) >> 21;
+ s21 += carry20;
+ s20 -= carry20 * ((uint64_t) 1L << 21);
+ carry22 = (s22 + (int64_t) (1L << 20)) >> 21;
+ s23 += carry22;
+ s22 -= carry22 * ((uint64_t) 1L << 21);
+
+ carry1 = (s1 + (int64_t) (1L << 20)) >> 21;
+ s2 += carry1;
+ s1 -= carry1 * ((uint64_t) 1L << 21);
+ carry3 = (s3 + (int64_t) (1L << 20)) >> 21;
+ s4 += carry3;
+ s3 -= carry3 * ((uint64_t) 1L << 21);
+ carry5 = (s5 + (int64_t) (1L << 20)) >> 21;
+ s6 += carry5;
+ s5 -= carry5 * ((uint64_t) 1L << 21);
+ carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
+ s8 += carry7;
+ s7 -= carry7 * ((uint64_t) 1L << 21);
+ carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
+ s10 += carry9;
+ s9 -= carry9 * ((uint64_t) 1L << 21);
+ carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
+ s12 += carry11;
+ s11 -= carry11 * ((uint64_t) 1L << 21);
+ carry13 = (s13 + (int64_t) (1L << 20)) >> 21;
+ s14 += carry13;
+ s13 -= carry13 * ((uint64_t) 1L << 21);
+ carry15 = (s15 + (int64_t) (1L << 20)) >> 21;
+ s16 += carry15;
+ s15 -= carry15 * ((uint64_t) 1L << 21);
+ carry17 = (s17 + (int64_t) (1L << 20)) >> 21;
+ s18 += carry17;
+ s17 -= carry17 * ((uint64_t) 1L << 21);
+ carry19 = (s19 + (int64_t) (1L << 20)) >> 21;
+ s20 += carry19;
+ s19 -= carry19 * ((uint64_t) 1L << 21);
+ carry21 = (s21 + (int64_t) (1L << 20)) >> 21;
+ s22 += carry21;
+ s21 -= carry21 * ((uint64_t) 1L << 21);
+
+ s11 += s23 * 666643;
+ s12 += s23 * 470296;
+ s13 += s23 * 654183;
+ s14 -= s23 * 997805;
+ s15 += s23 * 136657;
+ s16 -= s23 * 683901;
+
+ s10 += s22 * 666643;
+ s11 += s22 * 470296;
+ s12 += s22 * 654183;
+ s13 -= s22 * 997805;
+ s14 += s22 * 136657;
+ s15 -= s22 * 683901;
+
+ s9 += s21 * 666643;
+ s10 += s21 * 470296;
+ s11 += s21 * 654183;
+ s12 -= s21 * 997805;
+ s13 += s21 * 136657;
+ s14 -= s21 * 683901;
+
+ s8 += s20 * 666643;
+ s9 += s20 * 470296;
+ s10 += s20 * 654183;
+ s11 -= s20 * 997805;
+ s12 += s20 * 136657;
+ s13 -= s20 * 683901;
+
+ s7 += s19 * 666643;
+ s8 += s19 * 470296;
+ s9 += s19 * 654183;
+ s10 -= s19 * 997805;
+ s11 += s19 * 136657;
+ s12 -= s19 * 683901;
+
+ s6 += s18 * 666643;
+ s7 += s18 * 470296;
+ s8 += s18 * 654183;
+ s9 -= s18 * 997805;
+ s10 += s18 * 136657;
+ s11 -= s18 * 683901;
+
+ carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
+ s7 += carry6;
+ s6 -= carry6 * ((uint64_t) 1L << 21);
+ carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
+ s9 += carry8;
+ s8 -= carry8 * ((uint64_t) 1L << 21);
+ carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
+ s11 += carry10;
+ s10 -= carry10 * ((uint64_t) 1L << 21);
+ carry12 = (s12 + (int64_t) (1L << 20)) >> 21;
+ s13 += carry12;
+ s12 -= carry12 * ((uint64_t) 1L << 21);
+ carry14 = (s14 + (int64_t) (1L << 20)) >> 21;
+ s15 += carry14;
+ s14 -= carry14 * ((uint64_t) 1L << 21);
+ carry16 = (s16 + (int64_t) (1L << 20)) >> 21;
+ s17 += carry16;
+ s16 -= carry16 * ((uint64_t) 1L << 21);
+
+ carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
+ s8 += carry7;
+ s7 -= carry7 * ((uint64_t) 1L << 21);
+ carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
+ s10 += carry9;
+ s9 -= carry9 * ((uint64_t) 1L << 21);
+ carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
+ s12 += carry11;
+ s11 -= carry11 * ((uint64_t) 1L << 21);
+ carry13 = (s13 + (int64_t) (1L << 20)) >> 21;
+ s14 += carry13;
+ s13 -= carry13 * ((uint64_t) 1L << 21);
+ carry15 = (s15 + (int64_t) (1L << 20)) >> 21;
+ s16 += carry15;
+ s15 -= carry15 * ((uint64_t) 1L << 21);
+
+ s5 += s17 * 666643;
+ s6 += s17 * 470296;
+ s7 += s17 * 654183;
+ s8 -= s17 * 997805;
+ s9 += s17 * 136657;
+ s10 -= s17 * 683901;
+
+ s4 += s16 * 666643;
+ s5 += s16 * 470296;
+ s6 += s16 * 654183;
+ s7 -= s16 * 997805;
+ s8 += s16 * 136657;
+ s9 -= s16 * 683901;
+
+ s3 += s15 * 666643;
+ s4 += s15 * 470296;
+ s5 += s15 * 654183;
+ s6 -= s15 * 997805;
+ s7 += s15 * 136657;
+ s8 -= s15 * 683901;
+
+ s2 += s14 * 666643;
+ s3 += s14 * 470296;
+ s4 += s14 * 654183;
+ s5 -= s14 * 997805;
+ s6 += s14 * 136657;
+ s7 -= s14 * 683901;
+
+ s1 += s13 * 666643;
+ s2 += s13 * 470296;
+ s3 += s13 * 654183;
+ s4 -= s13 * 997805;
+ s5 += s13 * 136657;
+ s6 -= s13 * 683901;
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = (s0 + (int64_t) (1L << 20)) >> 21;
+ s1 += carry0;
+ s0 -= carry0 * ((uint64_t) 1L << 21);
+ carry2 = (s2 + (int64_t) (1L << 20)) >> 21;
+ s3 += carry2;
+ s2 -= carry2 * ((uint64_t) 1L << 21);
+ carry4 = (s4 + (int64_t) (1L << 20)) >> 21;
+ s5 += carry4;
+ s4 -= carry4 * ((uint64_t) 1L << 21);
+ carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
+ s7 += carry6;
+ s6 -= carry6 * ((uint64_t) 1L << 21);
+ carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
+ s9 += carry8;
+ s8 -= carry8 * ((uint64_t) 1L << 21);
+ carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
+ s11 += carry10;
+ s10 -= carry10 * ((uint64_t) 1L << 21);
+
+ carry1 = (s1 + (int64_t) (1L << 20)) >> 21;
+ s2 += carry1;
+ s1 -= carry1 * ((uint64_t) 1L << 21);
+ carry3 = (s3 + (int64_t) (1L << 20)) >> 21;
+ s4 += carry3;
+ s3 -= carry3 * ((uint64_t) 1L << 21);
+ carry5 = (s5 + (int64_t) (1L << 20)) >> 21;
+ s6 += carry5;
+ s5 -= carry5 * ((uint64_t) 1L << 21);
+ carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
+ s8 += carry7;
+ s7 -= carry7 * ((uint64_t) 1L << 21);
+ carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
+ s10 += carry9;
+ s9 -= carry9 * ((uint64_t) 1L << 21);
+ carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
+ s12 += carry11;
+ s11 -= carry11 * ((uint64_t) 1L << 21);
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = s0 >> 21;
+ s1 += carry0;
+ s0 -= carry0 * ((uint64_t) 1L << 21);
+ carry1 = s1 >> 21;
+ s2 += carry1;
+ s1 -= carry1 * ((uint64_t) 1L << 21);
+ carry2 = s2 >> 21;
+ s3 += carry2;
+ s2 -= carry2 * ((uint64_t) 1L << 21);
+ carry3 = s3 >> 21;
+ s4 += carry3;
+ s3 -= carry3 * ((uint64_t) 1L << 21);
+ carry4 = s4 >> 21;
+ s5 += carry4;
+ s4 -= carry4 * ((uint64_t) 1L << 21);
+ carry5 = s5 >> 21;
+ s6 += carry5;
+ s5 -= carry5 * ((uint64_t) 1L << 21);
+ carry6 = s6 >> 21;
+ s7 += carry6;
+ s6 -= carry6 * ((uint64_t) 1L << 21);
+ carry7 = s7 >> 21;
+ s8 += carry7;
+ s7 -= carry7 * ((uint64_t) 1L << 21);
+ carry8 = s8 >> 21;
+ s9 += carry8;
+ s8 -= carry8 * ((uint64_t) 1L << 21);
+ carry9 = s9 >> 21;
+ s10 += carry9;
+ s9 -= carry9 * ((uint64_t) 1L << 21);
+ carry10 = s10 >> 21;
+ s11 += carry10;
+ s10 -= carry10 * ((uint64_t) 1L << 21);
+ carry11 = s11 >> 21;
+ s12 += carry11;
+ s11 -= carry11 * ((uint64_t) 1L << 21);
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+
+ carry0 = s0 >> 21;
+ s1 += carry0;
+ s0 -= carry0 * ((uint64_t) 1L << 21);
+ carry1 = s1 >> 21;
+ s2 += carry1;
+ s1 -= carry1 * ((uint64_t) 1L << 21);
+ carry2 = s2 >> 21;
+ s3 += carry2;
+ s2 -= carry2 * ((uint64_t) 1L << 21);
+ carry3 = s3 >> 21;
+ s4 += carry3;
+ s3 -= carry3 * ((uint64_t) 1L << 21);
+ carry4 = s4 >> 21;
+ s5 += carry4;
+ s4 -= carry4 * ((uint64_t) 1L << 21);
+ carry5 = s5 >> 21;
+ s6 += carry5;
+ s5 -= carry5 * ((uint64_t) 1L << 21);
+ carry6 = s6 >> 21;
+ s7 += carry6;
+ s6 -= carry6 * ((uint64_t) 1L << 21);
+ carry7 = s7 >> 21;
+ s8 += carry7;
+ s7 -= carry7 * ((uint64_t) 1L << 21);
+ carry8 = s8 >> 21;
+ s9 += carry8;
+ s8 -= carry8 * ((uint64_t) 1L << 21);
+ carry9 = s9 >> 21;
+ s10 += carry9;
+ s9 -= carry9 * ((uint64_t) 1L << 21);
+ carry10 = s10 >> 21;
+ s11 += carry10;
+ s10 -= carry10 * ((uint64_t) 1L << 21);
+
+ s[0] = s0 >> 0;
+ s[1] = s0 >> 8;
+ s[2] = (s0 >> 16) | (s1 * ((uint64_t) 1 << 5));
+ s[3] = s1 >> 3;
+ s[4] = s1 >> 11;
+ s[5] = (s1 >> 19) | (s2 * ((uint64_t) 1 << 2));
+ s[6] = s2 >> 6;
+ s[7] = (s2 >> 14) | (s3 * ((uint64_t) 1 << 7));
+ s[8] = s3 >> 1;
+ s[9] = s3 >> 9;
+ s[10] = (s3 >> 17) | (s4 * ((uint64_t) 1 << 4));
+ s[11] = s4 >> 4;
+ s[12] = s4 >> 12;
+ s[13] = (s4 >> 20) | (s5 * ((uint64_t) 1 << 1));
+ s[14] = s5 >> 7;
+ s[15] = (s5 >> 15) | (s6 * ((uint64_t) 1 << 6));
+ s[16] = s6 >> 2;
+ s[17] = s6 >> 10;
+ s[18] = (s6 >> 18) | (s7 * ((uint64_t) 1 << 3));
+ s[19] = s7 >> 5;
+ s[20] = s7 >> 13;
+ s[21] = s8 >> 0;
+ s[22] = s8 >> 8;
+ s[23] = (s8 >> 16) | (s9 * ((uint64_t) 1 << 5));
+ s[24] = s9 >> 3;
+ s[25] = s9 >> 11;
+ s[26] = (s9 >> 19) | (s10 * ((uint64_t) 1 << 2));
+ s[27] = s10 >> 6;
+ s[28] = (s10 >> 14) | (s11 * ((uint64_t) 1 << 7));
+ s[29] = s11 >> 1;
+ s[30] = s11 >> 9;
+ s[31] = s11 >> 17;
+}
+
+/*
+ Input:
+ s[0]+256*s[1]+...+256^63*s[63] = s
+ *
+ Output:
+ s[0]+256*s[1]+...+256^31*s[31] = s mod l
+ where l = 2^252 + 27742317777372353535851937790883648493.
+ Overwrites s in place.
+ */
+
+void
+sc25519_reduce(unsigned char *s)
+{
+ int64_t s0 = 2097151 & load_3(s);
+ int64_t s1 = 2097151 & (load_4(s + 2) >> 5);
+ int64_t s2 = 2097151 & (load_3(s + 5) >> 2);
+ int64_t s3 = 2097151 & (load_4(s + 7) >> 7);
+ int64_t s4 = 2097151 & (load_4(s + 10) >> 4);
+ int64_t s5 = 2097151 & (load_3(s + 13) >> 1);
+ int64_t s6 = 2097151 & (load_4(s + 15) >> 6);
+ int64_t s7 = 2097151 & (load_3(s + 18) >> 3);
+ int64_t s8 = 2097151 & load_3(s + 21);
+ int64_t s9 = 2097151 & (load_4(s + 23) >> 5);
+ int64_t s10 = 2097151 & (load_3(s + 26) >> 2);
+ int64_t s11 = 2097151 & (load_4(s + 28) >> 7);
+ int64_t s12 = 2097151 & (load_4(s + 31) >> 4);
+ int64_t s13 = 2097151 & (load_3(s + 34) >> 1);
+ int64_t s14 = 2097151 & (load_4(s + 36) >> 6);
+ int64_t s15 = 2097151 & (load_3(s + 39) >> 3);
+ int64_t s16 = 2097151 & load_3(s + 42);
+ int64_t s17 = 2097151 & (load_4(s + 44) >> 5);
+ int64_t s18 = 2097151 & (load_3(s + 47) >> 2);
+ int64_t s19 = 2097151 & (load_4(s + 49) >> 7);
+ int64_t s20 = 2097151 & (load_4(s + 52) >> 4);
+ int64_t s21 = 2097151 & (load_3(s + 55) >> 1);
+ int64_t s22 = 2097151 & (load_4(s + 57) >> 6);
+ int64_t s23 = (load_4(s + 60) >> 3);
+
+ int64_t carry0;
+ int64_t carry1;
+ int64_t carry2;
+ int64_t carry3;
+ int64_t carry4;
+ int64_t carry5;
+ int64_t carry6;
+ int64_t carry7;
+ int64_t carry8;
+ int64_t carry9;
+ int64_t carry10;
+ int64_t carry11;
+ int64_t carry12;
+ int64_t carry13;
+ int64_t carry14;
+ int64_t carry15;
+ int64_t carry16;
+
+ s11 += s23 * 666643;
+ s12 += s23 * 470296;
+ s13 += s23 * 654183;
+ s14 -= s23 * 997805;
+ s15 += s23 * 136657;
+ s16 -= s23 * 683901;
+
+ s10 += s22 * 666643;
+ s11 += s22 * 470296;
+ s12 += s22 * 654183;
+ s13 -= s22 * 997805;
+ s14 += s22 * 136657;
+ s15 -= s22 * 683901;
+
+ s9 += s21 * 666643;
+ s10 += s21 * 470296;
+ s11 += s21 * 654183;
+ s12 -= s21 * 997805;
+ s13 += s21 * 136657;
+ s14 -= s21 * 683901;
+
+ s8 += s20 * 666643;
+ s9 += s20 * 470296;
+ s10 += s20 * 654183;
+ s11 -= s20 * 997805;
+ s12 += s20 * 136657;
+ s13 -= s20 * 683901;
+
+ s7 += s19 * 666643;
+ s8 += s19 * 470296;
+ s9 += s19 * 654183;
+ s10 -= s19 * 997805;
+ s11 += s19 * 136657;
+ s12 -= s19 * 683901;
+
+ s6 += s18 * 666643;
+ s7 += s18 * 470296;
+ s8 += s18 * 654183;
+ s9 -= s18 * 997805;
+ s10 += s18 * 136657;
+ s11 -= s18 * 683901;
+
+ carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
+ s7 += carry6;
+ s6 -= carry6 * ((uint64_t) 1L << 21);
+ carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
+ s9 += carry8;
+ s8 -= carry8 * ((uint64_t) 1L << 21);
+ carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
+ s11 += carry10;
+ s10 -= carry10 * ((uint64_t) 1L << 21);
+ carry12 = (s12 + (int64_t) (1L << 20)) >> 21;
+ s13 += carry12;
+ s12 -= carry12 * ((uint64_t) 1L << 21);
+ carry14 = (s14 + (int64_t) (1L << 20)) >> 21;
+ s15 += carry14;
+ s14 -= carry14 * ((uint64_t) 1L << 21);
+ carry16 = (s16 + (int64_t) (1L << 20)) >> 21;
+ s17 += carry16;
+ s16 -= carry16 * ((uint64_t) 1L << 21);
+
+ carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
+ s8 += carry7;
+ s7 -= carry7 * ((uint64_t) 1L << 21);
+ carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
+ s10 += carry9;
+ s9 -= carry9 * ((uint64_t) 1L << 21);
+ carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
+ s12 += carry11;
+ s11 -= carry11 * ((uint64_t) 1L << 21);
+ carry13 = (s13 + (int64_t) (1L << 20)) >> 21;
+ s14 += carry13;
+ s13 -= carry13 * ((uint64_t) 1L << 21);
+ carry15 = (s15 + (int64_t) (1L << 20)) >> 21;
+ s16 += carry15;
+ s15 -= carry15 * ((uint64_t) 1L << 21);
+
+ s5 += s17 * 666643;
+ s6 += s17 * 470296;
+ s7 += s17 * 654183;
+ s8 -= s17 * 997805;
+ s9 += s17 * 136657;
+ s10 -= s17 * 683901;
+
+ s4 += s16 * 666643;
+ s5 += s16 * 470296;
+ s6 += s16 * 654183;
+ s7 -= s16 * 997805;
+ s8 += s16 * 136657;
+ s9 -= s16 * 683901;
+
+ s3 += s15 * 666643;
+ s4 += s15 * 470296;
+ s5 += s15 * 654183;
+ s6 -= s15 * 997805;
+ s7 += s15 * 136657;
+ s8 -= s15 * 683901;
+
+ s2 += s14 * 666643;
+ s3 += s14 * 470296;
+ s4 += s14 * 654183;
+ s5 -= s14 * 997805;
+ s6 += s14 * 136657;
+ s7 -= s14 * 683901;
+
+ s1 += s13 * 666643;
+ s2 += s13 * 470296;
+ s3 += s13 * 654183;
+ s4 -= s13 * 997805;
+ s5 += s13 * 136657;
+ s6 -= s13 * 683901;
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = (s0 + (int64_t) (1L << 20)) >> 21;
+ s1 += carry0;
+ s0 -= carry0 * ((uint64_t) 1L << 21);
+ carry2 = (s2 + (int64_t) (1L << 20)) >> 21;
+ s3 += carry2;
+ s2 -= carry2 * ((uint64_t) 1L << 21);
+ carry4 = (s4 + (int64_t) (1L << 20)) >> 21;
+ s5 += carry4;
+ s4 -= carry4 * ((uint64_t) 1L << 21);
+ carry6 = (s6 + (int64_t) (1L << 20)) >> 21;
+ s7 += carry6;
+ s6 -= carry6 * ((uint64_t) 1L << 21);
+ carry8 = (s8 + (int64_t) (1L << 20)) >> 21;
+ s9 += carry8;
+ s8 -= carry8 * ((uint64_t) 1L << 21);
+ carry10 = (s10 + (int64_t) (1L << 20)) >> 21;
+ s11 += carry10;
+ s10 -= carry10 * ((uint64_t) 1L << 21);
+
+ carry1 = (s1 + (int64_t) (1L << 20)) >> 21;
+ s2 += carry1;
+ s1 -= carry1 * ((uint64_t) 1L << 21);
+ carry3 = (s3 + (int64_t) (1L << 20)) >> 21;
+ s4 += carry3;
+ s3 -= carry3 * ((uint64_t) 1L << 21);
+ carry5 = (s5 + (int64_t) (1L << 20)) >> 21;
+ s6 += carry5;
+ s5 -= carry5 * ((uint64_t) 1L << 21);
+ carry7 = (s7 + (int64_t) (1L << 20)) >> 21;
+ s8 += carry7;
+ s7 -= carry7 * ((uint64_t) 1L << 21);
+ carry9 = (s9 + (int64_t) (1L << 20)) >> 21;
+ s10 += carry9;
+ s9 -= carry9 * ((uint64_t) 1L << 21);
+ carry11 = (s11 + (int64_t) (1L << 20)) >> 21;
+ s12 += carry11;
+ s11 -= carry11 * ((uint64_t) 1L << 21);
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = s0 >> 21;
+ s1 += carry0;
+ s0 -= carry0 * ((uint64_t) 1L << 21);
+ carry1 = s1 >> 21;
+ s2 += carry1;
+ s1 -= carry1 * ((uint64_t) 1L << 21);
+ carry2 = s2 >> 21;
+ s3 += carry2;
+ s2 -= carry2 * ((uint64_t) 1L << 21);
+ carry3 = s3 >> 21;
+ s4 += carry3;
+ s3 -= carry3 * ((uint64_t) 1L << 21);
+ carry4 = s4 >> 21;
+ s5 += carry4;
+ s4 -= carry4 * ((uint64_t) 1L << 21);
+ carry5 = s5 >> 21;
+ s6 += carry5;
+ s5 -= carry5 * ((uint64_t) 1L << 21);
+ carry6 = s6 >> 21;
+ s7 += carry6;
+ s6 -= carry6 * ((uint64_t) 1L << 21);
+ carry7 = s7 >> 21;
+ s8 += carry7;
+ s7 -= carry7 * ((uint64_t) 1L << 21);
+ carry8 = s8 >> 21;
+ s9 += carry8;
+ s8 -= carry8 * ((uint64_t) 1L << 21);
+ carry9 = s9 >> 21;
+ s10 += carry9;
+ s9 -= carry9 * ((uint64_t) 1L << 21);
+ carry10 = s10 >> 21;
+ s11 += carry10;
+ s10 -= carry10 * ((uint64_t) 1L << 21);
+ carry11 = s11 >> 21;
+ s12 += carry11;
+ s11 -= carry11 * ((uint64_t) 1L << 21);
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+
+ carry0 = s0 >> 21;
+ s1 += carry0;
+ s0 -= carry0 * ((uint64_t) 1L << 21);
+ carry1 = s1 >> 21;
+ s2 += carry1;
+ s1 -= carry1 * ((uint64_t) 1L << 21);
+ carry2 = s2 >> 21;
+ s3 += carry2;
+ s2 -= carry2 * ((uint64_t) 1L << 21);
+ carry3 = s3 >> 21;
+ s4 += carry3;
+ s3 -= carry3 * ((uint64_t) 1L << 21);
+ carry4 = s4 >> 21;
+ s5 += carry4;
+ s4 -= carry4 * ((uint64_t) 1L << 21);
+ carry5 = s5 >> 21;
+ s6 += carry5;
+ s5 -= carry5 * ((uint64_t) 1L << 21);
+ carry6 = s6 >> 21;
+ s7 += carry6;
+ s6 -= carry6 * ((uint64_t) 1L << 21);
+ carry7 = s7 >> 21;
+ s8 += carry7;
+ s7 -= carry7 * ((uint64_t) 1L << 21);
+ carry8 = s8 >> 21;
+ s9 += carry8;
+ s8 -= carry8 * ((uint64_t) 1L << 21);
+ carry9 = s9 >> 21;
+ s10 += carry9;
+ s9 -= carry9 * ((uint64_t) 1L << 21);
+ carry10 = s10 >> 21;
+ s11 += carry10;
+ s10 -= carry10 * ((uint64_t) 1L << 21);
+
+ s[0] = s0 >> 0;
+ s[1] = s0 >> 8;
+ s[2] = (s0 >> 16) | (s1 * ((uint64_t) 1 << 5));
+ s[3] = s1 >> 3;
+ s[4] = s1 >> 11;
+ s[5] = (s1 >> 19) | (s2 * ((uint64_t) 1 << 2));
+ s[6] = s2 >> 6;
+ s[7] = (s2 >> 14) | (s3 * ((uint64_t) 1 << 7));
+ s[8] = s3 >> 1;
+ s[9] = s3 >> 9;
+ s[10] = (s3 >> 17) | (s4 * ((uint64_t) 1 << 4));
+ s[11] = s4 >> 4;
+ s[12] = s4 >> 12;
+ s[13] = (s4 >> 20) | (s5 * ((uint64_t) 1 << 1));
+ s[14] = s5 >> 7;
+ s[15] = (s5 >> 15) | (s6 * ((uint64_t) 1 << 6));
+ s[16] = s6 >> 2;
+ s[17] = s6 >> 10;
+ s[18] = (s6 >> 18) | (s7 * ((uint64_t) 1 << 3));
+ s[19] = s7 >> 5;
+ s[20] = s7 >> 13;
+ s[21] = s8 >> 0;
+ s[22] = s8 >> 8;
+ s[23] = (s8 >> 16) | (s9 * ((uint64_t) 1 << 5));
+ s[24] = s9 >> 3;
+ s[25] = s9 >> 11;
+ s[26] = (s9 >> 19) | (s10 * ((uint64_t) 1 << 2));
+ s[27] = s10 >> 6;
+ s[28] = (s10 >> 14) | (s11 * ((uint64_t) 1 << 7));
+ s[29] = s11 >> 1;
+ s[30] = s11 >> 9;
+ s[31] = s11 >> 17;
+}
+
+int
+sc25519_is_canonical(const unsigned char *s)
+{
+ /* 2^252+27742317777372353535851937790883648493 */
+ static const unsigned char L[32] = {
+ 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7,
+ 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
+ };
+ unsigned char c = 0;
+ unsigned char n = 1;
+ unsigned int i = 32;
+
+ do {
+ i--;
+ c |= ((s[i] - L[i]) >> 8) & n;
+ n &= ((s[i] ^ L[i]) - 1) >> 8;
+ } while (i != 0);
+
+ return (c != 0);
+}
+
+static void
+chi25519(fe25519 out, const fe25519 z)
+{
+ fe25519 t0, t1, t2, t3;
+ int i;
+
+ fe25519_sq(t0, z);
+ fe25519_mul(t1, t0, z);
+ fe25519_sq(t0, t1);
+ fe25519_sq(t2, t0);
+ fe25519_sq(t2, t2);
+ fe25519_mul(t2, t2, t0);
+ fe25519_mul(t1, t2, z);
+ fe25519_sq(t2, t1);
+
+ for (i = 1; i < 5; i++) {
+ fe25519_sq(t2, t2);
+ }
+ fe25519_mul(t1, t2, t1);
+ fe25519_sq(t2, t1);
+ for (i = 1; i < 10; i++) {
+ fe25519_sq(t2, t2);
+ }
+ fe25519_mul(t2, t2, t1);
+ fe25519_sq(t3, t2);
+ for (i = 1; i < 20; i++) {
+ fe25519_sq(t3, t3);
+ }
+ fe25519_mul(t2, t3, t2);
+ fe25519_sq(t2, t2);
+ for (i = 1; i < 10; i++) {
+ fe25519_sq(t2, t2);
+ }
+ fe25519_mul(t1, t2, t1);
+ fe25519_sq(t2, t1);
+ for (i = 1; i < 50; i++) {
+ fe25519_sq(t2, t2);
+ }
+ fe25519_mul(t2, t2, t1);
+ fe25519_sq(t3, t2);
+ for (i = 1; i < 100; i++) {
+ fe25519_sq(t3, t3);
+ }
+ fe25519_mul(t2, t3, t2);
+ fe25519_sq(t2, t2);
+ for (i = 1; i < 50; i++) {
+ fe25519_sq(t2, t2);
+ }
+ fe25519_mul(t1, t2, t1);
+ fe25519_sq(t1, t1);
+ for (i = 1; i < 4; i++) {
+ fe25519_sq(t1, t1);
+ }
+ fe25519_mul(out, t1, t0);
+}
+
+void
+ge25519_from_uniform(unsigned char s[32], const unsigned char r[32])
+{
+ fe25519 e;
+ fe25519 negx;
+ fe25519 rr2;
+ fe25519 x, x2, x3;
+ ge25519_p3 p3;
+ ge25519_p1p1 p1;
+ ge25519_p2 p2;
+ unsigned int e_is_minus_1;
+ unsigned char x_sign;
+
+ memcpy(s, r, 32);
+ x_sign = s[31] & 0x80;
+ s[31] &= 0x7f;
+
+ fe25519_frombytes(rr2, s);
+
+ /* elligator */
+ fe25519_sq2(rr2, rr2);
+ rr2[0]++;
+ fe25519_invert(rr2, rr2);
+ fe25519_mul(x, curve25519_A, rr2);
+ fe25519_neg(x, x);
+
+ fe25519_sq(x2, x);
+ fe25519_mul(x3, x, x2);
+ fe25519_add(e, x3, x);
+ fe25519_mul(x2, x2, curve25519_A);
+ fe25519_add(e, x2, e);
+
+ chi25519(e, e);
+
+ fe25519_tobytes(s, e);
+ e_is_minus_1 = s[1] & 1;
+ fe25519_neg(negx, x);
+ fe25519_cmov(x, negx, e_is_minus_1);
+ fe25519_0(x2);
+ fe25519_cmov(x2, curve25519_A, e_is_minus_1);
+ fe25519_sub(x, x, x2);
+
+ /* yed = (x-1)/(x+1) */
+ {
+ fe25519 one;
+ fe25519 x_plus_one;
+ fe25519 x_plus_one_inv;
+ fe25519 x_minus_one;
+ fe25519 yed;
+
+ fe25519_1(one);
+ fe25519_add(x_plus_one, x, one);
+ fe25519_sub(x_minus_one, x, one);
+ fe25519_invert(x_plus_one_inv, x_plus_one);
+ fe25519_mul(yed, x_minus_one, x_plus_one_inv);
+ fe25519_tobytes(s, yed);
+ }
+
+ /* recover x */
+ s[31] |= x_sign;
+ if (ge25519_frombytes(&p3, s) != 0) {
+ abort(); /* LCOV_EXCL_LINE */
+ }
+
+ /* multiply by the cofactor */
+ ge25519_p3_dbl(&p1, &p3);
+ ge25519_p1p1_to_p2(&p2, &p1);
+ ge25519_p2_dbl(&p1, &p2);
+ ge25519_p1p1_to_p2(&p2, &p1);
+ ge25519_p2_dbl(&p1, &p2);
+ ge25519_p1p1_to_p3(&p3, &p1);
+
+ ge25519_p3_tobytes(s, &p3);
+}
diff --git a/libs/libsodium/src/crypto_core/ed25519/ref10/fe_25_5/base.h b/libs/libsodium/src/crypto_core/ed25519/ref10/fe_25_5/base.h
new file mode 100644
index 0000000000..e18530bbb1
--- /dev/null
+++ b/libs/libsodium/src/crypto_core/ed25519/ref10/fe_25_5/base.h
@@ -0,0 +1,1344 @@
+{ /* 0/31 */
+ {
+ { 25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605 },
+ { -12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378 },
+ { -8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546 }
+ },
+ {
+ { -12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303 },
+ { -21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081 },
+ { 26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697 }
+ },
+ {
+ { 15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024 },
+ { 16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574 },
+ { 30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357 }
+ },
+ {
+ { -17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540 },
+ { 23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397 },
+ { 7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325 }
+ },
+ {
+ { 10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380 },
+ { 4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306 },
+ { 19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942 }
+ },
+ {
+ { -15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777 },
+ { -8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737 },
+ { -18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652 }
+ },
+ {
+ { 5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766 },
+ { -30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701 },
+ { 28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300 }
+ },
+ {
+ { 14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726 },
+ { -7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955 },
+ { 27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425 }
+ }
+},
+{ /* 1/31 */
+ {
+ { -13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171 },
+ { 27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510 },
+ { 17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660 }
+ },
+ {
+ { -10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639 },
+ { 29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963 },
+ { 5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950 }
+ },
+ {
+ { -27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568 },
+ { 12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335 },
+ { 25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628 }
+ },
+ {
+ { -26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007 },
+ { -2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772 },
+ { -22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653 }
+ },
+ {
+ { 2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567 },
+ { 13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686 },
+ { 21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372 }
+ },
+ {
+ { -13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887 },
+ { -23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954 },
+ { -29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953 }
+ },
+ {
+ { 24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833 },
+ { -16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532 },
+ { -22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876 }
+ },
+ {
+ { 2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268 },
+ { 33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214 },
+ { 1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038 }
+ }
+},
+{ /* 2/31 */
+ {
+ { 6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800 },
+ { 4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645 },
+ { -4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664 }
+ },
+ {
+ { 1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933 },
+ { -25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182 },
+ { -17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222 }
+ },
+ {
+ { -18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991 },
+ { 20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880 },
+ { 9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092 }
+ },
+ {
+ { -16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295 },
+ { 19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788 },
+ { 8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553 }
+ },
+ {
+ { -15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026 },
+ { 11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347 },
+ { -18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033 }
+ },
+ {
+ { -23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395 },
+ { -27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278 },
+ { 1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890 }
+ },
+ {
+ { 32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995 },
+ { -30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596 },
+ { -11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891 }
+ },
+ {
+ { 31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060 },
+ { 11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608 },
+ { -20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606 }
+ }
+},
+{ /* 3/31 */
+ {
+ { 7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389 },
+ { -19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016 },
+ { -11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341 }
+ },
+ {
+ { -22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505 },
+ { 14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553 },
+ { -28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655 }
+ },
+ {
+ { 15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220 },
+ { 12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631 },
+ { -4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099 }
+ },
+ {
+ { 26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556 },
+ { 14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749 },
+ { 236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930 }
+ },
+ {
+ { 1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391 },
+ { 5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253 },
+ { 20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066 }
+ },
+ {
+ { 24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958 },
+ { -11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082 },
+ { -28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383 }
+ },
+ {
+ { -30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521 },
+ { -11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807 },
+ { 23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948 }
+ },
+ {
+ { 9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134 },
+ { -32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455 },
+ { 27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629 }
+ }
+},
+{ /* 4/31 */
+ {
+ { -8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069 },
+ { -32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746 },
+ { 24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919 }
+ },
+ {
+ { 11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837 },
+ { 8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906 },
+ { -28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771 }
+ },
+ {
+ { -25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817 },
+ { 10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098 },
+ { 10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409 }
+ },
+ {
+ { -12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504 },
+ { -26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727 },
+ { 28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420 }
+ },
+ {
+ { -32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003 },
+ { -1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605 },
+ { -30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384 }
+ },
+ {
+ { -26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701 },
+ { -23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683 },
+ { 29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708 }
+ },
+ {
+ { -3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563 },
+ { -19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260 },
+ { -5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387 }
+ },
+ {
+ { -19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672 },
+ { 23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686 },
+ { -24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665 }
+ }
+},
+{ /* 5/31 */
+ {
+ { 11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182 },
+ { -31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277 },
+ { 14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628 }
+ },
+ {
+ { -4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474 },
+ { -26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539 },
+ { -25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822 }
+ },
+ {
+ { -10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970 },
+ { 19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756 },
+ { -24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508 }
+ },
+ {
+ { -26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683 },
+ { -10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655 },
+ { -20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158 }
+ },
+ {
+ { -4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125 },
+ { -15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839 },
+ { -20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664 }
+ },
+ {
+ { 27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294 },
+ { -18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899 },
+ { -11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070 }
+ },
+ {
+ { 3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294 },
+ { -15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949 },
+ { -21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083 }
+ },
+ {
+ { 31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420 },
+ { -5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940 },
+ { 29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396 }
+ }
+},
+{ /* 6/31 */
+ {
+ { -12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567 },
+ { 20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127 },
+ { -16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294 }
+ },
+ {
+ { -12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887 },
+ { 22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964 },
+ { 16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195 }
+ },
+ {
+ { 9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244 },
+ { 24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999 },
+ { -1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762 }
+ },
+ {
+ { -18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274 },
+ { -33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236 },
+ { -16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605 }
+ },
+ {
+ { -13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761 },
+ { -22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884 },
+ { -6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482 }
+ },
+ {
+ { -24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638 },
+ { -11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490 },
+ { -32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170 }
+ },
+ {
+ { 5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736 },
+ { 10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124 },
+ { -17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392 }
+ },
+ {
+ { 8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029 },
+ { 6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048 },
+ { 28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958 }
+ }
+},
+{ /* 7/31 */
+ {
+ { 24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593 },
+ { 26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071 },
+ { -11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692 }
+ },
+ {
+ { 11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687 },
+ { -160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441 },
+ { -20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001 }
+ },
+ {
+ { -938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460 },
+ { -19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007 },
+ { -21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762 }
+ },
+ {
+ { 15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005 },
+ { -9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674 },
+ { 4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035 }
+ },
+ {
+ { 7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590 },
+ { -2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957 },
+ { -30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812 }
+ },
+ {
+ { 33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740 },
+ { -18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122 },
+ { -27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158 }
+ },
+ {
+ { 8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885 },
+ { 26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140 },
+ { 19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857 }
+ },
+ {
+ { 801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155 },
+ { 19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260 },
+ { 19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483 }
+ }
+},
+{ /* 8/31 */
+ {
+ { -3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677 },
+ { 32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815 },
+ { 22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751 }
+ },
+ {
+ { -16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203 },
+ { -11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208 },
+ { 1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230 }
+ },
+ {
+ { 16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850 },
+ { -21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389 },
+ { -9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968 }
+ },
+ {
+ { -11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689 },
+ { 14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880 },
+ { 5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304 }
+ },
+ {
+ { 30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632 },
+ { -3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412 },
+ { 20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566 }
+ },
+ {
+ { -20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038 },
+ { -26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232 },
+ { -1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943 }
+ },
+ {
+ { 17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856 },
+ { 23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738 },
+ { 15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971 }
+ },
+ {
+ { -27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718 },
+ { -13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697 },
+ { -11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883 }
+ }
+},
+{ /* 9/31 */
+ {
+ { 5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912 },
+ { -26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358 },
+ { 3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849 }
+ },
+ {
+ { 29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307 },
+ { -14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977 },
+ { -6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335 }
+ },
+ {
+ { -29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644 },
+ { -22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616 },
+ { -27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735 }
+ },
+ {
+ { -21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099 },
+ { 29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341 },
+ { -936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336 }
+ },
+ {
+ { -23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646 },
+ { 31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425 },
+ { -17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388 }
+ },
+ {
+ { -31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743 },
+ { -16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822 },
+ { -8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462 }
+ },
+ {
+ { 18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985 },
+ { 9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702 },
+ { -22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797 }
+ },
+ {
+ { 21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293 },
+ { 27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100 },
+ { 19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688 }
+ }
+},
+{ /* 10/31 */
+ {
+ { 12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186 },
+ { 2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610 },
+ { -2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707 }
+ },
+ {
+ { 7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220 },
+ { 915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025 },
+ { 32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044 }
+ },
+ {
+ { 32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992 },
+ { -4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027 },
+ { 21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197 }
+ },
+ {
+ { 8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901 },
+ { 31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952 },
+ { 19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878 }
+ },
+ {
+ { -28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390 },
+ { 32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730 },
+ { 2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730 }
+ },
+ {
+ { -19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180 },
+ { -30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272 },
+ { -15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715 }
+ },
+ {
+ { -22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970 },
+ { -31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772 },
+ { -17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865 }
+ },
+ {
+ { 15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750 },
+ { 20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373 },
+ { 32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348 }
+ }
+},
+{ /* 11/31 */
+ {
+ { 9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144 },
+ { -22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195 },
+ { 5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086 }
+ },
+ {
+ { -13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684 },
+ { -8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518 },
+ { -2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233 }
+ },
+ {
+ { -5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793 },
+ { -2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794 },
+ { 580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435 }
+ },
+ {
+ { 23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921 },
+ { 13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518 },
+ { 2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563 }
+ },
+ {
+ { 14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278 },
+ { -27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024 },
+ { 4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030 }
+ },
+ {
+ { 10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783 },
+ { 27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717 },
+ { 6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844 }
+ },
+ {
+ { 14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333 },
+ { 16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048 },
+ { 22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760 }
+ },
+ {
+ { -4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760 },
+ { -15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757 },
+ { -2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112 }
+ }
+},
+{ /* 12/31 */
+ {
+ { -19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468 },
+ { 3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184 },
+ { 10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289 }
+ },
+ {
+ { 15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066 },
+ { 24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882 },
+ { 13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226 }
+ },
+ {
+ { 16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101 },
+ { 29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279 },
+ { -6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811 }
+ },
+ {
+ { 27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709 },
+ { 20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714 },
+ { -2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121 }
+ },
+ {
+ { 9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464 },
+ { 12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847 },
+ { 13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400 }
+ },
+ {
+ { 4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414 },
+ { -15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158 },
+ { 17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045 }
+ },
+ {
+ { -461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415 },
+ { -5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459 },
+ { -31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079 }
+ },
+ {
+ { 21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412 },
+ { -20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743 },
+ { -14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836 }
+ }
+},
+{ /* 13/31 */
+ {
+ { 12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022 },
+ { 18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429 },
+ { -6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065 }
+ },
+ {
+ { 30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861 },
+ { 10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000 },
+ { -33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101 }
+ },
+ {
+ { 32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815 },
+ { 29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642 },
+ { 10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966 }
+ },
+ {
+ { 25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574 },
+ { -21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742 },
+ { -18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689 }
+ },
+ {
+ { 12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020 },
+ { -10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772 },
+ { 3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982 }
+ },
+ {
+ { -14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953 },
+ { -16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218 },
+ { -17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265 }
+ },
+ {
+ { 29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073 },
+ { -3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325 },
+ { -11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798 }
+ },
+ {
+ { -4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870 },
+ { -7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863 },
+ { -13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927 }
+ }
+},
+{ /* 14/31 */
+ {
+ { -2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267 },
+ { -9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663 },
+ { 22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862 }
+ },
+ {
+ { -25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673 },
+ { 15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943 },
+ { 15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020 }
+ },
+ {
+ { -4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238 },
+ { 11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064 },
+ { 14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795 }
+ },
+ {
+ { 15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052 },
+ { -10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904 },
+ { 29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531 }
+ },
+ {
+ { -13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979 },
+ { -5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841 },
+ { 10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431 }
+ },
+ {
+ { 10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324 },
+ { -31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940 },
+ { 10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320 }
+ },
+ {
+ { -15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184 },
+ { 14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114 },
+ { 30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878 }
+ },
+ {
+ { 12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784 },
+ { -2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091 },
+ { -16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585 }
+ }
+},
+{ /* 15/31 */
+ {
+ { -8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208 },
+ { 10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864 },
+ { 17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661 }
+ },
+ {
+ { 7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233 },
+ { 26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212 },
+ { -12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525 }
+ },
+ {
+ { -24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068 },
+ { 9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397 },
+ { -8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988 }
+ },
+ {
+ { 5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889 },
+ { 32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038 },
+ { 14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697 }
+ },
+ {
+ { 20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875 },
+ { -25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905 },
+ { -25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656 }
+ },
+ {
+ { 11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818 },
+ { 27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714 },
+ { 10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203 }
+ },
+ {
+ { 20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931 },
+ { -30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024 },
+ { -23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084 }
+ },
+ {
+ { -1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204 },
+ { 20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817 },
+ { 27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667 }
+ }
+},
+{ /* 16/31 */
+ {
+ { 11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504 },
+ { -12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768 },
+ { -19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255 }
+ },
+ {
+ { 6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790 },
+ { 1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438 },
+ { -22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333 }
+ },
+ {
+ { 17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971 },
+ { 31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905 },
+ { 29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409 }
+ },
+ {
+ { 12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409 },
+ { 6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499 },
+ { -8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363 }
+ },
+ {
+ { 28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664 },
+ { -11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324 },
+ { -21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940 }
+ },
+ {
+ { 13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990 },
+ { -17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914 },
+ { -25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290 }
+ },
+ {
+ { 24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257 },
+ { -6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433 },
+ { -16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236 }
+ },
+ {
+ { -12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045 },
+ { 11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093 },
+ { -1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347 }
+ }
+},
+{ /* 17/31 */
+ {
+ { -28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191 },
+ { -15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507 },
+ { -12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906 }
+ },
+ {
+ { 3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018 },
+ { -16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109 },
+ { -23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926 }
+ },
+ {
+ { -24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528 },
+ { 8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625 },
+ { -32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286 }
+ },
+ {
+ { 2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033 },
+ { 27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866 },
+ { 21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896 }
+ },
+ {
+ { 30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075 },
+ { 26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347 },
+ { -22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437 }
+ },
+ {
+ { -5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165 },
+ { -18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588 },
+ { -32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193 }
+ },
+ {
+ { -19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017 },
+ { -28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883 },
+ { 21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961 }
+ },
+ {
+ { 8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043 },
+ { 29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663 },
+ { -20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362 }
+ }
+},
+{ /* 18/31 */
+ {
+ { -33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860 },
+ { 2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466 },
+ { -24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063 }
+ },
+ {
+ { -26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997 },
+ { -1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295 },
+ { -13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369 }
+ },
+ {
+ { 9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385 },
+ { 18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109 },
+ { 2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906 }
+ },
+ {
+ { 4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424 },
+ { -19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185 },
+ { 7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962 }
+ },
+ {
+ { -7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325 },
+ { 10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593 },
+ { 696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404 }
+ },
+ {
+ { -11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644 },
+ { 17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801 },
+ { 26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804 }
+ },
+ {
+ { -31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884 },
+ { -586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577 },
+ { -9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849 }
+ },
+ {
+ { 32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473 },
+ { -8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644 },
+ { -2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319 }
+ }
+},
+{ /* 19/31 */
+ {
+ { -11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599 },
+ { -9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768 },
+ { -27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084 }
+ },
+ {
+ { -27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328 },
+ { -15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369 },
+ { 20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920 }
+ },
+ {
+ { 12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815 },
+ { -32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025 },
+ { -21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397 }
+ },
+ {
+ { -20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448 },
+ { 6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981 },
+ { 30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165 }
+ },
+ {
+ { 32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501 },
+ { 17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073 },
+ { -1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861 }
+ },
+ {
+ { 14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845 },
+ { -1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211 },
+ { 18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870 }
+ },
+ {
+ { 10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096 },
+ { 33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803 },
+ { -32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168 }
+ },
+ {
+ { 30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965 },
+ { -14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505 },
+ { 18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598 }
+ }
+},
+{ /* 20/31 */
+ {
+ { 5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782 },
+ { 5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900 },
+ { -31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479 }
+ },
+ {
+ { -12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208 },
+ { 8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232 },
+ { 17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719 }
+ },
+ {
+ { 16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271 },
+ { -4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326 },
+ { -8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132 }
+ },
+ {
+ { 14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300 },
+ { 8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570 },
+ { 15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670 }
+ },
+ {
+ { -2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994 },
+ { -12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913 },
+ { 31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317 }
+ },
+ {
+ { -25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730 },
+ { 842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096 },
+ { -4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078 }
+ },
+ {
+ { -15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411 },
+ { -19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905 },
+ { -9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654 }
+ },
+ {
+ { -28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870 },
+ { -23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498 },
+ { 12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579 }
+ }
+},
+{ /* 21/31 */
+ {
+ { 14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677 },
+ { 10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647 },
+ { -2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743 }
+ },
+ {
+ { -25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468 },
+ { 21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375 },
+ { -25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155 }
+ },
+ {
+ { 6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725 },
+ { -12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612 },
+ { -10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943 }
+ },
+ {
+ { -30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944 },
+ { 30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928 },
+ { 9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406 }
+ },
+ {
+ { 22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139 },
+ { -8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963 },
+ { -31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693 }
+ },
+ {
+ { 1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734 },
+ { -448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680 },
+ { -24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410 }
+ },
+ {
+ { -9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931 },
+ { -16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654 },
+ { 22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710 }
+ },
+ {
+ { 29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180 },
+ { -26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684 },
+ { -10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895 }
+ }
+},
+{ /* 22/31 */
+ {
+ { 22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501 },
+ { -11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413 },
+ { 6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880 }
+ },
+ {
+ { -8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874 },
+ { 22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962 },
+ { -7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899 }
+ },
+ {
+ { 21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152 },
+ { 9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063 },
+ { 7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080 }
+ },
+ {
+ { -9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146 },
+ { -17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183 },
+ { -19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133 }
+ },
+ {
+ { -32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421 },
+ { -3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622 },
+ { -4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197 }
+ },
+ {
+ { 2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663 },
+ { 31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753 },
+ { 4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755 }
+ },
+ {
+ { -9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862 },
+ { -26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118 },
+ { 26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171 }
+ },
+ {
+ { 15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380 },
+ { 16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824 },
+ { 28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270 }
+ }
+},
+{ /* 23/31 */
+ {
+ { -817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438 },
+ { -31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584 },
+ { -594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562 }
+ },
+ {
+ { 30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471 },
+ { 18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610 },
+ { 19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269 }
+ },
+ {
+ { -30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650 },
+ { 14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369 },
+ { 19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461 }
+ },
+ {
+ { 30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462 },
+ { -5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793 },
+ { -2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218 }
+ },
+ {
+ { -24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226 },
+ { 18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019 },
+ { -15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037 }
+ },
+ {
+ { 31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171 },
+ { -17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132 },
+ { -28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841 }
+ },
+ {
+ { 21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181 },
+ { -33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210 },
+ { -1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040 }
+ },
+ {
+ { 3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935 },
+ { 24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105 },
+ { -28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814 }
+ }
+},
+{ /* 24/31 */
+ {
+ { 793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852 },
+ { 5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581 },
+ { -4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646 }
+ },
+ {
+ { 10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844 },
+ { 10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025 },
+ { 27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453 }
+ },
+ {
+ { -23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068 },
+ { 4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192 },
+ { -17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921 }
+ },
+ {
+ { -9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259 },
+ { -12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426 },
+ { -5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072 }
+ },
+ {
+ { -17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305 },
+ { 13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832 },
+ { 28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943 }
+ },
+ {
+ { -16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011 },
+ { 24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447 },
+ { 17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494 }
+ },
+ {
+ { -28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245 },
+ { -20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859 },
+ { 28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915 }
+ },
+ {
+ { 16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707 },
+ { 10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848 },
+ { -11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224 }
+ }
+},
+{ /* 25/31 */
+ {
+ { -25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391 },
+ { 15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215 },
+ { -23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101 }
+ },
+ {
+ { 23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713 },
+ { 21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849 },
+ { -7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930 }
+ },
+ {
+ { -29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940 },
+ { -21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031 },
+ { -17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404 }
+ },
+ {
+ { -25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243 },
+ { -23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116 },
+ { -24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525 }
+ },
+ {
+ { -23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509 },
+ { -10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883 },
+ { 15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865 }
+ },
+ {
+ { -3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660 },
+ { 4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273 },
+ { -28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138 }
+ },
+ {
+ { -25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560 },
+ { -10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135 },
+ { 2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941 }
+ },
+ {
+ { -4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739 },
+ { 18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756 },
+ { -30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819 }
+ }
+},
+{ /* 26/31 */
+ {
+ { -6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347 },
+ { -27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028 },
+ { 21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075 }
+ },
+ {
+ { 16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799 },
+ { -2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609 },
+ { -25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817 }
+ },
+ {
+ { -23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989 },
+ { -30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523 },
+ { 4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278 }
+ },
+ {
+ { 31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045 },
+ { 19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377 },
+ { 24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480 }
+ },
+ {
+ { 17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016 },
+ { 510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426 },
+ { 18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525 }
+ },
+ {
+ { 13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396 },
+ { 9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080 },
+ { 12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892 }
+ },
+ {
+ { 15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275 },
+ { 11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074 },
+ { 20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140 }
+ },
+ {
+ { -16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717 },
+ { -1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101 },
+ { 24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127 }
+ }
+},
+{ /* 27/31 */
+ {
+ { -12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632 },
+ { -26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415 },
+ { -31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160 }
+ },
+ {
+ { 31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876 },
+ { 22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625 },
+ { -15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478 }
+ },
+ {
+ { 27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164 },
+ { 26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595 },
+ { -7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248 }
+ },
+ {
+ { -16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858 },
+ { 15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193 },
+ { 8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184 }
+ },
+ {
+ { -18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942 },
+ { -1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635 },
+ { 21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948 }
+ },
+ {
+ { 11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935 },
+ { -25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415 },
+ { -15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416 }
+ },
+ {
+ { -7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018 },
+ { 4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778 },
+ { 366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659 }
+ },
+ {
+ { -24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385 },
+ { 18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503 },
+ { 476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329 }
+ }
+},
+{ /* 28/31 */
+ {
+ { 20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056 },
+ { -13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838 },
+ { 24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948 }
+ },
+ {
+ { -3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691 },
+ { -15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118 },
+ { -23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517 }
+ },
+ {
+ { -20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269 },
+ { -6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904 },
+ { -23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589 }
+ },
+ {
+ { -28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193 },
+ { -7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910 },
+ { -30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930 }
+ },
+ {
+ { -7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667 },
+ { 25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481 },
+ { -9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876 }
+ },
+ {
+ { 22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640 },
+ { -8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278 },
+ { -21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112 }
+ },
+ {
+ { 26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272 },
+ { 17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012 },
+ { -10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221 }
+ },
+ {
+ { 30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046 },
+ { 13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345 },
+ { -19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310 }
+ }
+},
+{ /* 29/31 */
+ {
+ { 19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937 },
+ { 31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636 },
+ { -9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008 }
+ },
+ {
+ { -2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429 },
+ { -15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576 },
+ { 31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066 }
+ },
+ {
+ { -9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490 },
+ { -12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104 },
+ { 33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053 }
+ },
+ {
+ { 31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275 },
+ { -20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511 },
+ { 22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095 }
+ },
+ {
+ { -28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439 },
+ { 23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939 },
+ { -23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424 }
+ },
+ {
+ { 2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310 },
+ { 3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608 },
+ { -32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079 }
+ },
+ {
+ { -23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101 },
+ { 21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418 },
+ { 18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576 }
+ },
+ {
+ { 30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356 },
+ { 9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996 },
+ { -26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099 }
+ }
+},
+{ /* 30/31 */
+ {
+ { -26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728 },
+ { -13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658 },
+ { -10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242 }
+ },
+ {
+ { -21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001 },
+ { -4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766 },
+ { 18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373 }
+ },
+ {
+ { 26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458 },
+ { -17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628 },
+ { -13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657 }
+ },
+ {
+ { -23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062 },
+ { 25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616 },
+ { 31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014 }
+ },
+ {
+ { 24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383 },
+ { -25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814 },
+ { -20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718 }
+ },
+ {
+ { 30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417 },
+ { 2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222 },
+ { 33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444 }
+ },
+ {
+ { -20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597 },
+ { 23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970 },
+ { 1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799 }
+ },
+ {
+ { -5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647 },
+ { 13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511 },
+ { -29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032 }
+ }
+},
+{ /* 31/31 */
+ {
+ { 9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834 },
+ { -23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461 },
+ { 29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062 }
+ },
+ {
+ { -25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516 },
+ { -20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547 },
+ { -24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240 }
+ },
+ {
+ { -17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038 },
+ { -33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741 },
+ { 16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103 }
+ },
+ {
+ { -19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747 },
+ { -1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323 },
+ { 31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016 }
+ },
+ {
+ { -14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373 },
+ { 15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228 },
+ { -2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141 }
+ },
+ {
+ { 16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399 },
+ { 11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831 },
+ { -185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376 }
+ },
+ {
+ { -32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313 },
+ { -18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958 },
+ { -6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577 }
+ },
+ {
+ { -22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743 },
+ { 29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684 },
+ { -20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476 }
+ }
+}
diff --git a/libs/libsodium/src/crypto_core/ed25519/ref10/fe_25_5/base2.h b/libs/libsodium/src/crypto_core/ed25519/ref10/fe_25_5/base2.h
new file mode 100644
index 0000000000..90a1457eab
--- /dev/null
+++ b/libs/libsodium/src/crypto_core/ed25519/ref10/fe_25_5/base2.h
@@ -0,0 +1,40 @@
+{
+ { 25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605 },
+ { -12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378 },
+ { -8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546 }
+},
+{
+ { 15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024 },
+ { 16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574 },
+ { 30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357 }
+},
+{
+ { 10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380 },
+ { 4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306 },
+ { 19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942 }
+},
+{
+ { 5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766 },
+ { -30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701 },
+ { 28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300 }
+},
+{
+ { -22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877 },
+ { -6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951 },
+ { 4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784 }
+},
+{
+ { -25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436 },
+ { 25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918 },
+ { 23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877 }
+},
+{
+ { -33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800 },
+ { -25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305 },
+ { -13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300 }
+},
+{
+ { -3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876 },
+ { -24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619 },
+ { -3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683 }
+}
diff --git a/libs/libsodium/src/crypto_core/ed25519/ref10/fe_25_5/constants.h b/libs/libsodium/src/crypto_core/ed25519/ref10/fe_25_5/constants.h
new file mode 100644
index 0000000000..3dc9156a31
--- /dev/null
+++ b/libs/libsodium/src/crypto_core/ed25519/ref10/fe_25_5/constants.h
@@ -0,0 +1,20 @@
+/* 37095705934669439343138083508754565189542113879843219016388785533085940283555 */
+static const fe25519 d = {
+ -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116
+};
+
+/* 2 * d =
+ * 16295367250680780974490674513165176452449235426866156013048779062215315747161
+ */
+static const fe25519 d2 = {
+ -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199 };
+
+/* sqrt(-1) */
+static const fe25519 sqrtm1 = {
+ -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482
+};
+
+/* A = 486662 */
+static const fe25519 curve25519_A = {
+ 486662, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
diff --git a/libs/libsodium/src/crypto_core/ed25519/ref10/fe_25_5/fe.h b/libs/libsodium/src/crypto_core/ed25519/ref10/fe_25_5/fe.h
new file mode 100644
index 0000000000..f216669e4e
--- /dev/null
+++ b/libs/libsodium/src/crypto_core/ed25519/ref10/fe_25_5/fe.h
@@ -0,0 +1,220 @@
+/*
+ Ignores top bit of h.
+ */
+
+void
+fe25519_frombytes(fe25519 h, const unsigned char *s)
+{
+ int64_t h0 = load_4(s);
+ int64_t h1 = load_3(s + 4) << 6;
+ int64_t h2 = load_3(s + 7) << 5;
+ int64_t h3 = load_3(s + 10) << 3;
+ int64_t h4 = load_3(s + 13) << 2;
+ int64_t h5 = load_4(s + 16);
+ int64_t h6 = load_3(s + 20) << 7;
+ int64_t h7 = load_3(s + 23) << 5;
+ int64_t h8 = load_3(s + 26) << 4;
+ int64_t h9 = (load_3(s + 29) & 8388607) << 2;
+
+ int64_t carry0;
+ int64_t carry1;
+ int64_t carry2;
+ int64_t carry3;
+ int64_t carry4;
+ int64_t carry5;
+ int64_t carry6;
+ int64_t carry7;
+ int64_t carry8;
+ int64_t carry9;
+
+ carry9 = (h9 + (int64_t)(1L << 24)) >> 25;
+ h0 += carry9 * 19;
+ h9 -= carry9 * ((uint64_t) 1L << 25);
+ carry1 = (h1 + (int64_t)(1L << 24)) >> 25;
+ h2 += carry1;
+ h1 -= carry1 * ((uint64_t) 1L << 25);
+ carry3 = (h3 + (int64_t)(1L << 24)) >> 25;
+ h4 += carry3;
+ h3 -= carry3 * ((uint64_t) 1L << 25);
+ carry5 = (h5 + (int64_t)(1L << 24)) >> 25;
+ h6 += carry5;
+ h5 -= carry5 * ((uint64_t) 1L << 25);
+ carry7 = (h7 + (int64_t)(1L << 24)) >> 25;
+ h8 += carry7;
+ h7 -= carry7 * ((uint64_t) 1L << 25);
+
+ carry0 = (h0 + (int64_t)(1L << 25)) >> 26;
+ h1 += carry0;
+ h0 -= carry0 * ((uint64_t) 1L << 26);
+ carry2 = (h2 + (int64_t)(1L << 25)) >> 26;
+ h3 += carry2;
+ h2 -= carry2 * ((uint64_t) 1L << 26);
+ carry4 = (h4 + (int64_t)(1L << 25)) >> 26;
+ h5 += carry4;
+ h4 -= carry4 * ((uint64_t) 1L << 26);
+ carry6 = (h6 + (int64_t)(1L << 25)) >> 26;
+ h7 += carry6;
+ h6 -= carry6 * ((uint64_t) 1L << 26);
+ carry8 = (h8 + (int64_t)(1L << 25)) >> 26;
+ h9 += carry8;
+ h8 -= carry8 * ((uint64_t) 1L << 26);
+
+ h[0] = (int32_t) h0;
+ h[1] = (int32_t) h1;
+ h[2] = (int32_t) h2;
+ h[3] = (int32_t) h3;
+ h[4] = (int32_t) h4;
+ h[5] = (int32_t) h5;
+ h[6] = (int32_t) h6;
+ h[7] = (int32_t) h7;
+ h[8] = (int32_t) h8;
+ h[9] = (int32_t) h9;
+}
+
+/*
+ Preconditions:
+ |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+
+ Write p=2^255-19; q=floor(h/p).
+ Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
+
+ Proof:
+ Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
+ Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4.
+
+ Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
+ Then 0<y<1.
+
+ Write r=h-pq.
+ Have 0<=r<=p-1=2^255-20.
+ Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
+
+ Write x=r+19(2^-255)r+y.
+ Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
+
+ Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
+ so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
+*/
+
+static void
+fe25519_reduce(fe25519 h, const fe25519 f)
+{
+ int32_t h0 = f[0];
+ int32_t h1 = f[1];
+ int32_t h2 = f[2];
+ int32_t h3 = f[3];
+ int32_t h4 = f[4];
+ int32_t h5 = f[5];
+ int32_t h6 = f[6];
+ int32_t h7 = f[7];
+ int32_t h8 = f[8];
+ int32_t h9 = f[9];
+
+ int32_t q;
+ int32_t carry0, carry1, carry2, carry3, carry4, carry5, carry6, carry7, carry8, carry9;
+
+ q = (19 * h9 + ((uint32_t) 1L << 24)) >> 25;
+ q = (h0 + q) >> 26;
+ q = (h1 + q) >> 25;
+ q = (h2 + q) >> 26;
+ q = (h3 + q) >> 25;
+ q = (h4 + q) >> 26;
+ q = (h5 + q) >> 25;
+ q = (h6 + q) >> 26;
+ q = (h7 + q) >> 25;
+ q = (h8 + q) >> 26;
+ q = (h9 + q) >> 25;
+
+ /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */
+ h0 += 19 * q;
+ /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
+
+ carry0 = h0 >> 26;
+ h1 += carry0;
+ h0 -= carry0 * ((uint32_t) 1L << 26);
+ carry1 = h1 >> 25;
+ h2 += carry1;
+ h1 -= carry1 * ((uint32_t) 1L << 25);
+ carry2 = h2 >> 26;
+ h3 += carry2;
+ h2 -= carry2 * ((uint32_t) 1L << 26);
+ carry3 = h3 >> 25;
+ h4 += carry3;
+ h3 -= carry3 * ((uint32_t) 1L << 25);
+ carry4 = h4 >> 26;
+ h5 += carry4;
+ h4 -= carry4 * ((uint32_t) 1L << 26);
+ carry5 = h5 >> 25;
+ h6 += carry5;
+ h5 -= carry5 * ((uint32_t) 1L << 25);
+ carry6 = h6 >> 26;
+ h7 += carry6;
+ h6 -= carry6 * ((uint32_t) 1L << 26);
+ carry7 = h7 >> 25;
+ h8 += carry7;
+ h7 -= carry7 * ((uint32_t) 1L << 25);
+ carry8 = h8 >> 26;
+ h9 += carry8;
+ h8 -= carry8 * ((uint32_t) 1L << 26);
+ carry9 = h9 >> 25;
+ h9 -= carry9 * ((uint32_t) 1L << 25);
+
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+ h[5] = h5;
+ h[6] = h6;
+ h[7] = h7;
+ h[8] = h8;
+ h[9] = h9;
+}
+
+/*
+ Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
+ Have h0+...+2^230 h9 between 0 and 2^255-1;
+ evidently 2^255 h10-2^255 q = 0.
+
+ Goal: Output h0+...+2^230 h9.
+ */
+
+void
+fe25519_tobytes(unsigned char *s, const fe25519 h)
+{
+ fe25519 t;
+
+ fe25519_reduce(t, h);
+ s[0] = t[0] >> 0;
+ s[1] = t[0] >> 8;
+ s[2] = t[0] >> 16;
+ s[3] = (t[0] >> 24) | (t[1] * ((uint32_t) 1 << 2));
+ s[4] = t[1] >> 6;
+ s[5] = t[1] >> 14;
+ s[6] = (t[1] >> 22) | (t[2] * ((uint32_t) 1 << 3));
+ s[7] = t[2] >> 5;
+ s[8] = t[2] >> 13;
+ s[9] = (t[2] >> 21) | (t[3] * ((uint32_t) 1 << 5));
+ s[10] = t[3] >> 3;
+ s[11] = t[3] >> 11;
+ s[12] = (t[3] >> 19) | (t[4] * ((uint32_t) 1 << 6));
+ s[13] = t[4] >> 2;
+ s[14] = t[4] >> 10;
+ s[15] = t[4] >> 18;
+ s[16] = t[5] >> 0;
+ s[17] = t[5] >> 8;
+ s[18] = t[5] >> 16;
+ s[19] = (t[5] >> 24) | (t[6] * ((uint32_t) 1 << 1));
+ s[20] = t[6] >> 7;
+ s[21] = t[6] >> 15;
+ s[22] = (t[6] >> 23) | (t[7] * ((uint32_t) 1 << 3));
+ s[23] = t[7] >> 5;
+ s[24] = t[7] >> 13;
+ s[25] = (t[7] >> 21) | (t[8] * ((uint32_t) 1 << 4));
+ s[26] = t[8] >> 4;
+ s[27] = t[8] >> 12;
+ s[28] = (t[8] >> 20) | (t[9] * ((uint32_t) 1 << 6));
+ s[29] = t[9] >> 2;
+ s[30] = t[9] >> 10;
+ s[31] = t[9] >> 18;
+}
diff --git a/libs/libsodium/src/crypto_core/ed25519/ref10/fe_51/base.h b/libs/libsodium/src/crypto_core/ed25519/ref10/fe_51/base.h
new file mode 100644
index 0000000000..6b3b833e7a
--- /dev/null
+++ b/libs/libsodium/src/crypto_core/ed25519/ref10/fe_51/base.h
@@ -0,0 +1,1344 @@
+{ /* 0/31 */
+ {
+ { 1288382639258501, 245678601348599, 269427782077623, 1462984067271730, 137412439391563 },
+ { 62697248952638, 204681361388450, 631292143396476, 338455783676468, 1213667448819585 },
+ { 301289933810280, 1259582250014073, 1422107436869536, 796239922652654, 1953934009299142 }
+ },
+ {
+ { 1380971894829527, 790832306631236, 2067202295274102, 1995808275510000, 1566530869037010 },
+ { 463307831301544, 432984605774163, 1610641361907204, 750899048855000, 1894842303421586 },
+ { 748439484463711, 1033211726465151, 1396005112841647, 1611506220286469, 1972177495910992 }
+ },
+ {
+ { 1601611775252272, 1720807796594148, 1132070835939856, 1260455018889551, 2147779492816911 },
+ { 316559037616741, 2177824224946892, 1459442586438991, 1461528397712656, 751590696113597 },
+ { 1850748884277385, 1200145853858453, 1068094770532492, 672251375690438, 1586055907191707 }
+ },
+ {
+ { 934282339813791, 1846903124198670, 1172395437954843, 1007037127761661, 1830588347719256 },
+ { 1694390458783935, 1735906047636159, 705069562067493, 648033061693059, 696214010414170 },
+ { 1121406372216585, 192876649532226, 190294192191717, 1994165897297032, 2245000007398739 }
+ },
+ {
+ { 769950342298419, 132954430919746, 844085933195555, 974092374476333, 726076285546016 },
+ { 425251763115706, 608463272472562, 442562545713235, 837766094556764, 374555092627893 },
+ { 1086255230780037, 274979815921559, 1960002765731872, 929474102396301, 1190409889297339 }
+ },
+ {
+ { 1388594989461809, 316767091099457, 394298842192982, 1230079486801005, 1440737038838979 },
+ { 7380825640100, 146210432690483, 304903576448906, 1198869323871120, 997689833219095 },
+ { 1181317918772081, 114573476638901, 262805072233344, 265712217171332, 294181933805782 }
+ },
+ {
+ { 665000864555967, 2065379846933859, 370231110385876, 350988370788628, 1233371373142985 },
+ { 2019367628972465, 676711900706637, 110710997811333, 1108646842542025, 517791959672113 },
+ { 965130719900578, 247011430587952, 526356006571389, 91986625355052, 2157223321444601 }
+ },
+ {
+ { 2068619540119183, 1966274918058806, 957728544705549, 729906502578991, 159834893065166 },
+ { 2073601412052185, 31021124762708, 264500969797082, 248034690651703, 1030252227928288 },
+ { 551790716293402, 1989538725166328, 801169423371717, 2052451893578887, 678432056995012 }
+ }
+},
+{ /* 1/31 */
+ {
+ { 1368953770187805, 790347636712921, 437508475667162, 2142576377050580, 1932081720066286 },
+ { 953638594433374, 1092333936795051, 1419774766716690, 805677984380077, 859228993502513 },
+ { 1200766035879111, 20142053207432, 1465634435977050, 1645256912097844, 295121984874596 }
+ },
+ {
+ { 1735718747031557, 1248237894295956, 1204753118328107, 976066523550493, 65943769534592 },
+ { 1060098822528990, 1586825862073490, 212301317240126, 1975302711403555, 666724059764335 },
+ { 1091990273418756, 1572899409348578, 80968014455247, 306009358661350, 1520450739132526 }
+ },
+ {
+ { 1480517209436112, 1511153322193952, 1244343858991172, 304788150493241, 369136856496443 },
+ { 2151330273626164, 762045184746182, 1688074332551515, 823046109005759, 907602769079491 },
+ { 2047386910586836, 168470092900250, 1552838872594810, 340951180073789, 360819374702533 }
+ },
+ {
+ { 1982622644432056, 2014393600336956, 128909208804214, 1617792623929191, 105294281913815 },
+ { 980234343912898, 1712256739246056, 588935272190264, 204298813091998, 841798321043288 },
+ { 197561292938973, 454817274782871, 1963754960082318, 2113372252160468, 971377527342673 }
+ },
+ {
+ { 164699448829328, 3127451757672, 1199504971548753, 1766155447043652, 1899238924683527 },
+ { 732262946680281, 1674412764227063, 2182456405662809, 1350894754474250, 558458873295247 },
+ { 2103305098582922, 1960809151316468, 715134605001343, 1454892949167181, 40827143824949 }
+ },
+ {
+ { 1239289043050212, 1744654158124578, 758702410031698, 1796762995074688, 1603056663766 },
+ { 2232056027107988, 987343914584615, 2115594492994461, 1819598072792159, 1119305654014850 },
+ { 320153677847348, 939613871605645, 641883205761567, 1930009789398224, 329165806634126 }
+ },
+ {
+ { 980930490474130, 1242488692177893, 1251446316964684, 1086618677993530, 1961430968465772 },
+ { 276821765317453, 1536835591188030, 1305212741412361, 61473904210175, 2051377036983058 },
+ { 833449923882501, 1750270368490475, 1123347002068295, 185477424765687, 278090826653186 }
+ },
+ {
+ { 794524995833413, 1849907304548286, 53348672473145, 1272368559505217, 1147304168324779 },
+ { 1504846112759364, 1203096289004681, 562139421471418, 274333017451844, 1284344053775441 },
+ { 483048732424432, 2116063063343382, 30120189902313, 292451576741007, 1156379271702225 }
+ }
+},
+{ /* 2/31 */
+ {
+ { 928372153029038, 2147692869914564, 1455665844462196, 1986737809425946, 185207050258089 },
+ { 137732961814206, 706670923917341, 1387038086865771, 1965643813686352, 1384777115696347 },
+ { 481144981981577, 2053319313589856, 2065402289827512, 617954271490316, 1106602634668125 }
+ },
+ {
+ { 696298019648792, 893299659040895, 1148636718636009, 26734077349617, 2203955659340681 },
+ { 657390353372855, 998499966885562, 991893336905797, 810470207106761, 343139804608786 },
+ { 791736669492960, 934767652997115, 824656780392914, 1759463253018643, 361530362383518 }
+ },
+ {
+ { 2022541353055597, 2094700262587466, 1551008075025686, 242785517418164, 695985404963562 },
+ { 1287487199965223, 2215311941380308, 1552928390931986, 1664859529680196, 1125004975265243 },
+ { 677434665154918, 989582503122485, 1817429540898386, 1052904935475344, 1143826298169798 }
+ },
+ {
+ { 367266328308408, 318431188922404, 695629353755355, 634085657580832, 24581612564426 },
+ { 773360688841258, 1815381330538070, 363773437667376, 539629987070205, 783280434248437 },
+ { 180820816194166, 168937968377394, 748416242794470, 1227281252254508, 1567587861004268 }
+ },
+ {
+ { 478775558583645, 2062896624554807, 699391259285399, 358099408427873, 1277310261461761 },
+ { 1984740906540026, 1079164179400229, 1056021349262661, 1659958556483663, 1088529069025527 },
+ { 580736401511151, 1842931091388998, 1177201471228238, 2075460256527244, 1301133425678027 }
+ },
+ {
+ { 1515728832059182, 1575261009617579, 1510246567196186, 191078022609704, 116661716289141 },
+ { 1295295738269652, 1714742313707026, 545583042462581, 2034411676262552, 1513248090013606 },
+ { 230710545179830, 30821514358353, 760704303452229, 390668103790604, 573437871383156 }
+ },
+ {
+ { 1169380107545646, 263167233745614, 2022901299054448, 819900753251120, 2023898464874585 },
+ { 2102254323485823, 1570832666216754, 34696906544624, 1993213739807337, 70638552271463 },
+ { 894132856735058, 548675863558441, 845349339503395, 1942269668326667, 1615682209874691 }
+ },
+ {
+ { 1287670217537834, 1222355136884920, 1846481788678694, 1150426571265110, 1613523400722047 },
+ { 793388516527298, 1315457083650035, 1972286999342417, 1901825953052455, 338269477222410 },
+ { 550201530671806, 778605267108140, 2063911101902983, 115500557286349, 2041641272971022 }
+ }
+},
+{ /* 3/31 */
+ {
+ { 717255318455100, 519313764361315, 2080406977303708, 541981206705521, 774328150311600 },
+ { 261715221532238, 1795354330069993, 1496878026850283, 499739720521052, 389031152673770 },
+ { 1997217696294013, 1717306351628065, 1684313917746180, 1644426076011410, 1857378133465451 }
+ },
+ {
+ { 1475434724792648, 76931896285979, 1116729029771667, 2002544139318042, 725547833803938 },
+ { 2022306639183567, 726296063571875, 315345054448644, 1058733329149221, 1448201136060677 },
+ { 1710065158525665, 1895094923036397, 123988286168546, 1145519900776355, 1607510767693874 }
+ },
+ {
+ { 561605375422540, 1071733543815037, 131496498800990, 1946868434569999, 828138133964203 },
+ { 1548495173745801, 442310529226540, 998072547000384, 553054358385281, 644824326376171 },
+ { 1445526537029440, 2225519789662536, 914628859347385, 1064754194555068, 1660295614401091 }
+ },
+ {
+ { 1199690223111956, 24028135822341, 66638289244341, 57626156285975, 565093967979607 },
+ { 876926774220824, 554618976488214, 1012056309841565, 839961821554611, 1414499340307677 },
+ { 703047626104145, 1266841406201770, 165556500219173, 486991595001879, 1011325891650656 }
+ },
+ {
+ { 1622861044480487, 1156394801573634, 1869132565415504, 327103985777730, 2095342781472284 },
+ { 334886927423922, 489511099221528, 129160865966726, 1720809113143481, 619700195649254 },
+ { 1646545795166119, 1758370782583567, 714746174550637, 1472693650165135, 898994790308209 }
+ },
+ {
+ { 333403773039279, 295772542452938, 1693106465353610, 912330357530760, 471235657950362 },
+ { 1811196219982022, 1068969825533602, 289602974833439, 1988956043611592, 863562343398367 },
+ { 906282429780072, 2108672665779781, 432396390473936, 150625823801893, 1708930497638539 }
+ },
+ {
+ { 925664675702328, 21416848568684, 1831436641861340, 601157008940113, 371818055044496 },
+ { 1479786007267725, 1738881859066675, 68646196476567, 2146507056100328, 1247662817535471 },
+ { 52035296774456, 939969390708103, 312023458773250, 59873523517659, 1231345905848899 }
+ },
+ {
+ { 643355106415761, 290186807495774, 2013561737429023, 319648069511546, 393736678496162 },
+ { 129358342392716, 1932811617704777, 1176749390799681, 398040349861790, 1170779668090425 },
+ { 2051980782668029, 121859921510665, 2048329875753063, 1235229850149665, 519062146124755 }
+ }
+},
+{ /* 4/31 */
+ {
+ { 1608170971973096, 415809060360428, 1350468408164766, 2038620059057678, 1026904485989112 },
+ { 1837656083115103, 1510134048812070, 906263674192061, 1821064197805734, 565375124676301 },
+ { 578027192365650, 2034800251375322, 2128954087207123, 478816193810521, 2196171989962750 }
+ },
+ {
+ { 1633188840273139, 852787172373708, 1548762607215796, 1266275218902681, 1107218203325133 },
+ { 462189358480054, 1784816734159228, 1611334301651368, 1303938263943540, 707589560319424 },
+ { 1038829280972848, 38176604650029, 753193246598573, 1136076426528122, 595709990562434 }
+ },
+ {
+ { 1408451820859834, 2194984964010833, 2198361797561729, 1061962440055713, 1645147963442934 },
+ { 4701053362120, 1647641066302348, 1047553002242085, 1923635013395977, 206970314902065 },
+ { 1750479161778571, 1362553355169293, 1891721260220598, 966109370862782, 1024913988299801 }
+ },
+ {
+ { 212699049131723, 1117950018299775, 1873945661751056, 1403802921984058, 130896082652698 },
+ { 636808533673210, 1262201711667560, 390951380330599, 1663420692697294, 561951321757406 },
+ { 520731594438141, 1446301499955692, 273753264629267, 1565101517999256, 1019411827004672 }
+ },
+ {
+ { 926527492029409, 1191853477411379, 734233225181171, 184038887541270, 1790426146325343 },
+ { 1464651961852572, 1483737295721717, 1519450561335517, 1161429831763785, 405914998179977 },
+ { 996126634382301, 796204125879525, 127517800546509, 344155944689303, 615279846169038 }
+ },
+ {
+ { 738724080975276, 2188666632415296, 1961313708559162, 1506545807547587, 1151301638969740 },
+ { 622917337413835, 1218989177089035, 1284857712846592, 970502061709359, 351025208117090 },
+ { 2067814584765580, 1677855129927492, 2086109782475197, 235286517313238, 1416314046739645 }
+ },
+ {
+ { 586844262630358, 307444381952195, 458399356043426, 602068024507062, 1028548203415243 },
+ { 678489922928203, 2016657584724032, 90977383049628, 1026831907234582, 615271492942522 },
+ { 301225714012278, 1094837270268560, 1202288391010439, 644352775178361, 1647055902137983 }
+ },
+ {
+ { 1210746697896478, 1416608304244708, 686487477217856, 1245131191434135, 1051238336855737 },
+ { 1135604073198207, 1683322080485474, 769147804376683, 2086688130589414, 900445683120379 },
+ { 1971518477615628, 401909519527336, 448627091057375, 1409486868273821, 1214789035034363 }
+ }
+},
+{ /* 5/31 */
+ {
+ { 1364039144731711, 1897497433586190, 2203097701135459, 145461396811251, 1349844460790699 },
+ { 1045230323257973, 818206601145807, 630513189076103, 1672046528998132, 807204017562437 },
+ { 439961968385997, 386362664488986, 1382706320807688, 309894000125359, 2207801346498567 }
+ },
+ {
+ { 1229004686397588, 920643968530863, 123975893911178, 681423993215777, 1400559197080973 },
+ { 2003766096898049, 170074059235165, 1141124258967971, 1485419893480973, 1573762821028725 },
+ { 729905708611432, 1270323270673202, 123353058984288, 426460209632942, 2195574535456672 }
+ },
+ {
+ { 1271140255321235, 2044363183174497, 52125387634689, 1445120246694705, 942541986339084 },
+ { 1761608437466135, 583360847526804, 1586706389685493, 2157056599579261, 1170692369685772 },
+ { 871476219910823, 1878769545097794, 2241832391238412, 548957640601001, 690047440233174 }
+ },
+ {
+ { 297194732135507, 1366347803776820, 1301185512245601, 561849853336294, 1533554921345731 },
+ { 999628998628371, 1132836708493400, 2084741674517453, 469343353015612, 678782988708035 },
+ { 2189427607417022, 699801937082607, 412764402319267, 1478091893643349, 2244675696854460 }
+ },
+ {
+ { 1712292055966563, 204413590624874, 1405738637332841, 408981300829763, 861082219276721 },
+ { 508561155940631, 966928475686665, 2236717801150132, 424543858577297, 2089272956986143 },
+ { 221245220129925, 1156020201681217, 491145634799213, 542422431960839, 828100817819207 }
+ },
+ {
+ { 153756971240384, 1299874139923977, 393099165260502, 1058234455773022, 996989038681183 },
+ { 559086812798481, 573177704212711, 1629737083816402, 1399819713462595, 1646954378266038 },
+ { 1887963056288059, 228507035730124, 1468368348640282, 930557653420194, 613513962454686 }
+ },
+ {
+ { 1224529808187553, 1577022856702685, 2206946542980843, 625883007765001, 279930793512158 },
+ { 1076287717051609, 1114455570543035, 187297059715481, 250446884292121, 1885187512550540 },
+ { 902497362940219, 76749815795675, 1657927525633846, 1420238379745202, 1340321636548352 }
+ },
+ {
+ { 1129576631190784, 1281994010027327, 996844254743018, 257876363489249, 1150850742055018 },
+ { 628740660038789, 1943038498527841, 467786347793886, 1093341428303375, 235413859513003 },
+ { 237425418909360, 469614029179605, 1512389769174935, 1241726368345357, 441602891065214 }
+ }
+},
+{ /* 6/31 */
+ {
+ { 1736417953058555, 726531315520508, 1833335034432527, 1629442561574747, 624418919286085 },
+ { 1960754663920689, 497040957888962, 1909832851283095, 1271432136996826, 2219780368020940 },
+ { 1537037379417136, 1358865369268262, 2130838645654099, 828733687040705, 1999987652890901 }
+ },
+ {
+ { 629042105241814, 1098854999137608, 887281544569320, 1423102019874777, 7911258951561 },
+ { 1811562332665373, 1501882019007673, 2213763501088999, 359573079719636, 36370565049116 },
+ { 218907117361280, 1209298913016966, 1944312619096112, 1130690631451061, 1342327389191701 }
+ },
+ {
+ { 1369976867854704, 1396479602419169, 1765656654398856, 2203659200586299, 998327836117241 },
+ { 2230701885562825, 1348173180338974, 2172856128624598, 1426538746123771, 444193481326151 },
+ { 784210426627951, 918204562375674, 1284546780452985, 1324534636134684, 1872449409642708 }
+ },
+ {
+ { 319638829540294, 596282656808406, 2037902696412608, 1557219121643918, 341938082688094 },
+ { 1901860206695915, 2004489122065736, 1625847061568236, 973529743399879, 2075287685312905 },
+ { 1371853944110545, 1042332820512553, 1949855697918254, 1791195775521505, 37487364849293 }
+ },
+ {
+ { 687200189577855, 1082536651125675, 644224940871546, 340923196057951, 343581346747396 },
+ { 2082717129583892, 27829425539422, 145655066671970, 1690527209845512, 1865260509673478 },
+ { 1059729620568824, 2163709103470266, 1440302280256872, 1769143160546397, 869830310425069 }
+ },
+ {
+ { 1609516219779025, 777277757338817, 2101121130363987, 550762194946473, 1905542338659364 },
+ { 2024821921041576, 426948675450149, 595133284085473, 471860860885970, 600321679413000 },
+ { 598474602406721, 1468128276358244, 1191923149557635, 1501376424093216, 1281662691293476 }
+ },
+ {
+ { 1721138489890707, 1264336102277790, 433064545421287, 1359988423149466, 1561871293409447 },
+ { 719520245587143, 393380711632345, 132350400863381, 1543271270810729, 1819543295798660 },
+ { 396397949784152, 1811354474471839, 1362679985304303, 2117033964846756, 498041172552279 }
+ },
+ {
+ { 1812471844975748, 1856491995543149, 126579494584102, 1036244859282620, 1975108050082550 },
+ { 650623932407995, 1137551288410575, 2125223403615539, 1725658013221271, 2134892965117796 },
+ { 522584000310195, 1241762481390450, 1743702789495384, 2227404127826575, 1686746002148897 }
+ }
+},
+{ /* 7/31 */
+ {
+ { 427904865186312, 1703211129693455, 1585368107547509, 1436984488744336, 761188534613978 },
+ { 318101947455002, 248138407995851, 1481904195303927, 309278454311197, 1258516760217879 },
+ { 1275068538599310, 513726919533379, 349926553492294, 688428871968420, 1702400196000666 }
+ },
+ {
+ { 1061864036265233, 961611260325381, 321859632700838, 1045600629959517, 1985130202504038 },
+ { 1558816436882417, 1962896332636523, 1337709822062152, 1501413830776938, 294436165831932 },
+ { 818359826554971, 1862173000996177, 626821592884859, 573655738872376, 1749691246745455 }
+ },
+ {
+ { 1988022651432119, 1082111498586040, 1834020786104821, 1454826876423687, 692929915223122 },
+ { 2146513703733331, 584788900394667, 464965657279958, 2183973639356127, 238371159456790 },
+ { 1129007025494441, 2197883144413266, 265142755578169, 971864464758890, 1983715884903702 }
+ },
+ {
+ { 1291366624493075, 381456718189114, 1711482489312444, 1815233647702022, 892279782992467 },
+ { 444548969917454, 1452286453853356, 2113731441506810, 645188273895859, 810317625309512 },
+ { 2242724082797924, 1373354730327868, 1006520110883049, 2147330369940688, 1151816104883620 }
+ },
+ {
+ { 1745720200383796, 1911723143175317, 2056329390702074, 355227174309849, 879232794371100 },
+ { 163723479936298, 115424889803150, 1156016391581227, 1894942220753364, 1970549419986329 },
+ { 681981452362484, 267208874112496, 1374683991933094, 638600984916117, 646178654558546 }
+ },
+ {
+ { 13378654854251, 106237307029567, 1944412051589651, 1841976767925457, 230702819835573 },
+ { 260683893467075, 854060306077237, 913639551980112, 4704576840123, 280254810808712 },
+ { 715374893080287, 1173334812210491, 1806524662079626, 1894596008000979, 398905715033393 }
+ },
+ {
+ { 500026409727661, 1596431288195371, 1420380351989370, 985211561521489, 392444930785633 },
+ { 2096421546958141, 1922523000950363, 789831022876840, 427295144688779, 320923973161730 },
+ { 1927770723575450, 1485792977512719, 1850996108474547, 551696031508956, 2126047405475647 }
+ },
+ {
+ { 2112099158080148, 742570803909715, 6484558077432, 1951119898618916, 93090382703416 },
+ { 383905201636970, 859946997631870, 855623867637644, 1017125780577795, 794250831877809 },
+ { 77571826285752, 999304298101753, 487841111777762, 1038031143212339, 339066367948762 }
+ }
+},
+{ /* 8/31 */
+ {
+ { 674994775520533, 266035846330789, 826951213393478, 1405007746162285, 1781791018620876 },
+ { 1001412661522686, 348196197067298, 1666614366723946, 888424995032760, 580747687801357 },
+ { 1939560076207777, 1409892634407635, 552574736069277, 383854338280405, 190706709864139 }
+ },
+ {
+ { 2177087163428741, 1439255351721944, 1208070840382793, 2230616362004769, 1396886392021913 },
+ { 676962063230039, 1880275537148808, 2046721011602706, 888463247083003, 1318301552024067 },
+ { 1466980508178206, 617045217998949, 652303580573628, 757303753529064, 207583137376902 }
+ },
+ {
+ { 1511056752906902, 105403126891277, 493434892772846, 1091943425335976, 1802717338077427 },
+ { 1853982405405128, 1878664056251147, 1528011020803992, 1019626468153565, 1128438412189035 },
+ { 1963939888391106, 293456433791664, 697897559513649, 985882796904380, 796244541237972 }
+ },
+ {
+ { 416770998629779, 389655552427054, 1314476859406756, 1749382513022778, 1161905598739491 },
+ { 1428358296490651, 1027115282420478, 304840698058337, 441410174026628, 1819358356278573 },
+ { 204943430200135, 1554861433819175, 216426658514651, 264149070665950, 2047097371738319 }
+ },
+ {
+ { 1934415182909034, 1393285083565062, 516409331772960, 1157690734993892, 121039666594268 },
+ { 662035583584445, 286736105093098, 1131773000510616, 818494214211439, 472943792054479 },
+ { 665784778135882, 1893179629898606, 808313193813106, 276797254706413, 1563426179676396 }
+ },
+ {
+ { 945205108984232, 526277562959295, 1324180513733566, 1666970227868664, 153547609289173 },
+ { 2031433403516252, 203996615228162, 170487168837083, 981513604791390, 843573964916831 },
+ { 1476570093962618, 838514669399805, 1857930577281364, 2017007352225784, 317085545220047 }
+ },
+ {
+ { 1461557121912842, 1600674043318359, 2157134900399597, 1670641601940616, 127765583803283 },
+ { 1293543509393474, 2143624609202546, 1058361566797508, 214097127393994, 946888515472729 },
+ { 357067959932916, 1290876214345711, 521245575443703, 1494975468601005, 800942377643885 }
+ },
+ {
+ { 566116659100033, 820247422481740, 994464017954148, 327157611686365, 92591318111744 },
+ { 617256647603209, 1652107761099439, 1857213046645471, 1085597175214970, 817432759830522 },
+ { 771808161440705, 1323510426395069, 680497615846440, 851580615547985, 1320806384849017 }
+ }
+},
+{ /* 9/31 */
+ {
+ { 1219260086131915, 647169006596815, 79601124759706, 2161724213426748, 404861897060198 },
+ { 1327968293887866, 1335500852943256, 1401587164534264, 558137311952440, 1551360549268902 },
+ { 417621685193956, 1429953819744454, 396157358457099, 1940470778873255, 214000046234152 }
+ },
+ {
+ { 1268047918491973, 2172375426948536, 1533916099229249, 1761293575457130, 1590622667026765 },
+ { 1627072914981959, 2211603081280073, 1912369601616504, 1191770436221309, 2187309757525860 },
+ { 1149147819689533, 378692712667677, 828475842424202, 2218619146419342, 70688125792186 }
+ },
+ {
+ { 1299739417079761, 1438616663452759, 1536729078504412, 2053896748919838, 1008421032591246 },
+ { 2040723824657366, 399555637875075, 632543375452995, 872649937008051, 1235394727030233 },
+ { 2211311599327900, 2139787259888175, 938706616835350, 12609661139114, 2081897930719789 }
+ },
+ {
+ { 1324994503390450, 336982330582631, 1183998925654177, 1091654665913274, 48727673971319 },
+ { 1845522914617879, 1222198248335542, 150841072760134, 1927029069940982, 1189913404498011 },
+ { 1079559557592645, 2215338383666441, 1903569501302605, 49033973033940, 305703433934152 }
+ },
+ {
+ { 94653405416909, 1386121349852999, 1062130477891762, 36553947479274, 833669648948846 },
+ { 1432015813136298, 440364795295369, 1395647062821501, 1976874522764578, 934452372723352 },
+ { 1296625309219774, 2068273464883862, 1858621048097805, 1492281814208508, 2235868981918946 }
+ },
+ {
+ { 1490330266465570, 1858795661361448, 1436241134969763, 294573218899647, 1208140011028933 },
+ { 1282462923712748, 741885683986255, 2027754642827561, 518989529541027, 1826610009555945 },
+ { 1525827120027511, 723686461809551, 1597702369236987, 244802101764964, 1502833890372311 }
+ },
+ {
+ { 113622036244513, 1233740067745854, 674109952278496, 2114345180342965, 166764512856263 },
+ { 2041668749310338, 2184405322203901, 1633400637611036, 2110682505536899, 2048144390084644 },
+ { 503058759232932, 760293024620937, 2027152777219493, 666858468148475, 1539184379870952 }
+ },
+ {
+ { 1916168475367211, 915626432541343, 883217071712575, 363427871374304, 1976029821251593 },
+ { 678039535434506, 570587290189340, 1605302676614120, 2147762562875701, 1706063797091704 },
+ { 1439489648586438, 2194580753290951, 832380563557396, 561521973970522, 584497280718389 }
+ }
+},
+{ /* 10/31 */
+ {
+ { 187989455492609, 681223515948275, 1933493571072456, 1872921007304880, 488162364135671 },
+ { 1413466089534451, 410844090765630, 1397263346404072, 408227143123410, 1594561803147811 },
+ { 2102170800973153, 719462588665004, 1479649438510153, 1097529543970028, 1302363283777685 }
+ },
+ {
+ { 942065717847195, 1069313679352961, 2007341951411051, 70973416446291, 1419433790163706 },
+ { 1146565545556377, 1661971299445212, 406681704748893, 564452436406089, 1109109865829139 },
+ { 2214421081775077, 1165671861210569, 1890453018796184, 3556249878661, 442116172656317 }
+ },
+ {
+ { 753830546620811, 1666955059895019, 1530775289309243, 1119987029104146, 2164156153857580 },
+ { 615171919212796, 1523849404854568, 854560460547503, 2067097370290715, 1765325848586042 },
+ { 1094538949313667, 1796592198908825, 870221004284388, 2025558921863561, 1699010892802384 }
+ },
+ {
+ { 1951351290725195, 1916457206844795, 198025184438026, 1909076887557595, 1938542290318919 },
+ { 1014323197538413, 869150639940606, 1756009942696599, 1334952557375672, 1544945379082874 },
+ { 764055910920305, 1603590757375439, 146805246592357, 1843313433854297, 954279890114939 }
+ },
+ {
+ { 80113526615750, 764536758732259, 1055139345100233, 469252651759390, 617897512431515 },
+ { 74497112547268, 740094153192149, 1745254631717581, 727713886503130, 1283034364416928 },
+ { 525892105991110, 1723776830270342, 1476444848991936, 573789489857760, 133864092632978 }
+ },
+ {
+ { 542611720192581, 1986812262899321, 1162535242465837, 481498966143464, 544600533583622 },
+ { 64123227344372, 1239927720647794, 1360722983445904, 222610813654661, 62429487187991 },
+ { 1793193323953132, 91096687857833, 70945970938921, 2158587638946380, 1537042406482111 }
+ },
+ {
+ { 1895854577604609, 1394895708949416, 1728548428495944, 1140864900240149, 563645333603061 },
+ { 141358280486863, 91435889572504, 1087208572552643, 1829599652522921, 1193307020643647 },
+ { 1611230858525381, 950720175540785, 499589887488610, 2001656988495019, 88977313255908 }
+ },
+ {
+ { 1189080501479658, 2184348804772597, 1040818725742319, 2018318290311834, 1712060030915354 },
+ { 873966876953756, 1090638350350440, 1708559325189137, 672344594801910, 1320437969700239 },
+ { 1508590048271766, 1131769479776094, 101550868699323, 428297785557897, 561791648661744 }
+ }
+},
+{ /* 11/31 */
+ {
+ { 756417570499462, 237882279232602, 2136263418594016, 1701968045454886, 703713185137472 },
+ { 1781187809325462, 1697624151492346, 1381393690939988, 175194132284669, 1483054666415238 },
+ { 2175517777364616, 708781536456029, 955668231122942, 1967557500069555, 2021208005604118 }
+ },
+ {
+ { 1115135966606887, 224217372950782, 915967306279222, 593866251291540, 561747094208006 },
+ { 1443163092879439, 391875531646162, 2180847134654632, 464538543018753, 1594098196837178 },
+ { 850858855888869, 319436476624586, 327807784938441, 740785849558761, 17128415486016 }
+ },
+ {
+ { 2132756334090067, 536247820155645, 48907151276867, 608473197600695, 1261689545022784 },
+ { 1525176236978354, 974205476721062, 293436255662638, 148269621098039, 137961998433963 },
+ { 1121075518299410, 2071745529082111, 1265567917414828, 1648196578317805, 496232102750820 }
+ },
+ {
+ { 122321229299801, 1022922077493685, 2001275453369484, 2017441881607947, 993205880778002 },
+ { 654925550560074, 1168810995576858, 575655959430926, 905758704861388, 496774564663534 },
+ { 1954109525779738, 2117022646152485, 338102630417180, 1194140505732026, 107881734943492 }
+ },
+ {
+ { 1714785840001267, 2036500018681589, 1876380234251966, 2056717182974196, 1645855254384642 },
+ { 106431476499341, 62482972120563, 1513446655109411, 807258751769522, 538491469114 },
+ { 2002850762893643, 1243624520538135, 1486040410574605, 2184752338181213, 378495998083531 }
+ },
+ {
+ { 922510868424903, 1089502620807680, 402544072617374, 1131446598479839, 1290278588136533 },
+ { 1867998812076769, 715425053580701, 39968586461416, 2173068014586163, 653822651801304 },
+ { 162892278589453, 182585796682149, 75093073137630, 497037941226502, 133871727117371 }
+ },
+ {
+ { 1914596576579670, 1608999621851578, 1987629837704609, 1519655314857977, 1819193753409464 },
+ { 1949315551096831, 1069003344994464, 1939165033499916, 1548227205730856, 1933767655861407 },
+ { 1730519386931635, 1393284965610134, 1597143735726030, 416032382447158, 1429665248828629 }
+ },
+ {
+ { 360275475604565, 547835731063078, 215360904187529, 596646739879007, 332709650425085 },
+ { 47602113726801, 1522314509708010, 437706261372925, 814035330438027, 335930650933545 },
+ { 1291597595523886, 1058020588994081, 402837842324045, 1363323695882781, 2105763393033193 }
+ }
+},
+{ /* 12/31 */
+ {
+ { 109521982566564, 1715257748585139, 1112231216891516, 2046641005101484, 134249157157013 },
+ { 2156991030936798, 2227544497153325, 1869050094431622, 754875860479115, 1754242344267058 },
+ { 1846089562873800, 98894784984326, 1412430299204844, 171351226625762, 1100604760929008 }
+ },
+ {
+ { 84172382130492, 499710970700046, 425749630620778, 1762872794206857, 612842602127960 },
+ { 868309334532756, 1703010512741873, 1952690008738057, 4325269926064, 2071083554962116 },
+ { 523094549451158, 401938899487815, 1407690589076010, 2022387426254453, 158660516411257 }
+ },
+ {
+ { 612867287630009, 448212612103814, 571629077419196, 1466796750919376, 1728478129663858 },
+ { 1723848973783452, 2208822520534681, 1718748322776940, 1974268454121942, 1194212502258141 },
+ { 1254114807944608, 977770684047110, 2010756238954993, 1783628927194099, 1525962994408256 }
+ },
+ {
+ { 232464058235826, 1948628555342434, 1835348780427694, 1031609499437291, 64472106918373 },
+ { 767338676040683, 754089548318405, 1523192045639075, 435746025122062, 512692508440385 },
+ { 1255955808701983, 1700487367990941, 1166401238800299, 1175121994891534, 1190934801395380 }
+ },
+ {
+ { 349144008168292, 1337012557669162, 1475912332999108, 1321618454900458, 47611291904320 },
+ { 877519947135419, 2172838026132651, 272304391224129, 1655143327559984, 886229406429814 },
+ { 375806028254706, 214463229793940, 572906353144089, 572168269875638, 697556386112979 }
+ },
+ {
+ { 1168827102357844, 823864273033637, 2071538752104697, 788062026895924, 599578340743362 },
+ { 1948116082078088, 2054898304487796, 2204939184983900, 210526805152138, 786593586607626 },
+ { 1915320147894736, 156481169009469, 655050471180417, 592917090415421, 2165897438660879 }
+ },
+ {
+ { 1726336468579724, 1119932070398949, 1929199510967666, 33918788322959, 1836837863503150 },
+ { 829996854845988, 217061778005138, 1686565909803640, 1346948817219846, 1723823550730181 },
+ { 384301494966394, 687038900403062, 2211195391021739, 254684538421383, 1245698430589680 }
+ },
+ {
+ { 1247567493562688, 1978182094455847, 183871474792955, 806570235643435, 288461518067916 },
+ { 1449077384734201, 38285445457996, 2136537659177832, 2146493000841573, 725161151123125 },
+ { 1201928866368855, 800415690605445, 1703146756828343, 997278587541744, 1858284414104014 }
+ }
+},
+{ /* 13/31 */
+ {
+ { 356468809648877, 782373916933152, 1718002439402870, 1392222252219254, 663171266061951 },
+ { 759628738230460, 1012693474275852, 353780233086498, 246080061387552, 2030378857679162 },
+ { 2040672435071076, 888593182036908, 1298443657189359, 1804780278521327, 354070726137060 }
+ },
+ {
+ { 1894938527423184, 1463213041477277, 474410505497651, 247294963033299, 877975941029128 },
+ { 207937160991127, 12966911039119, 820997788283092, 1010440472205286, 1701372890140810 },
+ { 218882774543183, 533427444716285, 1233243976733245, 435054256891319, 1509568989549904 }
+ },
+ {
+ { 1888838535711826, 1052177758340622, 1213553803324135, 169182009127332, 463374268115872 },
+ { 299137589460312, 1594371588983567, 868058494039073, 257771590636681, 1805012993142921 },
+ { 1806842755664364, 2098896946025095, 1356630998422878, 1458279806348064, 347755825962072 }
+ },
+ {
+ { 1402334161391744, 1560083671046299, 1008585416617747, 1147797150908892, 1420416683642459 },
+ { 665506704253369, 273770475169863, 799236974202630, 848328990077558, 1811448782807931 },
+ { 1468412523962641, 771866649897997, 1931766110147832, 799561180078482, 524837559150077 }
+ },
+ {
+ { 2223212657821850, 630416247363666, 2144451165500328, 816911130947791, 1024351058410032 },
+ { 1266603897524861, 156378408858100, 1275649024228779, 447738405888420, 253186462063095 },
+ { 2022215964509735, 136144366993649, 1800716593296582, 1193970603800203, 871675847064218 }
+ },
+ {
+ { 1862751661970328, 851596246739884, 1519315554814041, 1542798466547449, 1417975335901520 },
+ { 1228168094547481, 334133883362894, 587567568420081, 433612590281181, 603390400373205 },
+ { 121893973206505, 1843345804916664, 1703118377384911, 497810164760654, 101150811654673 }
+ },
+ {
+ { 458346255946468, 290909935619344, 1452768413850679, 550922875254215, 1537286854336538 },
+ { 584322311184395, 380661238802118, 114839394528060, 655082270500073, 2111856026034852 },
+ { 996965581008991, 2148998626477022, 1012273164934654, 1073876063914522, 1688031788934939 }
+ },
+ {
+ { 923487018849600, 2085106799623355, 528082801620136, 1606206360876188, 735907091712524 },
+ { 1697697887804317, 1335343703828273, 831288615207040, 949416685250051, 288760277392022 },
+ { 1419122478109648, 1325574567803701, 602393874111094, 2107893372601700, 1314159682671307 }
+ }
+},
+{ /* 14/31 */
+ {
+ { 2201150872731804, 2180241023425241, 97663456423163, 1633405770247824, 848945042443986 },
+ { 1173339555550611, 818605084277583, 47521504364289, 924108720564965, 735423405754506 },
+ { 830104860549448, 1886653193241086, 1600929509383773, 1475051275443631, 286679780900937 }
+ },
+ {
+ { 1577111294832995, 1030899169768747, 144900916293530, 1964672592979567, 568390100955250 },
+ { 278388655910247, 487143369099838, 927762205508727, 181017540174210, 1616886700741287 },
+ { 1191033906638969, 940823957346562, 1606870843663445, 861684761499847, 658674867251089 }
+ },
+ {
+ { 1875032594195546, 1427106132796197, 724736390962158, 901860512044740, 635268497268760 },
+ { 622869792298357, 1903919278950367, 1922588621661629, 1520574711600434, 1087100760174640 },
+ { 25465949416618, 1693639527318811, 1526153382657203, 125943137857169, 145276964043999 }
+ },
+ {
+ { 214739857969358, 920212862967915, 1939901550972269, 1211862791775221, 85097515720120 },
+ { 2006245852772938, 734762734836159, 254642929763427, 1406213292755966, 239303749517686 },
+ { 1619678837192149, 1919424032779215, 1357391272956794, 1525634040073113, 1310226789796241 }
+ },
+ {
+ { 1040763709762123, 1704449869235352, 605263070456329, 1998838089036355, 1312142911487502 },
+ { 1996723311435669, 1844342766567060, 985455700466044, 1165924681400960, 311508689870129 },
+ { 43173156290518, 2202883069785309, 1137787467085917, 1733636061944606, 1394992037553852 }
+ },
+ {
+ { 670078326344559, 555655025059356, 471959386282438, 2141455487356409, 849015953823125 },
+ { 2197214573372804, 794254097241315, 1030190060513737, 267632515541902, 2040478049202624 },
+ { 1812516004670529, 1609256702920783, 1706897079364493, 258549904773295, 996051247540686 }
+ },
+ {
+ { 1540374301420584, 1764656898914615, 1810104162020396, 923808779163088, 664390074196579 },
+ { 1323460699404750, 1262690757880991, 871777133477900, 1060078894988977, 1712236889662886 },
+ { 1696163952057966, 1391710137550823, 608793846867416, 1034391509472039, 1780770894075012 }
+ },
+ {
+ { 1367603834210841, 2131988646583224, 890353773628144, 1908908219165595, 270836895252891 },
+ { 597536315471731, 40375058742586, 1942256403956049, 1185484645495932, 312666282024145 },
+ { 1919411405316294, 1234508526402192, 1066863051997083, 1008444703737597, 1348810787701552 }
+ }
+},
+{ /* 15/31 */
+ {
+ { 2102881477513865, 1570274565945361, 1573617900503708, 18662635732583, 2232324307922098 },
+ { 1853931367696942, 8107973870707, 350214504129299, 775206934582587, 1752317649166792 },
+ { 1417148368003523, 721357181628282, 505725498207811, 373232277872983, 261634707184480 }
+ },
+ {
+ { 2186733281493267, 2250694917008620, 1014829812957440, 479998161452389, 83566193876474 },
+ { 1268116367301224, 560157088142809, 802626839600444, 2210189936605713, 1129993785579988 },
+ { 615183387352312, 917611676109240, 878893615973325, 978940963313282, 938686890583575 }
+ },
+ {
+ { 522024729211672, 1045059315315808, 1892245413707790, 1907891107684253, 2059998109500714 },
+ { 1799679152208884, 912132775900387, 25967768040979, 432130448590461, 274568990261996 },
+ { 98698809797682, 2144627600856209, 1907959298569602, 811491302610148, 1262481774981493 }
+ },
+ {
+ { 1791451399743152, 1713538728337276, 118349997257490, 1882306388849954, 158235232210248 },
+ { 1217809823321928, 2173947284933160, 1986927836272325, 1388114931125539, 12686131160169 },
+ { 1650875518872272, 1136263858253897, 1732115601395988, 734312880662190, 1252904681142109 }
+ },
+ {
+ { 372986456113865, 525430915458171, 2116279931702135, 501422713587815, 1907002872974925 },
+ { 803147181835288, 868941437997146, 316299302989663, 943495589630550, 571224287904572 },
+ { 227742695588364, 1776969298667369, 628602552821802, 457210915378118, 2041906378111140 }
+ },
+ {
+ { 815000523470260, 913085688728307, 1052060118271173, 1345536665214223, 541623413135555 },
+ { 1580216071604333, 1877997504342444, 857147161260913, 703522726778478, 2182763974211603 },
+ { 1870080310923419, 71988220958492, 1783225432016732, 615915287105016, 1035570475990230 }
+ },
+ {
+ { 730987750830150, 857613889540280, 1083813157271766, 1002817255970169, 1719228484436074 },
+ { 377616581647602, 1581980403078513, 804044118130621, 2034382823044191, 643844048472185 },
+ { 176957326463017, 1573744060478586, 528642225008045, 1816109618372371, 1515140189765006 }
+ },
+ {
+ { 1888911448245718, 1387110895611080, 1924503794066429, 1731539523700949, 2230378382645454 },
+ { 443392177002051, 233793396845137, 2199506622312416, 1011858706515937, 974676837063129 },
+ { 1846351103143623, 1949984838808427, 671247021915253, 1946756846184401, 1929296930380217 }
+ }
+},
+{ /* 16/31 */
+ {
+ { 849646212452002, 1410198775302919, 73767886183695, 1641663456615812, 762256272452411 },
+ { 692017667358279, 723305578826727, 1638042139863265, 748219305990306, 334589200523901 },
+ { 22893968530686, 2235758574399251, 1661465835630252, 925707319443452, 1203475116966621 }
+ },
+ {
+ { 801299035785166, 1733292596726131, 1664508947088596, 467749120991922, 1647498584535623 },
+ { 903105258014366, 427141894933047, 561187017169777, 1884330244401954, 1914145708422219 },
+ { 1344191060517578, 1960935031767890, 1518838929955259, 1781502350597190, 1564784025565682 }
+ },
+ {
+ { 673723351748086, 1979969272514923, 1175287312495508, 1187589090978666, 1881897672213940 },
+ { 1917185587363432, 1098342571752737, 5935801044414, 2000527662351839, 1538640296181569 },
+ { 2495540013192, 678856913479236, 224998292422872, 219635787698590, 1972465269000940 }
+ },
+ {
+ { 271413961212179, 1353052061471651, 344711291283483, 2014925838520662, 2006221033113941 },
+ { 194583029968109, 514316781467765, 829677956235672, 1676415686873082, 810104584395840 },
+ { 1980510813313589, 1948645276483975, 152063780665900, 129968026417582, 256984195613935 }
+ },
+ {
+ { 1860190562533102, 1936576191345085, 461100292705964, 1811043097042830, 957486749306835 },
+ { 796664815624365, 1543160838872951, 1500897791837765, 1667315977988401, 599303877030711 },
+ { 1151480509533204, 2136010406720455, 738796060240027, 319298003765044, 1150614464349587 }
+ },
+ {
+ { 1731069268103150, 735642447616087, 1364750481334268, 417232839982871, 927108269127661 },
+ { 1017222050227968, 1987716148359, 2234319589635701, 621282683093392, 2132553131763026 },
+ { 1567828528453324, 1017807205202360, 565295260895298, 829541698429100, 307243822276582 }
+ },
+ {
+ { 249079270936248, 1501514259790706, 947909724204848, 944551802437487, 552658763982480 },
+ { 2089966982947227, 1854140343916181, 2151980759220007, 2139781292261749, 158070445864917 },
+ { 1338766321464554, 1906702607371284, 1519569445519894, 115384726262267, 1393058953390992 }
+ },
+ {
+ { 1364621558265400, 1512388234908357, 1926731583198686, 2041482526432505, 920401122333774 },
+ { 1884844597333588, 601480070269079, 620203503079537, 1079527400117915, 1202076693132015 },
+ { 840922919763324, 727955812569642, 1303406629750194, 522898432152867, 294161410441865 }
+ }
+},
+{ /* 17/31 */
+ {
+ { 353760790835310, 1598361541848743, 1122905698202299, 1922533590158905, 419107700666580 },
+ { 359856369838236, 180914355488683, 861726472646627, 218807937262986, 575626773232501 },
+ { 755467689082474, 909202735047934, 730078068932500, 936309075711518, 2007798262842972 }
+ },
+ {
+ { 1609384177904073, 362745185608627, 1335318541768201, 800965770436248, 547877979267412 },
+ { 984339177776787, 815727786505884, 1645154585713747, 1659074964378553, 1686601651984156 },
+ { 1697863093781930, 599794399429786, 1104556219769607, 830560774794755, 12812858601017 }
+ },
+ {
+ { 1168737550514982, 897832437380552, 463140296333799, 302564600022547, 2008360505135501 },
+ { 1856930662813910, 678090852002597, 1920179140755167, 1259527833759868, 55540971895511 },
+ { 1158643631044921, 476554103621892, 178447851439725, 1305025542653569, 103433927680625 }
+ },
+ {
+ { 2176793111709008, 1576725716350391, 2009350167273523, 2012390194631546, 2125297410909580 },
+ { 825403285195098, 2144208587560784, 1925552004644643, 1915177840006985, 1015952128947864 },
+ { 1807108316634472, 1534392066433717, 347342975407218, 1153820745616376, 7375003497471 }
+ },
+ {
+ { 983061001799725, 431211889901241, 2201903782961093, 817393911064341, 2214616493042167 },
+ { 228567918409756, 865093958780220, 358083886450556, 159617889659320, 1360637926292598 },
+ { 234147501399755, 2229469128637390, 2175289352258889, 1397401514549353, 1885288963089922 }
+ },
+ {
+ { 1111762412951562, 252849572507389, 1048714233823341, 146111095601446, 1237505378776770 },
+ { 1113790697840279, 1051167139966244, 1045930658550944, 2011366241542643, 1686166824620755 },
+ { 1054097349305049, 1872495070333352, 182121071220717, 1064378906787311, 100273572924182 }
+ },
+ {
+ { 1306410853171605, 1627717417672447, 50983221088417, 1109249951172250, 870201789081392 },
+ { 104233794644221, 1548919791188248, 2224541913267306, 2054909377116478, 1043803389015153 },
+ { 216762189468802, 707284285441622, 190678557969733, 973969342604308, 1403009538434867 }
+ },
+ {
+ { 1279024291038477, 344776835218310, 273722096017199, 1834200436811442, 634517197663804 },
+ { 343805853118335, 1302216857414201, 566872543223541, 2051138939539004, 321428858384280 },
+ { 470067171324852, 1618629234173951, 2000092177515639, 7307679772789, 1117521120249968 }
+ }
+},
+{ /* 18/31 */
+ {
+ { 278151578291475, 1810282338562947, 1771599529530998, 1383659409671631, 685373414471841 },
+ { 577009397403102, 1791440261786291, 2177643735971638, 174546149911960, 1412505077782326 },
+ { 893719721537457, 1201282458018197, 1522349501711173, 58011597740583, 1130406465887139 }
+ },
+ {
+ { 412607348255453, 1280455764199780, 2233277987330768, 14180080401665, 331584698417165 },
+ { 262483770854550, 990511055108216, 526885552771698, 571664396646158, 354086190278723 },
+ { 1820352417585487, 24495617171480, 1547899057533253, 10041836186225, 480457105094042 }
+ },
+ {
+ { 2023310314989233, 637905337525881, 2106474638900687, 557820711084072, 1687858215057826 },
+ { 1144168702609745, 604444390410187, 1544541121756138, 1925315550126027, 626401428894002 },
+ { 1922168257351784, 2018674099908659, 1776454117494445, 956539191509034, 36031129147635 }
+ },
+ {
+ { 544644538748041, 1039872944430374, 876750409130610, 710657711326551, 1216952687484972 },
+ { 58242421545916, 2035812695641843, 2118491866122923, 1191684463816273, 46921517454099 },
+ { 272268252444639, 1374166457774292, 2230115177009552, 1053149803909880, 1354288411641016 }
+ },
+ {
+ { 1857910905368338, 1754729879288912, 885945464109877, 1516096106802166, 1602902393369811 },
+ { 1193437069800958, 901107149704790, 999672920611411, 477584824802207, 364239578697845 },
+ { 886299989548838, 1538292895758047, 1590564179491896, 1944527126709657, 837344427345298 }
+ },
+ {
+ { 754558365378305, 1712186480903618, 1703656826337531, 750310918489786, 518996040250900 },
+ { 1309847803895382, 1462151862813074, 211370866671570, 1544595152703681, 1027691798954090 },
+ { 803217563745370, 1884799722343599, 1357706345069218, 2244955901722095, 730869460037413 }
+ },
+ {
+ { 689299471295966, 1831210565161071, 1375187341585438, 1106284977546171, 1893781834054269 },
+ { 696351368613042, 1494385251239250, 738037133616932, 636385507851544, 927483222611406 },
+ { 1949114198209333, 1104419699537997, 783495707664463, 1747473107602770, 2002634765788641 }
+ },
+ {
+ { 1607325776830197, 530883941415333, 1451089452727895, 1581691157083423, 496100432831154 },
+ { 1068900648804224, 2006891997072550, 1134049269345549, 1638760646180091, 2055396084625778 },
+ { 2222475519314561, 1870703901472013, 1884051508440561, 1344072275216753, 1318025677799069 }
+ }
+},
+{ /* 19/31 */
+ {
+ { 155711679280656, 681100400509288, 389811735211209, 2135723811340709, 408733211204125 },
+ { 7813206966729, 194444201427550, 2071405409526507, 1065605076176312, 1645486789731291 },
+ { 16625790644959, 1647648827778410, 1579910185572704, 436452271048548, 121070048451050 }
+ },
+ {
+ { 1037263028552531, 568385780377829, 297953104144430, 1558584511931211, 2238221839292471 },
+ { 190565267697443, 672855706028058, 338796554369226, 337687268493904, 853246848691734 },
+ { 1763863028400139, 766498079432444, 1321118624818005, 69494294452268, 858786744165651 }
+ },
+ {
+ { 1292056768563024, 1456632109855638, 1100631247050184, 1386133165675321, 1232898350193752 },
+ { 366253102478259, 525676242508811, 1449610995265438, 1183300845322183, 185960306491545 },
+ { 28315355815982, 460422265558930, 1799675876678724, 1969256312504498, 1051823843138725 }
+ },
+ {
+ { 156914999361983, 1606148405719949, 1665208410108430, 317643278692271, 1383783705665320 },
+ { 54684536365732, 2210010038536222, 1194984798155308, 535239027773705, 1516355079301361 },
+ { 1484387703771650, 198537510937949, 2186282186359116, 617687444857508, 647477376402122 }
+ },
+ {
+ { 2147715541830533, 500032538445817, 646380016884826, 352227855331122, 1488268620408052 },
+ { 159386186465542, 1877626593362941, 618737197060512, 1026674284330807, 1158121760792685 },
+ { 1744544377739822, 1964054180355661, 1685781755873170, 2169740670377448, 1286112621104591 }
+ },
+ {
+ { 81977249784993, 1667943117713086, 1668983819634866, 1605016835177615, 1353960708075544 },
+ { 1602253788689063, 439542044889886, 2220348297664483, 657877410752869, 157451572512238 },
+ { 1029287186166717, 65860128430192, 525298368814832, 1491902500801986, 1461064796385400 }
+ },
+ {
+ { 408216988729246, 2121095722306989, 913562102267595, 1879708920318308, 241061448436731 },
+ { 1185483484383269, 1356339572588553, 584932367316448, 102132779946470, 1792922621116791 },
+ { 1966196870701923, 2230044620318636, 1425982460745905, 261167817826569, 46517743394330 }
+ },
+ {
+ { 107077591595359, 884959942172345, 27306869797400, 2224911448949390, 964352058245223 },
+ { 1730194207717538, 431790042319772, 1831515233279467, 1372080552768581, 1074513929381760 },
+ { 1450880638731607, 1019861580989005, 1229729455116861, 1174945729836143, 826083146840706 }
+ }
+},
+{ /* 20/31 */
+ {
+ { 1899935429242705, 1602068751520477, 940583196550370, 82431069053859, 1540863155745696 },
+ { 2136688454840028, 2099509000964294, 1690800495246475, 1217643678575476, 828720645084218 },
+ { 765548025667841, 462473984016099, 998061409979798, 546353034089527, 2212508972466858 }
+ },
+ {
+ { 46575283771160, 892570971573071, 1281983193144090, 1491520128287375, 75847005908304 },
+ { 1801436127943107, 1734436817907890, 1268728090345068, 167003097070711, 2233597765834956 },
+ { 1997562060465113, 1048700225534011, 7615603985628, 1855310849546841, 2242557647635213 }
+ },
+ {
+ { 1161017320376250, 492624580169043, 2169815802355237, 976496781732542, 1770879511019629 },
+ { 1357044908364776, 729130645262438, 1762469072918979, 1365633616878458, 181282906404941 },
+ { 1080413443139865, 1155205815510486, 1848782073549786, 622566975152580, 124965574467971 }
+ },
+ {
+ { 1184526762066993, 247622751762817, 692129017206356, 820018689412496, 2188697339828085 },
+ { 2020536369003019, 202261491735136, 1053169669150884, 2056531979272544, 778165514694311 },
+ { 237404399610207, 1308324858405118, 1229680749538400, 720131409105291, 1958958863624906 }
+ },
+ {
+ { 515583508038846, 17656978857189, 1717918437373989, 1568052070792483, 46975803123923 },
+ { 281527309158085, 36970532401524, 866906920877543, 2222282602952734, 1289598729589882 },
+ { 1278207464902042, 494742455008756, 1262082121427081, 1577236621659884, 1888786707293291 }
+ },
+ {
+ { 353042527954210, 1830056151907359, 1111731275799225, 174960955838824, 404312815582675 },
+ { 2064251142068628, 1666421603389706, 1419271365315441, 468767774902855, 191535130366583 },
+ { 1716987058588002, 1859366439773457, 1767194234188234, 64476199777924, 1117233614485261 }
+ },
+ {
+ { 984292135520292, 135138246951259, 2220652137473167, 1722843421165029, 190482558012909 },
+ { 298845952651262, 1166086588952562, 1179896526238434, 1347812759398693, 1412945390096208 },
+ { 1143239552672925, 906436640714209, 2177000572812152, 2075299936108548, 325186347798433 }
+ },
+ {
+ { 721024854374772, 684487861263316, 1373438744094159, 2193186935276995, 1387043709851261 },
+ { 418098668140962, 715065997721283, 1471916138376055, 2168570337288357, 937812682637044 },
+ { 1043584187226485, 2143395746619356, 2209558562919611, 482427979307092, 847556718384018 }
+ }
+},
+{ /* 21/31 */
+ {
+ { 1248731221520759, 1465200936117687, 540803492710140, 52978634680892, 261434490176109 },
+ { 1057329623869501, 620334067429122, 461700859268034, 2012481616501857, 297268569108938 },
+ { 1055352180870759, 1553151421852298, 1510903185371259, 1470458349428097, 1226259419062731 }
+ },
+ {
+ { 1492988790301668, 790326625573331, 1190107028409745, 1389394752159193, 1620408196604194 },
+ { 47000654413729, 1004754424173864, 1868044813557703, 173236934059409, 588771199737015 },
+ { 30498470091663, 1082245510489825, 576771653181956, 806509986132686, 1317634017056939 }
+ },
+ {
+ { 420308055751555, 1493354863316002, 165206721528088, 1884845694919786, 2065456951573059 },
+ { 1115636332012334, 1854340990964155, 83792697369514, 1972177451994021, 457455116057587 },
+ { 1698968457310898, 1435137169051090, 1083661677032510, 938363267483709, 340103887207182 }
+ },
+ {
+ { 1995325341336574, 911500251774648, 164010755403692, 855378419194762, 1573601397528842 },
+ { 241719380661528, 310028521317150, 1215881323380194, 1408214976493624, 2141142156467363 },
+ { 1315157046163473, 727368447885818, 1363466668108618, 1668921439990361, 1398483384337907 }
+ },
+ {
+ { 75029678299646, 1015388206460473, 1849729037055212, 1939814616452984, 444404230394954 },
+ { 2053597130993710, 2024431685856332, 2233550957004860, 2012407275509545, 872546993104440 },
+ { 1217269667678610, 599909351968693, 1390077048548598, 1471879360694802, 739586172317596 }
+ },
+ {
+ { 1718318639380794, 1560510726633958, 904462881159922, 1418028351780052, 94404349451937 },
+ { 2132502667405250, 214379346175414, 1502748313768060, 1960071701057800, 1353971822643138 },
+ { 319394212043702, 2127459436033571, 717646691535162, 663366796076914, 318459064945314 }
+ },
+ {
+ { 405989424923593, 1960452633787083, 667349034401665, 1492674260767112, 1451061489880787 },
+ { 947085906234007, 323284730494107, 1485778563977200, 728576821512394, 901584347702286 },
+ { 1575783124125742, 2126210792434375, 1569430791264065, 1402582372904727, 1891780248341114 }
+ },
+ {
+ { 838432205560695, 1997703511451664, 1018791879907867, 1662001808174331, 78328132957753 },
+ { 739152638255629, 2074935399403557, 505483666745895, 1611883356514088, 628654635394878 },
+ { 1822054032121349, 643057948186973, 7306757352712, 577249257962099, 284735863382083 }
+ }
+},
+{ /* 22/31 */
+ {
+ { 1366558556363930, 1448606567552086, 1478881020944768, 165803179355898, 1115718458123498 },
+ { 204146226972102, 1630511199034723, 2215235214174763, 174665910283542, 956127674017216 },
+ { 1562934578796716, 1070893489712745, 11324610642270, 958989751581897, 2172552325473805 }
+ },
+ {
+ { 1770564423056027, 735523631664565, 1326060113795289, 1509650369341127, 65892421582684 },
+ { 623682558650637, 1337866509471512, 990313350206649, 1314236615762469, 1164772974270275 },
+ { 223256821462517, 723690150104139, 1000261663630601, 933280913953265, 254872671543046 }
+ },
+ {
+ { 1969087237026041, 624795725447124, 1335555107635969, 2069986355593023, 1712100149341902 },
+ { 1236103475266979, 1837885883267218, 1026072585230455, 1025865513954973, 1801964901432134 },
+ { 1115241013365517, 1712251818829143, 2148864332502771, 2096001471438138, 2235017246626125 }
+ },
+ {
+ { 1299268198601632, 2047148477845621, 2165648650132450, 1612539282026145, 514197911628890 },
+ { 118352772338543, 1067608711804704, 1434796676193498, 1683240170548391, 230866769907437 },
+ { 1850689576796636, 1601590730430274, 1139674615958142, 1954384401440257, 76039205311 }
+ },
+ {
+ { 1723387471374172, 997301467038410, 533927635123657, 20928644693965, 1756575222802513 },
+ { 2146711623855116, 503278928021499, 625853062251406, 1109121378393107, 1033853809911861 },
+ { 571005965509422, 2005213373292546, 1016697270349626, 56607856974274, 914438579435146 }
+ },
+ {
+ { 1346698876211176, 2076651707527589, 1084761571110205, 265334478828406, 1068954492309671 },
+ { 1769967932677654, 1695893319756416, 1151863389675920, 1781042784397689, 400287774418285 },
+ { 1851867764003121, 403841933237558, 820549523771987, 761292590207581, 1743735048551143 }
+ },
+ {
+ { 410915148140008, 2107072311871739, 1004367461876503, 99684895396761, 1180818713503224 },
+ { 285945406881439, 648174397347453, 1098403762631981, 1366547441102991, 1505876883139217 },
+ { 672095903120153, 1675918957959872, 636236529315028, 1569297300327696, 2164144194785875 }
+ },
+ {
+ { 1902708175321798, 1035343530915438, 1178560808893263, 301095684058146, 1280977479761118 },
+ { 1615357281742403, 404257611616381, 2160201349780978, 1160947379188955, 1578038619549541 },
+ { 2013087639791217, 822734930507457, 1785668418619014, 1668650702946164, 389450875221715 }
+ }
+},
+{ /* 23/31 */
+ {
+ { 453918449698368, 106406819929001, 2072540975937135, 308588860670238, 1304394580755385 },
+ { 1295082798350326, 2091844511495996, 1851348972587817, 3375039684596, 789440738712837 },
+ { 2083069137186154, 848523102004566, 993982213589257, 1405313299916317, 1532824818698468 }
+ },
+ {
+ { 1495961298852430, 1397203457344779, 1774950217066942, 139302743555696, 66603584342787 },
+ { 1782411379088302, 1096724939964781, 27593390721418, 542241850291353, 1540337798439873 },
+ { 693543956581437, 171507720360750, 1557908942697227, 1074697073443438, 1104093109037196 }
+ },
+ {
+ { 345288228393419, 1099643569747172, 134881908403743, 1740551994106740, 248212179299770 },
+ { 231429562203065, 1526290236421172, 2021375064026423, 1520954495658041, 806337791525116 },
+ { 1079623667189886, 872403650198613, 766894200588288, 2163700860774109, 2023464507911816 }
+ },
+ {
+ { 854645372543796, 1936406001954827, 151460662541253, 825325739271555, 1554306377287556 },
+ { 1497138821904622, 1044820250515590, 1742593886423484, 1237204112746837, 849047450816987 },
+ { 667962773375330, 1897271816877105, 1399712621683474, 1143302161683099, 2081798441209593 }
+ },
+ {
+ { 127147851567005, 1936114012888110, 1704424366552046, 856674880716312, 716603621335359 },
+ { 1072409664800960, 2146937497077528, 1508780108920651, 935767602384853, 1112800433544068 },
+ { 333549023751292, 280219272863308, 2104176666454852, 1036466864875785, 536135186520207 }
+ },
+ {
+ { 373666279883137, 146457241530109, 304116267127857, 416088749147715, 1258577131183391 },
+ { 1186115062588401, 2251609796968486, 1098944457878953, 1153112761201374, 1791625503417267 },
+ { 1870078460219737, 2129630962183380, 852283639691142, 292865602592851, 401904317342226 }
+ },
+ {
+ { 1361070124828035, 815664541425524, 1026798897364671, 1951790935390647, 555874891834790 },
+ { 1546301003424277, 459094500062839, 1097668518375311, 1780297770129643, 720763293687608 },
+ { 1212405311403990, 1536693382542438, 61028431067459, 1863929423417129, 1223219538638038 }
+ },
+ {
+ { 1294303766540260, 1183557465955093, 882271357233093, 63854569425375, 2213283684565087 },
+ { 339050984211414, 601386726509773, 413735232134068, 966191255137228, 1839475899458159 },
+ { 235605972169408, 2174055643032978, 1538335001838863, 1281866796917192, 1815940222628465 }
+ }
+},
+{ /* 24/31 */
+ {
+ { 1632352921721536, 1833328609514701, 2092779091951987, 1923956201873226, 2210068022482919 },
+ { 35271216625062, 1712350667021807, 983664255668860, 98571260373038, 1232645608559836 },
+ { 1998172393429622, 1798947921427073, 784387737563581, 1589352214827263, 1589861734168180 }
+ },
+ {
+ { 1733739258725305, 31715717059538, 201969945218860, 992093044556990, 1194308773174556 },
+ { 846415389605137, 746163495539180, 829658752826080, 592067705956946, 957242537821393 },
+ { 1758148849754419, 619249044817679, 168089007997045, 1371497636330523, 1867101418880350 }
+ },
+ {
+ { 326633984209635, 261759506071016, 1700682323676193, 1577907266349064, 1217647663383016 },
+ { 1714182387328607, 1477856482074168, 574895689942184, 2159118410227270, 1555532449716575 },
+ { 853828206885131, 998498946036955, 1835887550391235, 207627336608048, 258363815956050 }
+ },
+ {
+ { 141141474651677, 1236728744905256, 643101419899887, 1646615130509173, 1208239602291765 },
+ { 1501663228068911, 1354879465566912, 1444432675498247, 897812463852601, 855062598754348 },
+ { 714380763546606, 1032824444965790, 1774073483745338, 1063840874947367, 1738680636537158 }
+ },
+ {
+ { 1640635546696252, 633168953192112, 2212651044092396, 30590958583852, 368515260889378 },
+ { 1171650314802029, 1567085444565577, 1453660792008405, 757914533009261, 1619511342778196 },
+ { 420958967093237, 971103481109486, 2169549185607107, 1301191633558497, 1661514101014240 }
+ },
+ {
+ { 907123651818302, 1332556122804146, 1824055253424487, 1367614217442959, 1982558335973172 },
+ { 1121533090144639, 1021251337022187, 110469995947421, 1511059774758394, 2110035908131662 },
+ { 303213233384524, 2061932261128138, 352862124777736, 40828818670255, 249879468482660 }
+ },
+ {
+ { 856559257852200, 508517664949010, 1378193767894916, 1723459126947129, 1962275756614521 },
+ { 1445691340537320, 40614383122127, 402104303144865, 485134269878232, 1659439323587426 },
+ { 20057458979482, 1183363722525800, 2140003847237215, 2053873950687614, 2112017736174909 }
+ },
+ {
+ { 2228654250927986, 1483591363415267, 1368661293910956, 1076511285177291, 526650682059608 },
+ { 709481497028540, 531682216165724, 316963769431931, 1814315888453765, 258560242424104 },
+ { 1053447823660455, 1955135194248683, 1010900954918985, 1182614026976701, 1240051576966610 }
+ }
+},
+{ /* 25/31 */
+ {
+ { 1957943897155497, 1788667368028035, 137692910029106, 1039519607062, 826404763313028 },
+ { 1848942433095597, 1582009882530495, 1849292741020143, 1068498323302788, 2001402229799484 },
+ { 1528282417624269, 2142492439828191, 2179662545816034, 362568973150328, 1591374675250271 }
+ },
+ {
+ { 160026679434388, 232341189218716, 2149181472355545, 598041771119831, 183859001910173 },
+ { 2013278155187349, 662660471354454, 793981225706267, 411706605985744, 804490933124791 },
+ { 2051892037280204, 488391251096321, 2230187337030708, 930221970662692, 679002758255210 }
+ },
+ {
+ { 1530723630438670, 875873929577927, 341560134269988, 449903119530753, 1055551308214179 },
+ { 1461835919309432, 1955256480136428, 180866187813063, 1551979252664528, 557743861963950 },
+ { 359179641731115, 1324915145732949, 902828372691474, 294254275669987, 1887036027752957 }
+ },
+ {
+ { 2043271609454323, 2038225437857464, 1317528426475850, 1398989128982787, 2027639881006861 },
+ { 2072902725256516, 312132452743412, 309930885642209, 996244312618453, 1590501300352303 },
+ { 1397254305160710, 695734355138021, 2233992044438756, 1776180593969996, 1085588199351115 }
+ },
+ {
+ { 440567051331029, 254894786356681, 493869224930222, 1556322069683366, 1567456540319218 },
+ { 1950722461391320, 1907845598854797, 1822757481635527, 2121567704750244, 73811931471221 },
+ { 387139307395758, 2058036430315676, 1220915649965325, 1794832055328951, 1230009312169328 }
+ },
+ {
+ { 1765973779329517, 659344059446977, 19821901606666, 1301928341311214, 1116266004075885 },
+ { 1127572801181483, 1224743760571696, 1276219889847274, 1529738721702581, 1589819666871853 },
+ { 2181229378964934, 2190885205260020, 1511536077659137, 1246504208580490, 668883326494241 }
+ },
+ {
+ { 437866655573314, 669026411194768, 81896997980338, 523874406393178, 245052060935236 },
+ { 1975438052228868, 1071801519999806, 594652299224319, 1877697652668809, 1489635366987285 },
+ { 958592545673770, 233048016518599, 851568750216589, 567703851596087, 1740300006094761 }
+ },
+ {
+ { 2014540178270324, 192672779514432, 213877182641530, 2194819933853411, 1716422829364835 },
+ { 1540769606609725, 2148289943846077, 1597804156127445, 1230603716683868, 815423458809453 },
+ { 1738560251245018, 1779576754536888, 1783765347671392, 1880170990446751, 1088225159617541 }
+ }
+},
+{ /* 26/31 */
+ {
+ { 659303913929492, 1956447718227573, 1830568515922666, 841069049744408, 1669607124206368 },
+ { 1143465490433355, 1532194726196059, 1093276745494697, 481041706116088, 2121405433561163 },
+ { 1686424298744462, 1451806974487153, 266296068846582, 1834686947542675, 1720762336132256 }
+ },
+ {
+ { 889217026388959, 1043290623284660, 856125087551909, 1669272323124636, 1603340330827879 },
+ { 1206396181488998, 333158148435054, 1402633492821422, 1120091191722026, 1945474114550509 },
+ { 766720088232571, 1512222781191002, 1189719893490790, 2091302129467914, 2141418006894941 }
+ },
+ {
+ { 419663647306612, 1998875112167987, 1426599870253707, 1154928355379510, 486538532138187 },
+ { 938160078005954, 1421776319053174, 1941643234741774, 180002183320818, 1414380336750546 },
+ { 398001940109652, 1577721237663248, 1012748649830402, 1540516006905144, 1011684812884559 }
+ },
+ {
+ { 1653276489969630, 6081825167624, 1921777941170836, 1604139841794531, 861211053640641 },
+ { 996661541407379, 1455877387952927, 744312806857277, 139213896196746, 1000282908547789 },
+ { 1450817495603008, 1476865707053229, 1030490562252053, 620966950353376, 1744760161539058 }
+ },
+ {
+ { 559728410002599, 37056661641185, 2038622963352006, 1637244893271723, 1026565352238948 },
+ { 962165956135846, 1116599660248791, 182090178006815, 1455605467021751, 196053588803284 },
+ { 796863823080135, 1897365583584155, 420466939481601, 2165972651724672, 932177357788289 }
+ },
+ {
+ { 877047233620632, 1375632631944375, 643773611882121, 660022738847877, 19353932331831 },
+ { 2216943882299338, 394841323190322, 2222656898319671, 558186553950529, 1077236877025190 },
+ { 801118384953213, 1914330175515892, 574541023311511, 1471123787903705, 1526158900256288 }
+ },
+ {
+ { 949617889087234, 2207116611267331, 912920039141287, 501158539198789, 62362560771472 },
+ { 1474518386765335, 1760793622169197, 1157399790472736, 1622864308058898, 165428294422792 },
+ { 1961673048027128, 102619413083113, 1051982726768458, 1603657989805485, 1941613251499678 }
+ },
+ {
+ { 1401939116319266, 335306339903072, 72046196085786, 862423201496006, 850518754531384 },
+ { 1234706593321979, 1083343891215917, 898273974314935, 1640859118399498, 157578398571149 },
+ { 1143483057726416, 1992614991758919, 674268662140796, 1773370048077526, 674318359920189 }
+ }
+},
+{ /* 27/31 */
+ {
+ { 1835401379538542, 173900035308392, 818247630716732, 1762100412152786, 1021506399448291 },
+ { 1506632088156630, 2127481795522179, 513812919490255, 140643715928370, 442476620300318 },
+ { 2056683376856736, 219094741662735, 2193541883188309, 1841182310235800, 556477468664293 }
+ },
+ {
+ { 1315019427910827, 1049075855992603, 2066573052986543, 266904467185534, 2040482348591520 },
+ { 94096246544434, 922482381166992, 24517828745563, 2139430508542503, 2097139044231004 },
+ { 537697207950515, 1399352016347350, 1563663552106345, 2148749520888918, 549922092988516 }
+ },
+ {
+ { 1747985413252434, 680511052635695, 1809559829982725, 594274250930054, 201673170745982 },
+ { 323583936109569, 1973572998577657, 1192219029966558, 79354804385273, 1374043025560347 },
+ { 213277331329947, 416202017849623, 1950535221091783, 1313441578103244, 2171386783823658 }
+ },
+ {
+ { 189088804229831, 993969372859110, 895870121536987, 1547301535298256, 1477373024911350 },
+ { 1620578418245010, 541035331188469, 2235785724453865, 2154865809088198, 1974627268751826 },
+ { 1346805451740245, 1350981335690626, 942744349501813, 2155094562545502, 1012483751693409 }
+ },
+ {
+ { 2107080134091762, 1132567062788208, 1824935377687210, 769194804343737, 1857941799971888 },
+ { 1074666112436467, 249279386739593, 1174337926625354, 1559013532006480, 1472287775519121 },
+ { 1872620123779532, 1892932666768992, 1921559078394978, 1270573311796160, 1438913646755037 }
+ },
+ {
+ { 837390187648199, 1012253300223599, 989780015893987, 1351393287739814, 328627746545550 },
+ { 1028328827183114, 1711043289969857, 1350832470374933, 1923164689604327, 1495656368846911 },
+ { 1900828492104143, 430212361082163, 687437570852799, 832514536673512, 1685641495940794 }
+ },
+ {
+ { 842632847936398, 605670026766216, 290836444839585, 163210774892356, 2213815011799645 },
+ { 1176336383453996, 1725477294339771, 12700622672454, 678015708818208, 162724078519879 },
+ { 1448049969043497, 1789411762943521, 385587766217753, 90201620913498, 832999441066823 }
+ },
+ {
+ { 516086333293313, 2240508292484616, 1351669528166508, 1223255565316488, 750235824427138 },
+ { 1263624896582495, 1102602401673328, 526302183714372, 2152015839128799, 1483839308490010 },
+ { 442991718646863, 1599275157036458, 1925389027579192, 899514691371390, 350263251085160 }
+ }
+},
+{ /* 28/31 */
+ {
+ { 1689713572022143, 593854559254373, 978095044791970, 1985127338729499, 1676069120347625 },
+ { 1557207018622683, 340631692799603, 1477725909476187, 614735951619419, 2033237123746766 },
+ { 968764929340557, 1225534776710944, 662967304013036, 1155521416178595, 791142883466590 }
+ },
+ {
+ { 1487081286167458, 993039441814934, 1792378982844640, 698652444999874, 2153908693179754 },
+ { 1123181311102823, 685575944875442, 507605465509927, 1412590462117473, 568017325228626 },
+ { 560258797465417, 2193971151466401, 1824086900849026, 579056363542056, 1690063960036441 }
+ },
+ {
+ { 1918407319222416, 353767553059963, 1930426334528099, 1564816146005724, 1861342381708096 },
+ { 2131325168777276, 1176636658428908, 1756922641512981, 1390243617176012, 1966325177038383 },
+ { 2063958120364491, 2140267332393533, 699896251574968, 273268351312140, 375580724713232 }
+ },
+ {
+ { 2024297515263178, 416959329722687, 1079014235017302, 171612225573183, 1031677520051053 },
+ { 2033900009388450, 1744902869870788, 2190580087917640, 1949474984254121, 231049754293748 },
+ { 343868674606581, 550155864008088, 1450580864229630, 481603765195050, 896972360018042 }
+ },
+ {
+ { 2151139328380127, 314745882084928, 59756825775204, 1676664391494651, 2048348075599360 },
+ { 1528930066340597, 1605003907059576, 1055061081337675, 1458319101947665, 1234195845213142 },
+ { 830430507734812, 1780282976102377, 1425386760709037, 362399353095425, 2168861579799910 }
+ },
+ {
+ { 1155762232730333, 980662895504006, 2053766700883521, 490966214077606, 510405877041357 },
+ { 1683750316716132, 652278688286128, 1221798761193539, 1897360681476669, 319658166027343 },
+ { 618808732869972, 72755186759744, 2060379135624181, 1730731526741822, 48862757828238 }
+ },
+ {
+ { 1463171970593505, 1143040711767452, 614590986558883, 1409210575145591, 1882816996436803 },
+ { 2230133264691131, 563950955091024, 2042915975426398, 827314356293472, 672028980152815 },
+ { 264204366029760, 1654686424479449, 2185050199932931, 2207056159091748, 506015669043634 }
+ },
+ {
+ { 1784446333136569, 1973746527984364, 334856327359575, 1156769775884610, 1023950124675478 },
+ { 2065270940578383, 31477096270353, 306421879113491, 181958643936686, 1907105536686083 },
+ { 1496516440779464, 1748485652986458, 872778352227340, 818358834654919, 97932669284220 }
+ }
+},
+{ /* 29/31 */
+ {
+ { 471636015770351, 672455402793577, 1804995246884103, 1842309243470804, 1501862504981682 },
+ { 1013216974933691, 538921919682598, 1915776722521558, 1742822441583877, 1886550687916656 },
+ { 2094270000643336, 303971879192276, 40801275554748, 649448917027930, 1818544418535447 }
+ },
+ {
+ { 2241737709499165, 549397817447461, 838180519319392, 1725686958520781, 1705639080897747 },
+ { 1216074541925116, 50120933933509, 1565829004133810, 721728156134580, 349206064666188 },
+ { 948617110470858, 346222547451945, 1126511960599975, 1759386906004538, 493053284802266 }
+ },
+ {
+ { 1454933046815146, 874696014266362, 1467170975468588, 1432316382418897, 2111710746366763 },
+ { 2105387117364450, 1996463405126433, 1303008614294500, 851908115948209, 1353742049788635 },
+ { 750300956351719, 1487736556065813, 15158817002104, 1511998221598392, 971739901354129 }
+ },
+ {
+ { 1874648163531693, 2124487685930551, 1810030029384882, 918400043048335, 586348627300650 },
+ { 1235084464747900, 1166111146432082, 1745394857881591, 1405516473883040, 4463504151617 },
+ { 1663810156463827, 327797390285791, 1341846161759410, 1964121122800605, 1747470312055380 }
+ },
+ {
+ { 660005247548233, 2071860029952887, 1358748199950107, 911703252219107, 1014379923023831 },
+ { 2206641276178231, 1690587809721504, 1600173622825126, 2156096097634421, 1106822408548216 },
+ { 1344788193552206, 1949552134239140, 1735915881729557, 675891104100469, 1834220014427292 }
+ },
+ {
+ { 1920949492387964, 158885288387530, 70308263664033, 626038464897817, 1468081726101009 },
+ { 622221042073383, 1210146474039168, 1742246422343683, 1403839361379025, 417189490895736 },
+ { 22727256592983, 168471543384997, 1324340989803650, 1839310709638189, 504999476432775 }
+ },
+ {
+ { 1313240518756327, 1721896294296942, 52263574587266, 2065069734239232, 804910473424630 },
+ { 1337466662091884, 1287645354669772, 2018019646776184, 652181229374245, 898011753211715 },
+ { 1969792547910734, 779969968247557, 2011350094423418, 1823964252907487, 1058949448296945 }
+ },
+ {
+ { 207343737062002, 1118176942430253, 758894594548164, 806764629546266, 1157700123092949 },
+ { 1273565321399022, 1638509681964574, 759235866488935, 666015124346707, 897983460943405 },
+ { 1717263794012298, 1059601762860786, 1837819172257618, 1054130665797229, 680893204263559 }
+ }
+},
+{ /* 30/31 */
+ {
+ { 2237039662793603, 2249022333361206, 2058613546633703, 149454094845279, 2215176649164582 },
+ { 79472182719605, 1851130257050174, 1825744808933107, 821667333481068, 781795293511946 },
+ { 755822026485370, 152464789723500, 1178207602290608, 410307889503239, 156581253571278 }
+ },
+ {
+ { 1418185496130297, 484520167728613, 1646737281442950, 1401487684670265, 1349185550126961 },
+ { 1495380034400429, 325049476417173, 46346894893933, 1553408840354856, 828980101835683 },
+ { 1280337889310282, 2070832742866672, 1640940617225222, 2098284908289951, 450929509534434 }
+ },
+ {
+ { 407703353998781, 126572141483652, 286039827513621, 1999255076709338, 2030511179441770 },
+ { 1254958221100483, 1153235960999843, 942907704968834, 637105404087392, 1149293270147267 },
+ { 894249020470196, 400291701616810, 406878712230981, 1599128793487393, 1145868722604026 }
+ },
+ {
+ { 1497955250203334, 110116344653260, 1128535642171976, 1900106496009660, 129792717460909 },
+ { 452487513298665, 1352120549024569, 1173495883910956, 1999111705922009, 367328130454226 },
+ { 1717539401269642, 1475188995688487, 891921989653942, 836824441505699, 1885988485608364 }
+ },
+ {
+ { 1241784121422547, 187337051947583, 1118481812236193, 428747751936362, 30358898927325 },
+ { 2022432361201842, 1088816090685051, 1977843398539868, 1854834215890724, 564238862029357 },
+ { 938868489100585, 1100285072929025, 1017806255688848, 1957262154788833, 152787950560442 }
+ },
+ {
+ { 867319417678923, 620471962942542, 226032203305716, 342001443957629, 1761675818237336 },
+ { 1295072362439987, 931227904689414, 1355731432641687, 922235735834035, 892227229410209 },
+ { 1680989767906154, 535362787031440, 2136691276706570, 1942228485381244, 1267350086882274 }
+ },
+ {
+ { 366018233770527, 432660629755596, 126409707644535, 1973842949591662, 645627343442376 },
+ { 535509430575217, 546885533737322, 1524675609547799, 2138095752851703, 1260738089896827 },
+ { 1159906385590467, 2198530004321610, 714559485023225, 81880727882151, 1484020820037082 }
+ },
+ {
+ { 1377485731340769, 2046328105512000, 1802058637158797, 62146136768173, 1356993908853901 },
+ { 2013612215646735, 1830770575920375, 536135310219832, 609272325580394, 270684344495013 },
+ { 1237542585982777, 2228682050256790, 1385281931622824, 593183794882890, 493654978552689 }
+ }
+},
+{ /* 31/31 */
+ {
+ { 47341488007760, 1891414891220257, 983894663308928, 176161768286818, 1126261115179708 },
+ { 1694030170963455, 502038567066200, 1691160065225467, 949628319562187, 275110186693066 },
+ { 1124515748676336, 1661673816593408, 1499640319059718, 1584929449166988, 558148594103306 }
+ },
+ {
+ { 1784525599998356, 1619698033617383, 2097300287550715, 258265458103756, 1905684794832758 },
+ { 1288941072872766, 931787902039402, 190731008859042, 2006859954667190, 1005931482221702 },
+ { 1465551264822703, 152905080555927, 680334307368453, 173227184634745, 666407097159852 }
+ },
+ {
+ { 2111017076203943, 1378760485794347, 1248583954016456, 1352289194864422, 1895180776543896 },
+ { 171348223915638, 662766099800389, 462338943760497, 466917763340314, 656911292869115 },
+ { 488623681976577, 866497561541722, 1708105560937768, 1673781214218839, 1506146329818807 }
+ },
+ {
+ { 160425464456957, 950394373239689, 430497123340934, 711676555398832, 320964687779005 },
+ { 988979367990485, 1359729327576302, 1301834257246029, 294141160829308, 29348272277475 },
+ { 1434382743317910, 100082049942065, 221102347892623, 186982837860588, 1305765053501834 }
+ },
+ {
+ { 2205916462268190, 499863829790820, 961960554686616, 158062762756985, 1841471168298305 },
+ { 1191737341426592, 1847042034978363, 1382213545049056, 1039952395710448, 788812858896859 },
+ { 1346965964571152, 1291881610839830, 2142916164336056, 786821641205979, 1571709146321039 }
+ },
+ {
+ { 787164375951248, 202869205373189, 1356590421032140, 1431233331032510, 786341368775957 },
+ { 492448143532951, 304105152670757, 1761767168301056, 233782684697790, 1981295323106089 },
+ { 665807507761866, 1343384868355425, 895831046139653, 439338948736892, 1986828765695105 }
+ },
+ {
+ { 756096210874553, 1721699973539149, 258765301727885, 1390588532210645, 1212530909934781 },
+ { 852891097972275, 1816988871354562, 1543772755726524, 1174710635522444, 202129090724628 },
+ { 1205281565824323, 22430498399418, 992947814485516, 1392458699738672, 688441466734558 }
+ },
+ {
+ { 1050627428414972, 1955849529137135, 2171162376368357, 91745868298214, 447733118757826 },
+ { 1287181461435438, 622722465530711, 880952150571872, 741035693459198, 311565274989772 },
+ { 1003649078149734, 545233927396469, 1849786171789880, 1318943684880434, 280345687170552 }
+ }
+}
diff --git a/libs/libsodium/src/crypto_core/ed25519/ref10/fe_51/base2.h b/libs/libsodium/src/crypto_core/ed25519/ref10/fe_51/base2.h
new file mode 100644
index 0000000000..d088241657
--- /dev/null
+++ b/libs/libsodium/src/crypto_core/ed25519/ref10/fe_51/base2.h
@@ -0,0 +1,40 @@
+{
+ { 1288382639258501, 245678601348599, 269427782077623, 1462984067271730, 137412439391563 },
+ { 62697248952638, 204681361388450, 631292143396476, 338455783676468, 1213667448819585 },
+ { 301289933810280, 1259582250014073, 1422107436869536, 796239922652654, 1953934009299142 }
+},
+{
+ { 1601611775252272, 1720807796594148, 1132070835939856, 1260455018889551, 2147779492816911 },
+ { 316559037616741, 2177824224946892, 1459442586438991, 1461528397712656, 751590696113597 },
+ { 1850748884277385, 1200145853858453, 1068094770532492, 672251375690438, 1586055907191707 }
+},
+{
+ { 769950342298419, 132954430919746, 844085933195555, 974092374476333, 726076285546016 },
+ { 425251763115706, 608463272472562, 442562545713235, 837766094556764, 374555092627893 },
+ { 1086255230780037, 274979815921559, 1960002765731872, 929474102396301, 1190409889297339 }
+},
+{
+ { 665000864555967, 2065379846933859, 370231110385876, 350988370788628, 1233371373142985 },
+ { 2019367628972465, 676711900706637, 110710997811333, 1108646842542025, 517791959672113 },
+ { 965130719900578, 247011430587952, 526356006571389, 91986625355052, 2157223321444601 }
+},
+{
+ { 1802695059465007, 1664899123557221, 593559490740857, 2160434469266659, 927570450755031 },
+ { 1725674970513508, 1933645953859181, 1542344539275782, 1767788773573747, 1297447965928905 },
+ { 1381809363726107, 1430341051343062, 2061843536018959, 1551778050872521, 2036394857967624 }
+},
+{
+ { 1970894096313054, 528066325833207, 1619374932191227, 2207306624415883, 1169170329061080 },
+ { 2070390218572616, 1458919061857835, 624171843017421, 1055332792707765, 433987520732508 },
+ { 893653801273833, 1168026499324677, 1242553501121234, 1306366254304474, 1086752658510815 }
+},
+{
+ { 213454002618221, 939771523987438, 1159882208056014, 317388369627517, 621213314200687 },
+ { 1971678598905747, 338026507889165, 762398079972271, 655096486107477, 42299032696322 },
+ { 177130678690680, 1754759263300204, 1864311296286618, 1180675631479880, 1292726903152791 }
+},
+{
+ { 1913163449625248, 460779200291993, 2193883288642314, 1008900146920800, 1721983679009502 },
+ { 1070401523076875, 1272492007800961, 1910153608563310, 2075579521696771, 1191169788841221 },
+ { 692896803108118, 500174642072499, 2068223309439677, 1162190621851337, 1426986007309901 }
+}
diff --git a/libs/libsodium/src/crypto_core/ed25519/ref10/fe_51/constants.h b/libs/libsodium/src/crypto_core/ed25519/ref10/fe_51/constants.h
new file mode 100644
index 0000000000..53b75c6b45
--- /dev/null
+++ b/libs/libsodium/src/crypto_core/ed25519/ref10/fe_51/constants.h
@@ -0,0 +1,21 @@
+/* 37095705934669439343138083508754565189542113879843219016388785533085940283555 */
+static const fe25519 d = {
+ 929955233495203, 466365720129213, 1662059464998953, 2033849074728123, 1442794654840575
+};
+
+/* 2 * d =
+ * 16295367250680780974490674513165176452449235426866156013048779062215315747161
+ */
+static const fe25519 d2 = {
+ 1859910466990425, 932731440258426, 1072319116312658, 1815898335770999, 633789495995903
+};
+
+/* sqrt(-1) */
+static const fe25519 sqrtm1 = {
+ 1718705420411056, 234908883556509, 2233514472574048, 2117202627021982, 765476049583133
+};
+
+/* A = 486662 */
+static const fe25519 curve25519_A = {
+ 486662, 0, 0, 0, 0
+};
diff --git a/libs/libsodium/src/crypto_core/ed25519/ref10/fe_51/fe.h b/libs/libsodium/src/crypto_core/ed25519/ref10/fe_51/fe.h
new file mode 100644
index 0000000000..de876264c8
--- /dev/null
+++ b/libs/libsodium/src/crypto_core/ed25519/ref10/fe_51/fe.h
@@ -0,0 +1,116 @@
+/*
+ Ignores top bit of h.
+ */
+
+void
+fe25519_frombytes(fe25519 h, const unsigned char *s)
+{
+ const uint64_t mask = 0x7ffffffffffffULL;
+ uint64_t h0, h1, h2, h3, h4;
+
+ h0 = (LOAD64_LE(s ) ) & mask;
+ h1 = (LOAD64_LE(s + 6) >> 3) & mask;
+ h2 = (LOAD64_LE(s + 12) >> 6) & mask;
+ h3 = (LOAD64_LE(s + 19) >> 1) & mask;
+ h4 = (LOAD64_LE(s + 24) >> 12) & mask;
+
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+}
+
+static void
+fe25519_reduce(fe25519 h, const fe25519 f)
+{
+ const uint64_t mask = 0x7ffffffffffffULL;
+ uint128_t t[5];
+
+ t[0] = f[0];
+ t[1] = f[1];
+ t[2] = f[2];
+ t[3] = f[3];
+ t[4] = f[4];
+
+ t[1] += t[0] >> 51;
+ t[0] &= mask;
+ t[2] += t[1] >> 51;
+ t[1] &= mask;
+ t[3] += t[2] >> 51;
+ t[2] &= mask;
+ t[4] += t[3] >> 51;
+ t[3] &= mask;
+ t[0] += 19 * (t[4] >> 51);
+ t[4] &= mask;
+
+ t[1] += t[0] >> 51;
+ t[0] &= mask;
+ t[2] += t[1] >> 51;
+ t[1] &= mask;
+ t[3] += t[2] >> 51;
+ t[2] &= mask;
+ t[4] += t[3] >> 51;
+ t[3] &= mask;
+ t[0] += 19 * (t[4] >> 51);
+ t[4] &= mask;
+
+ /* now t is between 0 and 2^255-1, properly carried. */
+ /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */
+
+ t[0] += 19ULL;
+
+ t[1] += t[0] >> 51;
+ t[0] &= mask;
+ t[2] += t[1] >> 51;
+ t[1] &= mask;
+ t[3] += t[2] >> 51;
+ t[2] &= mask;
+ t[4] += t[3] >> 51;
+ t[3] &= mask;
+ t[0] += 19ULL * (t[4] >> 51);
+ t[4] &= mask;
+
+ /* now between 19 and 2^255-1 in both cases, and offset by 19. */
+
+ t[0] += 0x8000000000000 - 19ULL;
+ t[1] += 0x8000000000000 - 1ULL;
+ t[2] += 0x8000000000000 - 1ULL;
+ t[3] += 0x8000000000000 - 1ULL;
+ t[4] += 0x8000000000000 - 1ULL;
+
+ /* now between 2^255 and 2^256-20, and offset by 2^255. */
+
+ t[1] += t[0] >> 51;
+ t[0] &= mask;
+ t[2] += t[1] >> 51;
+ t[1] &= mask;
+ t[3] += t[2] >> 51;
+ t[2] &= mask;
+ t[4] += t[3] >> 51;
+ t[3] &= mask;
+ t[4] &= mask;
+
+ h[0] = t[0];
+ h[1] = t[1];
+ h[2] = t[2];
+ h[3] = t[3];
+ h[4] = t[4];
+}
+
+void
+fe25519_tobytes(unsigned char *s, const fe25519 h)
+{
+ fe25519 t;
+ uint64_t t0, t1, t2, t3;
+
+ fe25519_reduce(t, h);
+ t0 = t[0] | (t[1] << 51);
+ t1 = (t[1] >> 13) | (t[2] << 38);
+ t2 = (t[2] >> 26) | (t[3] << 25);
+ t3 = (t[3] >> 39) | (t[4] << 12);
+ STORE64_LE(s + 0, t0);
+ STORE64_LE(s + 8, t1);
+ STORE64_LE(s + 16, t2);
+ STORE64_LE(s + 24, t3);
+}
diff --git a/libs/libsodium/src/crypto_core/hchacha20/core_hchacha20.c b/libs/libsodium/src/crypto_core/hchacha20/core_hchacha20.c
new file mode 100644
index 0000000000..39ab26a6da
--- /dev/null
+++ b/libs/libsodium/src/crypto_core/hchacha20/core_hchacha20.c
@@ -0,0 +1,93 @@
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "crypto_core_hchacha20.h"
+#include "private/common.h"
+
+#define QUARTERROUND(A, B, C, D) \
+ do { \
+ A += B; D = ROTL32(D ^ A, 16); \
+ C += D; B = ROTL32(B ^ C, 12); \
+ A += B; D = ROTL32(D ^ A, 8); \
+ C += D; B = ROTL32(B ^ C, 7); \
+ } while(0)
+
+int
+crypto_core_hchacha20(unsigned char *out, const unsigned char *in,
+ const unsigned char *k, const unsigned char *c)
+{
+ int i;
+ uint32_t x0, x1, x2, x3, x4, x5, x6, x7;
+ uint32_t x8, x9, x10, x11, x12, x13, x14, x15;
+
+ if (c == NULL) {
+ x0 = 0x61707865;
+ x1 = 0x3320646e;
+ x2 = 0x79622d32;
+ x3 = 0x6b206574;
+ } else {
+ x0 = LOAD32_LE(c + 0);
+ x1 = LOAD32_LE(c + 4);
+ x2 = LOAD32_LE(c + 8);
+ x3 = LOAD32_LE(c + 12);
+ }
+ x4 = LOAD32_LE(k + 0);
+ x5 = LOAD32_LE(k + 4);
+ x6 = LOAD32_LE(k + 8);
+ x7 = LOAD32_LE(k + 12);
+ x8 = LOAD32_LE(k + 16);
+ x9 = LOAD32_LE(k + 20);
+ x10 = LOAD32_LE(k + 24);
+ x11 = LOAD32_LE(k + 28);
+ x12 = LOAD32_LE(in + 0);
+ x13 = LOAD32_LE(in + 4);
+ x14 = LOAD32_LE(in + 8);
+ x15 = LOAD32_LE(in + 12);
+
+ for (i = 0; i < 10; i++) {
+ QUARTERROUND(x0, x4, x8, x12);
+ QUARTERROUND(x1, x5, x9, x13);
+ QUARTERROUND(x2, x6, x10, x14);
+ QUARTERROUND(x3, x7, x11, x15);
+ QUARTERROUND(x0, x5, x10, x15);
+ QUARTERROUND(x1, x6, x11, x12);
+ QUARTERROUND(x2, x7, x8, x13);
+ QUARTERROUND(x3, x4, x9, x14);
+ }
+
+ STORE32_LE(out + 0, x0);
+ STORE32_LE(out + 4, x1);
+ STORE32_LE(out + 8, x2);
+ STORE32_LE(out + 12, x3);
+ STORE32_LE(out + 16, x12);
+ STORE32_LE(out + 20, x13);
+ STORE32_LE(out + 24, x14);
+ STORE32_LE(out + 28, x15);
+
+ return 0;
+}
+
+size_t
+crypto_core_hchacha20_outputbytes(void)
+{
+ return crypto_core_hchacha20_OUTPUTBYTES;
+}
+
+size_t
+crypto_core_hchacha20_inputbytes(void)
+{
+ return crypto_core_hchacha20_INPUTBYTES;
+}
+
+size_t
+crypto_core_hchacha20_keybytes(void)
+{
+ return crypto_core_hchacha20_KEYBYTES;
+}
+
+size_t
+crypto_core_hchacha20_constbytes(void)
+{
+ return crypto_core_hchacha20_CONSTBYTES;
+}
diff --git a/libs/libsodium/src/crypto_core/hsalsa20/core_hsalsa20.c b/libs/libsodium/src/crypto_core/hsalsa20/core_hsalsa20.c
new file mode 100644
index 0000000000..37c4923af6
--- /dev/null
+++ b/libs/libsodium/src/crypto_core/hsalsa20/core_hsalsa20.c
@@ -0,0 +1,21 @@
+#include "crypto_core_hsalsa20.h"
+
+size_t
+crypto_core_hsalsa20_outputbytes(void) {
+ return crypto_core_hsalsa20_OUTPUTBYTES;
+}
+
+size_t
+crypto_core_hsalsa20_inputbytes(void) {
+ return crypto_core_hsalsa20_INPUTBYTES;
+}
+
+size_t
+crypto_core_hsalsa20_keybytes(void) {
+ return crypto_core_hsalsa20_KEYBYTES;
+}
+
+size_t
+crypto_core_hsalsa20_constbytes(void) {
+ return crypto_core_hsalsa20_CONSTBYTES;
+}
diff --git a/libs/libsodium/src/crypto_core/hsalsa20/ref2/core_hsalsa20_ref2.c b/libs/libsodium/src/crypto_core/hsalsa20/ref2/core_hsalsa20_ref2.c
new file mode 100644
index 0000000000..1d1220fee2
--- /dev/null
+++ b/libs/libsodium/src/crypto_core/hsalsa20/ref2/core_hsalsa20_ref2.c
@@ -0,0 +1,95 @@
+/*
+version 20080912
+D. J. Bernstein
+Public domain.
+*/
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "crypto_core_hsalsa20.h"
+#include "private/common.h"
+
+#define ROUNDS 20
+#define U32C(v) (v##U)
+
+int
+crypto_core_hsalsa20(unsigned char *out,
+ const unsigned char *in,
+ const unsigned char *k,
+ const unsigned char *c)
+{
+ uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8,
+ x9, x10, x11, x12, x13, x14, x15;
+ int i;
+
+ if (c == NULL) {
+ x0 = U32C(0x61707865);
+ x5 = U32C(0x3320646e);
+ x10 = U32C(0x79622d32);
+ x15 = U32C(0x6b206574);
+ } else {
+ x0 = LOAD32_LE(c + 0);
+ x5 = LOAD32_LE(c + 4);
+ x10 = LOAD32_LE(c + 8);
+ x15 = LOAD32_LE(c + 12);
+ }
+ x1 = LOAD32_LE(k + 0);
+ x2 = LOAD32_LE(k + 4);
+ x3 = LOAD32_LE(k + 8);
+ x4 = LOAD32_LE(k + 12);
+ x11 = LOAD32_LE(k + 16);
+ x12 = LOAD32_LE(k + 20);
+ x13 = LOAD32_LE(k + 24);
+ x14 = LOAD32_LE(k + 28);
+ x6 = LOAD32_LE(in + 0);
+ x7 = LOAD32_LE(in + 4);
+ x8 = LOAD32_LE(in + 8);
+ x9 = LOAD32_LE(in + 12);
+
+ for (i = ROUNDS; i > 0; i -= 2) {
+ x4 ^= ROTL32(x0 + x12, 7);
+ x8 ^= ROTL32(x4 + x0, 9);
+ x12 ^= ROTL32(x8 + x4, 13);
+ x0 ^= ROTL32(x12 + x8, 18);
+ x9 ^= ROTL32(x5 + x1, 7);
+ x13 ^= ROTL32(x9 + x5, 9);
+ x1 ^= ROTL32(x13 + x9, 13);
+ x5 ^= ROTL32(x1 + x13, 18);
+ x14 ^= ROTL32(x10 + x6, 7);
+ x2 ^= ROTL32(x14 + x10, 9);
+ x6 ^= ROTL32(x2 + x14, 13);
+ x10 ^= ROTL32(x6 + x2, 18);
+ x3 ^= ROTL32(x15 + x11, 7);
+ x7 ^= ROTL32(x3 + x15, 9);
+ x11 ^= ROTL32(x7 + x3, 13);
+ x15 ^= ROTL32(x11 + x7, 18);
+ x1 ^= ROTL32(x0 + x3, 7);
+ x2 ^= ROTL32(x1 + x0, 9);
+ x3 ^= ROTL32(x2 + x1, 13);
+ x0 ^= ROTL32(x3 + x2, 18);
+ x6 ^= ROTL32(x5 + x4, 7);
+ x7 ^= ROTL32(x6 + x5, 9);
+ x4 ^= ROTL32(x7 + x6, 13);
+ x5 ^= ROTL32(x4 + x7, 18);
+ x11 ^= ROTL32(x10 + x9, 7);
+ x8 ^= ROTL32(x11 + x10, 9);
+ x9 ^= ROTL32(x8 + x11, 13);
+ x10 ^= ROTL32(x9 + x8, 18);
+ x12 ^= ROTL32(x15 + x14, 7);
+ x13 ^= ROTL32(x12 + x15, 9);
+ x14 ^= ROTL32(x13 + x12, 13);
+ x15 ^= ROTL32(x14 + x13, 18);
+ }
+
+ STORE32_LE(out + 0, x0);
+ STORE32_LE(out + 4, x5);
+ STORE32_LE(out + 8, x10);
+ STORE32_LE(out + 12, x15);
+ STORE32_LE(out + 16, x6);
+ STORE32_LE(out + 20, x7);
+ STORE32_LE(out + 24, x8);
+ STORE32_LE(out + 28, x9);
+
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_core/salsa/ref/core_salsa_ref.c b/libs/libsodium/src/crypto_core/salsa/ref/core_salsa_ref.c
new file mode 100644
index 0000000000..a077d7f4db
--- /dev/null
+++ b/libs/libsodium/src/crypto_core/salsa/ref/core_salsa_ref.c
@@ -0,0 +1,195 @@
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "crypto_core_salsa20.h"
+#include "crypto_core_salsa2012.h"
+#include "crypto_core_salsa208.h"
+#include "private/common.h"
+
+static void
+crypto_core_salsa(unsigned char *out, const unsigned char *in,
+ const unsigned char *k, const unsigned char *c,
+ const int rounds)
+{
+ uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14,
+ x15;
+ uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14,
+ j15;
+ int i;
+
+ j0 = x0 = 0x61707865;
+ j5 = x5 = 0x3320646e;
+ j10 = x10 = 0x79622d32;
+ j15 = x15 = 0x6b206574;
+ if (c != NULL) {
+ j0 = x0 = LOAD32_LE(c + 0);
+ j5 = x5 = LOAD32_LE(c + 4);
+ j10 = x10 = LOAD32_LE(c + 8);
+ j15 = x15 = LOAD32_LE(c + 12);
+ }
+ j1 = x1 = LOAD32_LE(k + 0);
+ j2 = x2 = LOAD32_LE(k + 4);
+ j3 = x3 = LOAD32_LE(k + 8);
+ j4 = x4 = LOAD32_LE(k + 12);
+ j11 = x11 = LOAD32_LE(k + 16);
+ j12 = x12 = LOAD32_LE(k + 20);
+ j13 = x13 = LOAD32_LE(k + 24);
+ j14 = x14 = LOAD32_LE(k + 28);
+
+ j6 = x6 = LOAD32_LE(in + 0);
+ j7 = x7 = LOAD32_LE(in + 4);
+ j8 = x8 = LOAD32_LE(in + 8);
+ j9 = x9 = LOAD32_LE(in + 12);
+
+ for (i = 0; i < rounds; i += 2) {
+ x4 ^= ROTL32(x0 + x12, 7);
+ x8 ^= ROTL32(x4 + x0, 9);
+ x12 ^= ROTL32(x8 + x4, 13);
+ x0 ^= ROTL32(x12 + x8, 18);
+ x9 ^= ROTL32(x5 + x1, 7);
+ x13 ^= ROTL32(x9 + x5, 9);
+ x1 ^= ROTL32(x13 + x9, 13);
+ x5 ^= ROTL32(x1 + x13, 18);
+ x14 ^= ROTL32(x10 + x6, 7);
+ x2 ^= ROTL32(x14 + x10, 9);
+ x6 ^= ROTL32(x2 + x14, 13);
+ x10 ^= ROTL32(x6 + x2, 18);
+ x3 ^= ROTL32(x15 + x11, 7);
+ x7 ^= ROTL32(x3 + x15, 9);
+ x11 ^= ROTL32(x7 + x3, 13);
+ x15 ^= ROTL32(x11 + x7, 18);
+ x1 ^= ROTL32(x0 + x3, 7);
+ x2 ^= ROTL32(x1 + x0, 9);
+ x3 ^= ROTL32(x2 + x1, 13);
+ x0 ^= ROTL32(x3 + x2, 18);
+ x6 ^= ROTL32(x5 + x4, 7);
+ x7 ^= ROTL32(x6 + x5, 9);
+ x4 ^= ROTL32(x7 + x6, 13);
+ x5 ^= ROTL32(x4 + x7, 18);
+ x11 ^= ROTL32(x10 + x9, 7);
+ x8 ^= ROTL32(x11 + x10, 9);
+ x9 ^= ROTL32(x8 + x11, 13);
+ x10 ^= ROTL32(x9 + x8, 18);
+ x12 ^= ROTL32(x15 + x14, 7);
+ x13 ^= ROTL32(x12 + x15, 9);
+ x14 ^= ROTL32(x13 + x12, 13);
+ x15 ^= ROTL32(x14 + x13, 18);
+ }
+ STORE32_LE(out + 0, x0 + j0);
+ STORE32_LE(out + 4, x1 + j1);
+ STORE32_LE(out + 8, x2 + j2);
+ STORE32_LE(out + 12, x3 + j3);
+ STORE32_LE(out + 16, x4 + j4);
+ STORE32_LE(out + 20, x5 + j5);
+ STORE32_LE(out + 24, x6 + j6);
+ STORE32_LE(out + 28, x7 + j7);
+ STORE32_LE(out + 32, x8 + j8);
+ STORE32_LE(out + 36, x9 + j9);
+ STORE32_LE(out + 40, x10 + j10);
+ STORE32_LE(out + 44, x11 + j11);
+ STORE32_LE(out + 48, x12 + j12);
+ STORE32_LE(out + 52, x13 + j13);
+ STORE32_LE(out + 56, x14 + j14);
+ STORE32_LE(out + 60, x15 + j15);
+}
+
+int
+crypto_core_salsa20(unsigned char *out, const unsigned char *in,
+ const unsigned char *k, const unsigned char *c)
+{
+ crypto_core_salsa(out, in, k, c, 20);
+ return 0;
+}
+
+size_t
+crypto_core_salsa20_outputbytes(void)
+{
+ return crypto_core_salsa20_OUTPUTBYTES;
+}
+
+size_t
+crypto_core_salsa20_inputbytes(void)
+{
+ return crypto_core_salsa20_INPUTBYTES;
+}
+
+size_t
+crypto_core_salsa20_keybytes(void)
+{
+ return crypto_core_salsa20_KEYBYTES;
+}
+
+size_t
+crypto_core_salsa20_constbytes(void)
+{
+ return crypto_core_salsa20_CONSTBYTES;
+}
+
+#ifndef MINIMAL
+
+int
+crypto_core_salsa2012(unsigned char *out, const unsigned char *in,
+ const unsigned char *k, const unsigned char *c)
+{
+ crypto_core_salsa(out, in, k, c, 12);
+ return 0;
+}
+
+size_t
+crypto_core_salsa2012_outputbytes(void)
+{
+ return crypto_core_salsa2012_OUTPUTBYTES;
+}
+
+size_t
+crypto_core_salsa2012_inputbytes(void)
+{
+ return crypto_core_salsa2012_INPUTBYTES;
+}
+
+size_t
+crypto_core_salsa2012_keybytes(void)
+{
+ return crypto_core_salsa2012_KEYBYTES;
+}
+
+size_t
+crypto_core_salsa2012_constbytes(void)
+{
+ return crypto_core_salsa2012_CONSTBYTES;
+}
+
+int
+crypto_core_salsa208(unsigned char *out, const unsigned char *in,
+ const unsigned char *k, const unsigned char *c)
+{
+ crypto_core_salsa(out, in, k, c, 8);
+ return 0;
+}
+
+size_t
+crypto_core_salsa208_outputbytes(void)
+{
+ return crypto_core_salsa208_OUTPUTBYTES;
+}
+
+size_t
+crypto_core_salsa208_inputbytes(void)
+{
+ return crypto_core_salsa208_INPUTBYTES;
+}
+
+size_t
+crypto_core_salsa208_keybytes(void)
+{
+ return crypto_core_salsa208_KEYBYTES;
+}
+
+size_t
+crypto_core_salsa208_constbytes(void)
+{
+ return crypto_core_salsa208_CONSTBYTES;
+}
+
+#endif
diff --git a/libs/libsodium/src/crypto_generichash/blake2b/generichash_blake2.c b/libs/libsodium/src/crypto_generichash/blake2b/generichash_blake2.c
new file mode 100644
index 0000000000..781d4c584e
--- /dev/null
+++ b/libs/libsodium/src/crypto_generichash/blake2b/generichash_blake2.c
@@ -0,0 +1,55 @@
+#include "crypto_generichash_blake2b.h"
+#include "randombytes.h"
+
+size_t
+crypto_generichash_blake2b_bytes_min(void) {
+ return crypto_generichash_blake2b_BYTES_MIN;
+}
+
+size_t
+crypto_generichash_blake2b_bytes_max(void) {
+ return crypto_generichash_blake2b_BYTES_MAX;
+}
+
+size_t
+crypto_generichash_blake2b_bytes(void) {
+ return crypto_generichash_blake2b_BYTES;
+}
+
+size_t
+crypto_generichash_blake2b_keybytes_min(void) {
+ return crypto_generichash_blake2b_KEYBYTES_MIN;
+}
+
+size_t
+crypto_generichash_blake2b_keybytes_max(void) {
+ return crypto_generichash_blake2b_KEYBYTES_MAX;
+}
+
+size_t
+crypto_generichash_blake2b_keybytes(void) {
+ return crypto_generichash_blake2b_KEYBYTES;
+}
+
+size_t
+crypto_generichash_blake2b_saltbytes(void) {
+ return crypto_generichash_blake2b_SALTBYTES;
+}
+
+size_t
+crypto_generichash_blake2b_personalbytes(void) {
+ return crypto_generichash_blake2b_PERSONALBYTES;
+}
+
+size_t
+crypto_generichash_blake2b_statebytes(void)
+{
+ return (sizeof(crypto_generichash_blake2b_state) + (size_t) 63U)
+ & ~(size_t) 63U;
+}
+
+void
+crypto_generichash_blake2b_keygen(unsigned char k[crypto_generichash_blake2b_KEYBYTES])
+{
+ randombytes_buf(k, crypto_generichash_blake2b_KEYBYTES);
+}
diff --git a/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2.h b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2.h
new file mode 100644
index 0000000000..c6c4fccbb7
--- /dev/null
+++ b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2.h
@@ -0,0 +1,109 @@
+/*
+ BLAKE2 reference source code package - reference C implementations
+
+ Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
+
+ To the extent possible under law, the author(s) have dedicated all copyright
+ and related and neighboring rights to this software to the public domain
+ worldwide. This software is distributed without any warranty.
+
+ All code is triple-licensed under the
+ [CC0](http://creativecommons.org/publicdomain/zero/1.0), the
+ [OpenSSL Licence](https://www.openssl.org/source/license.html), or
+ the [Apache Public License 2.0](http://www.apache.org/licenses/LICENSE-2.0),
+ at your choosing.
+ */
+
+#ifndef blake2_H
+#define blake2_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "crypto_generichash_blake2b.h"
+#include "export.h"
+
+#define blake2b_init_param crypto_generichash_blake2b__init_param
+#define blake2b_init crypto_generichash_blake2b__init
+#define blake2b_init_salt_personal \
+ crypto_generichash_blake2b__init_salt_personal
+#define blake2b_init_key crypto_generichash_blake2b__init_key
+#define blake2b_init_key_salt_personal \
+ crypto_generichash_blake2b__init_key_salt_personal
+#define blake2b_update crypto_generichash_blake2b__update
+#define blake2b_final crypto_generichash_blake2b__final
+#define blake2b crypto_generichash_blake2b__blake2b
+#define blake2b_salt_personal crypto_generichash_blake2b__blake2b_salt_personal
+#define blake2b_pick_best_implementation \
+ crypto_generichash_blake2b__pick_best_implementation
+
+enum blake2b_constant {
+ BLAKE2B_BLOCKBYTES = 128,
+ BLAKE2B_OUTBYTES = 64,
+ BLAKE2B_KEYBYTES = 64,
+ BLAKE2B_SALTBYTES = 16,
+ BLAKE2B_PERSONALBYTES = 16
+};
+
+#if defined(__IBMC__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma pack(1)
+#else
+#pragma pack(push, 1)
+#endif
+
+typedef struct blake2b_param_ {
+ uint8_t digest_length; /* 1 */
+ uint8_t key_length; /* 2 */
+ uint8_t fanout; /* 3 */
+ uint8_t depth; /* 4 */
+ uint8_t leaf_length[4]; /* 8 */
+ uint8_t node_offset[8]; /* 16 */
+ uint8_t node_depth; /* 17 */
+ uint8_t inner_length; /* 18 */
+ uint8_t reserved[14]; /* 32 */
+ uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
+ uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
+} blake2b_param;
+
+typedef crypto_generichash_blake2b_state blake2b_state;
+
+#if defined(__IBMC__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma pack()
+#else
+#pragma pack(pop)
+#endif
+
+/* Streaming API */
+int blake2b_init(blake2b_state *S, const uint8_t outlen);
+int blake2b_init_salt_personal(blake2b_state *S, const uint8_t outlen,
+ const void *salt, const void *personal);
+int blake2b_init_key(blake2b_state *S, const uint8_t outlen, const void *key,
+ const uint8_t keylen);
+int blake2b_init_key_salt_personal(blake2b_state *S, const uint8_t outlen,
+ const void *key, const uint8_t keylen,
+ const void *salt, const void *personal);
+int blake2b_init_param(blake2b_state *S, const blake2b_param *P);
+int blake2b_update(blake2b_state *S, const uint8_t *in, uint64_t inlen);
+int blake2b_final(blake2b_state *S, uint8_t *out, uint8_t outlen);
+
+/* Simple API */
+int blake2b(uint8_t *out, const void *in, const void *key, const uint8_t outlen,
+ const uint64_t inlen, uint8_t keylen);
+int blake2b_salt_personal(uint8_t *out, const void *in, const void *key,
+ const uint8_t outlen, const uint64_t inlen,
+ uint8_t keylen, const void *salt,
+ const void *personal);
+
+typedef int (*blake2b_compress_fn)(blake2b_state *S,
+ const uint8_t block[BLAKE2B_BLOCKBYTES]);
+int blake2b_pick_best_implementation(void);
+int blake2b_compress_ref(blake2b_state *S,
+ const uint8_t block[BLAKE2B_BLOCKBYTES]);
+int blake2b_compress_ssse3(blake2b_state *S,
+ const uint8_t block[BLAKE2B_BLOCKBYTES]);
+int blake2b_compress_sse41(blake2b_state *S,
+ const uint8_t block[BLAKE2B_BLOCKBYTES]);
+int blake2b_compress_avx2(blake2b_state *S,
+ const uint8_t block[BLAKE2B_BLOCKBYTES]);
+
+#endif
diff --git a/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-avx2.c b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-avx2.c
new file mode 100644
index 0000000000..7cb41fb6e7
--- /dev/null
+++ b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-avx2.c
@@ -0,0 +1,49 @@
+
+#define BLAKE2_USE_SSSE3
+#define BLAKE2_USE_SSE41
+#define BLAKE2_USE_AVX2
+
+#include <stdint.h>
+#include <string.h>
+
+#include "blake2.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#if defined(HAVE_AVX2INTRIN_H) && defined(HAVE_EMMINTRIN_H) && \
+ defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# pragma GCC target("ssse3")
+# pragma GCC target("sse4.1")
+# pragma GCC target("avx2")
+# endif
+
+# include <emmintrin.h>
+# include <immintrin.h>
+# include <smmintrin.h>
+# include <tmmintrin.h>
+
+# include "blake2b-compress-avx2.h"
+
+CRYPTO_ALIGN(64)
+static const uint64_t blake2b_IV[8] = {
+ 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
+ 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+};
+
+int
+blake2b_compress_avx2(blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES])
+{
+ __m256i a = LOADU(&S->h[0]);
+ __m256i b = LOADU(&S->h[4]);
+ BLAKE2B_COMPRESS_V1(a, b, block, S->t[0], S->t[1], S->f[0], S->f[1]);
+ STOREU(&S->h[0], a);
+ STOREU(&S->h[4], b);
+
+ return 0;
+}
+
+#endif
diff --git a/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-avx2.h b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-avx2.h
new file mode 100644
index 0000000000..21acb2fa0c
--- /dev/null
+++ b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-avx2.h
@@ -0,0 +1,140 @@
+
+#ifndef blake2b_compress_avx2_H
+#define blake2b_compress_avx2_H
+
+#define LOAD128(p) _mm_load_si128((__m128i *) (p))
+#define STORE128(p, r) _mm_store_si128((__m128i *) (p), r)
+
+#define LOADU128(p) _mm_loadu_si128((__m128i *) (p))
+#define STOREU128(p, r) _mm_storeu_si128((__m128i *) (p), r)
+
+#define LOAD(p) _mm256_load_si256((__m256i *) (p))
+#define STORE(p, r) _mm256_store_si256((__m256i *) (p), r)
+
+#define LOADU(p) _mm256_loadu_si256((__m256i *) (p))
+#define STOREU(p, r) _mm256_storeu_si256((__m256i *) (p), r)
+
+static inline uint64_t
+LOADU64(const void *p)
+{
+ uint64_t v;
+ memcpy(&v, p, sizeof v);
+ return v;
+}
+
+#define ROTATE16 \
+ _mm256_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9, 2, \
+ 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9)
+
+#define ROTATE24 \
+ _mm256_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10, 3, \
+ 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10)
+
+#define ADD(a, b) _mm256_add_epi64(a, b)
+#define SUB(a, b) _mm256_sub_epi64(a, b)
+
+#define XOR(a, b) _mm256_xor_si256(a, b)
+#define AND(a, b) _mm256_and_si256(a, b)
+#define OR(a, b) _mm256_or_si256(a, b)
+
+#define ROT32(x) _mm256_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1))
+#define ROT24(x) _mm256_shuffle_epi8((x), ROTATE24)
+#define ROT16(x) _mm256_shuffle_epi8((x), ROTATE16)
+#define ROT63(x) _mm256_or_si256(_mm256_srli_epi64((x), 63), ADD((x), (x)))
+
+#define BLAKE2B_G1_V1(a, b, c, d, m) \
+ do { \
+ a = ADD(a, m); \
+ a = ADD(a, b); \
+ d = XOR(d, a); \
+ d = ROT32(d); \
+ c = ADD(c, d); \
+ b = XOR(b, c); \
+ b = ROT24(b); \
+ } while (0)
+
+#define BLAKE2B_G2_V1(a, b, c, d, m) \
+ do { \
+ a = ADD(a, m); \
+ a = ADD(a, b); \
+ d = XOR(d, a); \
+ d = ROT16(d); \
+ c = ADD(c, d); \
+ b = XOR(b, c); \
+ b = ROT63(b); \
+ } while (0)
+
+#define BLAKE2B_DIAG_V1(a, b, c, d) \
+ do { \
+ d = _mm256_permute4x64_epi64(d, _MM_SHUFFLE(2, 1, 0, 3)); \
+ c = _mm256_permute4x64_epi64(c, _MM_SHUFFLE(1, 0, 3, 2)); \
+ b = _mm256_permute4x64_epi64(b, _MM_SHUFFLE(0, 3, 2, 1)); \
+ } while (0)
+
+#define BLAKE2B_UNDIAG_V1(a, b, c, d) \
+ do { \
+ d = _mm256_permute4x64_epi64(d, _MM_SHUFFLE(0, 3, 2, 1)); \
+ c = _mm256_permute4x64_epi64(c, _MM_SHUFFLE(1, 0, 3, 2)); \
+ b = _mm256_permute4x64_epi64(b, _MM_SHUFFLE(2, 1, 0, 3)); \
+ } while (0)
+
+#include "blake2b-load-avx2.h"
+
+#define BLAKE2B_ROUND_V1(a, b, c, d, r, m) \
+ do { \
+ __m256i b0; \
+ BLAKE2B_LOAD_MSG_##r##_1(b0); \
+ BLAKE2B_G1_V1(a, b, c, d, b0); \
+ BLAKE2B_LOAD_MSG_##r##_2(b0); \
+ BLAKE2B_G2_V1(a, b, c, d, b0); \
+ BLAKE2B_DIAG_V1(a, b, c, d); \
+ BLAKE2B_LOAD_MSG_##r##_3(b0); \
+ BLAKE2B_G1_V1(a, b, c, d, b0); \
+ BLAKE2B_LOAD_MSG_##r##_4(b0); \
+ BLAKE2B_G2_V1(a, b, c, d, b0); \
+ BLAKE2B_UNDIAG_V1(a, b, c, d); \
+ } while (0)
+
+#define BLAKE2B_ROUNDS_V1(a, b, c, d, m) \
+ do { \
+ BLAKE2B_ROUND_V1(a, b, c, d, 0, (m)); \
+ BLAKE2B_ROUND_V1(a, b, c, d, 1, (m)); \
+ BLAKE2B_ROUND_V1(a, b, c, d, 2, (m)); \
+ BLAKE2B_ROUND_V1(a, b, c, d, 3, (m)); \
+ BLAKE2B_ROUND_V1(a, b, c, d, 4, (m)); \
+ BLAKE2B_ROUND_V1(a, b, c, d, 5, (m)); \
+ BLAKE2B_ROUND_V1(a, b, c, d, 6, (m)); \
+ BLAKE2B_ROUND_V1(a, b, c, d, 7, (m)); \
+ BLAKE2B_ROUND_V1(a, b, c, d, 8, (m)); \
+ BLAKE2B_ROUND_V1(a, b, c, d, 9, (m)); \
+ BLAKE2B_ROUND_V1(a, b, c, d, 10, (m)); \
+ BLAKE2B_ROUND_V1(a, b, c, d, 11, (m)); \
+ } while (0)
+
+#define DECLARE_MESSAGE_WORDS(m) \
+ const __m256i m0 = _mm256_broadcastsi128_si256(LOADU128((m) + 0)); \
+ const __m256i m1 = _mm256_broadcastsi128_si256(LOADU128((m) + 16)); \
+ const __m256i m2 = _mm256_broadcastsi128_si256(LOADU128((m) + 32)); \
+ const __m256i m3 = _mm256_broadcastsi128_si256(LOADU128((m) + 48)); \
+ const __m256i m4 = _mm256_broadcastsi128_si256(LOADU128((m) + 64)); \
+ const __m256i m5 = _mm256_broadcastsi128_si256(LOADU128((m) + 80)); \
+ const __m256i m6 = _mm256_broadcastsi128_si256(LOADU128((m) + 96)); \
+ const __m256i m7 = _mm256_broadcastsi128_si256(LOADU128((m) + 112)); \
+ __m256i t0, t1;
+
+#define BLAKE2B_COMPRESS_V1(a, b, m, t0, t1, f0, f1) \
+ do { \
+ DECLARE_MESSAGE_WORDS(m) \
+ const __m256i iv0 = a; \
+ const __m256i iv1 = b; \
+ __m256i c = LOAD(&blake2b_IV[0]); \
+ __m256i d = \
+ XOR(LOAD(&blake2b_IV[4]), _mm256_set_epi64x(f1, f0, t1, t0)); \
+ BLAKE2B_ROUNDS_V1(a, b, c, d, m); \
+ a = XOR(a, c); \
+ b = XOR(b, d); \
+ a = XOR(a, iv0); \
+ b = XOR(b, iv1); \
+ } while (0)
+
+#endif
diff --git a/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-ref.c b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-ref.c
new file mode 100644
index 0000000000..614fa34af7
--- /dev/null
+++ b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-ref.c
@@ -0,0 +1,93 @@
+
+#include <stdint.h>
+#include <string.h>
+
+#include "blake2.h"
+#include "private/common.h"
+
+CRYPTO_ALIGN(64)
+static const uint64_t blake2b_IV[8] = {
+ 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
+ 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+};
+
+static const uint8_t blake2b_sigma[12][16] = {
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
+ { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
+ { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
+ { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
+ { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
+ { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
+ { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
+ { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
+ { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
+};
+
+int
+blake2b_compress_ref(blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES])
+{
+ uint64_t m[16];
+ uint64_t v[16];
+ int i;
+
+ for (i = 0; i < 16; ++i)
+ m[i] = LOAD64_LE(block + i * sizeof(m[i]));
+
+ for (i = 0; i < 8; ++i)
+ v[i] = S->h[i];
+
+ v[8] = blake2b_IV[0];
+ v[9] = blake2b_IV[1];
+ v[10] = blake2b_IV[2];
+ v[11] = blake2b_IV[3];
+ v[12] = S->t[0] ^ blake2b_IV[4];
+ v[13] = S->t[1] ^ blake2b_IV[5];
+ v[14] = S->f[0] ^ blake2b_IV[6];
+ v[15] = S->f[1] ^ blake2b_IV[7];
+#define G(r, i, a, b, c, d) \
+ do { \
+ a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \
+ d = ROTR64(d ^ a, 32); \
+ c = c + d; \
+ b = ROTR64(b ^ c, 24); \
+ a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \
+ d = ROTR64(d ^ a, 16); \
+ c = c + d; \
+ b = ROTR64(b ^ c, 63); \
+ } while (0)
+#define ROUND(r) \
+ do { \
+ G(r, 0, v[0], v[4], v[8], v[12]); \
+ G(r, 1, v[1], v[5], v[9], v[13]); \
+ G(r, 2, v[2], v[6], v[10], v[14]); \
+ G(r, 3, v[3], v[7], v[11], v[15]); \
+ G(r, 4, v[0], v[5], v[10], v[15]); \
+ G(r, 5, v[1], v[6], v[11], v[12]); \
+ G(r, 6, v[2], v[7], v[8], v[13]); \
+ G(r, 7, v[3], v[4], v[9], v[14]); \
+ } while (0)
+ ROUND(0);
+ ROUND(1);
+ ROUND(2);
+ ROUND(3);
+ ROUND(4);
+ ROUND(5);
+ ROUND(6);
+ ROUND(7);
+ ROUND(8);
+ ROUND(9);
+ ROUND(10);
+ ROUND(11);
+
+ for (i = 0; i < 8; ++i) {
+ S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
+ }
+
+#undef G
+#undef ROUND
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-sse41.c b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-sse41.c
new file mode 100644
index 0000000000..9e5c0c5081
--- /dev/null
+++ b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-sse41.c
@@ -0,0 +1,87 @@
+
+#define BLAKE2_USE_SSSE3
+#define BLAKE2_USE_SSE41
+
+#include <stdint.h>
+#include <string.h>
+
+#include "blake2.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H) && \
+ defined(HAVE_SMMINTRIN_H)
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# pragma GCC target("ssse3")
+# pragma GCC target("sse4.1")
+# endif
+
+# include <emmintrin.h>
+# include <smmintrin.h>
+# include <tmmintrin.h>
+
+# include "blake2b-compress-sse41.h"
+
+CRYPTO_ALIGN(64)
+static const uint64_t blake2b_IV[8] = {
+ 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
+ 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+};
+
+int
+blake2b_compress_sse41(blake2b_state *S,
+ const uint8_t block[BLAKE2B_BLOCKBYTES])
+{
+ __m128i row1l, row1h;
+ __m128i row2l, row2h;
+ __m128i row3l, row3h;
+ __m128i row4l, row4h;
+ __m128i b0, b1;
+ __m128i t0, t1;
+ const __m128i r16 =
+ _mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9);
+ const __m128i r24 =
+ _mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10);
+ const __m128i m0 = LOADU(block + 00);
+ const __m128i m1 = LOADU(block + 16);
+ const __m128i m2 = LOADU(block + 32);
+ const __m128i m3 = LOADU(block + 48);
+ const __m128i m4 = LOADU(block + 64);
+ const __m128i m5 = LOADU(block + 80);
+ const __m128i m6 = LOADU(block + 96);
+ const __m128i m7 = LOADU(block + 112);
+ row1l = LOADU(&S->h[0]);
+ row1h = LOADU(&S->h[2]);
+ row2l = LOADU(&S->h[4]);
+ row2h = LOADU(&S->h[6]);
+ row3l = LOADU(&blake2b_IV[0]);
+ row3h = LOADU(&blake2b_IV[2]);
+ row4l = _mm_xor_si128(LOADU(&blake2b_IV[4]), LOADU(&S->t[0]));
+ row4h = _mm_xor_si128(LOADU(&blake2b_IV[6]), LOADU(&S->f[0]));
+ ROUND(0);
+ ROUND(1);
+ ROUND(2);
+ ROUND(3);
+ ROUND(4);
+ ROUND(5);
+ ROUND(6);
+ ROUND(7);
+ ROUND(8);
+ ROUND(9);
+ ROUND(10);
+ ROUND(11);
+ row1l = _mm_xor_si128(row3l, row1l);
+ row1h = _mm_xor_si128(row3h, row1h);
+ STOREU(&S->h[0], _mm_xor_si128(LOADU(&S->h[0]), row1l));
+ STOREU(&S->h[2], _mm_xor_si128(LOADU(&S->h[2]), row1h));
+ row2l = _mm_xor_si128(row4l, row2l);
+ row2h = _mm_xor_si128(row4h, row2h);
+ STOREU(&S->h[4], _mm_xor_si128(LOADU(&S->h[4]), row2l));
+ STOREU(&S->h[6], _mm_xor_si128(LOADU(&S->h[6]), row2h));
+ return 0;
+}
+
+#endif
diff --git a/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-sse41.h b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-sse41.h
new file mode 100644
index 0000000000..ac78e5bb1e
--- /dev/null
+++ b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-sse41.h
@@ -0,0 +1,103 @@
+
+#ifndef blake2b_compress_sse41_H
+#define blake2b_compress_sse41_H
+
+#define LOADU(p) _mm_loadu_si128((const __m128i *) (const void *) (p))
+#define STOREU(p, r) _mm_storeu_si128((__m128i *) (void *) (p), r)
+
+#define _mm_roti_epi64(x, c) \
+ (-(c) == 32) \
+ ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1)) \
+ : (-(c) == 24) \
+ ? _mm_shuffle_epi8((x), r24) \
+ : (-(c) == 16) \
+ ? _mm_shuffle_epi8((x), r16) \
+ : (-(c) == 63) \
+ ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
+ _mm_add_epi64((x), (x))) \
+ : _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
+ _mm_slli_epi64((x), 64 - (-(c))))
+
+#define G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1) \
+ row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \
+ row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \
+ \
+ row4l = _mm_xor_si128(row4l, row1l); \
+ row4h = _mm_xor_si128(row4h, row1h); \
+ \
+ row4l = _mm_roti_epi64(row4l, -32); \
+ row4h = _mm_roti_epi64(row4h, -32); \
+ \
+ row3l = _mm_add_epi64(row3l, row4l); \
+ row3h = _mm_add_epi64(row3h, row4h); \
+ \
+ row2l = _mm_xor_si128(row2l, row3l); \
+ row2h = _mm_xor_si128(row2h, row3h); \
+ \
+ row2l = _mm_roti_epi64(row2l, -24); \
+ row2h = _mm_roti_epi64(row2h, -24);
+
+#define G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1) \
+ row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \
+ row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \
+ \
+ row4l = _mm_xor_si128(row4l, row1l); \
+ row4h = _mm_xor_si128(row4h, row1h); \
+ \
+ row4l = _mm_roti_epi64(row4l, -16); \
+ row4h = _mm_roti_epi64(row4h, -16); \
+ \
+ row3l = _mm_add_epi64(row3l, row4l); \
+ row3h = _mm_add_epi64(row3h, row4h); \
+ \
+ row2l = _mm_xor_si128(row2l, row3l); \
+ row2h = _mm_xor_si128(row2h, row3h); \
+ \
+ row2l = _mm_roti_epi64(row2l, -63); \
+ row2h = _mm_roti_epi64(row2h, -63);
+
+#define DIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
+ t0 = _mm_alignr_epi8(row2h, row2l, 8); \
+ t1 = _mm_alignr_epi8(row2l, row2h, 8); \
+ row2l = t0; \
+ row2h = t1; \
+ \
+ t0 = row3l; \
+ row3l = row3h; \
+ row3h = t0; \
+ \
+ t0 = _mm_alignr_epi8(row4h, row4l, 8); \
+ t1 = _mm_alignr_epi8(row4l, row4h, 8); \
+ row4l = t1; \
+ row4h = t0;
+
+#define UNDIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
+ t0 = _mm_alignr_epi8(row2l, row2h, 8); \
+ t1 = _mm_alignr_epi8(row2h, row2l, 8); \
+ row2l = t0; \
+ row2h = t1; \
+ \
+ t0 = row3l; \
+ row3l = row3h; \
+ row3h = t0; \
+ \
+ t0 = _mm_alignr_epi8(row4l, row4h, 8); \
+ t1 = _mm_alignr_epi8(row4h, row4l, 8); \
+ row4l = t1; \
+ row4h = t0;
+
+#include "blake2b-load-sse41.h"
+
+#define ROUND(r) \
+ LOAD_MSG_##r##_1(b0, b1); \
+ G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1); \
+ LOAD_MSG_##r##_2(b0, b1); \
+ G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1); \
+ DIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
+ LOAD_MSG_##r##_3(b0, b1); \
+ G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1); \
+ LOAD_MSG_##r##_4(b0, b1); \
+ G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1); \
+ UNDIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h);
+
+#endif
diff --git a/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-ssse3.c b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-ssse3.c
new file mode 100644
index 0000000000..a207a64d40
--- /dev/null
+++ b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-ssse3.c
@@ -0,0 +1,90 @@
+
+#include <stdint.h>
+#include <string.h>
+
+#include "blake2.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# pragma GCC target("ssse3")
+# endif
+
+# include <emmintrin.h>
+# include <tmmintrin.h>
+
+# include "blake2b-compress-ssse3.h"
+
+CRYPTO_ALIGN(64)
+static const uint64_t blake2b_IV[8] = {
+ 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
+ 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+};
+
+int
+blake2b_compress_ssse3(blake2b_state *S,
+ const uint8_t block[BLAKE2B_BLOCKBYTES])
+{
+ __m128i row1l, row1h;
+ __m128i row2l, row2h;
+ __m128i row3l, row3h;
+ __m128i row4l, row4h;
+ __m128i b0, b1;
+ __m128i t0, t1;
+ const __m128i r16 =
+ _mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9);
+ const __m128i r24 =
+ _mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10);
+ const uint64_t m0 = ((uint64_t *) block)[0];
+ const uint64_t m1 = ((uint64_t *) block)[1];
+ const uint64_t m2 = ((uint64_t *) block)[2];
+ const uint64_t m3 = ((uint64_t *) block)[3];
+ const uint64_t m4 = ((uint64_t *) block)[4];
+ const uint64_t m5 = ((uint64_t *) block)[5];
+ const uint64_t m6 = ((uint64_t *) block)[6];
+ const uint64_t m7 = ((uint64_t *) block)[7];
+ const uint64_t m8 = ((uint64_t *) block)[8];
+ const uint64_t m9 = ((uint64_t *) block)[9];
+ const uint64_t m10 = ((uint64_t *) block)[10];
+ const uint64_t m11 = ((uint64_t *) block)[11];
+ const uint64_t m12 = ((uint64_t *) block)[12];
+ const uint64_t m13 = ((uint64_t *) block)[13];
+ const uint64_t m14 = ((uint64_t *) block)[14];
+ const uint64_t m15 = ((uint64_t *) block)[15];
+
+ row1l = LOADU(&S->h[0]);
+ row1h = LOADU(&S->h[2]);
+ row2l = LOADU(&S->h[4]);
+ row2h = LOADU(&S->h[6]);
+ row3l = LOADU(&blake2b_IV[0]);
+ row3h = LOADU(&blake2b_IV[2]);
+ row4l = _mm_xor_si128(LOADU(&blake2b_IV[4]), LOADU(&S->t[0]));
+ row4h = _mm_xor_si128(LOADU(&blake2b_IV[6]), LOADU(&S->f[0]));
+ ROUND(0);
+ ROUND(1);
+ ROUND(2);
+ ROUND(3);
+ ROUND(4);
+ ROUND(5);
+ ROUND(6);
+ ROUND(7);
+ ROUND(8);
+ ROUND(9);
+ ROUND(10);
+ ROUND(11);
+ row1l = _mm_xor_si128(row3l, row1l);
+ row1h = _mm_xor_si128(row3h, row1h);
+ STOREU(&S->h[0], _mm_xor_si128(LOADU(&S->h[0]), row1l));
+ STOREU(&S->h[2], _mm_xor_si128(LOADU(&S->h[2]), row1h));
+ row2l = _mm_xor_si128(row4l, row2l);
+ row2h = _mm_xor_si128(row4h, row2h);
+ STOREU(&S->h[4], _mm_xor_si128(LOADU(&S->h[4]), row2l));
+ STOREU(&S->h[6], _mm_xor_si128(LOADU(&S->h[6]), row2h));
+ return 0;
+}
+
+#endif
diff --git a/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-ssse3.h b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-ssse3.h
new file mode 100644
index 0000000000..9a7164fe25
--- /dev/null
+++ b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-compress-ssse3.h
@@ -0,0 +1,103 @@
+
+#ifndef blake2b_compress_ssse3_H
+#define blake2b_compress_ssse3_H
+
+#define LOADU(p) _mm_loadu_si128((const __m128i *) (const void *) (p))
+#define STOREU(p, r) _mm_storeu_si128((__m128i *) (void *) (p), r)
+
+#define _mm_roti_epi64(x, c) \
+ (-(c) == 32) \
+ ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1)) \
+ : (-(c) == 24) \
+ ? _mm_shuffle_epi8((x), r24) \
+ : (-(c) == 16) \
+ ? _mm_shuffle_epi8((x), r16) \
+ : (-(c) == 63) \
+ ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
+ _mm_add_epi64((x), (x))) \
+ : _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
+ _mm_slli_epi64((x), 64 - (-(c))))
+
+#define G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1) \
+ row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \
+ row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \
+ \
+ row4l = _mm_xor_si128(row4l, row1l); \
+ row4h = _mm_xor_si128(row4h, row1h); \
+ \
+ row4l = _mm_roti_epi64(row4l, -32); \
+ row4h = _mm_roti_epi64(row4h, -32); \
+ \
+ row3l = _mm_add_epi64(row3l, row4l); \
+ row3h = _mm_add_epi64(row3h, row4h); \
+ \
+ row2l = _mm_xor_si128(row2l, row3l); \
+ row2h = _mm_xor_si128(row2h, row3h); \
+ \
+ row2l = _mm_roti_epi64(row2l, -24); \
+ row2h = _mm_roti_epi64(row2h, -24);
+
+#define G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1) \
+ row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \
+ row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \
+ \
+ row4l = _mm_xor_si128(row4l, row1l); \
+ row4h = _mm_xor_si128(row4h, row1h); \
+ \
+ row4l = _mm_roti_epi64(row4l, -16); \
+ row4h = _mm_roti_epi64(row4h, -16); \
+ \
+ row3l = _mm_add_epi64(row3l, row4l); \
+ row3h = _mm_add_epi64(row3h, row4h); \
+ \
+ row2l = _mm_xor_si128(row2l, row3l); \
+ row2h = _mm_xor_si128(row2h, row3h); \
+ \
+ row2l = _mm_roti_epi64(row2l, -63); \
+ row2h = _mm_roti_epi64(row2h, -63);
+
+#define DIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
+ t0 = _mm_alignr_epi8(row2h, row2l, 8); \
+ t1 = _mm_alignr_epi8(row2l, row2h, 8); \
+ row2l = t0; \
+ row2h = t1; \
+ \
+ t0 = row3l; \
+ row3l = row3h; \
+ row3h = t0; \
+ \
+ t0 = _mm_alignr_epi8(row4h, row4l, 8); \
+ t1 = _mm_alignr_epi8(row4l, row4h, 8); \
+ row4l = t1; \
+ row4h = t0;
+
+#define UNDIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h) \
+ t0 = _mm_alignr_epi8(row2l, row2h, 8); \
+ t1 = _mm_alignr_epi8(row2h, row2l, 8); \
+ row2l = t0; \
+ row2h = t1; \
+ \
+ t0 = row3l; \
+ row3l = row3h; \
+ row3h = t0; \
+ \
+ t0 = _mm_alignr_epi8(row4l, row4h, 8); \
+ t1 = _mm_alignr_epi8(row4h, row4l, 8); \
+ row4l = t1; \
+ row4h = t0;
+
+#include "blake2b-load-sse2.h"
+
+#define ROUND(r) \
+ LOAD_MSG_##r##_1(b0, b1); \
+ G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1); \
+ LOAD_MSG_##r##_2(b0, b1); \
+ G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1); \
+ DIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h); \
+ LOAD_MSG_##r##_3(b0, b1); \
+ G1(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1); \
+ LOAD_MSG_##r##_4(b0, b1); \
+ G2(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h, b0, b1); \
+ UNDIAGONALIZE(row1l, row2l, row3l, row4l, row1h, row2h, row3h, row4h);
+
+#endif
diff --git a/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-load-avx2.h b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-load-avx2.h
new file mode 100644
index 0000000000..8c15f177c7
--- /dev/null
+++ b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-load-avx2.h
@@ -0,0 +1,340 @@
+#ifndef blake2b_load_avx2_H
+#define blake2b_load_avx2_H
+
+#define BLAKE2B_LOAD_MSG_0_1(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m0, m1); \
+ t1 = _mm256_unpacklo_epi64(m2, m3); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_0_2(b0) \
+ do { \
+ t0 = _mm256_unpackhi_epi64(m0, m1); \
+ t1 = _mm256_unpackhi_epi64(m2, m3); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_0_3(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m4, m5); \
+ t1 = _mm256_unpacklo_epi64(m6, m7); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_0_4(b0) \
+ do { \
+ t0 = _mm256_unpackhi_epi64(m4, m5); \
+ t1 = _mm256_unpackhi_epi64(m6, m7); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_1_1(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m7, m2); \
+ t1 = _mm256_unpackhi_epi64(m4, m6); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_1_2(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m5, m4); \
+ t1 = _mm256_alignr_epi8(m3, m7, 8); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_1_3(b0) \
+ do { \
+ t0 = _mm256_shuffle_epi32(m0, _MM_SHUFFLE(1, 0, 3, 2)); \
+ t1 = _mm256_unpackhi_epi64(m5, m2); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_1_4(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m6, m1); \
+ t1 = _mm256_unpackhi_epi64(m3, m1); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_2_1(b0) \
+ do { \
+ t0 = _mm256_alignr_epi8(m6, m5, 8); \
+ t1 = _mm256_unpackhi_epi64(m2, m7); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_2_2(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m4, m0); \
+ t1 = _mm256_blend_epi32(m6, m1, 0x33); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_2_3(b0) \
+ do { \
+ t0 = _mm256_blend_epi32(m1, m5, 0x33); \
+ t1 = _mm256_unpackhi_epi64(m3, m4); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_2_4(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m7, m3); \
+ t1 = _mm256_alignr_epi8(m2, m0, 8); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_3_1(b0) \
+ do { \
+ t0 = _mm256_unpackhi_epi64(m3, m1); \
+ t1 = _mm256_unpackhi_epi64(m6, m5); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_3_2(b0) \
+ do { \
+ t0 = _mm256_unpackhi_epi64(m4, m0); \
+ t1 = _mm256_unpacklo_epi64(m6, m7); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_3_3(b0) \
+ do { \
+ t0 = _mm256_blend_epi32(m2, m1, 0x33); \
+ t1 = _mm256_blend_epi32(m7, m2, 0x33); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_3_4(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m3, m5); \
+ t1 = _mm256_unpacklo_epi64(m0, m4); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_4_1(b0) \
+ do { \
+ t0 = _mm256_unpackhi_epi64(m4, m2); \
+ t1 = _mm256_unpacklo_epi64(m1, m5); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_4_2(b0) \
+ do { \
+ t0 = _mm256_blend_epi32(m3, m0, 0x33); \
+ t1 = _mm256_blend_epi32(m7, m2, 0x33); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_4_3(b0) \
+ do { \
+ t0 = _mm256_blend_epi32(m5, m7, 0x33); \
+ t1 = _mm256_blend_epi32(m1, m3, 0x33); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_4_4(b0) \
+ do { \
+ t0 = _mm256_alignr_epi8(m6, m0, 8); \
+ t1 = _mm256_blend_epi32(m6, m4, 0x33); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_5_1(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m1, m3); \
+ t1 = _mm256_unpacklo_epi64(m0, m4); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_5_2(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m6, m5); \
+ t1 = _mm256_unpackhi_epi64(m5, m1); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_5_3(b0) \
+ do { \
+ t0 = _mm256_blend_epi32(m3, m2, 0x33); \
+ t1 = _mm256_unpackhi_epi64(m7, m0); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_5_4(b0) \
+ do { \
+ t0 = _mm256_unpackhi_epi64(m6, m2); \
+ t1 = _mm256_blend_epi32(m4, m7, 0x33); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_6_1(b0) \
+ do { \
+ t0 = _mm256_blend_epi32(m0, m6, 0x33); \
+ t1 = _mm256_unpacklo_epi64(m7, m2); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_6_2(b0) \
+ do { \
+ t0 = _mm256_unpackhi_epi64(m2, m7); \
+ t1 = _mm256_alignr_epi8(m5, m6, 8); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_6_3(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m0, m3); \
+ t1 = _mm256_shuffle_epi32(m4, _MM_SHUFFLE(1, 0, 3, 2)); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_6_4(b0) \
+ do { \
+ t0 = _mm256_unpackhi_epi64(m3, m1); \
+ t1 = _mm256_blend_epi32(m5, m1, 0x33); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_7_1(b0) \
+ do { \
+ t0 = _mm256_unpackhi_epi64(m6, m3); \
+ t1 = _mm256_blend_epi32(m1, m6, 0x33); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_7_2(b0) \
+ do { \
+ t0 = _mm256_alignr_epi8(m7, m5, 8); \
+ t1 = _mm256_unpackhi_epi64(m0, m4); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_7_3(b0) \
+ do { \
+ t0 = _mm256_unpackhi_epi64(m2, m7); \
+ t1 = _mm256_unpacklo_epi64(m4, m1); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_7_4(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m0, m2); \
+ t1 = _mm256_unpacklo_epi64(m3, m5); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_8_1(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m3, m7); \
+ t1 = _mm256_alignr_epi8(m0, m5, 8); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_8_2(b0) \
+ do { \
+ t0 = _mm256_unpackhi_epi64(m7, m4); \
+ t1 = _mm256_alignr_epi8(m4, m1, 8); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_8_3(b0) \
+ do { \
+ t0 = m6; \
+ t1 = _mm256_alignr_epi8(m5, m0, 8); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_8_4(b0) \
+ do { \
+ t0 = _mm256_blend_epi32(m3, m1, 0x33); \
+ t1 = m2; \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_9_1(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m5, m4); \
+ t1 = _mm256_unpackhi_epi64(m3, m0); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_9_2(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m1, m2); \
+ t1 = _mm256_blend_epi32(m2, m3, 0x33); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_9_3(b0) \
+ do { \
+ t0 = _mm256_unpackhi_epi64(m7, m4); \
+ t1 = _mm256_unpackhi_epi64(m1, m6); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_9_4(b0) \
+ do { \
+ t0 = _mm256_alignr_epi8(m7, m5, 8); \
+ t1 = _mm256_unpacklo_epi64(m6, m0); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_10_1(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m0, m1); \
+ t1 = _mm256_unpacklo_epi64(m2, m3); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_10_2(b0) \
+ do { \
+ t0 = _mm256_unpackhi_epi64(m0, m1); \
+ t1 = _mm256_unpackhi_epi64(m2, m3); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_10_3(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m4, m5); \
+ t1 = _mm256_unpacklo_epi64(m6, m7); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_10_4(b0) \
+ do { \
+ t0 = _mm256_unpackhi_epi64(m4, m5); \
+ t1 = _mm256_unpackhi_epi64(m6, m7); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_11_1(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m7, m2); \
+ t1 = _mm256_unpackhi_epi64(m4, m6); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_11_2(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m5, m4); \
+ t1 = _mm256_alignr_epi8(m3, m7, 8); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_11_3(b0) \
+ do { \
+ t0 = _mm256_shuffle_epi32(m0, _MM_SHUFFLE(1, 0, 3, 2)); \
+ t1 = _mm256_unpackhi_epi64(m5, m2); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#define BLAKE2B_LOAD_MSG_11_4(b0) \
+ do { \
+ t0 = _mm256_unpacklo_epi64(m6, m1); \
+ t1 = _mm256_unpackhi_epi64(m3, m1); \
+ b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
+ } while (0)
+
+#endif
diff --git a/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-load-sse2.h b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-load-sse2.h
new file mode 100644
index 0000000000..8e67421aca
--- /dev/null
+++ b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-load-sse2.h
@@ -0,0 +1,164 @@
+/*
+ BLAKE2 reference source code package - optimized C implementations
+
+ Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
+
+ To the extent possible under law, the author(s) have dedicated all copyright
+ and related and neighboring rights to this software to the public domain
+ worldwide. This software is distributed without any warranty.
+
+ You should have received a copy of the CC0 Public Domain Dedication along
+ with
+ this software. If not, see
+ <http://creativecommons.org/publicdomain/zero/1.0/>.
+*/
+
+#ifndef blake2b_load_sse2_H
+#define blake2b_load_sse2_H
+
+#define LOAD_MSG_0_1(b0, b1) \
+ b0 = _mm_set_epi64x(m2, m0); \
+ b1 = _mm_set_epi64x(m6, m4)
+#define LOAD_MSG_0_2(b0, b1) \
+ b0 = _mm_set_epi64x(m3, m1); \
+ b1 = _mm_set_epi64x(m7, m5)
+#define LOAD_MSG_0_3(b0, b1) \
+ b0 = _mm_set_epi64x(m10, m8); \
+ b1 = _mm_set_epi64x(m14, m12)
+#define LOAD_MSG_0_4(b0, b1) \
+ b0 = _mm_set_epi64x(m11, m9); \
+ b1 = _mm_set_epi64x(m15, m13)
+#define LOAD_MSG_1_1(b0, b1) \
+ b0 = _mm_set_epi64x(m4, m14); \
+ b1 = _mm_set_epi64x(m13, m9)
+#define LOAD_MSG_1_2(b0, b1) \
+ b0 = _mm_set_epi64x(m8, m10); \
+ b1 = _mm_set_epi64x(m6, m15)
+#define LOAD_MSG_1_3(b0, b1) \
+ b0 = _mm_set_epi64x(m0, m1); \
+ b1 = _mm_set_epi64x(m5, m11)
+#define LOAD_MSG_1_4(b0, b1) \
+ b0 = _mm_set_epi64x(m2, m12); \
+ b1 = _mm_set_epi64x(m3, m7)
+#define LOAD_MSG_2_1(b0, b1) \
+ b0 = _mm_set_epi64x(m12, m11); \
+ b1 = _mm_set_epi64x(m15, m5)
+#define LOAD_MSG_2_2(b0, b1) \
+ b0 = _mm_set_epi64x(m0, m8); \
+ b1 = _mm_set_epi64x(m13, m2)
+#define LOAD_MSG_2_3(b0, b1) \
+ b0 = _mm_set_epi64x(m3, m10); \
+ b1 = _mm_set_epi64x(m9, m7)
+#define LOAD_MSG_2_4(b0, b1) \
+ b0 = _mm_set_epi64x(m6, m14); \
+ b1 = _mm_set_epi64x(m4, m1)
+#define LOAD_MSG_3_1(b0, b1) \
+ b0 = _mm_set_epi64x(m3, m7); \
+ b1 = _mm_set_epi64x(m11, m13)
+#define LOAD_MSG_3_2(b0, b1) \
+ b0 = _mm_set_epi64x(m1, m9); \
+ b1 = _mm_set_epi64x(m14, m12)
+#define LOAD_MSG_3_3(b0, b1) \
+ b0 = _mm_set_epi64x(m5, m2); \
+ b1 = _mm_set_epi64x(m15, m4)
+#define LOAD_MSG_3_4(b0, b1) \
+ b0 = _mm_set_epi64x(m10, m6); \
+ b1 = _mm_set_epi64x(m8, m0)
+#define LOAD_MSG_4_1(b0, b1) \
+ b0 = _mm_set_epi64x(m5, m9); \
+ b1 = _mm_set_epi64x(m10, m2)
+#define LOAD_MSG_4_2(b0, b1) \
+ b0 = _mm_set_epi64x(m7, m0); \
+ b1 = _mm_set_epi64x(m15, m4)
+#define LOAD_MSG_4_3(b0, b1) \
+ b0 = _mm_set_epi64x(m11, m14); \
+ b1 = _mm_set_epi64x(m3, m6)
+#define LOAD_MSG_4_4(b0, b1) \
+ b0 = _mm_set_epi64x(m12, m1); \
+ b1 = _mm_set_epi64x(m13, m8)
+#define LOAD_MSG_5_1(b0, b1) \
+ b0 = _mm_set_epi64x(m6, m2); \
+ b1 = _mm_set_epi64x(m8, m0)
+#define LOAD_MSG_5_2(b0, b1) \
+ b0 = _mm_set_epi64x(m10, m12); \
+ b1 = _mm_set_epi64x(m3, m11)
+#define LOAD_MSG_5_3(b0, b1) \
+ b0 = _mm_set_epi64x(m7, m4); \
+ b1 = _mm_set_epi64x(m1, m15)
+#define LOAD_MSG_5_4(b0, b1) \
+ b0 = _mm_set_epi64x(m5, m13); \
+ b1 = _mm_set_epi64x(m9, m14)
+#define LOAD_MSG_6_1(b0, b1) \
+ b0 = _mm_set_epi64x(m1, m12); \
+ b1 = _mm_set_epi64x(m4, m14)
+#define LOAD_MSG_6_2(b0, b1) \
+ b0 = _mm_set_epi64x(m15, m5); \
+ b1 = _mm_set_epi64x(m10, m13)
+#define LOAD_MSG_6_3(b0, b1) \
+ b0 = _mm_set_epi64x(m6, m0); \
+ b1 = _mm_set_epi64x(m8, m9)
+#define LOAD_MSG_6_4(b0, b1) \
+ b0 = _mm_set_epi64x(m3, m7); \
+ b1 = _mm_set_epi64x(m11, m2)
+#define LOAD_MSG_7_1(b0, b1) \
+ b0 = _mm_set_epi64x(m7, m13); \
+ b1 = _mm_set_epi64x(m3, m12)
+#define LOAD_MSG_7_2(b0, b1) \
+ b0 = _mm_set_epi64x(m14, m11); \
+ b1 = _mm_set_epi64x(m9, m1)
+#define LOAD_MSG_7_3(b0, b1) \
+ b0 = _mm_set_epi64x(m15, m5); \
+ b1 = _mm_set_epi64x(m2, m8)
+#define LOAD_MSG_7_4(b0, b1) \
+ b0 = _mm_set_epi64x(m4, m0); \
+ b1 = _mm_set_epi64x(m10, m6)
+#define LOAD_MSG_8_1(b0, b1) \
+ b0 = _mm_set_epi64x(m14, m6); \
+ b1 = _mm_set_epi64x(m0, m11)
+#define LOAD_MSG_8_2(b0, b1) \
+ b0 = _mm_set_epi64x(m9, m15); \
+ b1 = _mm_set_epi64x(m8, m3)
+#define LOAD_MSG_8_3(b0, b1) \
+ b0 = _mm_set_epi64x(m13, m12); \
+ b1 = _mm_set_epi64x(m10, m1)
+#define LOAD_MSG_8_4(b0, b1) \
+ b0 = _mm_set_epi64x(m7, m2); \
+ b1 = _mm_set_epi64x(m5, m4)
+#define LOAD_MSG_9_1(b0, b1) \
+ b0 = _mm_set_epi64x(m8, m10); \
+ b1 = _mm_set_epi64x(m1, m7)
+#define LOAD_MSG_9_2(b0, b1) \
+ b0 = _mm_set_epi64x(m4, m2); \
+ b1 = _mm_set_epi64x(m5, m6)
+#define LOAD_MSG_9_3(b0, b1) \
+ b0 = _mm_set_epi64x(m9, m15); \
+ b1 = _mm_set_epi64x(m13, m3)
+#define LOAD_MSG_9_4(b0, b1) \
+ b0 = _mm_set_epi64x(m14, m11); \
+ b1 = _mm_set_epi64x(m0, m12)
+#define LOAD_MSG_10_1(b0, b1) \
+ b0 = _mm_set_epi64x(m2, m0); \
+ b1 = _mm_set_epi64x(m6, m4)
+#define LOAD_MSG_10_2(b0, b1) \
+ b0 = _mm_set_epi64x(m3, m1); \
+ b1 = _mm_set_epi64x(m7, m5)
+#define LOAD_MSG_10_3(b0, b1) \
+ b0 = _mm_set_epi64x(m10, m8); \
+ b1 = _mm_set_epi64x(m14, m12)
+#define LOAD_MSG_10_4(b0, b1) \
+ b0 = _mm_set_epi64x(m11, m9); \
+ b1 = _mm_set_epi64x(m15, m13)
+#define LOAD_MSG_11_1(b0, b1) \
+ b0 = _mm_set_epi64x(m4, m14); \
+ b1 = _mm_set_epi64x(m13, m9)
+#define LOAD_MSG_11_2(b0, b1) \
+ b0 = _mm_set_epi64x(m8, m10); \
+ b1 = _mm_set_epi64x(m6, m15)
+#define LOAD_MSG_11_3(b0, b1) \
+ b0 = _mm_set_epi64x(m0, m1); \
+ b1 = _mm_set_epi64x(m5, m11)
+#define LOAD_MSG_11_4(b0, b1) \
+ b0 = _mm_set_epi64x(m2, m12); \
+ b1 = _mm_set_epi64x(m3, m7)
+
+#endif
diff --git a/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-load-sse41.h b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-load-sse41.h
new file mode 100644
index 0000000000..31745fc139
--- /dev/null
+++ b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-load-sse41.h
@@ -0,0 +1,307 @@
+/*
+ BLAKE2 reference source code package - optimized C implementations
+
+ Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
+
+ To the extent possible under law, the author(s) have dedicated all copyright
+ and related and neighboring rights to this software to the public domain
+ worldwide. This software is distributed without any warranty.
+
+ You should have received a copy of the CC0 Public Domain Dedication along
+ with
+ this software. If not, see
+ <http://creativecommons.org/publicdomain/zero/1.0/>.
+*/
+
+#ifndef blake2b_load_sse41_H
+#define blake2b_load_sse41_H
+
+#define LOAD_MSG_0_1(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m0, m1); \
+ b1 = _mm_unpacklo_epi64(m2, m3); \
+ } while (0)
+
+#define LOAD_MSG_0_2(b0, b1) \
+ do { \
+ b0 = _mm_unpackhi_epi64(m0, m1); \
+ b1 = _mm_unpackhi_epi64(m2, m3); \
+ } while (0)
+
+#define LOAD_MSG_0_3(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m4, m5); \
+ b1 = _mm_unpacklo_epi64(m6, m7); \
+ } while (0)
+
+#define LOAD_MSG_0_4(b0, b1) \
+ do { \
+ b0 = _mm_unpackhi_epi64(m4, m5); \
+ b1 = _mm_unpackhi_epi64(m6, m7); \
+ } while (0)
+
+#define LOAD_MSG_1_1(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m7, m2); \
+ b1 = _mm_unpackhi_epi64(m4, m6); \
+ } while (0)
+
+#define LOAD_MSG_1_2(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m5, m4); \
+ b1 = _mm_alignr_epi8(m3, m7, 8); \
+ } while (0)
+
+#define LOAD_MSG_1_3(b0, b1) \
+ do { \
+ b0 = _mm_shuffle_epi32(m0, _MM_SHUFFLE(1, 0, 3, 2)); \
+ b1 = _mm_unpackhi_epi64(m5, m2); \
+ } while (0)
+
+#define LOAD_MSG_1_4(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m6, m1); \
+ b1 = _mm_unpackhi_epi64(m3, m1); \
+ } while (0)
+
+#define LOAD_MSG_2_1(b0, b1) \
+ do { \
+ b0 = _mm_alignr_epi8(m6, m5, 8); \
+ b1 = _mm_unpackhi_epi64(m2, m7); \
+ } while (0)
+
+#define LOAD_MSG_2_2(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m4, m0); \
+ b1 = _mm_blend_epi16(m1, m6, 0xF0); \
+ } while (0)
+
+#define LOAD_MSG_2_3(b0, b1) \
+ do { \
+ b0 = _mm_blend_epi16(m5, m1, 0xF0); \
+ b1 = _mm_unpackhi_epi64(m3, m4); \
+ } while (0)
+
+#define LOAD_MSG_2_4(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m7, m3); \
+ b1 = _mm_alignr_epi8(m2, m0, 8); \
+ } while (0)
+
+#define LOAD_MSG_3_1(b0, b1) \
+ do { \
+ b0 = _mm_unpackhi_epi64(m3, m1); \
+ b1 = _mm_unpackhi_epi64(m6, m5); \
+ } while (0)
+
+#define LOAD_MSG_3_2(b0, b1) \
+ do { \
+ b0 = _mm_unpackhi_epi64(m4, m0); \
+ b1 = _mm_unpacklo_epi64(m6, m7); \
+ } while (0)
+
+#define LOAD_MSG_3_3(b0, b1) \
+ do { \
+ b0 = _mm_blend_epi16(m1, m2, 0xF0); \
+ b1 = _mm_blend_epi16(m2, m7, 0xF0); \
+ } while (0)
+
+#define LOAD_MSG_3_4(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m3, m5); \
+ b1 = _mm_unpacklo_epi64(m0, m4); \
+ } while (0)
+
+#define LOAD_MSG_4_1(b0, b1) \
+ do { \
+ b0 = _mm_unpackhi_epi64(m4, m2); \
+ b1 = _mm_unpacklo_epi64(m1, m5); \
+ } while (0)
+
+#define LOAD_MSG_4_2(b0, b1) \
+ do { \
+ b0 = _mm_blend_epi16(m0, m3, 0xF0); \
+ b1 = _mm_blend_epi16(m2, m7, 0xF0); \
+ } while (0)
+
+#define LOAD_MSG_4_3(b0, b1) \
+ do { \
+ b0 = _mm_blend_epi16(m7, m5, 0xF0); \
+ b1 = _mm_blend_epi16(m3, m1, 0xF0); \
+ } while (0)
+
+#define LOAD_MSG_4_4(b0, b1) \
+ do { \
+ b0 = _mm_alignr_epi8(m6, m0, 8); \
+ b1 = _mm_blend_epi16(m4, m6, 0xF0); \
+ } while (0)
+
+#define LOAD_MSG_5_1(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m1, m3); \
+ b1 = _mm_unpacklo_epi64(m0, m4); \
+ } while (0)
+
+#define LOAD_MSG_5_2(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m6, m5); \
+ b1 = _mm_unpackhi_epi64(m5, m1); \
+ } while (0)
+
+#define LOAD_MSG_5_3(b0, b1) \
+ do { \
+ b0 = _mm_blend_epi16(m2, m3, 0xF0); \
+ b1 = _mm_unpackhi_epi64(m7, m0); \
+ } while (0)
+
+#define LOAD_MSG_5_4(b0, b1) \
+ do { \
+ b0 = _mm_unpackhi_epi64(m6, m2); \
+ b1 = _mm_blend_epi16(m7, m4, 0xF0); \
+ } while (0)
+
+#define LOAD_MSG_6_1(b0, b1) \
+ do { \
+ b0 = _mm_blend_epi16(m6, m0, 0xF0); \
+ b1 = _mm_unpacklo_epi64(m7, m2); \
+ } while (0)
+
+#define LOAD_MSG_6_2(b0, b1) \
+ do { \
+ b0 = _mm_unpackhi_epi64(m2, m7); \
+ b1 = _mm_alignr_epi8(m5, m6, 8); \
+ } while (0)
+
+#define LOAD_MSG_6_3(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m0, m3); \
+ b1 = _mm_shuffle_epi32(m4, _MM_SHUFFLE(1, 0, 3, 2)); \
+ } while (0)
+
+#define LOAD_MSG_6_4(b0, b1) \
+ do { \
+ b0 = _mm_unpackhi_epi64(m3, m1); \
+ b1 = _mm_blend_epi16(m1, m5, 0xF0); \
+ } while (0)
+
+#define LOAD_MSG_7_1(b0, b1) \
+ do { \
+ b0 = _mm_unpackhi_epi64(m6, m3); \
+ b1 = _mm_blend_epi16(m6, m1, 0xF0); \
+ } while (0)
+
+#define LOAD_MSG_7_2(b0, b1) \
+ do { \
+ b0 = _mm_alignr_epi8(m7, m5, 8); \
+ b1 = _mm_unpackhi_epi64(m0, m4); \
+ } while (0)
+
+#define LOAD_MSG_7_3(b0, b1) \
+ do { \
+ b0 = _mm_unpackhi_epi64(m2, m7); \
+ b1 = _mm_unpacklo_epi64(m4, m1); \
+ } while (0)
+
+#define LOAD_MSG_7_4(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m0, m2); \
+ b1 = _mm_unpacklo_epi64(m3, m5); \
+ } while (0)
+
+#define LOAD_MSG_8_1(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m3, m7); \
+ b1 = _mm_alignr_epi8(m0, m5, 8); \
+ } while (0)
+
+#define LOAD_MSG_8_2(b0, b1) \
+ do { \
+ b0 = _mm_unpackhi_epi64(m7, m4); \
+ b1 = _mm_alignr_epi8(m4, m1, 8); \
+ } while (0)
+
+#define LOAD_MSG_8_3(b0, b1) \
+ do { \
+ b0 = m6; \
+ b1 = _mm_alignr_epi8(m5, m0, 8); \
+ } while (0)
+
+#define LOAD_MSG_8_4(b0, b1) \
+ do { \
+ b0 = _mm_blend_epi16(m1, m3, 0xF0); \
+ b1 = m2; \
+ } while (0)
+
+#define LOAD_MSG_9_1(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m5, m4); \
+ b1 = _mm_unpackhi_epi64(m3, m0); \
+ } while (0)
+
+#define LOAD_MSG_9_2(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m1, m2); \
+ b1 = _mm_blend_epi16(m3, m2, 0xF0); \
+ } while (0)
+
+#define LOAD_MSG_9_3(b0, b1) \
+ do { \
+ b0 = _mm_unpackhi_epi64(m7, m4); \
+ b1 = _mm_unpackhi_epi64(m1, m6); \
+ } while (0)
+
+#define LOAD_MSG_9_4(b0, b1) \
+ do { \
+ b0 = _mm_alignr_epi8(m7, m5, 8); \
+ b1 = _mm_unpacklo_epi64(m6, m0); \
+ } while (0)
+
+#define LOAD_MSG_10_1(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m0, m1); \
+ b1 = _mm_unpacklo_epi64(m2, m3); \
+ } while (0)
+
+#define LOAD_MSG_10_2(b0, b1) \
+ do { \
+ b0 = _mm_unpackhi_epi64(m0, m1); \
+ b1 = _mm_unpackhi_epi64(m2, m3); \
+ } while (0)
+
+#define LOAD_MSG_10_3(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m4, m5); \
+ b1 = _mm_unpacklo_epi64(m6, m7); \
+ } while (0)
+
+#define LOAD_MSG_10_4(b0, b1) \
+ do { \
+ b0 = _mm_unpackhi_epi64(m4, m5); \
+ b1 = _mm_unpackhi_epi64(m6, m7); \
+ } while (0)
+
+#define LOAD_MSG_11_1(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m7, m2); \
+ b1 = _mm_unpackhi_epi64(m4, m6); \
+ } while (0)
+
+#define LOAD_MSG_11_2(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m5, m4); \
+ b1 = _mm_alignr_epi8(m3, m7, 8); \
+ } while (0)
+
+#define LOAD_MSG_11_3(b0, b1) \
+ do { \
+ b0 = _mm_shuffle_epi32(m0, _MM_SHUFFLE(1, 0, 3, 2)); \
+ b1 = _mm_unpackhi_epi64(m5, m2); \
+ } while (0)
+
+#define LOAD_MSG_11_4(b0, b1) \
+ do { \
+ b0 = _mm_unpacklo_epi64(m6, m1); \
+ b1 = _mm_unpackhi_epi64(m3, m1); \
+ } while (0)
+
+#endif
diff --git a/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-ref.c b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-ref.c
new file mode 100644
index 0000000000..91435a1b16
--- /dev/null
+++ b/libs/libsodium/src/crypto_generichash/blake2b/ref/blake2b-ref.c
@@ -0,0 +1,436 @@
+/*
+ BLAKE2 reference source code package - C implementations
+
+ Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
+
+ To the extent possible under law, the author(s) have dedicated all copyright
+ and related and neighboring rights to this software to the public domain
+ worldwide. This software is distributed without any warranty.
+
+ You should have received a copy of the CC0 Public Domain Dedication along
+ with
+ this software. If not, see
+ <http://creativecommons.org/publicdomain/zero/1.0/>.
+*/
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "blake2.h"
+#include "core.h"
+#include "private/common.h"
+#include "runtime.h"
+#include "utils.h"
+
+static blake2b_compress_fn blake2b_compress = blake2b_compress_ref;
+
+static const uint64_t blake2b_IV[8] = {
+ 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
+ 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+};
+
+/* LCOV_EXCL_START */
+static inline int
+blake2b_set_lastnode(blake2b_state *S)
+{
+ S->f[1] = -1;
+ return 0;
+}
+/* LCOV_EXCL_STOP */
+
+static inline int
+blake2b_is_lastblock(const blake2b_state *S)
+{
+ return S->f[0] != 0;
+}
+
+static inline int
+blake2b_set_lastblock(blake2b_state *S)
+{
+ if (S->last_node)
+ blake2b_set_lastnode(S);
+
+ S->f[0] = -1;
+ return 0;
+}
+
+static inline int
+blake2b_increment_counter(blake2b_state *S, const uint64_t inc)
+{
+#ifdef HAVE_TI_MODE
+ uint128_t t = ((uint128_t) S->t[1] << 64) | S->t[0];
+ t += inc;
+ S->t[0] = (uint64_t)(t >> 0);
+ S->t[1] = (uint64_t)(t >> 64);
+#else
+ S->t[0] += inc;
+ S->t[1] += (S->t[0] < inc);
+#endif
+ return 0;
+}
+
+/* Parameter-related functions */
+static inline int
+blake2b_param_set_salt(blake2b_param *P, const uint8_t salt[BLAKE2B_SALTBYTES])
+{
+ memcpy(P->salt, salt, BLAKE2B_SALTBYTES);
+ return 0;
+}
+
+static inline int
+blake2b_param_set_personal(blake2b_param *P,
+ const uint8_t personal[BLAKE2B_PERSONALBYTES])
+{
+ memcpy(P->personal, personal, BLAKE2B_PERSONALBYTES);
+ return 0;
+}
+
+static inline int
+blake2b_init0(blake2b_state *S)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ S->h[i] = blake2b_IV[i];
+ }
+ memset(S->t, 0, offsetof(blake2b_state, last_node) + sizeof(S->last_node)
+ - offsetof(blake2b_state, t));
+ return 0;
+}
+
+/* init xors IV with input parameter block */
+int
+blake2b_init_param(blake2b_state *S, const blake2b_param *P)
+{
+ size_t i;
+ const uint8_t *p;
+
+ COMPILER_ASSERT(sizeof *P == 64);
+ blake2b_init0(S);
+ p = (const uint8_t *) (P);
+
+ /* IV XOR ParamBlock */
+ for (i = 0; i < 8; i++) {
+ S->h[i] ^= LOAD64_LE(p + sizeof(S->h[i]) * i);
+ }
+ return 0;
+}
+
+int
+blake2b_init(blake2b_state *S, const uint8_t outlen)
+{
+ blake2b_param P[1];
+
+ if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) {
+ sodium_misuse();
+ }
+ P->digest_length = outlen;
+ P->key_length = 0;
+ P->fanout = 1;
+ P->depth = 1;
+ STORE32_LE(P->leaf_length, 0);
+ STORE64_LE(P->node_offset, 0);
+ P->node_depth = 0;
+ P->inner_length = 0;
+ memset(P->reserved, 0, sizeof(P->reserved));
+ memset(P->salt, 0, sizeof(P->salt));
+ memset(P->personal, 0, sizeof(P->personal));
+ return blake2b_init_param(S, P);
+}
+
+int
+blake2b_init_salt_personal(blake2b_state *S, const uint8_t outlen,
+ const void *salt, const void *personal)
+{
+ blake2b_param P[1];
+
+ if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) {
+ sodium_misuse();
+ }
+ P->digest_length = outlen;
+ P->key_length = 0;
+ P->fanout = 1;
+ P->depth = 1;
+ STORE32_LE(P->leaf_length, 0);
+ STORE64_LE(P->node_offset, 0);
+ P->node_depth = 0;
+ P->inner_length = 0;
+ memset(P->reserved, 0, sizeof(P->reserved));
+ if (salt != NULL) {
+ blake2b_param_set_salt(P, (const uint8_t *) salt);
+ } else {
+ memset(P->salt, 0, sizeof(P->salt));
+ }
+ if (personal != NULL) {
+ blake2b_param_set_personal(P, (const uint8_t *) personal);
+ } else {
+ memset(P->personal, 0, sizeof(P->personal));
+ }
+ return blake2b_init_param(S, P);
+}
+
+int
+blake2b_init_key(blake2b_state *S, const uint8_t outlen, const void *key,
+ const uint8_t keylen)
+{
+ blake2b_param P[1];
+
+ if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) {
+ sodium_misuse();
+ }
+ if (!key || !keylen || keylen > BLAKE2B_KEYBYTES) {
+ sodium_misuse();
+ }
+ P->digest_length = outlen;
+ P->key_length = keylen;
+ P->fanout = 1;
+ P->depth = 1;
+ STORE32_LE(P->leaf_length, 0);
+ STORE64_LE(P->node_offset, 0);
+ P->node_depth = 0;
+ P->inner_length = 0;
+ memset(P->reserved, 0, sizeof(P->reserved));
+ memset(P->salt, 0, sizeof(P->salt));
+ memset(P->personal, 0, sizeof(P->personal));
+
+ if (blake2b_init_param(S, P) < 0) {
+ sodium_misuse();
+ }
+ {
+ uint8_t block[BLAKE2B_BLOCKBYTES];
+ memset(block, 0, BLAKE2B_BLOCKBYTES);
+ memcpy(block, key, keylen); /* keylen cannot be 0 */
+ blake2b_update(S, block, BLAKE2B_BLOCKBYTES);
+ sodium_memzero(block, BLAKE2B_BLOCKBYTES); /* Burn the key from stack */
+ }
+ return 0;
+}
+
+int
+blake2b_init_key_salt_personal(blake2b_state *S, const uint8_t outlen,
+ const void *key, const uint8_t keylen,
+ const void *salt, const void *personal)
+{
+ blake2b_param P[1];
+
+ if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) {
+ sodium_misuse();
+ }
+ if (!key || !keylen || keylen > BLAKE2B_KEYBYTES) {
+ sodium_misuse();
+ }
+ P->digest_length = outlen;
+ P->key_length = keylen;
+ P->fanout = 1;
+ P->depth = 1;
+ STORE32_LE(P->leaf_length, 0);
+ STORE64_LE(P->node_offset, 0);
+ P->node_depth = 0;
+ P->inner_length = 0;
+ memset(P->reserved, 0, sizeof(P->reserved));
+ if (salt != NULL) {
+ blake2b_param_set_salt(P, (const uint8_t *) salt);
+ } else {
+ memset(P->salt, 0, sizeof(P->salt));
+ }
+ if (personal != NULL) {
+ blake2b_param_set_personal(P, (const uint8_t *) personal);
+ } else {
+ memset(P->personal, 0, sizeof(P->personal));
+ }
+
+ if (blake2b_init_param(S, P) < 0) {
+ sodium_misuse();
+ }
+ {
+ uint8_t block[BLAKE2B_BLOCKBYTES];
+ memset(block, 0, BLAKE2B_BLOCKBYTES);
+ memcpy(block, key, keylen); /* keylen cannot be 0 */
+ blake2b_update(S, block, BLAKE2B_BLOCKBYTES);
+ sodium_memzero(block, BLAKE2B_BLOCKBYTES); /* Burn the key from stack */
+ }
+ return 0;
+}
+
+/* inlen now in bytes */
+int
+blake2b_update(blake2b_state *S, const uint8_t *in, uint64_t inlen)
+{
+ while (inlen > 0) {
+ size_t left = S->buflen;
+ size_t fill = 2 * BLAKE2B_BLOCKBYTES - left;
+
+ if (inlen > fill) {
+ memcpy(S->buf + left, in, fill); /* Fill buffer */
+ S->buflen += fill;
+ blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
+ blake2b_compress(S, S->buf); /* Compress */
+ memcpy(S->buf, S->buf + BLAKE2B_BLOCKBYTES,
+ BLAKE2B_BLOCKBYTES); /* Shift buffer left */
+ S->buflen -= BLAKE2B_BLOCKBYTES;
+ in += fill;
+ inlen -= fill;
+ } else /* inlen <= fill */
+ {
+ memcpy(S->buf + left, in, inlen);
+ S->buflen += inlen; /* Be lazy, do not compress */
+ in += inlen;
+ inlen -= inlen;
+ }
+ }
+
+ return 0;
+}
+
+int
+blake2b_final(blake2b_state *S, uint8_t *out, uint8_t outlen)
+{
+ unsigned char buffer[BLAKE2B_OUTBYTES];
+
+ if (!outlen || outlen > BLAKE2B_OUTBYTES) {
+ sodium_misuse();
+ }
+ if (blake2b_is_lastblock(S)) {
+ return -1;
+ }
+ if (S->buflen > BLAKE2B_BLOCKBYTES) {
+ blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
+ blake2b_compress(S, S->buf);
+ S->buflen -= BLAKE2B_BLOCKBYTES;
+ assert(S->buflen <= BLAKE2B_BLOCKBYTES);
+ memcpy(S->buf, S->buf + BLAKE2B_BLOCKBYTES, S->buflen);
+ }
+
+ blake2b_increment_counter(S, S->buflen);
+ blake2b_set_lastblock(S);
+ memset(S->buf + S->buflen, 0,
+ 2 * BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */
+ blake2b_compress(S, S->buf);
+
+ COMPILER_ASSERT(sizeof buffer == 64U);
+ STORE64_LE(buffer + 8 * 0, S->h[0]);
+ STORE64_LE(buffer + 8 * 1, S->h[1]);
+ STORE64_LE(buffer + 8 * 2, S->h[2]);
+ STORE64_LE(buffer + 8 * 3, S->h[3]);
+ STORE64_LE(buffer + 8 * 4, S->h[4]);
+ STORE64_LE(buffer + 8 * 5, S->h[5]);
+ STORE64_LE(buffer + 8 * 6, S->h[6]);
+ STORE64_LE(buffer + 8 * 7, S->h[7]);
+ memcpy(out, buffer, outlen); /* outlen <= BLAKE2B_OUTBYTES (64) */
+
+ sodium_memzero(S->h, sizeof S->h);
+ sodium_memzero(S->buf, sizeof S->buf);
+
+ return 0;
+}
+
+/* inlen, at least, should be uint64_t. Others can be size_t. */
+int
+blake2b(uint8_t *out, const void *in, const void *key, const uint8_t outlen,
+ const uint64_t inlen, uint8_t keylen)
+{
+ blake2b_state S[1];
+
+ /* Verify parameters */
+ if (NULL == in && inlen > 0) {
+ sodium_misuse();
+ }
+ if (NULL == out) {
+ sodium_misuse();
+ }
+ if (!outlen || outlen > BLAKE2B_OUTBYTES) {
+ sodium_misuse();
+ }
+ if (NULL == key && keylen > 0) {
+ sodium_misuse();
+ }
+ if (keylen > BLAKE2B_KEYBYTES) {
+ sodium_misuse();
+ }
+ if (keylen > 0) {
+ if (blake2b_init_key(S, outlen, key, keylen) < 0) {
+ sodium_misuse();
+ }
+ } else {
+ if (blake2b_init(S, outlen) < 0) {
+ sodium_misuse();
+ }
+ }
+
+ blake2b_update(S, (const uint8_t *) in, inlen);
+ blake2b_final(S, out, outlen);
+ return 0;
+}
+
+int
+blake2b_salt_personal(uint8_t *out, const void *in, const void *key,
+ const uint8_t outlen, const uint64_t inlen,
+ uint8_t keylen, const void *salt, const void *personal)
+{
+ blake2b_state S[1];
+
+ /* Verify parameters */
+ if (NULL == in && inlen > 0) {
+ sodium_misuse();
+ }
+ if (NULL == out) {
+ sodium_misuse();
+ }
+ if (!outlen || outlen > BLAKE2B_OUTBYTES) {
+ sodium_misuse();
+ }
+ if (NULL == key && keylen > 0) {
+ sodium_misuse();
+ }
+ if (keylen > BLAKE2B_KEYBYTES) {
+ sodium_misuse();
+ }
+ if (keylen > 0) {
+ if (blake2b_init_key_salt_personal(S, outlen, key, keylen, salt,
+ personal) < 0) {
+ sodium_misuse();
+ }
+ } else {
+ if (blake2b_init_salt_personal(S, outlen, salt, personal) < 0) {
+ sodium_misuse();
+ }
+ }
+
+ blake2b_update(S, (const uint8_t *) in, inlen);
+ blake2b_final(S, out, outlen);
+ return 0;
+}
+
+int
+blake2b_pick_best_implementation(void)
+{
+/* LCOV_EXCL_START */
+#if defined(HAVE_AVX2INTRIN_H) && defined(HAVE_TMMINTRIN_H) && \
+ defined(HAVE_SMMINTRIN_H)
+ if (sodium_runtime_has_avx2()) {
+ blake2b_compress = blake2b_compress_avx2;
+ return 0;
+ }
+#endif
+#if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H) && \
+ defined(HAVE_SMMINTRIN_H)
+ if (sodium_runtime_has_sse41()) {
+ blake2b_compress = blake2b_compress_sse41;
+ return 0;
+ }
+#endif
+#if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)
+ if (sodium_runtime_has_ssse3()) {
+ blake2b_compress = blake2b_compress_ssse3;
+ return 0;
+ }
+#endif
+ blake2b_compress = blake2b_compress_ref;
+
+ return 0;
+ /* LCOV_EXCL_STOP */
+}
diff --git a/libs/libsodium/src/crypto_generichash/blake2b/ref/generichash_blake2b.c b/libs/libsodium/src/crypto_generichash/blake2b/ref/generichash_blake2b.c
new file mode 100644
index 0000000000..4bd0855006
--- /dev/null
+++ b/libs/libsodium/src/crypto_generichash/blake2b/ref/generichash_blake2b.c
@@ -0,0 +1,111 @@
+
+#include <assert.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include "blake2.h"
+#include "crypto_generichash_blake2b.h"
+#include "private/implementations.h"
+
+int
+crypto_generichash_blake2b(unsigned char *out, size_t outlen,
+ const unsigned char *in, unsigned long long inlen,
+ const unsigned char *key, size_t keylen)
+{
+ if (outlen <= 0U || outlen > BLAKE2B_OUTBYTES ||
+ keylen > BLAKE2B_KEYBYTES || inlen > UINT64_MAX) {
+ return -1;
+ }
+ assert(outlen <= UINT8_MAX);
+ assert(keylen <= UINT8_MAX);
+
+ return blake2b((uint8_t *) out, in, key, (uint8_t) outlen, (uint64_t) inlen,
+ (uint8_t) keylen);
+}
+
+int
+crypto_generichash_blake2b_salt_personal(
+ unsigned char *out, size_t outlen, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *key, size_t keylen,
+ const unsigned char *salt, const unsigned char *personal)
+{
+ if (outlen <= 0U || outlen > BLAKE2B_OUTBYTES ||
+ keylen > BLAKE2B_KEYBYTES || inlen > UINT64_MAX) {
+ return -1;
+ }
+ assert(outlen <= UINT8_MAX);
+ assert(keylen <= UINT8_MAX);
+
+ return blake2b_salt_personal((uint8_t *) out, in, key, (uint8_t) outlen,
+ (uint64_t) inlen, (uint8_t) keylen, salt,
+ personal);
+}
+
+int
+crypto_generichash_blake2b_init(crypto_generichash_blake2b_state *state,
+ const unsigned char *key, const size_t keylen,
+ const size_t outlen)
+{
+ if (outlen <= 0U || outlen > BLAKE2B_OUTBYTES ||
+ keylen > BLAKE2B_KEYBYTES) {
+ return -1;
+ }
+ assert(outlen <= UINT8_MAX);
+ assert(keylen <= UINT8_MAX);
+ if (key == NULL || keylen <= 0U) {
+ if (blake2b_init(state, (uint8_t) outlen) != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ } else if (blake2b_init_key(state, (uint8_t) outlen, key,
+ (uint8_t) keylen) != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return 0;
+}
+
+int
+crypto_generichash_blake2b_init_salt_personal(
+ crypto_generichash_blake2b_state *state, const unsigned char *key,
+ const size_t keylen, const size_t outlen, const unsigned char *salt,
+ const unsigned char *personal)
+{
+ if (outlen <= 0U || outlen > BLAKE2B_OUTBYTES ||
+ keylen > BLAKE2B_KEYBYTES) {
+ return -1;
+ }
+ assert(outlen <= UINT8_MAX);
+ assert(keylen <= UINT8_MAX);
+ if (key == NULL || keylen <= 0U) {
+ if (blake2b_init_salt_personal(state, (uint8_t) outlen, salt,
+ personal) != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ } else if (blake2b_init_key_salt_personal(state, (uint8_t) outlen, key,
+ (uint8_t) keylen, salt,
+ personal) != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return 0;
+}
+
+int
+crypto_generichash_blake2b_update(crypto_generichash_blake2b_state *state,
+ const unsigned char *in,
+ unsigned long long inlen)
+{
+ return blake2b_update(state, (const uint8_t *) in, (uint64_t) inlen);
+}
+
+int
+crypto_generichash_blake2b_final(crypto_generichash_blake2b_state *state,
+ unsigned char *out, const size_t outlen)
+{
+ assert(outlen <= UINT8_MAX);
+ return blake2b_final(state, (uint8_t *) out, (uint8_t) outlen);
+}
+
+int
+_crypto_generichash_blake2b_pick_best_implementation(void)
+{
+ return blake2b_pick_best_implementation();
+}
diff --git a/libs/libsodium/src/crypto_generichash/crypto_generichash.c b/libs/libsodium/src/crypto_generichash/crypto_generichash.c
new file mode 100644
index 0000000000..a9a14e999a
--- /dev/null
+++ b/libs/libsodium/src/crypto_generichash/crypto_generichash.c
@@ -0,0 +1,91 @@
+
+#include "crypto_generichash.h"
+#include "randombytes.h"
+
+size_t
+crypto_generichash_bytes_min(void)
+{
+ return crypto_generichash_BYTES_MIN;
+}
+
+size_t
+crypto_generichash_bytes_max(void)
+{
+ return crypto_generichash_BYTES_MAX;
+}
+
+size_t
+crypto_generichash_bytes(void)
+{
+ return crypto_generichash_BYTES;
+}
+
+size_t
+crypto_generichash_keybytes_min(void)
+{
+ return crypto_generichash_KEYBYTES_MIN;
+}
+
+size_t
+crypto_generichash_keybytes_max(void)
+{
+ return crypto_generichash_KEYBYTES_MAX;
+}
+
+size_t
+crypto_generichash_keybytes(void)
+{
+ return crypto_generichash_KEYBYTES;
+}
+
+const char *
+crypto_generichash_primitive(void)
+{
+ return crypto_generichash_PRIMITIVE;
+}
+
+size_t
+crypto_generichash_statebytes(void)
+{
+ return (sizeof(crypto_generichash_state) + (size_t) 63U) & ~(size_t) 63U;
+}
+
+int
+crypto_generichash(unsigned char *out, size_t outlen, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *key,
+ size_t keylen)
+{
+ return crypto_generichash_blake2b(out, outlen, in, inlen, key, keylen);
+}
+
+int
+crypto_generichash_init(crypto_generichash_state *state,
+ const unsigned char *key,
+ const size_t keylen, const size_t outlen)
+{
+ return crypto_generichash_blake2b_init
+ ((crypto_generichash_blake2b_state *) state, key, keylen, outlen);
+}
+
+int
+crypto_generichash_update(crypto_generichash_state *state,
+ const unsigned char *in,
+ unsigned long long inlen)
+{
+ return crypto_generichash_blake2b_update
+ ((crypto_generichash_blake2b_state *) state, in, inlen);
+}
+
+int
+crypto_generichash_final(crypto_generichash_state *state,
+ unsigned char *out, const size_t outlen)
+{
+ return crypto_generichash_blake2b_final
+ ((crypto_generichash_blake2b_state *) state, out, outlen);
+}
+
+void
+crypto_generichash_keygen(unsigned char k[crypto_generichash_KEYBYTES])
+{
+ randombytes_buf(k, crypto_generichash_KEYBYTES);
+}
diff --git a/libs/libsodium/src/crypto_hash/crypto_hash.c b/libs/libsodium/src/crypto_hash/crypto_hash.c
new file mode 100644
index 0000000000..855c560ba5
--- /dev/null
+++ b/libs/libsodium/src/crypto_hash/crypto_hash.c
@@ -0,0 +1,20 @@
+
+#include "crypto_hash.h"
+
+size_t
+crypto_hash_bytes(void)
+{
+ return crypto_hash_BYTES;
+}
+
+int
+crypto_hash(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen)
+{
+ return crypto_hash_sha512(out, in, inlen);
+}
+
+const char *
+crypto_hash_primitive(void) {
+ return crypto_hash_PRIMITIVE;
+}
diff --git a/libs/libsodium/src/crypto_hash/sha256/cp/hash_sha256_cp.c b/libs/libsodium/src/crypto_hash/sha256/cp/hash_sha256_cp.c
new file mode 100644
index 0000000000..264054f98b
--- /dev/null
+++ b/libs/libsodium/src/crypto_hash/sha256/cp/hash_sha256_cp.c
@@ -0,0 +1,254 @@
+
+/*-
+ * Copyright 2005,2007,2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+
+#include "crypto_hash_sha256.h"
+#include "private/common.h"
+#include "utils.h"
+
+static void
+be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len / 4; i++) {
+ STORE32_BE(dst + i * 4, src[i]);
+ }
+}
+
+static void
+be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len / 4; i++) {
+ dst[i] = LOAD32_BE(src + i * 4);
+ }
+}
+
+static const uint32_t Krnd[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
+ 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
+ 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
+ 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
+ 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
+ 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
+#define Maj(x, y, z) ((x & (y | z)) | (y & z))
+#define SHR(x, n) (x >> n)
+#define ROTR(x, n) ROTR32(x, n)
+#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
+#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
+
+#define RND(a, b, c, d, e, f, g, h, k) \
+ h += S1(e) + Ch(e, f, g) + k; \
+ d += h; \
+ h += S0(a) + Maj(a, b, c);
+
+#define RNDr(S, W, i, ii) \
+ RND(S[(64 - i) % 8], S[(65 - i) % 8], S[(66 - i) % 8], S[(67 - i) % 8], \
+ S[(68 - i) % 8], S[(69 - i) % 8], S[(70 - i) % 8], S[(71 - i) % 8], \
+ W[i + ii] + Krnd[i + ii])
+
+#define MSCH(W, ii, i) \
+ W[i + ii + 16] = \
+ s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii]
+
+static void
+SHA256_Transform(uint32_t state[8], const uint8_t block[64], uint32_t W[64],
+ uint32_t S[8])
+{
+ int i;
+
+ be32dec_vect(W, block, 64);
+ memcpy(S, state, 32);
+ for (i = 0; i < 64; i += 16) {
+ RNDr(S, W, 0, i);
+ RNDr(S, W, 1, i);
+ RNDr(S, W, 2, i);
+ RNDr(S, W, 3, i);
+ RNDr(S, W, 4, i);
+ RNDr(S, W, 5, i);
+ RNDr(S, W, 6, i);
+ RNDr(S, W, 7, i);
+ RNDr(S, W, 8, i);
+ RNDr(S, W, 9, i);
+ RNDr(S, W, 10, i);
+ RNDr(S, W, 11, i);
+ RNDr(S, W, 12, i);
+ RNDr(S, W, 13, i);
+ RNDr(S, W, 14, i);
+ RNDr(S, W, 15, i);
+ if (i == 48) {
+ break;
+ }
+ MSCH(W, 0, i);
+ MSCH(W, 1, i);
+ MSCH(W, 2, i);
+ MSCH(W, 3, i);
+ MSCH(W, 4, i);
+ MSCH(W, 5, i);
+ MSCH(W, 6, i);
+ MSCH(W, 7, i);
+ MSCH(W, 8, i);
+ MSCH(W, 9, i);
+ MSCH(W, 10, i);
+ MSCH(W, 11, i);
+ MSCH(W, 12, i);
+ MSCH(W, 13, i);
+ MSCH(W, 14, i);
+ MSCH(W, 15, i);
+ }
+ for (i = 0; i < 8; i++) {
+ state[i] += S[i];
+ }
+}
+
+static const uint8_t PAD[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+static void
+SHA256_Pad(crypto_hash_sha256_state *state, uint32_t tmp32[64 + 8])
+{
+ unsigned int r;
+ unsigned int i;
+
+ r = (unsigned int) ((state->count >> 3) & 0x3f);
+ if (r < 56) {
+ for (i = 0; i < 56 - r; i++) {
+ state->buf[r + i] = PAD[i];
+ }
+ } else {
+ for (i = 0; i < 64 - r; i++) {
+ state->buf[r + i] = PAD[i];
+ }
+ SHA256_Transform(state->state, state->buf, &tmp32[0], &tmp32[64]);
+ memset(&state->buf[0], 0, 56);
+ }
+ STORE64_BE(&state->buf[56], state->count);
+ SHA256_Transform(state->state, state->buf, &tmp32[0], &tmp32[64]);
+}
+
+int
+crypto_hash_sha256_init(crypto_hash_sha256_state *state)
+{
+ static const uint32_t sha256_initial_state[8] = { 0x6a09e667, 0xbb67ae85,
+ 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c,
+ 0x1f83d9ab, 0x5be0cd19 };
+
+ state->count = (uint64_t) 0U;
+ memcpy(state->state, sha256_initial_state, sizeof sha256_initial_state);
+
+ return 0;
+}
+
+int
+crypto_hash_sha256_update(crypto_hash_sha256_state *state,
+ const unsigned char *in, unsigned long long inlen)
+{
+ uint32_t tmp32[64 + 8];
+ unsigned long long i;
+ unsigned long long r;
+
+ if (inlen <= 0U) {
+ return 0;
+ }
+ r = (unsigned long long) ((state->count >> 3) & 0x3f);
+
+ state->count += ((uint64_t) inlen) << 3;
+ if (inlen < 64 - r) {
+ for (i = 0; i < inlen; i++) {
+ state->buf[r + i] = in[i];
+ }
+ return 0;
+ }
+ for (i = 0; i < 64 - r; i++) {
+ state->buf[r + i] = in[i];
+ }
+ SHA256_Transform(state->state, state->buf, &tmp32[0], &tmp32[64]);
+ in += 64 - r;
+ inlen -= 64 - r;
+
+ while (inlen >= 64) {
+ SHA256_Transform(state->state, in, &tmp32[0], &tmp32[64]);
+ in += 64;
+ inlen -= 64;
+ }
+ inlen &= 63;
+ for (i = 0; i < inlen; i++) {
+ state->buf[i] = in[i];
+ }
+ sodium_memzero((void *) tmp32, sizeof tmp32);
+
+ return 0;
+}
+
+int
+crypto_hash_sha256_final(crypto_hash_sha256_state *state, unsigned char *out)
+{
+ uint32_t tmp32[64 + 8];
+
+ SHA256_Pad(state, tmp32);
+ be32enc_vect(out, state->state, 32);
+ sodium_memzero((void *) tmp32, sizeof tmp32);
+ sodium_memzero((void *) state, sizeof *state);
+
+ return 0;
+}
+
+int
+crypto_hash_sha256(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen)
+{
+ crypto_hash_sha256_state state;
+
+ crypto_hash_sha256_init(&state);
+ crypto_hash_sha256_update(&state, in, inlen);
+ crypto_hash_sha256_final(&state, out);
+
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_hash/sha256/hash_sha256.c b/libs/libsodium/src/crypto_hash/sha256/hash_sha256.c
new file mode 100644
index 0000000000..e729c811e6
--- /dev/null
+++ b/libs/libsodium/src/crypto_hash/sha256/hash_sha256.c
@@ -0,0 +1,13 @@
+#include "crypto_hash_sha256.h"
+
+size_t
+crypto_hash_sha256_bytes(void)
+{
+ return crypto_hash_sha256_BYTES;
+}
+
+size_t
+crypto_hash_sha256_statebytes(void)
+{
+ return sizeof(crypto_hash_sha256_state);
+}
diff --git a/libs/libsodium/src/crypto_hash/sha512/cp/hash_sha512_cp.c b/libs/libsodium/src/crypto_hash/sha512/cp/hash_sha512_cp.c
new file mode 100644
index 0000000000..8e0f36fb6b
--- /dev/null
+++ b/libs/libsodium/src/crypto_hash/sha512/cp/hash_sha512_cp.c
@@ -0,0 +1,282 @@
+
+/*-
+ * Copyright 2005,2007,2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+
+#include "crypto_hash_sha512.h"
+#include "private/common.h"
+#include "utils.h"
+
+static void
+be64enc_vect(unsigned char *dst, const uint64_t *src, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len / 8; i++) {
+ STORE64_BE(dst + i * 8, src[i]);
+ }
+}
+
+static void
+be64dec_vect(uint64_t *dst, const unsigned char *src, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len / 8; i++) {
+ dst[i] = LOAD64_BE(src + i * 8);
+ }
+}
+
+static const uint64_t Krnd[80] = {
+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
+ 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
+ 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
+ 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
+ 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
+ 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
+ 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
+ 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
+ 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
+ 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
+ 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
+ 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
+ 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
+ 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
+#define Maj(x, y, z) ((x & (y | z)) | (y & z))
+#define SHR(x, n) (x >> n)
+#define ROTR(x, n) ROTR64(x, n)
+#define S0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
+#define S1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
+#define s0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
+#define s1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6))
+
+#define RND(a, b, c, d, e, f, g, h, k) \
+ h += S1(e) + Ch(e, f, g) + k; \
+ d += h; \
+ h += S0(a) + Maj(a, b, c);
+
+#define RNDr(S, W, i, ii) \
+ RND(S[(80 - i) % 8], S[(81 - i) % 8], S[(82 - i) % 8], S[(83 - i) % 8], \
+ S[(84 - i) % 8], S[(85 - i) % 8], S[(86 - i) % 8], S[(87 - i) % 8], \
+ W[i + ii] + Krnd[i + ii])
+
+#define MSCH(W, ii, i) \
+ W[i + ii + 16] = \
+ s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii]
+
+static void
+SHA512_Transform(uint64_t *state, const uint8_t block[128], uint64_t W[80],
+ uint64_t S[8])
+{
+ int i;
+
+ be64dec_vect(W, block, 128);
+ memcpy(S, state, 64);
+ for (i = 0; i < 80; i += 16) {
+ RNDr(S, W, 0, i);
+ RNDr(S, W, 1, i);
+ RNDr(S, W, 2, i);
+ RNDr(S, W, 3, i);
+ RNDr(S, W, 4, i);
+ RNDr(S, W, 5, i);
+ RNDr(S, W, 6, i);
+ RNDr(S, W, 7, i);
+ RNDr(S, W, 8, i);
+ RNDr(S, W, 9, i);
+ RNDr(S, W, 10, i);
+ RNDr(S, W, 11, i);
+ RNDr(S, W, 12, i);
+ RNDr(S, W, 13, i);
+ RNDr(S, W, 14, i);
+ RNDr(S, W, 15, i);
+ if (i == 64) {
+ break;
+ }
+ MSCH(W, 0, i);
+ MSCH(W, 1, i);
+ MSCH(W, 2, i);
+ MSCH(W, 3, i);
+ MSCH(W, 4, i);
+ MSCH(W, 5, i);
+ MSCH(W, 6, i);
+ MSCH(W, 7, i);
+ MSCH(W, 8, i);
+ MSCH(W, 9, i);
+ MSCH(W, 10, i);
+ MSCH(W, 11, i);
+ MSCH(W, 12, i);
+ MSCH(W, 13, i);
+ MSCH(W, 14, i);
+ MSCH(W, 15, i);
+ }
+ for (i = 0; i < 8; i++) {
+ state[i] += S[i];
+ }
+}
+
+static const uint8_t PAD[128] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static void
+SHA512_Pad(crypto_hash_sha512_state *state, uint64_t tmp64[80 + 8])
+{
+ unsigned int r;
+ unsigned int i;
+
+ r = (unsigned int) ((state->count[1] >> 3) & 0x7f);
+ if (r < 112) {
+ for (i = 0; i < 112 - r; i++) {
+ state->buf[r + i] = PAD[i];
+ }
+ } else {
+ for (i = 0; i < 128 - r; i++) {
+ state->buf[r + i] = PAD[i];
+ }
+ SHA512_Transform(state->state, state->buf, &tmp64[0], &tmp64[80]);
+ memset(&state->buf[0], 0, 112);
+ }
+ be64enc_vect(&state->buf[112], state->count, 16);
+ SHA512_Transform(state->state, state->buf, &tmp64[0], &tmp64[80]);
+}
+
+int
+crypto_hash_sha512_init(crypto_hash_sha512_state *state)
+{
+ static const uint64_t sha512_initial_state[8] = {
+ 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
+ 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+ };
+
+ state->count[0] = state->count[1] = (uint64_t) 0U;
+ memcpy(state->state, sha512_initial_state, sizeof sha512_initial_state);
+
+ return 0;
+}
+
+int
+crypto_hash_sha512_update(crypto_hash_sha512_state *state,
+ const unsigned char *in, unsigned long long inlen)
+{
+ uint64_t tmp64[80 + 8];
+ uint64_t bitlen[2];
+ unsigned long long i;
+ unsigned long long r;
+
+ if (inlen <= 0U) {
+ return 0;
+ }
+ r = (unsigned long long) ((state->count[1] >> 3) & 0x7f);
+
+ bitlen[1] = ((uint64_t) inlen) << 3;
+ bitlen[0] = ((uint64_t) inlen) >> 61;
+ /* LCOV_EXCL_START */
+ if ((state->count[1] += bitlen[1]) < bitlen[1]) {
+ state->count[0]++;
+ }
+ /* LCOV_EXCL_STOP */
+ state->count[0] += bitlen[0];
+ if (inlen < 128 - r) {
+ for (i = 0; i < inlen; i++) {
+ state->buf[r + i] = in[i];
+ }
+ return 0;
+ }
+ for (i = 0; i < 128 - r; i++) {
+ state->buf[r + i] = in[i];
+ }
+ SHA512_Transform(state->state, state->buf, &tmp64[0], &tmp64[80]);
+ in += 128 - r;
+ inlen -= 128 - r;
+
+ while (inlen >= 128) {
+ SHA512_Transform(state->state, in, &tmp64[0], &tmp64[80]);
+ in += 128;
+ inlen -= 128;
+ }
+ inlen &= 127;
+ for (i = 0; i < inlen; i++) {
+ state->buf[i] = in[i];
+ }
+ sodium_memzero((void *) tmp64, sizeof tmp64);
+
+ return 0;
+}
+
+int
+crypto_hash_sha512_final(crypto_hash_sha512_state *state, unsigned char *out)
+{
+ uint64_t tmp64[80 + 8];
+
+ SHA512_Pad(state, tmp64);
+ be64enc_vect(out, state->state, 64);
+ sodium_memzero((void *) tmp64, sizeof tmp64);
+ sodium_memzero((void *) state, sizeof *state);
+
+ return 0;
+}
+
+int
+crypto_hash_sha512(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen)
+{
+ crypto_hash_sha512_state state;
+
+ crypto_hash_sha512_init(&state);
+ crypto_hash_sha512_update(&state, in, inlen);
+ crypto_hash_sha512_final(&state, out);
+
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_hash/sha512/hash_sha512.c b/libs/libsodium/src/crypto_hash/sha512/hash_sha512.c
new file mode 100644
index 0000000000..ba842b8bd4
--- /dev/null
+++ b/libs/libsodium/src/crypto_hash/sha512/hash_sha512.c
@@ -0,0 +1,13 @@
+#include "crypto_hash_sha512.h"
+
+size_t
+crypto_hash_sha512_bytes(void)
+{
+ return crypto_hash_sha512_BYTES;
+}
+
+size_t
+crypto_hash_sha512_statebytes(void)
+{
+ return sizeof(crypto_hash_sha512_state);
+}
diff --git a/libs/libsodium/src/crypto_kdf/blake2b/kdf_blake2b.c b/libs/libsodium/src/crypto_kdf/blake2b/kdf_blake2b.c
new file mode 100644
index 0000000000..2a690c9ac8
--- /dev/null
+++ b/libs/libsodium/src/crypto_kdf/blake2b/kdf_blake2b.c
@@ -0,0 +1,52 @@
+#include <errno.h>
+
+#include "crypto_kdf_blake2b.h"
+#include "crypto_generichash_blake2b.h"
+#include "private/common.h"
+
+size_t
+crypto_kdf_blake2b_bytes_min(void)
+{
+ return crypto_kdf_blake2b_BYTES_MIN;
+}
+
+size_t
+crypto_kdf_blake2b_bytes_max(void)
+{
+ return crypto_kdf_blake2b_BYTES_MAX;
+}
+
+size_t
+crypto_kdf_blake2b_contextbytes(void)
+{
+ return crypto_kdf_blake2b_CONTEXTBYTES;
+}
+
+size_t
+crypto_kdf_blake2b_keybytes(void)
+{
+ return crypto_kdf_blake2b_KEYBYTES;
+}
+
+int crypto_kdf_blake2b_derive_from_key(unsigned char *subkey, size_t subkey_len,
+ uint64_t subkey_id,
+ const char ctx[crypto_kdf_blake2b_CONTEXTBYTES],
+ const unsigned char key[crypto_kdf_blake2b_KEYBYTES])
+{
+ unsigned char ctx_padded[crypto_generichash_blake2b_PERSONALBYTES];
+ unsigned char salt[crypto_generichash_blake2b_SALTBYTES];
+
+ memcpy(ctx_padded, ctx, crypto_kdf_blake2b_CONTEXTBYTES);
+ memset(ctx_padded + crypto_kdf_blake2b_CONTEXTBYTES, 0, sizeof ctx_padded - crypto_kdf_blake2b_CONTEXTBYTES);
+ STORE64_LE(salt, subkey_id);
+ memset(salt + 8, 0, (sizeof salt) - 8);
+ if (subkey_len < crypto_kdf_blake2b_BYTES_MIN ||
+ subkey_len > crypto_kdf_blake2b_BYTES_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+ return crypto_generichash_blake2b_salt_personal(subkey, subkey_len,
+ NULL, 0,
+ key, crypto_kdf_blake2b_KEYBYTES,
+ salt, ctx_padded);
+}
diff --git a/libs/libsodium/src/crypto_kdf/crypto_kdf.c b/libs/libsodium/src/crypto_kdf/crypto_kdf.c
new file mode 100644
index 0000000000..b215d99ae6
--- /dev/null
+++ b/libs/libsodium/src/crypto_kdf/crypto_kdf.c
@@ -0,0 +1,49 @@
+
+#include "crypto_kdf.h"
+#include "randombytes.h"
+
+const char *
+crypto_kdf_primitive(void)
+{
+ return crypto_kdf_PRIMITIVE;
+}
+
+size_t
+crypto_kdf_bytes_min(void)
+{
+ return crypto_kdf_BYTES_MIN;
+}
+
+size_t
+crypto_kdf_bytes_max(void)
+{
+ return crypto_kdf_BYTES_MAX;
+}
+
+size_t
+crypto_kdf_contextbytes(void)
+{
+ return crypto_kdf_CONTEXTBYTES;
+}
+
+size_t
+crypto_kdf_keybytes(void)
+{
+ return crypto_kdf_KEYBYTES;
+}
+
+int
+crypto_kdf_derive_from_key(unsigned char *subkey, size_t subkey_len,
+ uint64_t subkey_id,
+ const char ctx[crypto_kdf_CONTEXTBYTES],
+ const unsigned char key[crypto_kdf_KEYBYTES])
+{
+ return crypto_kdf_blake2b_derive_from_key(subkey, subkey_len,
+ subkey_id, ctx, key);
+}
+
+void
+crypto_kdf_keygen(unsigned char k[crypto_kdf_KEYBYTES])
+{
+ randombytes_buf(k, crypto_kdf_KEYBYTES);
+}
diff --git a/libs/libsodium/src/crypto_kx/crypto_kx.c b/libs/libsodium/src/crypto_kx/crypto_kx.c
new file mode 100644
index 0000000000..877ab7ff4a
--- /dev/null
+++ b/libs/libsodium/src/crypto_kx/crypto_kx.c
@@ -0,0 +1,143 @@
+
+#include <stddef.h>
+
+#include "core.h"
+#include "crypto_generichash.h"
+#include "crypto_kx.h"
+#include "crypto_scalarmult.h"
+#include "private/common.h"
+#include "randombytes.h"
+#include "utils.h"
+
+int
+crypto_kx_seed_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES],
+ unsigned char sk[crypto_kx_SECRETKEYBYTES],
+ const unsigned char seed[crypto_kx_SEEDBYTES])
+{
+ crypto_generichash(sk, crypto_kx_SECRETKEYBYTES,
+ seed, crypto_kx_SEEDBYTES, NULL, 0);
+ return crypto_scalarmult_base(pk, sk);
+}
+
+int
+crypto_kx_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES],
+ unsigned char sk[crypto_kx_SECRETKEYBYTES])
+{
+ COMPILER_ASSERT(crypto_kx_SECRETKEYBYTES == crypto_scalarmult_SCALARBYTES);
+ COMPILER_ASSERT(crypto_kx_PUBLICKEYBYTES == crypto_scalarmult_BYTES);
+
+ randombytes_buf(sk, crypto_kx_SECRETKEYBYTES);
+ return crypto_scalarmult_base(pk, sk);
+}
+
+int
+crypto_kx_client_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES],
+ unsigned char tx[crypto_kx_SESSIONKEYBYTES],
+ const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES],
+ const unsigned char client_sk[crypto_kx_SECRETKEYBYTES],
+ const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES])
+{
+ crypto_generichash_state h;
+ unsigned char q[crypto_scalarmult_BYTES];
+ unsigned char keys[2 * crypto_kx_SESSIONKEYBYTES];
+ int i;
+
+ if (rx == NULL) {
+ rx = tx;
+ }
+ if (tx == NULL) {
+ tx = rx;
+ }
+ if (rx == NULL) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+ if (crypto_scalarmult(q, client_sk, server_pk) != 0) {
+ return -1;
+ }
+ COMPILER_ASSERT(sizeof keys <= crypto_generichash_BYTES_MAX);
+ crypto_generichash_init(&h, NULL, 0U, sizeof keys);
+ crypto_generichash_update(&h, q, crypto_scalarmult_BYTES);
+ sodium_memzero(q, sizeof q);
+ crypto_generichash_update(&h, client_pk, crypto_kx_PUBLICKEYBYTES);
+ crypto_generichash_update(&h, server_pk, crypto_kx_PUBLICKEYBYTES);
+ crypto_generichash_final(&h, keys, sizeof keys);
+ sodium_memzero(&h, sizeof h);
+ for (i = 0; i < crypto_kx_SESSIONKEYBYTES; i++) {
+ rx[i] = keys[i];
+ tx[i] = keys[i + crypto_kx_SESSIONKEYBYTES];
+ }
+ sodium_memzero(keys, sizeof keys);
+
+ return 0;
+}
+
+int
+crypto_kx_server_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES],
+ unsigned char tx[crypto_kx_SESSIONKEYBYTES],
+ const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES],
+ const unsigned char server_sk[crypto_kx_SECRETKEYBYTES],
+ const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES])
+{
+ crypto_generichash_state h;
+ unsigned char q[crypto_scalarmult_BYTES];
+ unsigned char keys[2 * crypto_kx_SESSIONKEYBYTES];
+ int i;
+
+ if (rx == NULL) {
+ rx = tx;
+ }
+ if (tx == NULL) {
+ tx = rx;
+ }
+ if (rx == NULL) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+ if (crypto_scalarmult(q, server_sk, client_pk) != 0) {
+ return -1;
+ }
+ COMPILER_ASSERT(sizeof keys <= crypto_generichash_BYTES_MAX);
+ crypto_generichash_init(&h, NULL, 0U, sizeof keys);
+ crypto_generichash_update(&h, q, crypto_scalarmult_BYTES);
+ sodium_memzero(q, sizeof q);
+ crypto_generichash_update(&h, client_pk, crypto_kx_PUBLICKEYBYTES);
+ crypto_generichash_update(&h, server_pk, crypto_kx_PUBLICKEYBYTES);
+ crypto_generichash_final(&h, keys, sizeof keys);
+ sodium_memzero(&h, sizeof h);
+ for (i = 0; i < crypto_kx_SESSIONKEYBYTES; i++) {
+ tx[i] = keys[i];
+ rx[i] = keys[i + crypto_kx_SESSIONKEYBYTES];
+ }
+ sodium_memzero(keys, sizeof keys);
+
+ return 0;
+}
+
+size_t
+crypto_kx_publickeybytes(void)
+{
+ return crypto_kx_PUBLICKEYBYTES;
+}
+
+size_t
+crypto_kx_secretkeybytes(void)
+{
+ return crypto_kx_SECRETKEYBYTES;
+}
+
+size_t
+crypto_kx_seedbytes(void)
+{
+ return crypto_kx_SEEDBYTES;
+}
+
+size_t
+crypto_kx_sessionkeybytes(void)
+{
+ return crypto_kx_SESSIONKEYBYTES;
+}
+
+const char *
+crypto_kx_primitive(void)
+{
+ return crypto_kx_PRIMITIVE;
+}
diff --git a/libs/libsodium/src/crypto_onetimeauth/crypto_onetimeauth.c b/libs/libsodium/src/crypto_onetimeauth/crypto_onetimeauth.c
new file mode 100644
index 0000000000..93567aae0b
--- /dev/null
+++ b/libs/libsodium/src/crypto_onetimeauth/crypto_onetimeauth.c
@@ -0,0 +1,71 @@
+
+#include "crypto_onetimeauth.h"
+#include "randombytes.h"
+
+size_t
+crypto_onetimeauth_statebytes(void)
+{
+ return sizeof(crypto_onetimeauth_state);
+}
+
+size_t
+crypto_onetimeauth_bytes(void)
+{
+ return crypto_onetimeauth_BYTES;
+}
+
+size_t
+crypto_onetimeauth_keybytes(void)
+{
+ return crypto_onetimeauth_KEYBYTES;
+}
+
+int
+crypto_onetimeauth(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k)
+{
+ return crypto_onetimeauth_poly1305(out, in, inlen, k);
+}
+
+int
+crypto_onetimeauth_verify(const unsigned char *h, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k)
+{
+ return crypto_onetimeauth_poly1305_verify(h, in, inlen, k);
+}
+
+int
+crypto_onetimeauth_init(crypto_onetimeauth_state *state,
+ const unsigned char *key)
+{
+ return crypto_onetimeauth_poly1305_init
+ ((crypto_onetimeauth_poly1305_state *) state, key);
+}
+
+int
+crypto_onetimeauth_update(crypto_onetimeauth_state *state,
+ const unsigned char *in,
+ unsigned long long inlen)
+{
+ return crypto_onetimeauth_poly1305_update
+ ((crypto_onetimeauth_poly1305_state *) state, in, inlen);
+}
+
+int
+crypto_onetimeauth_final(crypto_onetimeauth_state *state,
+ unsigned char *out)
+{
+ return crypto_onetimeauth_poly1305_final
+ ((crypto_onetimeauth_poly1305_state *) state, out);
+}
+
+const char *
+crypto_onetimeauth_primitive(void)
+{
+ return crypto_onetimeauth_PRIMITIVE;
+}
+
+void crypto_onetimeauth_keygen(unsigned char k[crypto_onetimeauth_KEYBYTES])
+{
+ randombytes_buf(k, crypto_onetimeauth_KEYBYTES);
+}
diff --git a/libs/libsodium/src/crypto_onetimeauth/poly1305/donna/poly1305_donna.c b/libs/libsodium/src/crypto_onetimeauth/poly1305/donna/poly1305_donna.c
new file mode 100644
index 0000000000..e798072f84
--- /dev/null
+++ b/libs/libsodium/src/crypto_onetimeauth/poly1305/donna/poly1305_donna.c
@@ -0,0 +1,124 @@
+
+#include "poly1305_donna.h"
+#include "crypto_verify_16.h"
+#include "private/common.h"
+#include "utils.h"
+
+#ifdef HAVE_TI_MODE
+#include "poly1305_donna64.h"
+#else
+#include "poly1305_donna32.h"
+#endif
+#include "../onetimeauth_poly1305.h"
+
+static void
+poly1305_update(poly1305_state_internal_t *st, const unsigned char *m,
+ unsigned long long bytes)
+{
+ unsigned long long i;
+
+ /* handle leftover */
+ if (st->leftover) {
+ unsigned long long want = (poly1305_block_size - st->leftover);
+
+ if (want > bytes) {
+ want = bytes;
+ }
+ for (i = 0; i < want; i++) {
+ st->buffer[st->leftover + i] = m[i];
+ }
+ bytes -= want;
+ m += want;
+ st->leftover += want;
+ if (st->leftover < poly1305_block_size) {
+ return;
+ }
+ poly1305_blocks(st, st->buffer, poly1305_block_size);
+ st->leftover = 0;
+ }
+
+ /* process full blocks */
+ if (bytes >= poly1305_block_size) {
+ unsigned long long want = (bytes & ~(poly1305_block_size - 1));
+
+ poly1305_blocks(st, m, want);
+ m += want;
+ bytes -= want;
+ }
+
+ /* store leftover */
+ if (bytes) {
+ for (i = 0; i < bytes; i++) {
+ st->buffer[st->leftover + i] = m[i];
+ }
+ st->leftover += bytes;
+ }
+}
+
+static int
+crypto_onetimeauth_poly1305_donna(unsigned char *out, const unsigned char *m,
+ unsigned long long inlen,
+ const unsigned char *key)
+{
+ CRYPTO_ALIGN(64) poly1305_state_internal_t state;
+
+ poly1305_init(&state, key);
+ poly1305_update(&state, m, inlen);
+ poly1305_finish(&state, out);
+
+ return 0;
+}
+
+static int
+crypto_onetimeauth_poly1305_donna_init(crypto_onetimeauth_poly1305_state *state,
+ const unsigned char *key)
+{
+ COMPILER_ASSERT(sizeof(crypto_onetimeauth_poly1305_state) >=
+ sizeof(poly1305_state_internal_t));
+ poly1305_init((poly1305_state_internal_t *) (void *) state, key);
+
+ return 0;
+}
+
+static int
+crypto_onetimeauth_poly1305_donna_update(
+ crypto_onetimeauth_poly1305_state *state, const unsigned char *in,
+ unsigned long long inlen)
+{
+ poly1305_update((poly1305_state_internal_t *) (void *) state, in, inlen);
+
+ return 0;
+}
+
+static int
+crypto_onetimeauth_poly1305_donna_final(
+ crypto_onetimeauth_poly1305_state *state, unsigned char *out)
+{
+ poly1305_finish((poly1305_state_internal_t *) (void *) state, out);
+
+ return 0;
+}
+
+static int
+crypto_onetimeauth_poly1305_donna_verify(const unsigned char *h,
+ const unsigned char *in,
+ unsigned long long inlen,
+ const unsigned char *k)
+{
+ unsigned char correct[16];
+
+ crypto_onetimeauth_poly1305_donna(correct, in, inlen, k);
+
+ return crypto_verify_16(h, correct);
+}
+
+struct crypto_onetimeauth_poly1305_implementation
+ crypto_onetimeauth_poly1305_donna_implementation = {
+ SODIUM_C99(.onetimeauth =) crypto_onetimeauth_poly1305_donna,
+ SODIUM_C99(.onetimeauth_verify =)
+ crypto_onetimeauth_poly1305_donna_verify,
+ SODIUM_C99(.onetimeauth_init =) crypto_onetimeauth_poly1305_donna_init,
+ SODIUM_C99(.onetimeauth_update =)
+ crypto_onetimeauth_poly1305_donna_update,
+ SODIUM_C99(.onetimeauth_final =) crypto_onetimeauth_poly1305_donna_final
+ };
diff --git a/libs/libsodium/src/crypto_onetimeauth/poly1305/donna/poly1305_donna.h b/libs/libsodium/src/crypto_onetimeauth/poly1305/donna/poly1305_donna.h
new file mode 100644
index 0000000000..d6474b3af4
--- /dev/null
+++ b/libs/libsodium/src/crypto_onetimeauth/poly1305/donna/poly1305_donna.h
@@ -0,0 +1,12 @@
+#ifndef poly1305_donna_H
+#define poly1305_donna_H
+
+#include <stddef.h>
+
+#include "../onetimeauth_poly1305.h"
+#include "crypto_onetimeauth_poly1305.h"
+
+extern struct crypto_onetimeauth_poly1305_implementation
+ crypto_onetimeauth_poly1305_donna_implementation;
+
+#endif /* poly1305_donna_H */
diff --git a/libs/libsodium/src/crypto_onetimeauth/poly1305/donna/poly1305_donna32.h b/libs/libsodium/src/crypto_onetimeauth/poly1305/donna/poly1305_donna32.h
new file mode 100644
index 0000000000..bcf447cd7d
--- /dev/null
+++ b/libs/libsodium/src/crypto_onetimeauth/poly1305/donna/poly1305_donna32.h
@@ -0,0 +1,235 @@
+/*
+ poly1305 implementation using 32 bit * 32 bit = 64 bit multiplication
+ and 64 bit addition
+*/
+
+#if defined(_MSC_VER)
+# define POLY1305_NOINLINE __declspec(noinline)
+#elif defined(__GNUC__)
+# define POLY1305_NOINLINE __attribute__((noinline))
+#else
+# define POLY1305_NOINLINE
+#endif
+
+#include "private/common.h"
+
+#define poly1305_block_size 16
+
+/* 17 + sizeof(unsigned long long) + 14*sizeof(unsigned long) */
+typedef struct poly1305_state_internal_t {
+ unsigned long r[5];
+ unsigned long h[5];
+ unsigned long pad[4];
+ unsigned long long leftover;
+ unsigned char buffer[poly1305_block_size];
+ unsigned char final;
+} poly1305_state_internal_t;
+
+static void
+poly1305_init(poly1305_state_internal_t *st, const unsigned char key[32])
+{
+ /* r &= 0xffffffc0ffffffc0ffffffc0fffffff - wiped after finalization */
+ st->r[0] = (LOAD32_LE(&key[0])) & 0x3ffffff;
+ st->r[1] = (LOAD32_LE(&key[3]) >> 2) & 0x3ffff03;
+ st->r[2] = (LOAD32_LE(&key[6]) >> 4) & 0x3ffc0ff;
+ st->r[3] = (LOAD32_LE(&key[9]) >> 6) & 0x3f03fff;
+ st->r[4] = (LOAD32_LE(&key[12]) >> 8) & 0x00fffff;
+
+ /* h = 0 */
+ st->h[0] = 0;
+ st->h[1] = 0;
+ st->h[2] = 0;
+ st->h[3] = 0;
+ st->h[4] = 0;
+
+ /* save pad for later */
+ st->pad[0] = LOAD32_LE(&key[16]);
+ st->pad[1] = LOAD32_LE(&key[20]);
+ st->pad[2] = LOAD32_LE(&key[24]);
+ st->pad[3] = LOAD32_LE(&key[28]);
+
+ st->leftover = 0;
+ st->final = 0;
+}
+
+static void
+poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m,
+ unsigned long long bytes)
+{
+ const unsigned long hibit = (st->final) ? 0UL : (1UL << 24); /* 1 << 128 */
+ unsigned long r0, r1, r2, r3, r4;
+ unsigned long s1, s2, s3, s4;
+ unsigned long h0, h1, h2, h3, h4;
+ unsigned long long d0, d1, d2, d3, d4;
+ unsigned long c;
+
+ r0 = st->r[0];
+ r1 = st->r[1];
+ r2 = st->r[2];
+ r3 = st->r[3];
+ r4 = st->r[4];
+
+ s1 = r1 * 5;
+ s2 = r2 * 5;
+ s3 = r3 * 5;
+ s4 = r4 * 5;
+
+ h0 = st->h[0];
+ h1 = st->h[1];
+ h2 = st->h[2];
+ h3 = st->h[3];
+ h4 = st->h[4];
+
+ while (bytes >= poly1305_block_size) {
+ /* h += m[i] */
+ h0 += (LOAD32_LE(m + 0)) & 0x3ffffff;
+ h1 += (LOAD32_LE(m + 3) >> 2) & 0x3ffffff;
+ h2 += (LOAD32_LE(m + 6) >> 4) & 0x3ffffff;
+ h3 += (LOAD32_LE(m + 9) >> 6) & 0x3ffffff;
+ h4 += (LOAD32_LE(m + 12) >> 8) | hibit;
+
+ /* h *= r */
+ d0 = ((unsigned long long) h0 * r0) + ((unsigned long long) h1 * s4) +
+ ((unsigned long long) h2 * s3) + ((unsigned long long) h3 * s2) +
+ ((unsigned long long) h4 * s1);
+ d1 = ((unsigned long long) h0 * r1) + ((unsigned long long) h1 * r0) +
+ ((unsigned long long) h2 * s4) + ((unsigned long long) h3 * s3) +
+ ((unsigned long long) h4 * s2);
+ d2 = ((unsigned long long) h0 * r2) + ((unsigned long long) h1 * r1) +
+ ((unsigned long long) h2 * r0) + ((unsigned long long) h3 * s4) +
+ ((unsigned long long) h4 * s3);
+ d3 = ((unsigned long long) h0 * r3) + ((unsigned long long) h1 * r2) +
+ ((unsigned long long) h2 * r1) + ((unsigned long long) h3 * r0) +
+ ((unsigned long long) h4 * s4);
+ d4 = ((unsigned long long) h0 * r4) + ((unsigned long long) h1 * r3) +
+ ((unsigned long long) h2 * r2) + ((unsigned long long) h3 * r1) +
+ ((unsigned long long) h4 * r0);
+
+ /* (partial) h %= p */
+ c = (unsigned long) (d0 >> 26);
+ h0 = (unsigned long) d0 & 0x3ffffff;
+ d1 += c;
+ c = (unsigned long) (d1 >> 26);
+ h1 = (unsigned long) d1 & 0x3ffffff;
+ d2 += c;
+ c = (unsigned long) (d2 >> 26);
+ h2 = (unsigned long) d2 & 0x3ffffff;
+ d3 += c;
+ c = (unsigned long) (d3 >> 26);
+ h3 = (unsigned long) d3 & 0x3ffffff;
+ d4 += c;
+ c = (unsigned long) (d4 >> 26);
+ h4 = (unsigned long) d4 & 0x3ffffff;
+ h0 += c * 5;
+ c = (h0 >> 26);
+ h0 = h0 & 0x3ffffff;
+ h1 += c;
+
+ m += poly1305_block_size;
+ bytes -= poly1305_block_size;
+ }
+
+ st->h[0] = h0;
+ st->h[1] = h1;
+ st->h[2] = h2;
+ st->h[3] = h3;
+ st->h[4] = h4;
+}
+
+static POLY1305_NOINLINE void
+poly1305_finish(poly1305_state_internal_t *st, unsigned char mac[16])
+{
+ unsigned long h0, h1, h2, h3, h4, c;
+ unsigned long g0, g1, g2, g3, g4;
+ unsigned long long f;
+ unsigned long mask;
+
+ /* process the remaining block */
+ if (st->leftover) {
+ unsigned long long i = st->leftover;
+
+ st->buffer[i++] = 1;
+ for (; i < poly1305_block_size; i++) {
+ st->buffer[i] = 0;
+ }
+ st->final = 1;
+ poly1305_blocks(st, st->buffer, poly1305_block_size);
+ }
+
+ /* fully carry h */
+ h0 = st->h[0];
+ h1 = st->h[1];
+ h2 = st->h[2];
+ h3 = st->h[3];
+ h4 = st->h[4];
+
+ c = h1 >> 26;
+ h1 = h1 & 0x3ffffff;
+ h2 += c;
+ c = h2 >> 26;
+ h2 = h2 & 0x3ffffff;
+ h3 += c;
+ c = h3 >> 26;
+ h3 = h3 & 0x3ffffff;
+ h4 += c;
+ c = h4 >> 26;
+ h4 = h4 & 0x3ffffff;
+ h0 += c * 5;
+ c = h0 >> 26;
+ h0 = h0 & 0x3ffffff;
+ h1 += c;
+
+ /* compute h + -p */
+ g0 = h0 + 5;
+ c = g0 >> 26;
+ g0 &= 0x3ffffff;
+ g1 = h1 + c;
+ c = g1 >> 26;
+ g1 &= 0x3ffffff;
+ g2 = h2 + c;
+ c = g2 >> 26;
+ g2 &= 0x3ffffff;
+ g3 = h3 + c;
+ c = g3 >> 26;
+ g3 &= 0x3ffffff;
+ g4 = h4 + c - (1UL << 26);
+
+ /* select h if h < p, or h + -p if h >= p */
+ mask = (g4 >> ((sizeof(unsigned long) * 8) - 1)) - 1;
+ g0 &= mask;
+ g1 &= mask;
+ g2 &= mask;
+ g3 &= mask;
+ g4 &= mask;
+ mask = ~mask;
+
+ h0 = (h0 & mask) | g0;
+ h1 = (h1 & mask) | g1;
+ h2 = (h2 & mask) | g2;
+ h3 = (h3 & mask) | g3;
+ h4 = (h4 & mask) | g4;
+
+ /* h = h % (2^128) */
+ h0 = ((h0) | (h1 << 26)) & 0xffffffff;
+ h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
+ h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
+ h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
+
+ /* mac = (h + pad) % (2^128) */
+ f = (unsigned long long) h0 + st->pad[0];
+ h0 = (unsigned long) f;
+ f = (unsigned long long) h1 + st->pad[1] + (f >> 32);
+ h1 = (unsigned long) f;
+ f = (unsigned long long) h2 + st->pad[2] + (f >> 32);
+ h2 = (unsigned long) f;
+ f = (unsigned long long) h3 + st->pad[3] + (f >> 32);
+ h3 = (unsigned long) f;
+
+ STORE32_LE(mac + 0, (uint32_t) h0);
+ STORE32_LE(mac + 4, (uint32_t) h1);
+ STORE32_LE(mac + 8, (uint32_t) h2);
+ STORE32_LE(mac + 12, (uint32_t) h3);
+
+ /* zero out the state */
+ sodium_memzero((void *) st, sizeof *st);
+}
diff --git a/libs/libsodium/src/crypto_onetimeauth/poly1305/donna/poly1305_donna64.h b/libs/libsodium/src/crypto_onetimeauth/poly1305/donna/poly1305_donna64.h
new file mode 100644
index 0000000000..e0ed754779
--- /dev/null
+++ b/libs/libsodium/src/crypto_onetimeauth/poly1305/donna/poly1305_donna64.h
@@ -0,0 +1,220 @@
+/*
+ poly1305 implementation using 64 bit * 64 bit = 128 bit multiplication
+ and 128 bit addition
+*/
+
+#include "private/common.h"
+
+#define MUL(out, x, y) out = ((uint128_t) x * y)
+#define ADD(out, in) out += in
+#define ADDLO(out, in) out += in
+#define SHR(in, shift) (unsigned long long) (in >> (shift))
+#define LO(in) (unsigned long long) (in)
+
+#if defined(_MSC_VER)
+# define POLY1305_NOINLINE __declspec(noinline)
+#elif defined(__GNUC__)
+# define POLY1305_NOINLINE __attribute__((noinline))
+#else
+# define POLY1305_NOINLINE
+#endif
+
+#define poly1305_block_size 16
+
+/* 17 + sizeof(unsigned long long) + 8*sizeof(unsigned long long) */
+typedef struct poly1305_state_internal_t {
+ unsigned long long r[3];
+ unsigned long long h[3];
+ unsigned long long pad[2];
+ unsigned long long leftover;
+ unsigned char buffer[poly1305_block_size];
+ unsigned char final;
+} poly1305_state_internal_t;
+
+static void
+poly1305_init(poly1305_state_internal_t *st, const unsigned char key[32])
+{
+ unsigned long long t0, t1;
+
+ /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
+ t0 = LOAD64_LE(&key[0]);
+ t1 = LOAD64_LE(&key[8]);
+
+ /* wiped after finalization */
+ st->r[0] = (t0) &0xffc0fffffff;
+ st->r[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
+ st->r[2] = ((t1 >> 24)) & 0x00ffffffc0f;
+
+ /* h = 0 */
+ st->h[0] = 0;
+ st->h[1] = 0;
+ st->h[2] = 0;
+
+ /* save pad for later */
+ st->pad[0] = LOAD64_LE(&key[16]);
+ st->pad[1] = LOAD64_LE(&key[24]);
+
+ st->leftover = 0;
+ st->final = 0;
+}
+
+static void
+poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m,
+ unsigned long long bytes)
+{
+ const unsigned long long hibit =
+ (st->final) ? 0ULL : (1ULL << 40); /* 1 << 128 */
+ unsigned long long r0, r1, r2;
+ unsigned long long s1, s2;
+ unsigned long long h0, h1, h2;
+ unsigned long long c;
+ uint128_t d0, d1, d2, d;
+
+ r0 = st->r[0];
+ r1 = st->r[1];
+ r2 = st->r[2];
+
+ h0 = st->h[0];
+ h1 = st->h[1];
+ h2 = st->h[2];
+
+ s1 = r1 * (5 << 2);
+ s2 = r2 * (5 << 2);
+
+ while (bytes >= poly1305_block_size) {
+ unsigned long long t0, t1;
+
+ /* h += m[i] */
+ t0 = LOAD64_LE(&m[0]);
+ t1 = LOAD64_LE(&m[8]);
+
+ h0 += ((t0) &0xfffffffffff);
+ h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff);
+ h2 += (((t1 >> 24)) & 0x3ffffffffff) | hibit;
+
+ /* h *= r */
+ MUL(d0, h0, r0);
+ MUL(d, h1, s2);
+ ADD(d0, d);
+ MUL(d, h2, s1);
+ ADD(d0, d);
+ MUL(d1, h0, r1);
+ MUL(d, h1, r0);
+ ADD(d1, d);
+ MUL(d, h2, s2);
+ ADD(d1, d);
+ MUL(d2, h0, r2);
+ MUL(d, h1, r1);
+ ADD(d2, d);
+ MUL(d, h2, r0);
+ ADD(d2, d);
+
+ /* (partial) h %= p */
+ c = SHR(d0, 44);
+ h0 = LO(d0) & 0xfffffffffff;
+ ADDLO(d1, c);
+ c = SHR(d1, 44);
+ h1 = LO(d1) & 0xfffffffffff;
+ ADDLO(d2, c);
+ c = SHR(d2, 42);
+ h2 = LO(d2) & 0x3ffffffffff;
+ h0 += c * 5;
+ c = (h0 >> 44);
+ h0 = h0 & 0xfffffffffff;
+ h1 += c;
+
+ m += poly1305_block_size;
+ bytes -= poly1305_block_size;
+ }
+
+ st->h[0] = h0;
+ st->h[1] = h1;
+ st->h[2] = h2;
+}
+
+static POLY1305_NOINLINE void
+poly1305_finish(poly1305_state_internal_t *st, unsigned char mac[16])
+{
+ unsigned long long h0, h1, h2, c;
+ unsigned long long g0, g1, g2;
+ unsigned long long t0, t1;
+
+ /* process the remaining block */
+ if (st->leftover) {
+ unsigned long long i = st->leftover;
+
+ st->buffer[i] = 1;
+
+ for (i = i + 1; i < poly1305_block_size; i++) {
+ st->buffer[i] = 0;
+ }
+ st->final = 1;
+ poly1305_blocks(st, st->buffer, poly1305_block_size);
+ }
+
+ /* fully carry h */
+ h0 = st->h[0];
+ h1 = st->h[1];
+ h2 = st->h[2];
+
+ c = (h1 >> 44);
+ h1 &= 0xfffffffffff;
+ h2 += c;
+ c = (h2 >> 42);
+ h2 &= 0x3ffffffffff;
+ h0 += c * 5;
+ c = (h0 >> 44);
+ h0 &= 0xfffffffffff;
+ h1 += c;
+ c = (h1 >> 44);
+ h1 &= 0xfffffffffff;
+ h2 += c;
+ c = (h2 >> 42);
+ h2 &= 0x3ffffffffff;
+ h0 += c * 5;
+ c = (h0 >> 44);
+ h0 &= 0xfffffffffff;
+ h1 += c;
+
+ /* compute h + -p */
+ g0 = h0 + 5;
+ c = (g0 >> 44);
+ g0 &= 0xfffffffffff;
+ g1 = h1 + c;
+ c = (g1 >> 44);
+ g1 &= 0xfffffffffff;
+ g2 = h2 + c - (1ULL << 42);
+
+ /* select h if h < p, or h + -p if h >= p */
+ c = (g2 >> ((sizeof(unsigned long long) * 8) - 1)) - 1;
+ g0 &= c;
+ g1 &= c;
+ g2 &= c;
+ c = ~c;
+ h0 = (h0 & c) | g0;
+ h1 = (h1 & c) | g1;
+ h2 = (h2 & c) | g2;
+
+ /* h = (h + pad) */
+ t0 = st->pad[0];
+ t1 = st->pad[1];
+
+ h0 += ((t0) &0xfffffffffff);
+ c = (h0 >> 44);
+ h0 &= 0xfffffffffff;
+ h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c;
+ c = (h1 >> 44);
+ h1 &= 0xfffffffffff;
+ h2 += (((t1 >> 24)) & 0x3ffffffffff) + c;
+ h2 &= 0x3ffffffffff;
+
+ /* mac = h % (2^128) */
+ h0 = ((h0) | (h1 << 44));
+ h1 = ((h1 >> 20) | (h2 << 24));
+
+ STORE64_LE(&mac[0], h0);
+ STORE64_LE(&mac[8], h1);
+
+ /* zero out the state */
+ sodium_memzero((void *) st, sizeof *st);
+}
diff --git a/libs/libsodium/src/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c b/libs/libsodium/src/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c
new file mode 100644
index 0000000000..d5e2efa297
--- /dev/null
+++ b/libs/libsodium/src/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c
@@ -0,0 +1,90 @@
+
+#include "onetimeauth_poly1305.h"
+#include "crypto_onetimeauth_poly1305.h"
+#include "private/common.h"
+#include "private/implementations.h"
+#include "randombytes.h"
+#include "runtime.h"
+
+#include "donna/poly1305_donna.h"
+#if defined(HAVE_TI_MODE) && defined(HAVE_EMMINTRIN_H)
+# include "sse2/poly1305_sse2.h"
+#endif
+
+static const crypto_onetimeauth_poly1305_implementation *implementation =
+ &crypto_onetimeauth_poly1305_donna_implementation;
+
+int
+crypto_onetimeauth_poly1305(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k)
+{
+ return implementation->onetimeauth(out, in, inlen, k);
+}
+
+int
+crypto_onetimeauth_poly1305_verify(const unsigned char *h,
+ const unsigned char *in,
+ unsigned long long inlen,
+ const unsigned char *k)
+{
+ return implementation->onetimeauth_verify(h, in, inlen, k);
+}
+
+int
+crypto_onetimeauth_poly1305_init(crypto_onetimeauth_poly1305_state *state,
+ const unsigned char *key)
+{
+ return implementation->onetimeauth_init(state, key);
+}
+
+int
+crypto_onetimeauth_poly1305_update(crypto_onetimeauth_poly1305_state *state,
+ const unsigned char *in,
+ unsigned long long inlen)
+{
+ return implementation->onetimeauth_update(state, in, inlen);
+}
+
+int
+crypto_onetimeauth_poly1305_final(crypto_onetimeauth_poly1305_state *state,
+ unsigned char *out)
+{
+ return implementation->onetimeauth_final(state, out);
+}
+
+size_t
+crypto_onetimeauth_poly1305_bytes(void)
+{
+ return crypto_onetimeauth_poly1305_BYTES;
+}
+
+size_t
+crypto_onetimeauth_poly1305_keybytes(void)
+{
+ return crypto_onetimeauth_poly1305_KEYBYTES;
+}
+
+size_t
+crypto_onetimeauth_poly1305_statebytes(void)
+{
+ return sizeof(crypto_onetimeauth_poly1305_state);
+}
+
+void
+crypto_onetimeauth_poly1305_keygen(
+ unsigned char k[crypto_onetimeauth_poly1305_KEYBYTES])
+{
+ randombytes_buf(k, crypto_onetimeauth_poly1305_KEYBYTES);
+}
+
+int
+_crypto_onetimeauth_poly1305_pick_best_implementation(void)
+{
+ implementation = &crypto_onetimeauth_poly1305_donna_implementation;
+#if defined(HAVE_TI_MODE) && defined(HAVE_EMMINTRIN_H)
+ if (sodium_runtime_has_sse2()) {
+ implementation = &crypto_onetimeauth_poly1305_sse2_implementation;
+ }
+#endif
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_onetimeauth/poly1305/onetimeauth_poly1305.h b/libs/libsodium/src/crypto_onetimeauth/poly1305/onetimeauth_poly1305.h
new file mode 100644
index 0000000000..243eadd50b
--- /dev/null
+++ b/libs/libsodium/src/crypto_onetimeauth/poly1305/onetimeauth_poly1305.h
@@ -0,0 +1,21 @@
+
+#ifndef onetimeauth_poly1305_H
+#define onetimeauth_poly1305_H
+
+#include "crypto_onetimeauth_poly1305.h"
+
+typedef struct crypto_onetimeauth_poly1305_implementation {
+ int (*onetimeauth)(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k);
+ int (*onetimeauth_verify)(const unsigned char *h, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k);
+ int (*onetimeauth_init)(crypto_onetimeauth_poly1305_state *state,
+ const unsigned char * key);
+ int (*onetimeauth_update)(crypto_onetimeauth_poly1305_state *state,
+ const unsigned char * in,
+ unsigned long long inlen);
+ int (*onetimeauth_final)(crypto_onetimeauth_poly1305_state *state,
+ unsigned char * out);
+} crypto_onetimeauth_poly1305_implementation;
+
+#endif
diff --git a/libs/libsodium/src/crypto_onetimeauth/poly1305/sse2/poly1305_sse2.c b/libs/libsodium/src/crypto_onetimeauth/poly1305/sse2/poly1305_sse2.c
new file mode 100644
index 0000000000..022f15249b
--- /dev/null
+++ b/libs/libsodium/src/crypto_onetimeauth/poly1305/sse2/poly1305_sse2.c
@@ -0,0 +1,949 @@
+
+#include <stdint.h>
+#include <string.h>
+
+#include "../onetimeauth_poly1305.h"
+#include "crypto_verify_16.h"
+#include "poly1305_sse2.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+#include "utils.h"
+
+#if defined(HAVE_TI_MODE) && defined(HAVE_EMMINTRIN_H)
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# endif
+
+# include <emmintrin.h>
+
+typedef __m128i xmmi;
+
+# if defined(_MSC_VER)
+# define POLY1305_NOINLINE __declspec(noinline)
+# elif defined(__GNUC__)
+# define POLY1305_NOINLINE __attribute__((noinline))
+# else
+# define POLY1305_NOINLINE
+# endif
+
+# define poly1305_block_size 32
+
+enum poly1305_state_flags_t {
+ poly1305_started = 1,
+ poly1305_final_shift8 = 4,
+ poly1305_final_shift16 = 8,
+ poly1305_final_r2_r = 16, /* use [r^2,r] for the final block */
+ poly1305_final_r_1 = 32 /* use [r,1] for the final block */
+};
+
+typedef struct poly1305_state_internal_t {
+ union {
+ uint64_t h[3];
+ uint32_t hh[10];
+ } H; /* 40 bytes */
+ uint32_t R[5]; /* 20 bytes */
+ uint32_t R2[5]; /* 20 bytes */
+ uint32_t R4[5]; /* 20 bytes */
+ uint64_t pad[2]; /* 16 bytes */
+ uint64_t flags; /* 8 bytes */
+ unsigned long long leftover; /* 8 bytes */
+ unsigned char buffer[poly1305_block_size]; /* 32 bytes */
+} poly1305_state_internal_t; /* 164 bytes total */
+
+/*
+ * _mm_loadl_epi64() is turned into a simple MOVQ. So, unaligned accesses are
+ * totally fine, even though this intrinsic requires a __m128i* input.
+ * This confuses dynamic analysis, so force alignment, only in debug mode.
+ */
+# ifdef DEBUG
+static xmmi
+_fakealign_mm_loadl_epi64(const void *m)
+{
+ xmmi tmp;
+ memcpy(&tmp, m, 8);
+
+ return _mm_loadl_epi64(&tmp);
+}
+# define _mm_loadl_epi64(X) _fakealign_mm_loadl_epi64(X)
+#endif
+
+/* copy 0-31 bytes */
+static inline void
+poly1305_block_copy31(unsigned char *dst, const unsigned char *src,
+ unsigned long long bytes)
+{
+ if (bytes & 16) {
+ _mm_store_si128((xmmi *) (void *) dst,
+ _mm_loadu_si128((const xmmi *) (const void *) src));
+ src += 16;
+ dst += 16;
+ }
+ if (bytes & 8) {
+ memcpy(dst, src, 8);
+ src += 8;
+ dst += 8;
+ }
+ if (bytes & 4) {
+ memcpy(dst, src, 4);
+ src += 4;
+ dst += 4;
+ }
+ if (bytes & 2) {
+ memcpy(dst, src, 2);
+ src += 2;
+ dst += 2;
+ }
+ if (bytes & 1) {
+ *dst = *src;
+ }
+}
+
+static POLY1305_NOINLINE void
+poly1305_init_ext(poly1305_state_internal_t *st, const unsigned char key[32],
+ unsigned long long bytes)
+{
+ uint32_t *R;
+ uint128_t d[3];
+ uint64_t r0, r1, r2;
+ uint64_t rt0, rt1, rt2, st2, c;
+ uint64_t t0, t1;
+ unsigned long long i;
+
+ if (!bytes) {
+ bytes = ~(unsigned long long) 0;
+ }
+ /* H = 0 */
+ _mm_storeu_si128((xmmi *) (void *) &st->H.hh[0], _mm_setzero_si128());
+ _mm_storeu_si128((xmmi *) (void *) &st->H.hh[4], _mm_setzero_si128());
+ _mm_storeu_si128((xmmi *) (void *) &st->H.hh[8], _mm_setzero_si128());
+
+ /* clamp key */
+ memcpy(&t0, key, 8);
+ memcpy(&t1, key + 8, 8);
+ r0 = t0 & 0xffc0fffffff;
+ t0 >>= 44;
+ t0 |= t1 << 20;
+ r1 = t0 & 0xfffffc0ffff;
+ t1 >>= 24;
+ r2 = t1 & 0x00ffffffc0f;
+
+ /* r^1 */
+ R = st->R;
+ R[0] = (uint32_t)(r0) &0x3ffffff;
+ R[1] = (uint32_t)((r0 >> 26) | (r1 << 18)) & 0x3ffffff;
+ R[2] = (uint32_t)((r1 >> 8)) & 0x3ffffff;
+ R[3] = (uint32_t)((r1 >> 34) | (r2 << 10)) & 0x3ffffff;
+ R[4] = (uint32_t)((r2 >> 16));
+
+ /* save pad */
+ memcpy(&st->pad[0], key + 16, 8);
+ memcpy(&st->pad[1], key + 24, 8);
+
+ rt0 = r0;
+ rt1 = r1;
+ rt2 = r2;
+
+ /* r^2, r^4 */
+ for (i = 0; i < 2; i++) {
+ if (i == 0) {
+ R = st->R2;
+ if (bytes <= 16) {
+ break;
+ }
+ } else if (i == 1) {
+ R = st->R4;
+ if (bytes < 96) {
+ break;
+ }
+ }
+ st2 = rt2 * (5 << 2);
+
+ d[0] = ((uint128_t) rt0 * rt0) + ((uint128_t)(rt1 * 2) * st2);
+ d[1] = ((uint128_t) rt2 * st2) + ((uint128_t)(rt0 * 2) * rt1);
+ d[2] = ((uint128_t) rt1 * rt1) + ((uint128_t)(rt2 * 2) * rt0);
+
+ rt0 = (uint64_t) d[0] & 0xfffffffffff;
+ c = (uint64_t)(d[0] >> 44);
+ d[1] += c;
+
+ rt1 = (uint64_t) d[1] & 0xfffffffffff;
+ c = (uint64_t)(d[1] >> 44);
+ d[2] += c;
+
+ rt2 = (uint64_t) d[2] & 0x3ffffffffff;
+ c = (uint64_t)(d[2] >> 42);
+ rt0 += c * 5;
+ c = (rt0 >> 44);
+ rt0 = rt0 & 0xfffffffffff;
+ rt1 += c;
+ c = (rt1 >> 44);
+ rt1 = rt1 & 0xfffffffffff;
+ rt2 += c; /* even if rt2 overflows, it will still fit in rp4 safely, and
+ is safe to multiply with */
+
+ R[0] = (uint32_t)(rt0) &0x3ffffff;
+ R[1] = (uint32_t)((rt0 >> 26) | (rt1 << 18)) & 0x3ffffff;
+ R[2] = (uint32_t)((rt1 >> 8)) & 0x3ffffff;
+ R[3] = (uint32_t)((rt1 >> 34) | (rt2 << 10)) & 0x3ffffff;
+ R[4] = (uint32_t)((rt2 >> 16));
+ }
+ st->flags = 0;
+ st->leftover = 0U;
+}
+
+static POLY1305_NOINLINE void
+poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m,
+ unsigned long long bytes)
+{
+ CRYPTO_ALIGN(64)
+ xmmi HIBIT =
+ _mm_shuffle_epi32(_mm_cvtsi32_si128(1 << 24), _MM_SHUFFLE(1, 0, 1, 0));
+ const xmmi MMASK = _mm_shuffle_epi32(_mm_cvtsi32_si128((1 << 26) - 1),
+ _MM_SHUFFLE(1, 0, 1, 0));
+ const xmmi FIVE =
+ _mm_shuffle_epi32(_mm_cvtsi32_si128(5), _MM_SHUFFLE(1, 0, 1, 0));
+ xmmi H0, H1, H2, H3, H4;
+ xmmi T0, T1, T2, T3, T4, T5, T6, T7, T8;
+ xmmi M0, M1, M2, M3, M4;
+ xmmi M5, M6, M7, M8;
+ xmmi C1, C2;
+ xmmi R20, R21, R22, R23, R24, S21, S22, S23, S24;
+ xmmi R40, R41, R42, R43, R44, S41, S42, S43, S44;
+
+ if (st->flags & poly1305_final_shift8) {
+ HIBIT = _mm_srli_si128(HIBIT, 8);
+ }
+ if (st->flags & poly1305_final_shift16) {
+ HIBIT = _mm_setzero_si128();
+ }
+ if (!(st->flags & poly1305_started)) {
+ /* H = [Mx,My] */
+ T5 = _mm_unpacklo_epi64(
+ _mm_loadl_epi64((const xmmi *) (const void *) (m + 0)),
+ _mm_loadl_epi64((const xmmi *) (const void *) (m + 16)));
+ T6 = _mm_unpacklo_epi64(
+ _mm_loadl_epi64((const xmmi *) (const void *) (m + 8)),
+ _mm_loadl_epi64((const xmmi *) (const void *) (m + 24)));
+ H0 = _mm_and_si128(MMASK, T5);
+ H1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
+ T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12));
+ H2 = _mm_and_si128(MMASK, T5);
+ H3 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
+ H4 = _mm_srli_epi64(T6, 40);
+ H4 = _mm_or_si128(H4, HIBIT);
+ m += 32;
+ bytes -= 32;
+ st->flags |= poly1305_started;
+ } else {
+ T0 = _mm_loadu_si128((const xmmi *) (const void *) &st->H.hh[0]);
+ T1 = _mm_loadu_si128((const xmmi *) (const void *) &st->H.hh[4]);
+ T2 = _mm_loadu_si128((const xmmi *) (const void *) &st->H.hh[8]);
+ H0 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(1, 1, 0, 0));
+ H1 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(3, 3, 2, 2));
+ H2 = _mm_shuffle_epi32(T1, _MM_SHUFFLE(1, 1, 0, 0));
+ H3 = _mm_shuffle_epi32(T1, _MM_SHUFFLE(3, 3, 2, 2));
+ H4 = _mm_shuffle_epi32(T2, _MM_SHUFFLE(1, 1, 0, 0));
+ }
+ if (st->flags & (poly1305_final_r2_r | poly1305_final_r_1)) {
+ if (st->flags & poly1305_final_r2_r) {
+ /* use [r^2, r] */
+ T2 = _mm_loadu_si128((const xmmi *) (const void *) &st->R[0]);
+ T3 = _mm_cvtsi32_si128(st->R[4]);
+ T0 = _mm_loadu_si128((const xmmi *) (const void *) &st->R2[0]);
+ T1 = _mm_cvtsi32_si128(st->R2[4]);
+ T4 = _mm_unpacklo_epi32(T0, T2);
+ T5 = _mm_unpackhi_epi32(T0, T2);
+ R24 = _mm_unpacklo_epi64(T1, T3);
+ } else {
+ /* use [r^1, 1] */
+ T0 = _mm_loadu_si128((const xmmi *) (const void *) &st->R[0]);
+ T1 = _mm_cvtsi32_si128(st->R[4]);
+ T2 = _mm_cvtsi32_si128(1);
+ T4 = _mm_unpacklo_epi32(T0, T2);
+ T5 = _mm_unpackhi_epi32(T0, T2);
+ R24 = T1;
+ }
+ R20 = _mm_shuffle_epi32(T4, _MM_SHUFFLE(1, 1, 0, 0));
+ R21 = _mm_shuffle_epi32(T4, _MM_SHUFFLE(3, 3, 2, 2));
+ R22 = _mm_shuffle_epi32(T5, _MM_SHUFFLE(1, 1, 0, 0));
+ R23 = _mm_shuffle_epi32(T5, _MM_SHUFFLE(3, 3, 2, 2));
+ } else {
+ /* use [r^2, r^2] */
+ T0 = _mm_loadu_si128((const xmmi *) (const void *) &st->R2[0]);
+ T1 = _mm_cvtsi32_si128(st->R2[4]);
+ R20 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(0, 0, 0, 0));
+ R21 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(1, 1, 1, 1));
+ R22 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(2, 2, 2, 2));
+ R23 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(3, 3, 3, 3));
+ R24 = _mm_shuffle_epi32(T1, _MM_SHUFFLE(0, 0, 0, 0));
+ }
+ S21 = _mm_mul_epu32(R21, FIVE);
+ S22 = _mm_mul_epu32(R22, FIVE);
+ S23 = _mm_mul_epu32(R23, FIVE);
+ S24 = _mm_mul_epu32(R24, FIVE);
+
+ if (bytes >= 64) {
+ T0 = _mm_loadu_si128((const xmmi *) (const void *) &st->R4[0]);
+ T1 = _mm_cvtsi32_si128(st->R4[4]);
+ R40 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(0, 0, 0, 0));
+ R41 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(1, 1, 1, 1));
+ R42 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(2, 2, 2, 2));
+ R43 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(3, 3, 3, 3));
+ R44 = _mm_shuffle_epi32(T1, _MM_SHUFFLE(0, 0, 0, 0));
+ S41 = _mm_mul_epu32(R41, FIVE);
+ S42 = _mm_mul_epu32(R42, FIVE);
+ S43 = _mm_mul_epu32(R43, FIVE);
+ S44 = _mm_mul_epu32(R44, FIVE);
+
+ while (bytes >= 64) {
+ xmmi v00, v01, v02, v03, v04;
+ xmmi v10, v11, v12, v13, v14;
+ xmmi v20, v21, v22, v23, v24;
+ xmmi v30, v31, v32, v33, v34;
+ xmmi v40, v41, v42, v43, v44;
+ xmmi T14, T15;
+
+ /* H *= [r^4,r^4], preload [Mx,My] */
+ T15 = S42;
+ T0 = H4;
+ T0 = _mm_mul_epu32(T0, S41);
+ v01 = H3;
+ v01 = _mm_mul_epu32(v01, T15);
+ T14 = S43;
+ T1 = H4;
+ T1 = _mm_mul_epu32(T1, T15);
+ v11 = H3;
+ v11 = _mm_mul_epu32(v11, T14);
+ T2 = H4;
+ T2 = _mm_mul_epu32(T2, T14);
+ T0 = _mm_add_epi64(T0, v01);
+ T15 = S44;
+ v02 = H2;
+ v02 = _mm_mul_epu32(v02, T14);
+ T3 = H4;
+ T3 = _mm_mul_epu32(T3, T15);
+ T1 = _mm_add_epi64(T1, v11);
+ v03 = H1;
+ v03 = _mm_mul_epu32(v03, T15);
+ v12 = H2;
+ v12 = _mm_mul_epu32(v12, T15);
+ T0 = _mm_add_epi64(T0, v02);
+ T14 = R40;
+ v21 = H3;
+ v21 = _mm_mul_epu32(v21, T15);
+ v31 = H3;
+ v31 = _mm_mul_epu32(v31, T14);
+ T0 = _mm_add_epi64(T0, v03);
+ T4 = H4;
+ T4 = _mm_mul_epu32(T4, T14);
+ T1 = _mm_add_epi64(T1, v12);
+ v04 = H0;
+ v04 = _mm_mul_epu32(v04, T14);
+ T2 = _mm_add_epi64(T2, v21);
+ v13 = H1;
+ v13 = _mm_mul_epu32(v13, T14);
+ T3 = _mm_add_epi64(T3, v31);
+ T15 = R41;
+ v22 = H2;
+ v22 = _mm_mul_epu32(v22, T14);
+ v32 = H2;
+ v32 = _mm_mul_epu32(v32, T15);
+ T0 = _mm_add_epi64(T0, v04);
+ v41 = H3;
+ v41 = _mm_mul_epu32(v41, T15);
+ T1 = _mm_add_epi64(T1, v13);
+ v14 = H0;
+ v14 = _mm_mul_epu32(v14, T15);
+ T2 = _mm_add_epi64(T2, v22);
+ T14 = R42;
+ T5 = _mm_unpacklo_epi64(
+ _mm_loadl_epi64((const xmmi *) (const void *) (m + 0)),
+ _mm_loadl_epi64((const xmmi *) (const void *) (m + 16)));
+ v23 = H1;
+ v23 = _mm_mul_epu32(v23, T15);
+ T3 = _mm_add_epi64(T3, v32);
+ v33 = H1;
+ v33 = _mm_mul_epu32(v33, T14);
+ T4 = _mm_add_epi64(T4, v41);
+ v42 = H2;
+ v42 = _mm_mul_epu32(v42, T14);
+ T1 = _mm_add_epi64(T1, v14);
+ T15 = R43;
+ T6 = _mm_unpacklo_epi64(
+ _mm_loadl_epi64((const xmmi *) (const void *) (m + 8)),
+ _mm_loadl_epi64((const xmmi *) (const void *) (m + 24)));
+ v24 = H0;
+ v24 = _mm_mul_epu32(v24, T14);
+ T2 = _mm_add_epi64(T2, v23);
+ v34 = H0;
+ v34 = _mm_mul_epu32(v34, T15);
+ T3 = _mm_add_epi64(T3, v33);
+ M0 = _mm_and_si128(MMASK, T5);
+ v43 = H1;
+ v43 = _mm_mul_epu32(v43, T15);
+ T4 = _mm_add_epi64(T4, v42);
+ M1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
+ v44 = H0;
+ v44 = _mm_mul_epu32(v44, R44);
+ T2 = _mm_add_epi64(T2, v24);
+ T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12));
+ T3 = _mm_add_epi64(T3, v34);
+ M3 = _mm_and_si128(MMASK, _mm_srli_epi64(T6, 14));
+ T4 = _mm_add_epi64(T4, v43);
+ M2 = _mm_and_si128(MMASK, T5);
+ T4 = _mm_add_epi64(T4, v44);
+ M4 = _mm_or_si128(_mm_srli_epi64(T6, 40), HIBIT);
+
+ /* H += [Mx',My'] */
+ T5 = _mm_loadu_si128((const xmmi *) (const void *) (m + 32));
+ T6 = _mm_loadu_si128((const xmmi *) (const void *) (m + 48));
+ T7 = _mm_unpacklo_epi32(T5, T6);
+ T8 = _mm_unpackhi_epi32(T5, T6);
+ M5 = _mm_unpacklo_epi32(T7, _mm_setzero_si128());
+ M6 = _mm_unpackhi_epi32(T7, _mm_setzero_si128());
+ M7 = _mm_unpacklo_epi32(T8, _mm_setzero_si128());
+ M8 = _mm_unpackhi_epi32(T8, _mm_setzero_si128());
+ M6 = _mm_slli_epi64(M6, 6);
+ M7 = _mm_slli_epi64(M7, 12);
+ M8 = _mm_slli_epi64(M8, 18);
+ T0 = _mm_add_epi64(T0, M5);
+ T1 = _mm_add_epi64(T1, M6);
+ T2 = _mm_add_epi64(T2, M7);
+ T3 = _mm_add_epi64(T3, M8);
+ T4 = _mm_add_epi64(T4, HIBIT);
+
+ /* H += [Mx,My]*[r^2,r^2] */
+ T15 = S22;
+ v00 = M4;
+ v00 = _mm_mul_epu32(v00, S21);
+ v01 = M3;
+ v01 = _mm_mul_epu32(v01, T15);
+ T14 = S23;
+ v10 = M4;
+ v10 = _mm_mul_epu32(v10, T15);
+ v11 = M3;
+ v11 = _mm_mul_epu32(v11, T14);
+ T0 = _mm_add_epi64(T0, v00);
+ v20 = M4;
+ v20 = _mm_mul_epu32(v20, T14);
+ T0 = _mm_add_epi64(T0, v01);
+ T15 = S24;
+ v02 = M2;
+ v02 = _mm_mul_epu32(v02, T14);
+ T1 = _mm_add_epi64(T1, v10);
+ v30 = M4;
+ v30 = _mm_mul_epu32(v30, T15);
+ T1 = _mm_add_epi64(T1, v11);
+ v03 = M1;
+ v03 = _mm_mul_epu32(v03, T15);
+ T2 = _mm_add_epi64(T2, v20);
+ v12 = M2;
+ v12 = _mm_mul_epu32(v12, T15);
+ T0 = _mm_add_epi64(T0, v02);
+ T14 = R20;
+ v21 = M3;
+ v21 = _mm_mul_epu32(v21, T15);
+ T3 = _mm_add_epi64(T3, v30);
+ v31 = M3;
+ v31 = _mm_mul_epu32(v31, T14);
+ T0 = _mm_add_epi64(T0, v03);
+ v40 = M4;
+ v40 = _mm_mul_epu32(v40, T14);
+ T1 = _mm_add_epi64(T1, v12);
+ v04 = M0;
+ v04 = _mm_mul_epu32(v04, T14);
+ T2 = _mm_add_epi64(T2, v21);
+ v13 = M1;
+ v13 = _mm_mul_epu32(v13, T14);
+ T3 = _mm_add_epi64(T3, v31);
+ T15 = R21;
+ v22 = M2;
+ v22 = _mm_mul_epu32(v22, T14);
+ T4 = _mm_add_epi64(T4, v40);
+ v32 = M2;
+ v32 = _mm_mul_epu32(v32, T15);
+ T0 = _mm_add_epi64(T0, v04);
+ v41 = M3;
+ v41 = _mm_mul_epu32(v41, T15);
+ T1 = _mm_add_epi64(T1, v13);
+ v14 = M0;
+ v14 = _mm_mul_epu32(v14, T15);
+ T2 = _mm_add_epi64(T2, v22);
+ T14 = R22;
+ v23 = M1;
+ v23 = _mm_mul_epu32(v23, T15);
+ T3 = _mm_add_epi64(T3, v32);
+ v33 = M1;
+ v33 = _mm_mul_epu32(v33, T14);
+ T4 = _mm_add_epi64(T4, v41);
+ v42 = M2;
+ v42 = _mm_mul_epu32(v42, T14);
+ T1 = _mm_add_epi64(T1, v14);
+ T15 = R23;
+ v24 = M0;
+ v24 = _mm_mul_epu32(v24, T14);
+ T2 = _mm_add_epi64(T2, v23);
+ v34 = M0;
+ v34 = _mm_mul_epu32(v34, T15);
+ T3 = _mm_add_epi64(T3, v33);
+ v43 = M1;
+ v43 = _mm_mul_epu32(v43, T15);
+ T4 = _mm_add_epi64(T4, v42);
+ v44 = M0;
+ v44 = _mm_mul_epu32(v44, R24);
+ T2 = _mm_add_epi64(T2, v24);
+ T3 = _mm_add_epi64(T3, v34);
+ T4 = _mm_add_epi64(T4, v43);
+ T4 = _mm_add_epi64(T4, v44);
+
+ /* reduce */
+ C1 = _mm_srli_epi64(T0, 26);
+ C2 = _mm_srli_epi64(T3, 26);
+ T0 = _mm_and_si128(T0, MMASK);
+ T3 = _mm_and_si128(T3, MMASK);
+ T1 = _mm_add_epi64(T1, C1);
+ T4 = _mm_add_epi64(T4, C2);
+ C1 = _mm_srli_epi64(T1, 26);
+ C2 = _mm_srli_epi64(T4, 26);
+ T1 = _mm_and_si128(T1, MMASK);
+ T4 = _mm_and_si128(T4, MMASK);
+ T2 = _mm_add_epi64(T2, C1);
+ T0 = _mm_add_epi64(T0, _mm_mul_epu32(C2, FIVE));
+ C1 = _mm_srli_epi64(T2, 26);
+ C2 = _mm_srli_epi64(T0, 26);
+ T2 = _mm_and_si128(T2, MMASK);
+ T0 = _mm_and_si128(T0, MMASK);
+ T3 = _mm_add_epi64(T3, C1);
+ T1 = _mm_add_epi64(T1, C2);
+ C1 = _mm_srli_epi64(T3, 26);
+ T3 = _mm_and_si128(T3, MMASK);
+ T4 = _mm_add_epi64(T4, C1);
+
+ /* Final: H = (H*[r^4,r^4] + [Mx,My]*[r^2,r^2] + [Mx',My']) */
+ H0 = T0;
+ H1 = T1;
+ H2 = T2;
+ H3 = T3;
+ H4 = T4;
+
+ m += 64;
+ bytes -= 64;
+ }
+ }
+
+ if (bytes >= 32) {
+ xmmi v01, v02, v03, v04;
+ xmmi v11, v12, v13, v14;
+ xmmi v21, v22, v23, v24;
+ xmmi v31, v32, v33, v34;
+ xmmi v41, v42, v43, v44;
+ xmmi T14, T15;
+
+ /* H *= [r^2,r^2] */
+ T15 = S22;
+ T0 = H4;
+ T0 = _mm_mul_epu32(T0, S21);
+ v01 = H3;
+ v01 = _mm_mul_epu32(v01, T15);
+ T14 = S23;
+ T1 = H4;
+ T1 = _mm_mul_epu32(T1, T15);
+ v11 = H3;
+ v11 = _mm_mul_epu32(v11, T14);
+ T2 = H4;
+ T2 = _mm_mul_epu32(T2, T14);
+ T0 = _mm_add_epi64(T0, v01);
+ T15 = S24;
+ v02 = H2;
+ v02 = _mm_mul_epu32(v02, T14);
+ T3 = H4;
+ T3 = _mm_mul_epu32(T3, T15);
+ T1 = _mm_add_epi64(T1, v11);
+ v03 = H1;
+ v03 = _mm_mul_epu32(v03, T15);
+ v12 = H2;
+ v12 = _mm_mul_epu32(v12, T15);
+ T0 = _mm_add_epi64(T0, v02);
+ T14 = R20;
+ v21 = H3;
+ v21 = _mm_mul_epu32(v21, T15);
+ v31 = H3;
+ v31 = _mm_mul_epu32(v31, T14);
+ T0 = _mm_add_epi64(T0, v03);
+ T4 = H4;
+ T4 = _mm_mul_epu32(T4, T14);
+ T1 = _mm_add_epi64(T1, v12);
+ v04 = H0;
+ v04 = _mm_mul_epu32(v04, T14);
+ T2 = _mm_add_epi64(T2, v21);
+ v13 = H1;
+ v13 = _mm_mul_epu32(v13, T14);
+ T3 = _mm_add_epi64(T3, v31);
+ T15 = R21;
+ v22 = H2;
+ v22 = _mm_mul_epu32(v22, T14);
+ v32 = H2;
+ v32 = _mm_mul_epu32(v32, T15);
+ T0 = _mm_add_epi64(T0, v04);
+ v41 = H3;
+ v41 = _mm_mul_epu32(v41, T15);
+ T1 = _mm_add_epi64(T1, v13);
+ v14 = H0;
+ v14 = _mm_mul_epu32(v14, T15);
+ T2 = _mm_add_epi64(T2, v22);
+ T14 = R22;
+ v23 = H1;
+ v23 = _mm_mul_epu32(v23, T15);
+ T3 = _mm_add_epi64(T3, v32);
+ v33 = H1;
+ v33 = _mm_mul_epu32(v33, T14);
+ T4 = _mm_add_epi64(T4, v41);
+ v42 = H2;
+ v42 = _mm_mul_epu32(v42, T14);
+ T1 = _mm_add_epi64(T1, v14);
+ T15 = R23;
+ v24 = H0;
+ v24 = _mm_mul_epu32(v24, T14);
+ T2 = _mm_add_epi64(T2, v23);
+ v34 = H0;
+ v34 = _mm_mul_epu32(v34, T15);
+ T3 = _mm_add_epi64(T3, v33);
+ v43 = H1;
+ v43 = _mm_mul_epu32(v43, T15);
+ T4 = _mm_add_epi64(T4, v42);
+ v44 = H0;
+ v44 = _mm_mul_epu32(v44, R24);
+ T2 = _mm_add_epi64(T2, v24);
+ T3 = _mm_add_epi64(T3, v34);
+ T4 = _mm_add_epi64(T4, v43);
+ T4 = _mm_add_epi64(T4, v44);
+
+ /* H += [Mx,My] */
+ if (m) {
+ T5 = _mm_loadu_si128((const xmmi *) (const void *) (m + 0));
+ T6 = _mm_loadu_si128((const xmmi *) (const void *) (m + 16));
+ T7 = _mm_unpacklo_epi32(T5, T6);
+ T8 = _mm_unpackhi_epi32(T5, T6);
+ M0 = _mm_unpacklo_epi32(T7, _mm_setzero_si128());
+ M1 = _mm_unpackhi_epi32(T7, _mm_setzero_si128());
+ M2 = _mm_unpacklo_epi32(T8, _mm_setzero_si128());
+ M3 = _mm_unpackhi_epi32(T8, _mm_setzero_si128());
+ M1 = _mm_slli_epi64(M1, 6);
+ M2 = _mm_slli_epi64(M2, 12);
+ M3 = _mm_slli_epi64(M3, 18);
+ T0 = _mm_add_epi64(T0, M0);
+ T1 = _mm_add_epi64(T1, M1);
+ T2 = _mm_add_epi64(T2, M2);
+ T3 = _mm_add_epi64(T3, M3);
+ T4 = _mm_add_epi64(T4, HIBIT);
+ }
+
+ /* reduce */
+ C1 = _mm_srli_epi64(T0, 26);
+ C2 = _mm_srli_epi64(T3, 26);
+ T0 = _mm_and_si128(T0, MMASK);
+ T3 = _mm_and_si128(T3, MMASK);
+ T1 = _mm_add_epi64(T1, C1);
+ T4 = _mm_add_epi64(T4, C2);
+ C1 = _mm_srli_epi64(T1, 26);
+ C2 = _mm_srli_epi64(T4, 26);
+ T1 = _mm_and_si128(T1, MMASK);
+ T4 = _mm_and_si128(T4, MMASK);
+ T2 = _mm_add_epi64(T2, C1);
+ T0 = _mm_add_epi64(T0, _mm_mul_epu32(C2, FIVE));
+ C1 = _mm_srli_epi64(T2, 26);
+ C2 = _mm_srli_epi64(T0, 26);
+ T2 = _mm_and_si128(T2, MMASK);
+ T0 = _mm_and_si128(T0, MMASK);
+ T3 = _mm_add_epi64(T3, C1);
+ T1 = _mm_add_epi64(T1, C2);
+ C1 = _mm_srli_epi64(T3, 26);
+ T3 = _mm_and_si128(T3, MMASK);
+ T4 = _mm_add_epi64(T4, C1);
+
+ /* H = (H*[r^2,r^2] + [Mx,My]) */
+ H0 = T0;
+ H1 = T1;
+ H2 = T2;
+ H3 = T3;
+ H4 = T4;
+ }
+
+ if (m) {
+ T0 = _mm_shuffle_epi32(H0, _MM_SHUFFLE(0, 0, 2, 0));
+ T1 = _mm_shuffle_epi32(H1, _MM_SHUFFLE(0, 0, 2, 0));
+ T2 = _mm_shuffle_epi32(H2, _MM_SHUFFLE(0, 0, 2, 0));
+ T3 = _mm_shuffle_epi32(H3, _MM_SHUFFLE(0, 0, 2, 0));
+ T4 = _mm_shuffle_epi32(H4, _MM_SHUFFLE(0, 0, 2, 0));
+ T0 = _mm_unpacklo_epi64(T0, T1);
+ T1 = _mm_unpacklo_epi64(T2, T3);
+ _mm_storeu_si128((xmmi *) (void *) &st->H.hh[0], T0);
+ _mm_storeu_si128((xmmi *) (void *) &st->H.hh[4], T1);
+ _mm_storel_epi64((xmmi *) (void *) &st->H.hh[8], T4);
+ } else {
+ uint32_t t0, t1, t2, t3, t4, b;
+ uint64_t h0, h1, h2, g0, g1, g2, c, nc;
+
+ /* H = H[0]+H[1] */
+ T0 = H0;
+ T1 = H1;
+ T2 = H2;
+ T3 = H3;
+ T4 = H4;
+
+ T0 = _mm_add_epi64(T0, _mm_srli_si128(T0, 8));
+ T1 = _mm_add_epi64(T1, _mm_srli_si128(T1, 8));
+ T2 = _mm_add_epi64(T2, _mm_srli_si128(T2, 8));
+ T3 = _mm_add_epi64(T3, _mm_srli_si128(T3, 8));
+ T4 = _mm_add_epi64(T4, _mm_srli_si128(T4, 8));
+
+ t0 = _mm_cvtsi128_si32(T0);
+ b = (t0 >> 26);
+ t0 &= 0x3ffffff;
+ t1 = _mm_cvtsi128_si32(T1) + b;
+ b = (t1 >> 26);
+ t1 &= 0x3ffffff;
+ t2 = _mm_cvtsi128_si32(T2) + b;
+ b = (t2 >> 26);
+ t2 &= 0x3ffffff;
+ t3 = _mm_cvtsi128_si32(T3) + b;
+ b = (t3 >> 26);
+ t3 &= 0x3ffffff;
+ t4 = _mm_cvtsi128_si32(T4) + b;
+
+ /* everything except t4 is in range, so this is all safe */
+ h0 = (((uint64_t) t0) | ((uint64_t) t1 << 26)) & 0xfffffffffffull;
+ h1 = (((uint64_t) t1 >> 18) | ((uint64_t) t2 << 8) |
+ ((uint64_t) t3 << 34)) &
+ 0xfffffffffffull;
+ h2 = (((uint64_t) t3 >> 10) | ((uint64_t) t4 << 16));
+
+ c = (h2 >> 42);
+ h2 &= 0x3ffffffffff;
+ h0 += c * 5;
+ c = (h0 >> 44);
+ h0 &= 0xfffffffffff;
+ h1 += c;
+ c = (h1 >> 44);
+ h1 &= 0xfffffffffff;
+ h2 += c;
+ c = (h2 >> 42);
+ h2 &= 0x3ffffffffff;
+ h0 += c * 5;
+ c = (h0 >> 44);
+ h0 &= 0xfffffffffff;
+ h1 += c;
+
+ g0 = h0 + 5;
+ c = (g0 >> 44);
+ g0 &= 0xfffffffffff;
+ g1 = h1 + c;
+ c = (g1 >> 44);
+ g1 &= 0xfffffffffff;
+ g2 = h2 + c - ((uint64_t) 1 << 42);
+
+ c = (g2 >> 63) - 1;
+ nc = ~c;
+ h0 = (h0 & nc) | (g0 & c);
+ h1 = (h1 & nc) | (g1 & c);
+ h2 = (h2 & nc) | (g2 & c);
+
+ st->H.h[0] = h0;
+ st->H.h[1] = h1;
+ st->H.h[2] = h2;
+ }
+}
+
+static void
+poly1305_update(poly1305_state_internal_t *st, const unsigned char *m,
+ unsigned long long bytes)
+{
+ unsigned long long i;
+
+ /* handle leftover */
+ if (st->leftover) {
+ unsigned long long want = (poly1305_block_size - st->leftover);
+
+ if (want > bytes) {
+ want = bytes;
+ }
+ for (i = 0; i < want; i++) {
+ st->buffer[st->leftover + i] = m[i];
+ }
+ bytes -= want;
+ m += want;
+ st->leftover += want;
+ if (st->leftover < poly1305_block_size) {
+ return;
+ }
+ poly1305_blocks(st, st->buffer, poly1305_block_size);
+ st->leftover = 0;
+ }
+
+ /* process full blocks */
+ if (bytes >= poly1305_block_size) {
+ unsigned long long want = (bytes & ~(poly1305_block_size - 1));
+
+ poly1305_blocks(st, m, want);
+ m += want;
+ bytes -= want;
+ }
+
+ /* store leftover */
+ if (bytes) {
+ for (i = 0; i < bytes; i++) {
+ st->buffer[st->leftover + i] = m[i];
+ }
+ st->leftover += bytes;
+ }
+}
+
+static POLY1305_NOINLINE void
+poly1305_finish_ext(poly1305_state_internal_t *st, const unsigned char *m,
+ unsigned long long leftover, unsigned char mac[16])
+{
+ uint64_t h0, h1, h2;
+
+ if (leftover) {
+ CRYPTO_ALIGN(16) unsigned char final[32] = { 0 };
+
+ poly1305_block_copy31(final, m, leftover);
+ if (leftover != 16) {
+ final[leftover] = 1;
+ }
+ st->flags |=
+ (leftover >= 16) ? poly1305_final_shift8 : poly1305_final_shift16;
+ poly1305_blocks(st, final, 32);
+ }
+
+ if (st->flags & poly1305_started) {
+ /* finalize, H *= [r^2,r], or H *= [r,1] */
+ if (!leftover || (leftover > 16)) {
+ st->flags |= poly1305_final_r2_r;
+ } else {
+ st->flags |= poly1305_final_r_1;
+ }
+ poly1305_blocks(st, NULL, 32);
+ }
+
+ h0 = st->H.h[0];
+ h1 = st->H.h[1];
+ h2 = st->H.h[2];
+
+ /* pad */
+ h0 = ((h0) | (h1 << 44));
+ h1 = ((h1 >> 20) | (h2 << 24));
+#ifdef HAVE_AMD64_ASM
+ __asm__ __volatile__(
+ "addq %2, %0 ;\n"
+ "adcq %3, %1 ;\n"
+ : "+r"(h0), "+r"(h1)
+ : "r"(st->pad[0]), "r"(st->pad[1])
+ : "flags", "cc");
+#else
+ {
+ uint128_t h;
+
+ memcpy(&h, &st->pad[0], 16);
+ h += ((uint128_t) h1 << 64) | h0;
+ h0 = (uint64_t) h;
+ h1 = (uint64_t)(h >> 64);
+ }
+#endif
+ _mm_storeu_si128((xmmi *) (void *) st + 0, _mm_setzero_si128());
+ _mm_storeu_si128((xmmi *) (void *) st + 1, _mm_setzero_si128());
+ _mm_storeu_si128((xmmi *) (void *) st + 2, _mm_setzero_si128());
+ _mm_storeu_si128((xmmi *) (void *) st + 3, _mm_setzero_si128());
+ _mm_storeu_si128((xmmi *) (void *) st + 4, _mm_setzero_si128());
+ _mm_storeu_si128((xmmi *) (void *) st + 5, _mm_setzero_si128());
+ _mm_storeu_si128((xmmi *) (void *) st + 6, _mm_setzero_si128());
+ _mm_storeu_si128((xmmi *) (void *) st + 7, _mm_setzero_si128());
+
+ memcpy(&mac[0], &h0, 8);
+ memcpy(&mac[8], &h1, 8);
+
+ sodium_memzero((void *) st, sizeof *st);
+}
+
+static void
+poly1305_finish(poly1305_state_internal_t *st, unsigned char mac[16])
+{
+ poly1305_finish_ext(st, st->buffer, st->leftover, mac);
+}
+
+static int
+crypto_onetimeauth_poly1305_sse2_init(crypto_onetimeauth_poly1305_state *state,
+ const unsigned char *key)
+{
+ COMPILER_ASSERT(sizeof(crypto_onetimeauth_poly1305_state) >=
+ sizeof(poly1305_state_internal_t));
+ poly1305_init_ext((poly1305_state_internal_t *) (void *) state, key, 0U);
+
+ return 0;
+}
+
+static int
+crypto_onetimeauth_poly1305_sse2_update(
+ crypto_onetimeauth_poly1305_state *state, const unsigned char *in,
+ unsigned long long inlen)
+{
+ poly1305_update((poly1305_state_internal_t *) (void *) state, in, inlen);
+
+ return 0;
+}
+
+static int
+crypto_onetimeauth_poly1305_sse2_final(crypto_onetimeauth_poly1305_state *state,
+ unsigned char *out)
+{
+ poly1305_finish((poly1305_state_internal_t *) (void *) state, out);
+
+ return 0;
+}
+
+static int
+crypto_onetimeauth_poly1305_sse2(unsigned char *out, const unsigned char *m,
+ unsigned long long inlen,
+ const unsigned char *key)
+{
+ CRYPTO_ALIGN(64) poly1305_state_internal_t st;
+ unsigned long long blocks;
+
+ poly1305_init_ext(&st, key, inlen);
+ blocks = inlen & ~31;
+ if (blocks > 0) {
+ poly1305_blocks(&st, m, blocks);
+ m += blocks;
+ inlen -= blocks;
+ }
+ poly1305_finish_ext(&st, m, inlen, out);
+
+ return 0;
+}
+
+static int
+crypto_onetimeauth_poly1305_sse2_verify(const unsigned char *h,
+ const unsigned char *in,
+ unsigned long long inlen,
+ const unsigned char *k)
+{
+ unsigned char correct[16];
+
+ crypto_onetimeauth_poly1305_sse2(correct, in, inlen, k);
+
+ return crypto_verify_16(h, correct);
+}
+
+struct crypto_onetimeauth_poly1305_implementation
+ crypto_onetimeauth_poly1305_sse2_implementation = {
+ SODIUM_C99(.onetimeauth =) crypto_onetimeauth_poly1305_sse2,
+ SODIUM_C99(.onetimeauth_verify =)
+ crypto_onetimeauth_poly1305_sse2_verify,
+ SODIUM_C99(.onetimeauth_init =) crypto_onetimeauth_poly1305_sse2_init,
+ SODIUM_C99(.onetimeauth_update =)
+ crypto_onetimeauth_poly1305_sse2_update,
+ SODIUM_C99(.onetimeauth_final =) crypto_onetimeauth_poly1305_sse2_final
+ };
+
+#endif
diff --git a/libs/libsodium/src/crypto_onetimeauth/poly1305/sse2/poly1305_sse2.h b/libs/libsodium/src/crypto_onetimeauth/poly1305/sse2/poly1305_sse2.h
new file mode 100644
index 0000000000..9177cad487
--- /dev/null
+++ b/libs/libsodium/src/crypto_onetimeauth/poly1305/sse2/poly1305_sse2.h
@@ -0,0 +1,12 @@
+#ifndef poly1305_sse2_H
+#define poly1305_sse2_H
+
+#include <stddef.h>
+
+#include "../onetimeauth_poly1305.h"
+#include "crypto_onetimeauth_poly1305.h"
+
+extern struct crypto_onetimeauth_poly1305_implementation
+ crypto_onetimeauth_poly1305_sse2_implementation;
+
+#endif /* poly1305_sse2_H */
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2-core.c b/libs/libsodium/src/crypto_pwhash/argon2/argon2-core.c
new file mode 100644
index 0000000000..b52b04d36d
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2-core.c
@@ -0,0 +1,549 @@
+/*
+ * Argon2 source code package
+ *
+ * Written by Daniel Dinu and Dmitry Khovratovich, 2015
+ *
+ * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication along
+ * with
+ * this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+
+#include "crypto_generichash_blake2b.h"
+#include "private/common.h"
+#include "private/implementations.h"
+#include "runtime.h"
+#include "utils.h"
+
+#include "argon2-core.h"
+#include "blake2b-long.h"
+
+#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
+# define MAP_ANON MAP_ANONYMOUS
+#endif
+#ifndef MAP_NOCORE
+# define MAP_NOCORE 0
+#endif
+#ifndef MAP_POPULATE
+# define MAP_POPULATE 0
+#endif
+
+static fill_segment_fn fill_segment = fill_segment_ref;
+
+static void
+load_block(block *dst, const void *input)
+{
+ unsigned i;
+ for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
+ dst->v[i] = LOAD64_LE((const uint8_t *) input + i * sizeof(dst->v[i]));
+ }
+}
+
+static void
+store_block(void *output, const block *src)
+{
+ unsigned i;
+ for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
+ STORE64_LE((uint8_t *) output + i * sizeof(src->v[i]), src->v[i]);
+ }
+}
+
+/***************Memory allocators*****************/
+/* Allocates memory to the given pointer
+ * @param memory pointer to the pointer to the memory
+ * @param m_cost number of blocks to allocate in the memory
+ * @return ARGON2_OK if @memory is a valid pointer and memory is allocated
+ */
+static int allocate_memory(block_region **memory, uint32_t m_cost);
+
+static int
+allocate_memory(block_region **region, uint32_t m_cost)
+{
+ void * base;
+ block *memory;
+ size_t memory_size;
+
+ if (region == NULL) {
+ return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
+ }
+ memory_size = sizeof(block) * m_cost;
+ if (m_cost == 0 ||
+ memory_size / m_cost !=
+ sizeof(block)) { /*1. Check for multiplication overflow*/
+ return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
+ }
+ *region = (block_region *) malloc(
+ sizeof(block_region)); /*2. Try to allocate region*/
+ if (!*region) {
+ return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
+ }
+ (*region)->base = (*region)->memory = NULL;
+
+#if defined(MAP_ANON) && defined(HAVE_MMAP)
+ if ((base = mmap(NULL, memory_size, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE | MAP_NOCORE | MAP_POPULATE,
+ -1, 0)) == MAP_FAILED) {
+ base = NULL; /* LCOV_EXCL_LINE */
+ } /* LCOV_EXCL_LINE */
+ memcpy(&memory, &base, sizeof memory);
+#elif defined(HAVE_POSIX_MEMALIGN)
+ if ((errno = posix_memalign((void **) &base, 64, memory_size)) != 0) {
+ base = NULL;
+ }
+ memcpy(&memory, &base, sizeof memory);
+#else
+ memory = NULL;
+ if (memory_size + 63 < memory_size) {
+ base = NULL;
+ errno = ENOMEM;
+ } else if ((base = malloc(memory_size + 63)) != NULL) {
+ uint8_t *aligned = ((uint8_t *) base) + 63;
+ aligned -= (uintptr_t) aligned & 63;
+ memcpy(&memory, &aligned, sizeof memory);
+ }
+#endif
+ if (base == NULL) {
+ return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
+ }
+ (*region)->base = base;
+ (*region)->memory = memory;
+ (*region)->size = memory_size;
+
+ return ARGON2_OK;
+}
+
+/*********Memory functions*/
+
+/* Clears memory
+ * @param instance pointer to the current instance
+ * @param clear_memory indicates if we clear the memory with zeros.
+ */
+static void clear_memory(argon2_instance_t *instance, int clear);
+
+static void
+clear_memory(argon2_instance_t *instance, int clear)
+{
+ /* LCOV_EXCL_START */
+ if (clear) {
+ if (instance->region != NULL) {
+ sodium_memzero(instance->region->memory,
+ sizeof(block) * instance->memory_blocks);
+ }
+ if (instance->pseudo_rands != NULL) {
+ sodium_memzero(instance->pseudo_rands,
+ sizeof(uint64_t) * instance->segment_length);
+ }
+ }
+ /* LCOV_EXCL_STOP */
+}
+
+/* Deallocates memory
+ * @param memory pointer to the blocks
+ */
+static void free_memory(block_region *memory);
+
+static void
+free_memory(block_region *region)
+{
+ if (region && region->base) {
+#if defined(MAP_ANON) && defined(HAVE_MMAP)
+ if (munmap(region->base, region->size)) {
+ return; /* LCOV_EXCL_LINE */
+ }
+#else
+ free(region->base);
+#endif
+ }
+ free(region);
+}
+
+void
+free_instance(argon2_instance_t *instance, int flags)
+{
+ /* Clear memory */
+ clear_memory(instance, flags & ARGON2_FLAG_CLEAR_MEMORY);
+
+ /* Deallocate the memory */
+ free(instance->pseudo_rands);
+ instance->pseudo_rands = NULL;
+ free_memory(instance->region);
+ instance->region = NULL;
+}
+
+void
+finalize(const argon2_context *context, argon2_instance_t *instance)
+{
+ if (context != NULL && instance != NULL) {
+ block blockhash;
+ uint32_t l;
+
+ copy_block(&blockhash,
+ instance->region->memory + instance->lane_length - 1);
+
+ /* XOR the last blocks */
+ for (l = 1; l < instance->lanes; ++l) {
+ uint32_t last_block_in_lane =
+ l * instance->lane_length + (instance->lane_length - 1);
+ xor_block(&blockhash,
+ instance->region->memory + last_block_in_lane);
+ }
+
+ /* Hash the result */
+ {
+ uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
+ store_block(blockhash_bytes, &blockhash);
+ blake2b_long(context->out, context->outlen, blockhash_bytes,
+ ARGON2_BLOCK_SIZE);
+ sodium_memzero(blockhash.v,
+ ARGON2_BLOCK_SIZE); /* clear blockhash */
+ sodium_memzero(blockhash_bytes,
+ ARGON2_BLOCK_SIZE); /* clear blockhash_bytes */
+ }
+
+ free_instance(instance, context->flags);
+ }
+}
+
+void
+fill_memory_blocks(argon2_instance_t *instance, uint32_t pass)
+{
+ argon2_position_t position;
+ uint32_t l;
+ uint32_t s;
+
+ if (instance == NULL || instance->lanes == 0) {
+ return; /* LCOV_EXCL_LINE */
+ }
+
+ position.pass = pass;
+ for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
+ position.slice = (uint8_t) s;
+ for (l = 0; l < instance->lanes; ++l) {
+ position.lane = l;
+ position.index = 0;
+ fill_segment(instance, position);
+ }
+ }
+}
+
+int
+validate_inputs(const argon2_context *context)
+{
+ /* LCOV_EXCL_START */
+ if (NULL == context) {
+ return ARGON2_INCORRECT_PARAMETER;
+ }
+
+ if (NULL == context->out) {
+ return ARGON2_OUTPUT_PTR_NULL;
+ }
+
+ /* Validate output length */
+ if (ARGON2_MIN_OUTLEN > context->outlen) {
+ return ARGON2_OUTPUT_TOO_SHORT;
+ }
+
+ if (ARGON2_MAX_OUTLEN < context->outlen) {
+ return ARGON2_OUTPUT_TOO_LONG;
+ }
+
+ /* Validate password (required param) */
+ if (NULL == context->pwd) {
+ if (0 != context->pwdlen) {
+ return ARGON2_PWD_PTR_MISMATCH;
+ }
+ }
+
+ if (ARGON2_MIN_PWD_LENGTH > context->pwdlen) {
+ return ARGON2_PWD_TOO_SHORT;
+ }
+
+ if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) {
+ return ARGON2_PWD_TOO_LONG;
+ }
+
+ /* Validate salt (required param) */
+ if (NULL == context->salt) {
+ if (0 != context->saltlen) {
+ return ARGON2_SALT_PTR_MISMATCH;
+ }
+ }
+
+ if (ARGON2_MIN_SALT_LENGTH > context->saltlen) {
+ return ARGON2_SALT_TOO_SHORT;
+ }
+
+ if (ARGON2_MAX_SALT_LENGTH < context->saltlen) {
+ return ARGON2_SALT_TOO_LONG;
+ }
+
+ /* Validate secret (optional param) */
+ if (NULL == context->secret) {
+ if (0 != context->secretlen) {
+ return ARGON2_SECRET_PTR_MISMATCH;
+ }
+ } else {
+ if (ARGON2_MIN_SECRET > context->secretlen) {
+ return ARGON2_SECRET_TOO_SHORT;
+ }
+
+ if (ARGON2_MAX_SECRET < context->secretlen) {
+ return ARGON2_SECRET_TOO_LONG;
+ }
+ }
+
+ /* Validate associated data (optional param) */
+ if (NULL == context->ad) {
+ if (0 != context->adlen) {
+ return ARGON2_AD_PTR_MISMATCH;
+ }
+ } else {
+ if (ARGON2_MIN_AD_LENGTH > context->adlen) {
+ return ARGON2_AD_TOO_SHORT;
+ }
+
+ if (ARGON2_MAX_AD_LENGTH < context->adlen) {
+ return ARGON2_AD_TOO_LONG;
+ }
+ }
+
+ /* Validate memory cost */
+ if (ARGON2_MIN_MEMORY > context->m_cost) {
+ return ARGON2_MEMORY_TOO_LITTLE;
+ }
+
+ if (ARGON2_MAX_MEMORY < context->m_cost) {
+ return ARGON2_MEMORY_TOO_MUCH;
+ }
+
+ if (context->m_cost < 8 * context->lanes) {
+ return ARGON2_MEMORY_TOO_LITTLE;
+ }
+
+ /* Validate time cost */
+ if (ARGON2_MIN_TIME > context->t_cost) {
+ return ARGON2_TIME_TOO_SMALL;
+ }
+
+ if (ARGON2_MAX_TIME < context->t_cost) {
+ return ARGON2_TIME_TOO_LARGE;
+ }
+
+ /* Validate lanes */
+ if (ARGON2_MIN_LANES > context->lanes) {
+ return ARGON2_LANES_TOO_FEW;
+ }
+
+ if (ARGON2_MAX_LANES < context->lanes) {
+ return ARGON2_LANES_TOO_MANY;
+ }
+
+ /* Validate threads */
+ if (ARGON2_MIN_THREADS > context->threads) {
+ return ARGON2_THREADS_TOO_FEW;
+ }
+
+ if (ARGON2_MAX_THREADS < context->threads) {
+ return ARGON2_THREADS_TOO_MANY;
+ }
+ /* LCOV_EXCL_STOP */
+
+ return ARGON2_OK;
+}
+
+void
+fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance)
+{
+ uint32_t l;
+ /* Make the first and second block in each lane as G(H0||i||0) or
+ G(H0||i||1) */
+ uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
+ for (l = 0; l < instance->lanes; ++l) {
+ STORE32_LE(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
+ STORE32_LE(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l);
+ blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
+ ARGON2_PREHASH_SEED_LENGTH);
+ load_block(&instance->region->memory[l * instance->lane_length + 0],
+ blockhash_bytes);
+
+ STORE32_LE(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
+ blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
+ ARGON2_PREHASH_SEED_LENGTH);
+ load_block(&instance->region->memory[l * instance->lane_length + 1],
+ blockhash_bytes);
+ }
+ sodium_memzero(blockhash_bytes, ARGON2_BLOCK_SIZE);
+}
+
+void
+initial_hash(uint8_t *blockhash, argon2_context *context, argon2_type type)
+{
+ crypto_generichash_blake2b_state BlakeHash;
+ uint8_t value[4U /* sizeof(uint32_t) */];
+
+ if (NULL == context || NULL == blockhash) {
+ return; /* LCOV_EXCL_LINE */
+ }
+
+ crypto_generichash_blake2b_init(&BlakeHash, NULL, 0U,
+ ARGON2_PREHASH_DIGEST_LENGTH);
+
+ STORE32_LE(value, context->lanes);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ STORE32_LE(value, context->outlen);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ STORE32_LE(value, context->m_cost);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ STORE32_LE(value, context->t_cost);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ STORE32_LE(value, ARGON2_VERSION_NUMBER);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ STORE32_LE(value, (uint32_t) type);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ STORE32_LE(value, context->pwdlen);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ if (context->pwd != NULL) {
+ crypto_generichash_blake2b_update(
+ &BlakeHash, (const uint8_t *) context->pwd, context->pwdlen);
+
+ /* LCOV_EXCL_START */
+ if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
+ sodium_memzero(context->pwd, context->pwdlen);
+ context->pwdlen = 0;
+ }
+ /* LCOV_EXCL_STOP */
+ }
+
+ STORE32_LE(value, context->saltlen);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ if (context->salt != NULL) {
+ crypto_generichash_blake2b_update(
+ &BlakeHash, (const uint8_t *) context->salt, context->saltlen);
+ }
+
+ STORE32_LE(value, context->secretlen);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ /* LCOV_EXCL_START */
+ if (context->secret != NULL) {
+ crypto_generichash_blake2b_update(
+ &BlakeHash, (const uint8_t *) context->secret, context->secretlen);
+
+ if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
+ sodium_memzero(context->secret, context->secretlen);
+ context->secretlen = 0;
+ }
+ }
+ /* LCOV_EXCL_STOP */
+
+ STORE32_LE(value, context->adlen);
+ crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
+
+ /* LCOV_EXCL_START */
+ if (context->ad != NULL) {
+ crypto_generichash_blake2b_update(
+ &BlakeHash, (const uint8_t *) context->ad, context->adlen);
+ }
+ /* LCOV_EXCL_STOP */
+
+ crypto_generichash_blake2b_final(&BlakeHash, blockhash,
+ ARGON2_PREHASH_DIGEST_LENGTH);
+}
+
+int
+initialize(argon2_instance_t *instance, argon2_context *context)
+{
+ uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
+ int result = ARGON2_OK;
+
+ if (instance == NULL || context == NULL) {
+ return ARGON2_INCORRECT_PARAMETER;
+ }
+
+ /* 1. Memory allocation */
+
+ if ((instance->pseudo_rands = (uint64_t *)
+ malloc(sizeof(uint64_t) * instance->segment_length)) == NULL) {
+ return ARGON2_MEMORY_ALLOCATION_ERROR;
+ }
+
+ result = allocate_memory(&(instance->region), instance->memory_blocks);
+ if (ARGON2_OK != result) {
+ free_instance(instance, context->flags);
+ return result;
+ }
+
+ /* 2. Initial hashing */
+ /* H_0 + 8 extra bytes to produce the first blocks */
+ /* uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; */
+ /* Hashing all inputs */
+ initial_hash(blockhash, context, instance->type);
+ /* Zeroing 8 extra bytes */
+ sodium_memzero(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
+ ARGON2_PREHASH_SEED_LENGTH - ARGON2_PREHASH_DIGEST_LENGTH);
+
+ /* 3. Creating first blocks, we always have at least two blocks in a slice
+ */
+ fill_first_blocks(blockhash, instance);
+ /* Clearing the hash */
+ sodium_memzero(blockhash, ARGON2_PREHASH_SEED_LENGTH);
+
+ return ARGON2_OK;
+}
+
+int
+argon2_pick_best_implementation(void)
+{
+/* LCOV_EXCL_START */
+#if defined(HAVE_AVX512FINTRIN_H) && defined(HAVE_AVX2INTRIN_H) && \
+ defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)
+ if (sodium_runtime_has_avx512f()) {
+ fill_segment = fill_segment_avx512f;
+ return 0;
+ }
+#endif
+#if defined(HAVE_AVX2INTRIN_H) && defined(HAVE_TMMINTRIN_H) && \
+ defined(HAVE_SMMINTRIN_H)
+ if (sodium_runtime_has_avx2()) {
+ fill_segment = fill_segment_avx2;
+ return 0;
+ }
+#endif
+#if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)
+ if (sodium_runtime_has_ssse3()) {
+ fill_segment = fill_segment_ssse3;
+ return 0;
+ }
+#endif
+ fill_segment = fill_segment_ref;
+
+ return 0;
+ /* LCOV_EXCL_STOP */
+}
+
+int
+_crypto_pwhash_argon2_pick_best_implementation(void)
+{
+ return argon2_pick_best_implementation();
+}
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2-core.h b/libs/libsodium/src/crypto_pwhash/argon2/argon2-core.h
new file mode 100644
index 0000000000..caab103891
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2-core.h
@@ -0,0 +1,297 @@
+/*
+ * Argon2 source code package
+ *
+ * Written by Daniel Dinu and Dmitry Khovratovich, 2015
+ *
+ * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication along
+ * with
+ * this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef argon2_core_H
+#define argon2_core_H
+
+#include <string.h>
+
+#include "argon2.h"
+
+/*************************Argon2 internal
+ * constants**************************************************/
+
+enum argon2_ctx_constants {
+ /* Version of the algorithm */
+ ARGON2_VERSION_NUMBER = 0x13,
+
+ /* Memory block size in bytes */
+ ARGON2_BLOCK_SIZE = 1024,
+ ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8,
+ ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16,
+ ARGON2_HWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 32,
+ ARGON2_512BIT_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 64,
+
+ /* Number of pseudo-random values generated by one call to Blake in Argon2i
+ to
+ generate reference block positions */
+ ARGON2_ADDRESSES_IN_BLOCK = 128,
+
+ /* Pre-hashing digest length and its extension*/
+ ARGON2_PREHASH_DIGEST_LENGTH = 64,
+ ARGON2_PREHASH_SEED_LENGTH = 72
+};
+
+/*************************Argon2 internal data
+ * types**************************************************/
+
+/*
+ * Structure for the (1KB) memory block implemented as 128 64-bit words.
+ * Memory blocks can be copied, XORed. Internal words can be accessed by [] (no
+ * bounds checking).
+ */
+typedef struct block_ {
+ uint64_t v[ARGON2_QWORDS_IN_BLOCK];
+} block;
+
+typedef struct block_region_ {
+ void * base;
+ block *memory;
+ size_t size;
+} block_region;
+
+/*****************Functions that work with the block******************/
+
+/* Initialize each byte of the block with @in */
+static inline void
+init_block_value(block *b, uint8_t in)
+{
+ memset(b->v, in, sizeof(b->v));
+}
+
+/* Copy block @src to block @dst */
+static inline void
+copy_block(block *dst, const block *src)
+{
+ memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK);
+}
+
+/* XOR @src onto @dst bytewise */
+static inline void
+xor_block(block *dst, const block *src)
+{
+ int i;
+ for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
+ dst->v[i] ^= src->v[i];
+ }
+}
+
+/*
+ * Argon2 instance: memory pointer, number of passes, amount of memory, type,
+ * and derived values.
+ * Used to evaluate the number and location of blocks to construct in each
+ * thread
+ */
+typedef struct Argon2_instance_t {
+ block_region *region; /* Memory region pointer */
+ uint64_t *pseudo_rands;
+ uint32_t passes; /* Number of passes */
+ uint32_t current_pass;
+ uint32_t memory_blocks; /* Number of blocks in memory */
+ uint32_t segment_length;
+ uint32_t lane_length;
+ uint32_t lanes;
+ uint32_t threads;
+ argon2_type type;
+ int print_internals; /* whether to print the memory blocks */
+} argon2_instance_t;
+
+/*
+ * Argon2 position: where we construct the block right now. Used to distribute
+ * work between threads.
+ */
+typedef struct Argon2_position_t {
+ uint32_t pass;
+ uint32_t lane;
+ uint8_t slice;
+ uint32_t index;
+} argon2_position_t;
+
+/*Struct that holds the inputs for thread handling FillSegment*/
+typedef struct Argon2_thread_data {
+ argon2_instance_t *instance_ptr;
+ argon2_position_t pos;
+} argon2_thread_data;
+
+/*************************Argon2 core
+ * functions**************************************************/
+
+/*
+ * Computes absolute position of reference block in the lane following a skewed
+ * distribution and using a pseudo-random value as input
+ * @param instance Pointer to the current instance
+ * @param position Pointer to the current position
+ * @param pseudo_rand 32-bit pseudo-random value used to determine the position
+ * @param same_lane Indicates if the block will be taken from the current lane.
+ * If so we can reference the current segment
+ * @pre All pointers must be valid
+ */
+static uint32_t index_alpha(const argon2_instance_t *instance,
+ const argon2_position_t *position, uint32_t pseudo_rand,
+ int same_lane)
+{
+ /*
+ * Pass 0:
+ * This lane : all already finished segments plus already constructed
+ * blocks in this segment
+ * Other lanes : all already finished segments
+ * Pass 1+:
+ * This lane : (SYNC_POINTS - 1) last segments plus already constructed
+ * blocks in this segment
+ * Other lanes : (SYNC_POINTS - 1) last segments
+ */
+ uint32_t reference_area_size;
+ uint64_t relative_position;
+ uint32_t start_position, absolute_position;
+
+ if (position->pass == 0) {
+ /* First pass */
+ if (position->slice == 0) {
+ /* First slice */
+ reference_area_size =
+ position->index - 1; /* all but the previous */
+ } else {
+ if (same_lane) {
+ /* The same lane => add current segment */
+ reference_area_size =
+ position->slice * instance->segment_length +
+ position->index - 1;
+ } else {
+ reference_area_size =
+ position->slice * instance->segment_length +
+ ((position->index == 0) ? (-1) : 0);
+ }
+ }
+ } else {
+ /* Second pass */
+ if (same_lane) {
+ reference_area_size = instance->lane_length -
+ instance->segment_length + position->index -
+ 1;
+ } else {
+ reference_area_size = instance->lane_length -
+ instance->segment_length +
+ ((position->index == 0) ? (-1) : 0);
+ }
+ }
+
+ /* 1.2.4. Mapping pseudo_rand to 0..<reference_area_size-1> and produce
+ * relative position */
+ relative_position = pseudo_rand;
+ relative_position = relative_position * relative_position >> 32;
+ relative_position = reference_area_size - 1 -
+ (reference_area_size * relative_position >> 32);
+
+ /* 1.2.5 Computing starting position */
+ start_position = 0;
+
+ if (position->pass != 0) {
+ start_position = (position->slice == ARGON2_SYNC_POINTS - 1)
+ ? 0
+ : (position->slice + 1) * instance->segment_length;
+ }
+
+ /* 1.2.6. Computing absolute position */
+ absolute_position = (start_position + relative_position) %
+ instance->lane_length; /* absolute position */
+ return absolute_position;
+}
+
+/*
+ * Function that validates all inputs against predefined restrictions and return
+ * an error code
+ * @param context Pointer to current Argon2 context
+ * @return ARGON2_OK if everything is all right, otherwise one of error codes
+ * (all defined in <argon2.h>
+ */
+int validate_inputs(const argon2_context *context);
+
+/*
+ * Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears
+ * password and secret if needed
+ * @param context Pointer to the Argon2 internal structure containing memory
+ * pointer, and parameters for time and space requirements.
+ * @param blockhash Buffer for pre-hashing digest
+ * @param type Argon2 type
+ * @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes
+ * allocated
+ */
+void initial_hash(uint8_t *blockhash, argon2_context *context,
+ argon2_type type);
+
+/*
+ * Function creates first 2 blocks per lane
+ * @param instance Pointer to the current instance
+ * @param blockhash Pointer to the pre-hashing digest
+ * @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values
+ */
+void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance);
+
+/*
+ * Function allocates memory, hashes the inputs with Blake, and creates first
+ * two blocks. Returns the pointer to the main memory with 2 blocks per lane
+ * initialized
+ * @param context Pointer to the Argon2 internal structure containing memory
+ * pointer, and parameters for time and space requirements.
+ * @param instance Current Argon2 instance
+ * @return Zero if successful, -1 if memory failed to allocate. @context->state
+ * will be modified if successful.
+ */
+int initialize(argon2_instance_t *instance, argon2_context *context);
+
+/*
+ * Deallocates memory. Used on error path.
+ */
+void free_instance(argon2_instance_t *instance, int flags);
+
+/*
+ * XORing the last block of each lane, hashing it, making the tag. Deallocates
+ * the memory.
+ * @param context Pointer to current Argon2 context (use only the out parameters
+ * from it)
+ * @param instance Pointer to current instance of Argon2
+ * @pre instance->state must point to necessary amount of memory
+ * @pre context->out must point to outlen bytes of memory
+ * @pre if context->free_cbk is not NULL, it should point to a function that
+ * deallocates memory
+ */
+void finalize(const argon2_context *context, argon2_instance_t *instance);
+
+/*
+ * Function that fills the segment using previous segments also from other
+ * threads
+ * @param instance Pointer to the current instance
+ * @param position Current position
+ * @pre all block pointers must be valid
+ */
+typedef void (*fill_segment_fn)(const argon2_instance_t *instance,
+ argon2_position_t position);
+int argon2_pick_best_implementation(void);
+void fill_segment_avx512f(const argon2_instance_t *instance,
+ argon2_position_t position);
+void fill_segment_avx2(const argon2_instance_t *instance,
+ argon2_position_t position);
+void fill_segment_ssse3(const argon2_instance_t *instance,
+ argon2_position_t position);
+void fill_segment_ref(const argon2_instance_t *instance,
+ argon2_position_t position);
+
+/*
+ * Function that fills the entire memory t_cost times based on the first two
+ * blocks in each lane
+ * @param instance Pointer to the current instance
+ * @return Zero if successful, -1 if memory failed to allocate
+ */
+void fill_memory_blocks(argon2_instance_t *instance, uint32_t pass);
+
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2-encoding.c b/libs/libsodium/src/crypto_pwhash/argon2/argon2-encoding.c
new file mode 100644
index 0000000000..a08acdda80
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2-encoding.c
@@ -0,0 +1,305 @@
+#include "argon2-encoding.h"
+#include "argon2-core.h"
+#include "utils.h"
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * Example code for a decoder and encoder of "hash strings", with Argon2
+ * parameters.
+ *
+ * The code was originally written by Thomas Pornin <pornin@bolet.org>,
+ * to whom comments and remarks may be sent. It is released under what
+ * should amount to Public Domain or its closest equivalent; the
+ * following mantra is supposed to incarnate that fact with all the
+ * proper legal rituals:
+ *
+ * ---------------------------------------------------------------------
+ * This file is provided under the terms of Creative Commons CC0 1.0
+ * Public Domain Dedication. To the extent possible under law, the
+ * author (Thomas Pornin) has waived all copyright and related or
+ * neighboring rights to this file. This work is published from: Canada.
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2015 Thomas Pornin
+ */
+
+/* ==================================================================== */
+
+/*
+ * Decode decimal integer from 'str'; the value is written in '*v'.
+ * Returned value is a pointer to the next non-decimal character in the
+ * string. If there is no digit at all, or the value encoding is not
+ * minimal (extra leading zeros), or the value does not fit in an
+ * 'unsigned long', then NULL is returned.
+ */
+static const char *
+decode_decimal(const char *str, unsigned long *v)
+{
+ const char *orig;
+ unsigned long acc;
+
+ acc = 0;
+ for (orig = str;; str++) {
+ int c;
+
+ c = *str;
+ if (c < '0' || c > '9') {
+ break;
+ }
+ c -= '0';
+ if (acc > (ULONG_MAX / 10)) {
+ return NULL;
+ }
+ acc *= 10;
+ if ((unsigned long) c > (ULONG_MAX - acc)) {
+ return NULL;
+ }
+ acc += (unsigned long) c;
+ }
+ if (str == orig || (*orig == '0' && str != (orig + 1))) {
+ return NULL;
+ }
+ *v = acc;
+ return str;
+}
+
+/* ==================================================================== */
+/*
+ * Code specific to Argon2.
+ *
+ * The code below applies the following format:
+ *
+ * $argon2<T>[$v=<num>]$m=<num>,t=<num>,p=<num>$<bin>$<bin>
+ *
+ * where <T> is either 'i', <num> is a decimal integer (positive, fits in an
+ * 'unsigned long') and <bin> is Base64-encoded data (no '=' padding characters,
+ * no newline or whitespace).
+ *
+ * The last two binary chunks (encoded in Base64) are, in that order,
+ * the salt and the output. Both are required. The binary salt length and the
+ * output length must be in the allowed ranges defined in argon2.h.
+ *
+ * The ctx struct must contain buffers large enough to hold the salt and pwd
+ * when it is fed into decode_string.
+ */
+
+/*
+ * Decode an Argon2i hash string into the provided structure 'ctx'.
+ * Returned value is ARGON2_OK on success.
+ */
+int
+decode_string(argon2_context *ctx, const char *str, argon2_type type)
+{
+/* Prefix checking */
+#define CC(prefix) \
+ do { \
+ size_t cc_len = strlen(prefix); \
+ if (strncmp(str, prefix, cc_len) != 0) { \
+ return ARGON2_DECODING_FAIL; \
+ } \
+ str += cc_len; \
+ } while ((void) 0, 0)
+
+/* Optional prefix checking with supplied code */
+#define CC_opt(prefix, code) \
+ do { \
+ size_t cc_len = strlen(prefix); \
+ if (strncmp(str, prefix, cc_len) == 0) { \
+ str += cc_len; \
+ { \
+ code; \
+ } \
+ } \
+ } while ((void) 0, 0)
+
+/* Decoding prefix into decimal */
+#define DECIMAL(x) \
+ do { \
+ unsigned long dec_x; \
+ str = decode_decimal(str, &dec_x); \
+ if (str == NULL) { \
+ return ARGON2_DECODING_FAIL; \
+ } \
+ (x) = dec_x; \
+ } while ((void) 0, 0)
+
+/* Decoding prefix into uint32_t decimal */
+#define DECIMAL_U32(x) \
+ do { \
+ unsigned long dec_x; \
+ str = decode_decimal(str, &dec_x); \
+ if (str == NULL || dec_x > UINT32_MAX) { \
+ return ARGON2_DECODING_FAIL; \
+ } \
+ (x) = (uint32_t)dec_x; \
+ } while ((void)0, 0)
+
+/* Decoding base64 into a binary buffer */
+#define BIN(buf, max_len, len) \
+ do { \
+ size_t bin_len = (max_len); \
+ const char *str_end; \
+ if (sodium_base642bin((buf), (max_len), str, strlen(str), NULL, \
+ &bin_len, &str_end, \
+ sodium_base64_VARIANT_ORIGINAL_NO_PADDING) != 0 || \
+ bin_len > UINT32_MAX) { \
+ return ARGON2_DECODING_FAIL; \
+ } \
+ (len) = (uint32_t) bin_len; \
+ str = str_end; \
+ } while ((void) 0, 0)
+
+ size_t maxsaltlen = ctx->saltlen;
+ size_t maxoutlen = ctx->outlen;
+ int validation_result;
+ uint32_t version = 0;
+
+ ctx->saltlen = 0;
+ ctx->outlen = 0;
+
+ if (type == Argon2_id) {
+ CC("$argon2id");
+ } else if (type == Argon2_i) {
+ CC("$argon2i");
+ } else {
+ return ARGON2_INCORRECT_TYPE;
+ }
+ CC("$v=");
+ DECIMAL_U32(version);
+ if (version != ARGON2_VERSION_NUMBER) {
+ return ARGON2_INCORRECT_TYPE;
+ }
+ CC("$m=");
+ DECIMAL_U32(ctx->m_cost);
+ if (ctx->m_cost > UINT32_MAX) {
+ return ARGON2_INCORRECT_TYPE;
+ }
+ CC(",t=");
+ DECIMAL_U32(ctx->t_cost);
+ if (ctx->t_cost > UINT32_MAX) {
+ return ARGON2_INCORRECT_TYPE;
+ }
+ CC(",p=");
+ DECIMAL_U32(ctx->lanes);
+ if (ctx->lanes > UINT32_MAX) {
+ return ARGON2_INCORRECT_TYPE;
+ }
+ ctx->threads = ctx->lanes;
+
+ CC("$");
+ BIN(ctx->salt, maxsaltlen, ctx->saltlen);
+ CC("$");
+ BIN(ctx->out, maxoutlen, ctx->outlen);
+ validation_result = validate_inputs(ctx);
+ if (validation_result != ARGON2_OK) {
+ return validation_result;
+ }
+ if (*str == 0) {
+ return ARGON2_OK;
+ }
+ return ARGON2_DECODING_FAIL;
+
+#undef CC
+#undef CC_opt
+#undef DECIMAL
+#undef BIN
+}
+
+#define U32_STR_MAXSIZE 11U
+
+static void
+u32_to_string(char *str, uint32_t x)
+{
+ char tmp[U32_STR_MAXSIZE - 1U];
+ size_t i;
+
+ i = sizeof tmp;
+ do {
+ tmp[--i] = (x % (uint32_t) 10U) + '0';
+ x /= (uint32_t) 10U;
+ } while (x != 0U && i != 0U);
+ memcpy(str, &tmp[i], (sizeof tmp) - i);
+ str[(sizeof tmp) - i] = 0;
+}
+
+/*
+ * Encode an argon2i hash string into the provided buffer. 'dst_len'
+ * contains the size, in characters, of the 'dst' buffer; if 'dst_len'
+ * is less than the number of required characters (including the
+ * terminating 0), then this function returns 0.
+ *
+ * If pp->output_len is 0, then the hash string will be a salt string
+ * (no output). if pp->salt_len is also 0, then the string will be a
+ * parameter-only string (no salt and no output).
+ *
+ * On success, ARGON2_OK is returned.
+ */
+int
+encode_string(char *dst, size_t dst_len, argon2_context *ctx, argon2_type type)
+{
+#define SS(str) \
+ do { \
+ size_t pp_len = strlen(str); \
+ if (pp_len >= dst_len) { \
+ return ARGON2_ENCODING_FAIL; \
+ } \
+ memcpy(dst, str, pp_len + 1); \
+ dst += pp_len; \
+ dst_len -= pp_len; \
+ } while ((void) 0, 0)
+
+#define SX(x) \
+ do { \
+ char tmp[U32_STR_MAXSIZE]; \
+ u32_to_string(tmp, x); \
+ SS(tmp); \
+ } while ((void) 0, 0)
+
+#define SB(buf, len) \
+ do { \
+ size_t sb_len; \
+ if (sodium_bin2base64(dst, dst_len, (buf), (len), \
+ sodium_base64_VARIANT_ORIGINAL_NO_PADDING) == NULL) { \
+ return ARGON2_ENCODING_FAIL; \
+ } \
+ sb_len = strlen(dst); \
+ dst += sb_len; \
+ dst_len -= sb_len; \
+ } while ((void) 0, 0)
+
+ int validation_result;
+
+ switch (type) {
+ case Argon2_id:
+ SS("$argon2id$v="); break;
+ case Argon2_i:
+ SS("$argon2i$v="); break;
+ default:
+ return ARGON2_ENCODING_FAIL;
+ }
+ validation_result = validate_inputs(ctx);
+ if (validation_result != ARGON2_OK) {
+ return validation_result;
+ }
+ SX(ARGON2_VERSION_NUMBER);
+ SS("$m=");
+ SX(ctx->m_cost);
+ SS(",t=");
+ SX(ctx->t_cost);
+ SS(",p=");
+ SX(ctx->lanes);
+
+ SS("$");
+ SB(ctx->salt, ctx->saltlen);
+
+ SS("$");
+ SB(ctx->out, ctx->outlen);
+ return ARGON2_OK;
+
+#undef SS
+#undef SX
+#undef SB
+}
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2-encoding.h b/libs/libsodium/src/crypto_pwhash/argon2/argon2-encoding.h
new file mode 100644
index 0000000000..e929b31dc3
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2-encoding.h
@@ -0,0 +1,33 @@
+#ifndef argon2_encoding_H
+#define argon2_encoding_H
+
+#include "argon2.h"
+
+/*
+ * encode an Argon2 hash string into the provided buffer. 'dst_len'
+ * contains the size, in characters, of the 'dst' buffer; if 'dst_len'
+ * is less than the number of required characters (including the
+ * terminating 0), then this function returns 0.
+ *
+ * if ctx->outlen is 0, then the hash string will be a salt string
+ * (no output). if ctx->saltlen is also 0, then the string will be a
+ * parameter-only string (no salt and no output).
+ *
+ * On success, ARGON2_OK is returned.
+ *
+ * No other parameters are checked
+ */
+int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
+ argon2_type type);
+
+/*
+ * Decodes an Argon2 hash string into the provided structure 'ctx'.
+ * The fields ctx.saltlen, ctx.adlen, ctx.outlen set the maximal salt, ad, out
+ * length values
+ * that are allowed; invalid input string causes an error
+ *
+ * Returned value is ARGON2_OK on success.
+ */
+int decode_string(argon2_context *ctx, const char *str, argon2_type type);
+
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-avx2.c b/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-avx2.c
new file mode 100644
index 0000000000..8acb42ca4d
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-avx2.c
@@ -0,0 +1,239 @@
+/*
+ * Argon2 source code package
+ *
+ * Written by Daniel Dinu and Dmitry Khovratovich, 2015
+ *
+ * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication along
+ * with
+ * this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "argon2-core.h"
+#include "argon2.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#if defined(HAVE_AVX2INTRIN_H) && defined(HAVE_EMMINTRIN_H) && \
+ defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# pragma GCC target("ssse3")
+# pragma GCC target("sse4.1")
+# pragma GCC target("avx2")
+# endif
+
+# ifdef _MSC_VER
+# include <intrin.h> /* for _mm_set_epi64x */
+# endif
+#include <emmintrin.h>
+#include <immintrin.h>
+#include <smmintrin.h>
+#include <tmmintrin.h>
+
+# include "blamka-round-avx2.h"
+
+static void
+fill_block(__m256i *state, const uint8_t *ref_block, uint8_t *next_block)
+{
+ __m256i block_XY[ARGON2_HWORDS_IN_BLOCK];
+ uint32_t i;
+
+ for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
+ block_XY[i] = state[i] = _mm256_xor_si256(
+ state[i], _mm256_loadu_si256((__m256i const *) (&ref_block[32 * i])));
+ }
+
+ for (i = 0; i < 4; ++i) {
+ BLAKE2_ROUND_1(state[8 * i + 0], state[8 * i + 4], state[8 * i + 1], state[8 * i + 5],
+ state[8 * i + 2], state[8 * i + 6], state[8 * i + 3], state[8 * i + 7]);
+ }
+
+ for (i = 0; i < 4; ++i) {
+ BLAKE2_ROUND_2(state[ 0 + i], state[ 4 + i], state[ 8 + i], state[12 + i],
+ state[16 + i], state[20 + i], state[24 + i], state[28 + i]);
+ }
+
+ for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
+ state[i] = _mm256_xor_si256(state[i], block_XY[i]);
+ _mm256_storeu_si256((__m256i *) (&next_block[32 * i]), state[i]);
+ }
+}
+
+static void
+fill_block_with_xor(__m256i *state, const uint8_t *ref_block,
+ uint8_t *next_block)
+{
+ __m256i block_XY[ARGON2_HWORDS_IN_BLOCK];
+ uint32_t i;
+
+ for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
+ state[i] = _mm256_xor_si256(
+ state[i], _mm256_loadu_si256((__m256i const *) (&ref_block[32 * i])));
+ block_XY[i] = _mm256_xor_si256(
+ state[i], _mm256_loadu_si256((__m256i const *) (&next_block[32 * i])));
+ }
+
+ for (i = 0; i < 4; ++i) {
+ BLAKE2_ROUND_1(state[8 * i + 0], state[8 * i + 4], state[8 * i + 1], state[8 * i + 5],
+ state[8 * i + 2], state[8 * i + 6], state[8 * i + 3], state[8 * i + 7]);
+ }
+
+ for (i = 0; i < 4; ++i) {
+ BLAKE2_ROUND_2(state[ 0 + i], state[ 4 + i], state[ 8 + i], state[12 + i],
+ state[16 + i], state[20 + i], state[24 + i], state[28 + i]);
+ }
+
+ for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
+ state[i] = _mm256_xor_si256(state[i], block_XY[i]);
+ _mm256_storeu_si256((__m256i *) (&next_block[32 * i]), state[i]);
+ }
+}
+
+static void
+generate_addresses(const argon2_instance_t *instance,
+ const argon2_position_t *position, uint64_t *pseudo_rands)
+{
+ block address_block, input_block, tmp_block;
+ uint32_t i;
+
+ init_block_value(&address_block, 0);
+ init_block_value(&input_block, 0);
+
+ if (instance != NULL && position != NULL) {
+ input_block.v[0] = position->pass;
+ input_block.v[1] = position->lane;
+ input_block.v[2] = position->slice;
+ input_block.v[3] = instance->memory_blocks;
+ input_block.v[4] = instance->passes;
+ input_block.v[5] = instance->type;
+
+ for (i = 0; i < instance->segment_length; ++i) {
+ if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
+ /* Temporary zero-initialized blocks */
+ __m256i zero_block[ARGON2_HWORDS_IN_BLOCK];
+ __m256i zero2_block[ARGON2_HWORDS_IN_BLOCK];
+
+ memset(zero_block, 0, sizeof(zero_block));
+ memset(zero2_block, 0, sizeof(zero2_block));
+ init_block_value(&address_block, 0);
+ init_block_value(&tmp_block, 0);
+ /* Increasing index counter */
+ input_block.v[6]++;
+ /* First iteration of G */
+ fill_block_with_xor(zero_block, (uint8_t *) &input_block.v,
+ (uint8_t *) &tmp_block.v);
+ /* Second iteration of G */
+ fill_block_with_xor(zero2_block, (uint8_t *) &tmp_block.v,
+ (uint8_t *) &address_block.v);
+ }
+
+ pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
+ }
+ }
+}
+
+void
+fill_segment_avx2(const argon2_instance_t *instance,
+ argon2_position_t position)
+{
+ block *ref_block = NULL, *curr_block = NULL;
+ uint64_t pseudo_rand, ref_index, ref_lane;
+ uint32_t prev_offset, curr_offset;
+ uint32_t starting_index, i;
+ __m256i state[ARGON2_HWORDS_IN_BLOCK];
+ int data_independent_addressing = 1;
+
+ /* Pseudo-random values that determine the reference block position */
+ uint64_t *pseudo_rands = NULL;
+
+ if (instance == NULL) {
+ return;
+ }
+
+ if (instance->type == Argon2_id &&
+ (position.pass != 0 || position.slice >= ARGON2_SYNC_POINTS / 2)) {
+ data_independent_addressing = 0;
+ }
+
+ pseudo_rands = instance->pseudo_rands;
+
+ if (data_independent_addressing) {
+ generate_addresses(instance, &position, pseudo_rands);
+ }
+
+ starting_index = 0;
+
+ if ((0 == position.pass) && (0 == position.slice)) {
+ starting_index = 2; /* we have already generated the first two blocks */
+ }
+
+ /* Offset of the current block */
+ curr_offset = position.lane * instance->lane_length +
+ position.slice * instance->segment_length + starting_index;
+
+ if (0 == curr_offset % instance->lane_length) {
+ /* Last block in this lane */
+ prev_offset = curr_offset + instance->lane_length - 1;
+ } else {
+ /* Previous block */
+ prev_offset = curr_offset - 1;
+ }
+
+ memcpy(state, ((instance->region->memory + prev_offset)->v),
+ ARGON2_BLOCK_SIZE);
+
+ for (i = starting_index; i < instance->segment_length;
+ ++i, ++curr_offset, ++prev_offset) {
+ /*1.1 Rotating prev_offset if needed */
+ if (curr_offset % instance->lane_length == 1) {
+ prev_offset = curr_offset - 1;
+ }
+
+ /* 1.2 Computing the index of the reference block */
+ /* 1.2.1 Taking pseudo-random value from the previous block */
+ if (data_independent_addressing) {
+#pragma warning(push)
+#pragma warning(disable : 6385)
+ pseudo_rand = pseudo_rands[i];
+#pragma warning(pop)
+ } else {
+ pseudo_rand = instance->region->memory[prev_offset].v[0];
+ }
+
+ /* 1.2.2 Computing the lane of the reference block */
+ ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
+
+ if ((position.pass == 0) && (position.slice == 0)) {
+ /* Can not reference other lanes yet */
+ ref_lane = position.lane;
+ }
+
+ /* 1.2.3 Computing the number of possible reference block within the
+ * lane.
+ */
+ position.index = i;
+ ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
+ ref_lane == position.lane);
+
+ /* 2 Creating a new block */
+ ref_block = instance->region->memory +
+ instance->lane_length * ref_lane + ref_index;
+ curr_block = instance->region->memory + curr_offset;
+ if (position.pass != 0) {
+ fill_block_with_xor(state, (uint8_t *) ref_block->v,
+ (uint8_t *) curr_block->v);
+ } else {
+ fill_block(state, (uint8_t *) ref_block->v,
+ (uint8_t *) curr_block->v);
+ }
+ }
+}
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-avx512f.c b/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-avx512f.c
new file mode 100644
index 0000000000..1f1ec8b3b4
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-avx512f.c
@@ -0,0 +1,244 @@
+/*
+ * Argon2 source code package
+ *
+ * Written by Daniel Dinu and Dmitry Khovratovich, 2015
+ *
+ * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication along
+ * with
+ * this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "argon2-core.h"
+#include "argon2.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#if defined(HAVE_AVX512FINTRIN_H) && defined(HAVE_AVX2INTRIN_H) && \
+ defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# pragma GCC target("ssse3")
+# pragma GCC target("sse4.1")
+# pragma GCC target("avx2")
+# pragma GCC target("avx512f")
+# endif
+
+# ifdef _MSC_VER
+# include <intrin.h> /* for _mm_set_epi64x */
+# endif
+#include <emmintrin.h>
+#include <immintrin.h>
+#include <smmintrin.h>
+#include <tmmintrin.h>
+
+# include "blamka-round-avx512f.h"
+
+static void
+fill_block(__m512i *state, const uint8_t *ref_block, uint8_t *next_block)
+{
+ __m512i block_XY[ARGON2_512BIT_WORDS_IN_BLOCK];
+ uint32_t i;
+
+ for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
+ block_XY[i] = state[i] = _mm512_xor_si512(
+ state[i], _mm512_loadu_si512((__m512i const *) (&ref_block[64 * i])));
+ }
+
+ for (i = 0; i < 2; ++i) {
+ BLAKE2_ROUND_1(
+ state[8 * i + 0], state[8 * i + 1], state[8 * i + 2], state[8 * i + 3],
+ state[8 * i + 4], state[8 * i + 5], state[8 * i + 6], state[8 * i + 7]);
+ }
+
+ for (i = 0; i < 2; ++i) {
+ BLAKE2_ROUND_2(
+ state[2 * 0 + i], state[2 * 1 + i], state[2 * 2 + i], state[2 * 3 + i],
+ state[2 * 4 + i], state[2 * 5 + i], state[2 * 6 + i], state[2 * 7 + i]);
+ }
+
+ for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
+ state[i] = _mm512_xor_si512(state[i], block_XY[i]);
+ _mm512_storeu_si512((__m512i *) (&next_block[64 * i]), state[i]);
+ }
+}
+
+static void
+fill_block_with_xor(__m512i *state, const uint8_t *ref_block,
+ uint8_t *next_block)
+{
+ __m512i block_XY[ARGON2_512BIT_WORDS_IN_BLOCK];
+ uint32_t i;
+
+ for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
+ state[i] = _mm512_xor_si512(
+ state[i], _mm512_loadu_si512((__m512i const *) (&ref_block[64 * i])));
+ block_XY[i] = _mm512_xor_si512(
+ state[i], _mm512_loadu_si512((__m512i const *) (&next_block[64 * i])));
+ }
+
+ for (i = 0; i < 2; ++i) {
+ BLAKE2_ROUND_1(
+ state[8 * i + 0], state[8 * i + 1], state[8 * i + 2], state[8 * i + 3],
+ state[8 * i + 4], state[8 * i + 5], state[8 * i + 6], state[8 * i + 7]);
+ }
+
+ for (i = 0; i < 2; ++i) {
+ BLAKE2_ROUND_2(
+ state[2 * 0 + i], state[2 * 1 + i], state[2 * 2 + i], state[2 * 3 + i],
+ state[2 * 4 + i], state[2 * 5 + i], state[2 * 6 + i], state[2 * 7 + i]);
+ }
+
+ for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
+ state[i] = _mm512_xor_si512(state[i], block_XY[i]);
+ _mm512_storeu_si512((__m512i *) (&next_block[64 * i]), state[i]);
+ }
+}
+
+static void
+generate_addresses(const argon2_instance_t *instance,
+ const argon2_position_t *position, uint64_t *pseudo_rands)
+{
+ block address_block, input_block, tmp_block;
+ uint32_t i;
+
+ init_block_value(&address_block, 0);
+ init_block_value(&input_block, 0);
+
+ if (instance != NULL && position != NULL) {
+ input_block.v[0] = position->pass;
+ input_block.v[1] = position->lane;
+ input_block.v[2] = position->slice;
+ input_block.v[3] = instance->memory_blocks;
+ input_block.v[4] = instance->passes;
+ input_block.v[5] = instance->type;
+
+ for (i = 0; i < instance->segment_length; ++i) {
+ if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
+ /* Temporary zero-initialized blocks */
+ __m512i zero_block[ARGON2_512BIT_WORDS_IN_BLOCK];
+ __m512i zero2_block[ARGON2_512BIT_WORDS_IN_BLOCK];
+
+ memset(zero_block, 0, sizeof(zero_block));
+ memset(zero2_block, 0, sizeof(zero2_block));
+ init_block_value(&address_block, 0);
+ init_block_value(&tmp_block, 0);
+ /* Increasing index counter */
+ input_block.v[6]++;
+ /* First iteration of G */
+ fill_block_with_xor(zero_block, (uint8_t *) &input_block.v,
+ (uint8_t *) &tmp_block.v);
+ /* Second iteration of G */
+ fill_block_with_xor(zero2_block, (uint8_t *) &tmp_block.v,
+ (uint8_t *) &address_block.v);
+ }
+
+ pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
+ }
+ }
+}
+
+void
+fill_segment_avx512f(const argon2_instance_t *instance,
+ argon2_position_t position)
+{
+ block *ref_block = NULL, *curr_block = NULL;
+ uint64_t pseudo_rand, ref_index, ref_lane;
+ uint32_t prev_offset, curr_offset;
+ uint32_t starting_index, i;
+ __m512i state[ARGON2_512BIT_WORDS_IN_BLOCK];
+ int data_independent_addressing = 1;
+
+ /* Pseudo-random values that determine the reference block position */
+ uint64_t *pseudo_rands = NULL;
+
+ if (instance == NULL) {
+ return;
+ }
+
+ if (instance->type == Argon2_id &&
+ (position.pass != 0 || position.slice >= ARGON2_SYNC_POINTS / 2)) {
+ data_independent_addressing = 0;
+ }
+
+ pseudo_rands = instance->pseudo_rands;
+
+ if (data_independent_addressing) {
+ generate_addresses(instance, &position, pseudo_rands);
+ }
+
+ starting_index = 0;
+
+ if ((0 == position.pass) && (0 == position.slice)) {
+ starting_index = 2; /* we have already generated the first two blocks */
+ }
+
+ /* Offset of the current block */
+ curr_offset = position.lane * instance->lane_length +
+ position.slice * instance->segment_length + starting_index;
+
+ if (0 == curr_offset % instance->lane_length) {
+ /* Last block in this lane */
+ prev_offset = curr_offset + instance->lane_length - 1;
+ } else {
+ /* Previous block */
+ prev_offset = curr_offset - 1;
+ }
+
+ memcpy(state, ((instance->region->memory + prev_offset)->v),
+ ARGON2_BLOCK_SIZE);
+
+ for (i = starting_index; i < instance->segment_length;
+ ++i, ++curr_offset, ++prev_offset) {
+ /*1.1 Rotating prev_offset if needed */
+ if (curr_offset % instance->lane_length == 1) {
+ prev_offset = curr_offset - 1;
+ }
+
+ /* 1.2 Computing the index of the reference block */
+ /* 1.2.1 Taking pseudo-random value from the previous block */
+ if (data_independent_addressing) {
+#pragma warning(push)
+#pragma warning(disable : 6385)
+ pseudo_rand = pseudo_rands[i];
+#pragma warning(pop)
+ } else {
+ pseudo_rand = instance->region->memory[prev_offset].v[0];
+ }
+
+ /* 1.2.2 Computing the lane of the reference block */
+ ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
+
+ if ((position.pass == 0) && (position.slice == 0)) {
+ /* Can not reference other lanes yet */
+ ref_lane = position.lane;
+ }
+
+ /* 1.2.3 Computing the number of possible reference block within the
+ * lane.
+ */
+ position.index = i;
+ ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
+ ref_lane == position.lane);
+
+ /* 2 Creating a new block */
+ ref_block = instance->region->memory +
+ instance->lane_length * ref_lane + ref_index;
+ curr_block = instance->region->memory + curr_offset;
+ if (position.pass != 0) {
+ fill_block_with_xor(state, (uint8_t *) ref_block->v,
+ (uint8_t *) curr_block->v);
+ } else {
+ fill_block(state, (uint8_t *) ref_block->v,
+ (uint8_t *) curr_block->v);
+ }
+ }
+}
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-ref.c b/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-ref.c
new file mode 100644
index 0000000000..75e8d8f5ea
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-ref.c
@@ -0,0 +1,233 @@
+/*
+ * Argon2 source code package
+ *
+ * Written by Daniel Dinu and Dmitry Khovratovich, 2015
+ *
+ * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication along
+ * with
+ * this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "argon2-core.h"
+#include "argon2.h"
+#include "blamka-round-ref.h"
+#include "private/common.h"
+
+static void
+fill_block(const block *prev_block, const block *ref_block, block *next_block)
+{
+ block blockR, block_tmp;
+ unsigned i;
+
+ copy_block(&blockR, ref_block);
+ xor_block(&blockR, prev_block);
+ copy_block(&block_tmp, &blockR);
+ /* Now blockR = ref_block + prev_block and bloc_tmp = ref_block + prev_block
+ Apply Blake2 on columns of 64-bit words: (0,1,...,15), then
+ (16,17,..31)... finally (112,113,...127) */
+ for (i = 0; i < 8; ++i) {
+ BLAKE2_ROUND_NOMSG(
+ blockR.v[16 * i], blockR.v[16 * i + 1], blockR.v[16 * i + 2],
+ blockR.v[16 * i + 3], blockR.v[16 * i + 4], blockR.v[16 * i + 5],
+ blockR.v[16 * i + 6], blockR.v[16 * i + 7], blockR.v[16 * i + 8],
+ blockR.v[16 * i + 9], blockR.v[16 * i + 10], blockR.v[16 * i + 11],
+ blockR.v[16 * i + 12], blockR.v[16 * i + 13], blockR.v[16 * i + 14],
+ blockR.v[16 * i + 15]);
+ }
+
+ /* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then
+ (2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */
+ for (i = 0; i < 8; i++) {
+ BLAKE2_ROUND_NOMSG(
+ blockR.v[2 * i], blockR.v[2 * i + 1], blockR.v[2 * i + 16],
+ blockR.v[2 * i + 17], blockR.v[2 * i + 32], blockR.v[2 * i + 33],
+ blockR.v[2 * i + 48], blockR.v[2 * i + 49], blockR.v[2 * i + 64],
+ blockR.v[2 * i + 65], blockR.v[2 * i + 80], blockR.v[2 * i + 81],
+ blockR.v[2 * i + 96], blockR.v[2 * i + 97], blockR.v[2 * i + 112],
+ blockR.v[2 * i + 113]);
+ }
+
+ copy_block(next_block, &block_tmp);
+ xor_block(next_block, &blockR);
+}
+
+static void
+fill_block_with_xor(const block *prev_block, const block *ref_block,
+ block *next_block)
+{
+ block blockR, block_tmp;
+ unsigned i;
+
+ copy_block(&blockR, ref_block);
+ xor_block(&blockR, prev_block);
+ copy_block(&block_tmp, &blockR);
+ xor_block(&block_tmp,
+ next_block); /* Saving the next block contents for XOR over */
+ /* Now blockR = ref_block + prev_block and bloc_tmp = ref_block + prev_block
+ * + next_block */
+ /* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then
+ (16,17,..31)... finally (112,113,...127) */
+ for (i = 0; i < 8; ++i) {
+ BLAKE2_ROUND_NOMSG(
+ blockR.v[16 * i], blockR.v[16 * i + 1], blockR.v[16 * i + 2],
+ blockR.v[16 * i + 3], blockR.v[16 * i + 4], blockR.v[16 * i + 5],
+ blockR.v[16 * i + 6], blockR.v[16 * i + 7], blockR.v[16 * i + 8],
+ blockR.v[16 * i + 9], blockR.v[16 * i + 10], blockR.v[16 * i + 11],
+ blockR.v[16 * i + 12], blockR.v[16 * i + 13], blockR.v[16 * i + 14],
+ blockR.v[16 * i + 15]);
+ }
+
+ /* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then
+ (2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */
+ for (i = 0; i < 8; i++) {
+ BLAKE2_ROUND_NOMSG(
+ blockR.v[2 * i], blockR.v[2 * i + 1], blockR.v[2 * i + 16],
+ blockR.v[2 * i + 17], blockR.v[2 * i + 32], blockR.v[2 * i + 33],
+ blockR.v[2 * i + 48], blockR.v[2 * i + 49], blockR.v[2 * i + 64],
+ blockR.v[2 * i + 65], blockR.v[2 * i + 80], blockR.v[2 * i + 81],
+ blockR.v[2 * i + 96], blockR.v[2 * i + 97], blockR.v[2 * i + 112],
+ blockR.v[2 * i + 113]);
+ }
+
+ copy_block(next_block, &block_tmp);
+ xor_block(next_block, &blockR);
+}
+
+/*
+ * Generate pseudo-random values to reference blocks in the segment and puts
+ * them into the array
+ * @param instance Pointer to the current instance
+ * @param position Pointer to the current position
+ * @param pseudo_rands Pointer to the array of 64-bit values
+ * @pre pseudo_rands must point to @a instance->segment_length allocated values
+ */
+static void
+generate_addresses(const argon2_instance_t *instance,
+ const argon2_position_t *position, uint64_t *pseudo_rands)
+{
+ block zero_block, input_block, address_block, tmp_block;
+ uint32_t i;
+
+ init_block_value(&zero_block, 0);
+ init_block_value(&input_block, 0);
+
+ if (instance != NULL && position != NULL) {
+ input_block.v[0] = position->pass;
+ input_block.v[1] = position->lane;
+ input_block.v[2] = position->slice;
+ input_block.v[3] = instance->memory_blocks;
+ input_block.v[4] = instance->passes;
+ input_block.v[5] = instance->type;
+
+ for (i = 0; i < instance->segment_length; ++i) {
+ if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
+ input_block.v[6]++;
+ init_block_value(&tmp_block, 0);
+ init_block_value(&address_block, 0);
+ fill_block_with_xor(&zero_block, &input_block, &tmp_block);
+ fill_block_with_xor(&zero_block, &tmp_block, &address_block);
+ }
+
+ pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
+ }
+ }
+}
+
+void
+fill_segment_ref(const argon2_instance_t *instance, argon2_position_t position)
+{
+ block *ref_block = NULL, *curr_block = NULL;
+ /* Pseudo-random values that determine the reference block position */
+ uint64_t *pseudo_rands = NULL;
+ uint64_t pseudo_rand, ref_index, ref_lane;
+ uint32_t prev_offset, curr_offset;
+ uint32_t starting_index;
+ uint32_t i;
+ int data_independent_addressing = 1;
+
+ if (instance == NULL) {
+ return;
+ }
+
+ if (instance->type == Argon2_id &&
+ (position.pass != 0 || position.slice >= ARGON2_SYNC_POINTS / 2)) {
+ data_independent_addressing = 0;
+ }
+
+ pseudo_rands = instance->pseudo_rands;
+
+ if (data_independent_addressing) {
+ generate_addresses(instance, &position, pseudo_rands);
+ }
+
+ starting_index = 0;
+
+ if ((0 == position.pass) && (0 == position.slice)) {
+ starting_index = 2; /* we have already generated the first two blocks */
+ }
+
+ /* Offset of the current block */
+ curr_offset = position.lane * instance->lane_length +
+ position.slice * instance->segment_length + starting_index;
+
+ if (0 == curr_offset % instance->lane_length) {
+ /* Last block in this lane */
+ prev_offset = curr_offset + instance->lane_length - 1;
+ } else {
+ /* Previous block */
+ prev_offset = curr_offset - 1;
+ }
+
+ for (i = starting_index; i < instance->segment_length;
+ ++i, ++curr_offset, ++prev_offset) {
+ /*1.1 Rotating prev_offset if needed */
+ if (curr_offset % instance->lane_length == 1) {
+ prev_offset = curr_offset - 1;
+ }
+
+ /* 1.2 Computing the index of the reference block */
+ /* 1.2.1 Taking pseudo-random value from the previous block */
+ if (data_independent_addressing) {
+#pragma warning(push)
+#pragma warning(disable : 6385)
+ pseudo_rand = pseudo_rands[i];
+#pragma warning(pop)
+ } else {
+ pseudo_rand = instance->region->memory[prev_offset].v[0];
+ }
+
+ /* 1.2.2 Computing the lane of the reference block */
+ ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
+
+ if ((position.pass == 0) && (position.slice == 0)) {
+ /* Can not reference other lanes yet */
+ ref_lane = position.lane;
+ }
+
+ /* 1.2.3 Computing the number of possible reference block within the
+ * lane.
+ */
+ position.index = i;
+ ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
+ ref_lane == position.lane);
+
+ /* 2 Creating a new block */
+ ref_block = instance->region->memory +
+ instance->lane_length * ref_lane + ref_index;
+ curr_block = instance->region->memory + curr_offset;
+ if (position.pass != 0) {
+ fill_block_with_xor(instance->region->memory + prev_offset,
+ ref_block, curr_block);
+ } else {
+ fill_block(instance->region->memory + prev_offset, ref_block,
+ curr_block);
+ }
+ }
+}
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-ssse3.c b/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-ssse3.c
new file mode 100644
index 0000000000..796c445560
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2-fill-block-ssse3.c
@@ -0,0 +1,238 @@
+/*
+ * Argon2 source code package
+ *
+ * Written by Daniel Dinu and Dmitry Khovratovich, 2015
+ *
+ * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication along
+ * with
+ * this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "argon2-core.h"
+#include "argon2.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# pragma GCC target("ssse3")
+# endif
+
+# ifdef _MSC_VER
+# include <intrin.h> /* for _mm_set_epi64x */
+# endif
+# include <emmintrin.h>
+# include <tmmintrin.h>
+
+# include "blamka-round-ssse3.h"
+
+static void
+fill_block(__m128i *state, const uint8_t *ref_block, uint8_t *next_block)
+{
+ __m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
+ uint32_t i;
+
+ for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
+ block_XY[i] = state[i] = _mm_xor_si128(
+ state[i], _mm_loadu_si128((__m128i const *) (&ref_block[16 * i])));
+ }
+
+ for (i = 0; i < 8; ++i) {
+ BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2],
+ state[8 * i + 3], state[8 * i + 4], state[8 * i + 5],
+ state[8 * i + 6], state[8 * i + 7]);
+ }
+
+ for (i = 0; i < 8; ++i) {
+ BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i],
+ state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i],
+ state[8 * 6 + i], state[8 * 7 + i]);
+ }
+
+ for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
+ state[i] = _mm_xor_si128(state[i], block_XY[i]);
+ _mm_storeu_si128((__m128i *) (&next_block[16 * i]), state[i]);
+ }
+}
+
+static void
+fill_block_with_xor(__m128i *state, const uint8_t *ref_block,
+ uint8_t *next_block)
+{
+ __m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
+ uint32_t i;
+
+ for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
+ state[i] = _mm_xor_si128(
+ state[i], _mm_loadu_si128((__m128i const *) (&ref_block[16 * i])));
+ block_XY[i] = _mm_xor_si128(
+ state[i], _mm_loadu_si128((__m128i const *) (&next_block[16 * i])));
+ }
+
+ for (i = 0; i < 8; ++i) {
+ BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2],
+ state[8 * i + 3], state[8 * i + 4], state[8 * i + 5],
+ state[8 * i + 6], state[8 * i + 7]);
+ }
+
+ for (i = 0; i < 8; ++i) {
+ BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i],
+ state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i],
+ state[8 * 6 + i], state[8 * 7 + i]);
+ }
+
+ for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
+ state[i] = _mm_xor_si128(state[i], block_XY[i]);
+ _mm_storeu_si128((__m128i *) (&next_block[16 * i]), state[i]);
+ }
+}
+
+static void
+generate_addresses(const argon2_instance_t *instance,
+ const argon2_position_t *position, uint64_t *pseudo_rands)
+{
+ block address_block, input_block, tmp_block;
+ uint32_t i;
+
+ init_block_value(&address_block, 0);
+ init_block_value(&input_block, 0);
+
+ if (instance != NULL && position != NULL) {
+ input_block.v[0] = position->pass;
+ input_block.v[1] = position->lane;
+ input_block.v[2] = position->slice;
+ input_block.v[3] = instance->memory_blocks;
+ input_block.v[4] = instance->passes;
+ input_block.v[5] = instance->type;
+
+ for (i = 0; i < instance->segment_length; ++i) {
+ if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
+ /* Temporary zero-initialized blocks */
+ __m128i zero_block[ARGON2_OWORDS_IN_BLOCK];
+ __m128i zero2_block[ARGON2_OWORDS_IN_BLOCK];
+
+ memset(zero_block, 0, sizeof(zero_block));
+ memset(zero2_block, 0, sizeof(zero2_block));
+ init_block_value(&address_block, 0);
+ init_block_value(&tmp_block, 0);
+ /* Increasing index counter */
+ input_block.v[6]++;
+ /* First iteration of G */
+ fill_block_with_xor(zero_block, (uint8_t *) &input_block.v,
+ (uint8_t *) &tmp_block.v);
+ /* Second iteration of G */
+ fill_block_with_xor(zero2_block, (uint8_t *) &tmp_block.v,
+ (uint8_t *) &address_block.v);
+ }
+
+ pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
+ }
+ }
+}
+
+void
+fill_segment_ssse3(const argon2_instance_t *instance,
+ argon2_position_t position)
+{
+ block *ref_block = NULL, *curr_block = NULL;
+ uint64_t pseudo_rand, ref_index, ref_lane;
+ uint32_t prev_offset, curr_offset;
+ uint32_t starting_index, i;
+ __m128i state[ARGON2_OWORDS_IN_BLOCK];
+ int data_independent_addressing = 1;
+
+ /* Pseudo-random values that determine the reference block position */
+ uint64_t *pseudo_rands = NULL;
+
+ if (instance == NULL) {
+ return;
+ }
+
+ if (instance->type == Argon2_id &&
+ (position.pass != 0 || position.slice >= ARGON2_SYNC_POINTS / 2)) {
+ data_independent_addressing = 0;
+ }
+
+ pseudo_rands = instance->pseudo_rands;
+
+ if (data_independent_addressing) {
+ generate_addresses(instance, &position, pseudo_rands);
+ }
+
+ starting_index = 0;
+
+ if ((0 == position.pass) && (0 == position.slice)) {
+ starting_index = 2; /* we have already generated the first two blocks */
+ }
+
+ /* Offset of the current block */
+ curr_offset = position.lane * instance->lane_length +
+ position.slice * instance->segment_length + starting_index;
+
+ if (0 == curr_offset % instance->lane_length) {
+ /* Last block in this lane */
+ prev_offset = curr_offset + instance->lane_length - 1;
+ } else {
+ /* Previous block */
+ prev_offset = curr_offset - 1;
+ }
+
+ memcpy(state, ((instance->region->memory + prev_offset)->v),
+ ARGON2_BLOCK_SIZE);
+
+ for (i = starting_index; i < instance->segment_length;
+ ++i, ++curr_offset, ++prev_offset) {
+ /*1.1 Rotating prev_offset if needed */
+ if (curr_offset % instance->lane_length == 1) {
+ prev_offset = curr_offset - 1;
+ }
+
+ /* 1.2 Computing the index of the reference block */
+ /* 1.2.1 Taking pseudo-random value from the previous block */
+ if (data_independent_addressing) {
+#pragma warning(push)
+#pragma warning(disable : 6385)
+ pseudo_rand = pseudo_rands[i];
+#pragma warning(pop)
+ } else {
+ pseudo_rand = instance->region->memory[prev_offset].v[0];
+ }
+
+ /* 1.2.2 Computing the lane of the reference block */
+ ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
+
+ if ((position.pass == 0) && (position.slice == 0)) {
+ /* Can not reference other lanes yet */
+ ref_lane = position.lane;
+ }
+
+ /* 1.2.3 Computing the number of possible reference block within the
+ * lane.
+ */
+ position.index = i;
+ ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
+ ref_lane == position.lane);
+
+ /* 2 Creating a new block */
+ ref_block = instance->region->memory +
+ instance->lane_length * ref_lane + ref_index;
+ curr_block = instance->region->memory + curr_offset;
+ if (position.pass != 0) {
+ fill_block_with_xor(state, (uint8_t *) ref_block->v,
+ (uint8_t *) curr_block->v);
+ } else {
+ fill_block(state, (uint8_t *) ref_block->v,
+ (uint8_t *) curr_block->v);
+ }
+ }
+}
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2.c b/libs/libsodium/src/crypto_pwhash/argon2/argon2.c
new file mode 100644
index 0000000000..ac1628c991
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2.c
@@ -0,0 +1,277 @@
+/*
+ * Argon2 source code package
+ *
+ * Written by Daniel Dinu and Dmitry Khovratovich, 2015
+ *
+ * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication along
+ * with
+ * this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils.h"
+
+#include "argon2-core.h"
+#include "argon2-encoding.h"
+#include "argon2.h"
+
+int
+argon2_ctx(argon2_context *context, argon2_type type)
+{
+ /* 1. Validate all inputs */
+ int result = validate_inputs(context);
+ uint32_t memory_blocks, segment_length;
+ uint32_t pass;
+ argon2_instance_t instance;
+
+ if (ARGON2_OK != result) {
+ return result;
+ }
+
+ if (type != Argon2_id && type != Argon2_i) {
+ return ARGON2_INCORRECT_TYPE;
+ }
+
+ /* 2. Align memory size */
+ /* Minimum memory_blocks = 8L blocks, where L is the number of lanes */
+ memory_blocks = context->m_cost;
+
+ if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) {
+ memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes;
+ }
+
+ segment_length = memory_blocks / (context->lanes * ARGON2_SYNC_POINTS);
+ /* Ensure that all segments have equal length */
+ memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS);
+
+ instance.region = NULL;
+ instance.passes = context->t_cost;
+ instance.current_pass = ~ 0U;
+ instance.memory_blocks = memory_blocks;
+ instance.segment_length = segment_length;
+ instance.lane_length = segment_length * ARGON2_SYNC_POINTS;
+ instance.lanes = context->lanes;
+ instance.threads = context->threads;
+ instance.type = type;
+
+ /* 3. Initialization: Hashing inputs, allocating memory, filling first
+ * blocks
+ */
+ result = initialize(&instance, context);
+
+ if (ARGON2_OK != result) {
+ return result;
+ }
+
+ /* 4. Filling memory */
+ for (pass = 0; pass < instance.passes; pass++) {
+ fill_memory_blocks(&instance, pass);
+ }
+
+ /* 5. Finalization */
+ finalize(context, &instance);
+
+ return ARGON2_OK;
+}
+
+int
+argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd, const size_t pwdlen,
+ const void *salt, const size_t saltlen, void *hash,
+ const size_t hashlen, char *encoded, const size_t encodedlen,
+ argon2_type type)
+{
+ argon2_context context;
+ int result;
+ uint8_t *out;
+
+ if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
+ return ARGON2_PWD_TOO_LONG;
+ }
+
+ if (hashlen > ARGON2_MAX_OUTLEN) {
+ return ARGON2_OUTPUT_TOO_LONG;
+ }
+
+ if (saltlen > ARGON2_MAX_SALT_LENGTH) {
+ return ARGON2_SALT_TOO_LONG;
+ }
+
+ out = (uint8_t *) malloc(hashlen);
+ if (!out) {
+ return ARGON2_MEMORY_ALLOCATION_ERROR;
+ }
+
+ context.out = (uint8_t *) out;
+ context.outlen = (uint32_t) hashlen;
+ context.pwd = (uint8_t *) pwd;
+ context.pwdlen = (uint32_t) pwdlen;
+ context.salt = (uint8_t *) salt;
+ context.saltlen = (uint32_t) saltlen;
+ context.secret = NULL;
+ context.secretlen = 0;
+ context.ad = NULL;
+ context.adlen = 0;
+ context.t_cost = t_cost;
+ context.m_cost = m_cost;
+ context.lanes = parallelism;
+ context.threads = parallelism;
+ context.flags = ARGON2_DEFAULT_FLAGS;
+
+ result = argon2_ctx(&context, type);
+
+ if (result != ARGON2_OK) {
+ sodium_memzero(out, hashlen);
+ free(out);
+ return result;
+ }
+
+ /* if raw hash requested, write it */
+ if (hash) {
+ memcpy(hash, out, hashlen);
+ }
+
+ /* if encoding requested, write it */
+ if (encoded && encodedlen) {
+ if (encode_string(encoded, encodedlen, &context, type) != ARGON2_OK) {
+ sodium_memzero(out, hashlen);
+ sodium_memzero(encoded, encodedlen);
+ free(out);
+ return ARGON2_ENCODING_FAIL;
+ }
+ }
+
+ sodium_memzero(out, hashlen);
+ free(out);
+
+ return ARGON2_OK;
+}
+
+int
+argon2i_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt,
+ const size_t saltlen, const size_t hashlen, char *encoded,
+ const size_t encodedlen)
+{
+ return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+ NULL, hashlen, encoded, encodedlen, Argon2_i);
+}
+
+int
+argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt, const size_t saltlen,
+ void *hash, const size_t hashlen)
+{
+ return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+ hash, hashlen, NULL, 0, Argon2_i);
+}
+
+int
+argon2id_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt,
+ const size_t saltlen, const size_t hashlen, char *encoded,
+ const size_t encodedlen)
+{
+ return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+ NULL, hashlen, encoded, encodedlen, Argon2_id);
+}
+
+int
+argon2id_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt, const size_t saltlen,
+ void *hash, const size_t hashlen)
+{
+ return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+ hash, hashlen, NULL, 0, Argon2_id);
+}
+
+int
+argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
+ argon2_type type)
+{
+ argon2_context ctx;
+ uint8_t *out;
+ int decode_result;
+ int ret;
+ size_t encoded_len;
+
+ memset(&ctx, 0, sizeof ctx);
+
+ ctx.pwd = NULL;
+ ctx.pwdlen = 0;
+ ctx.secret = NULL;
+ ctx.secretlen = 0;
+
+ /* max values, to be updated in decode_string */
+ encoded_len = strlen(encoded);
+ if (encoded_len > UINT32_MAX) {
+ return ARGON2_DECODING_LENGTH_FAIL;
+ }
+ ctx.adlen = (uint32_t) encoded_len;
+ ctx.saltlen = (uint32_t) encoded_len;
+ ctx.outlen = (uint32_t) encoded_len;
+
+ ctx.ad = (uint8_t *) malloc(ctx.adlen);
+ ctx.salt = (uint8_t *) malloc(ctx.saltlen);
+ ctx.out = (uint8_t *) malloc(ctx.outlen);
+ if (!ctx.out || !ctx.salt || !ctx.ad) {
+ free(ctx.ad);
+ free(ctx.salt);
+ free(ctx.out);
+ return ARGON2_MEMORY_ALLOCATION_ERROR;
+ }
+ out = (uint8_t *) malloc(ctx.outlen);
+ if (!out) {
+ free(ctx.ad);
+ free(ctx.salt);
+ free(ctx.out);
+ return ARGON2_MEMORY_ALLOCATION_ERROR;
+ }
+
+ decode_result = decode_string(&ctx, encoded, type);
+ if (decode_result != ARGON2_OK) {
+ free(ctx.ad);
+ free(ctx.salt);
+ free(ctx.out);
+ free(out);
+ return decode_result;
+ }
+
+ ret = argon2_hash(ctx.t_cost, ctx.m_cost, ctx.threads, pwd, pwdlen,
+ ctx.salt, ctx.saltlen, out, ctx.outlen, NULL, 0, type);
+
+ free(ctx.ad);
+ free(ctx.salt);
+
+ if (ret != ARGON2_OK || sodium_memcmp(out, ctx.out, ctx.outlen) != 0) {
+ ret = ARGON2_VERIFY_MISMATCH;
+ }
+ free(out);
+ free(ctx.out);
+
+ return ret;
+}
+
+int
+argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen)
+{
+ return argon2_verify(encoded, pwd, pwdlen, Argon2_i);
+}
+
+int
+argon2id_verify(const char *encoded, const void *pwd, const size_t pwdlen)
+{
+ return argon2_verify(encoded, pwd, pwdlen, Argon2_id);
+}
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/argon2.h b/libs/libsodium/src/crypto_pwhash/argon2/argon2.h
new file mode 100644
index 0000000000..85ca4dd373
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/argon2.h
@@ -0,0 +1,305 @@
+/*
+ * Argon2 source code package
+ *
+ * Written by Daniel Dinu and Dmitry Khovratovich, 2015
+ *
+ * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication along
+ * with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+#ifndef argon2_H
+#define argon2_H
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+ * Argon2 input parameter restrictions
+ */
+
+/* Minimum and maximum number of lanes (degree of parallelism) */
+#define ARGON2_MIN_LANES UINT32_C(1)
+#define ARGON2_MAX_LANES UINT32_C(0xFFFFFF)
+
+/* Minimum and maximum number of threads */
+#define ARGON2_MIN_THREADS UINT32_C(1)
+#define ARGON2_MAX_THREADS UINT32_C(0xFFFFFF)
+
+/* Number of synchronization points between lanes per pass */
+#define ARGON2_SYNC_POINTS UINT32_C(4)
+
+/* Minimum and maximum digest size in bytes */
+#define ARGON2_MIN_OUTLEN UINT32_C(16)
+#define ARGON2_MAX_OUTLEN UINT32_C(0xFFFFFFFF)
+
+/* Minimum and maximum number of memory blocks (each of BLOCK_SIZE bytes) */
+#define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS) /* 2 blocks per slice */
+
+#define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b))
+/* Max memory size is half the addressing space, topping at 2^32 blocks (4 TB)
+ */
+#define ARGON2_MAX_MEMORY_BITS \
+ ARGON2_MIN(UINT32_C(32), (sizeof(void *) * CHAR_BIT - 10 - 1))
+#define ARGON2_MAX_MEMORY \
+ ARGON2_MIN(UINT32_C(0xFFFFFFFF), UINT64_C(1) << ARGON2_MAX_MEMORY_BITS)
+
+/* Minimum and maximum number of passes */
+#define ARGON2_MIN_TIME UINT32_C(1)
+#define ARGON2_MAX_TIME UINT32_C(0xFFFFFFFF)
+
+/* Minimum and maximum password length in bytes */
+#define ARGON2_MIN_PWD_LENGTH UINT32_C(0)
+#define ARGON2_MAX_PWD_LENGTH UINT32_C(0xFFFFFFFF)
+
+/* Minimum and maximum associated data length in bytes */
+#define ARGON2_MIN_AD_LENGTH UINT32_C(0)
+#define ARGON2_MAX_AD_LENGTH UINT32_C(0xFFFFFFFF)
+
+/* Minimum and maximum salt length in bytes */
+#define ARGON2_MIN_SALT_LENGTH UINT32_C(8)
+#define ARGON2_MAX_SALT_LENGTH UINT32_C(0xFFFFFFFF)
+
+/* Minimum and maximum key length in bytes */
+#define ARGON2_MIN_SECRET UINT32_C(0)
+#define ARGON2_MAX_SECRET UINT32_C(0xFFFFFFFF)
+
+#define ARGON2_FLAG_CLEAR_PASSWORD (UINT32_C(1) << 0)
+#define ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1)
+#define ARGON2_FLAG_CLEAR_MEMORY (UINT32_C(1) << 2)
+#define ARGON2_DEFAULT_FLAGS (UINT32_C(0))
+
+/* Error codes */
+typedef enum Argon2_ErrorCodes {
+ ARGON2_OK = 0,
+
+ ARGON2_OUTPUT_PTR_NULL = -1,
+
+ ARGON2_OUTPUT_TOO_SHORT = -2,
+ ARGON2_OUTPUT_TOO_LONG = -3,
+
+ ARGON2_PWD_TOO_SHORT = -4,
+ ARGON2_PWD_TOO_LONG = -5,
+
+ ARGON2_SALT_TOO_SHORT = -6,
+ ARGON2_SALT_TOO_LONG = -7,
+
+ ARGON2_AD_TOO_SHORT = -8,
+ ARGON2_AD_TOO_LONG = -9,
+
+ ARGON2_SECRET_TOO_SHORT = -10,
+ ARGON2_SECRET_TOO_LONG = -11,
+
+ ARGON2_TIME_TOO_SMALL = -12,
+ ARGON2_TIME_TOO_LARGE = -13,
+
+ ARGON2_MEMORY_TOO_LITTLE = -14,
+ ARGON2_MEMORY_TOO_MUCH = -15,
+
+ ARGON2_LANES_TOO_FEW = -16,
+ ARGON2_LANES_TOO_MANY = -17,
+
+ ARGON2_PWD_PTR_MISMATCH = -18, /* NULL ptr with non-zero length */
+ ARGON2_SALT_PTR_MISMATCH = -19, /* NULL ptr with non-zero length */
+ ARGON2_SECRET_PTR_MISMATCH = -20, /* NULL ptr with non-zero length */
+ ARGON2_AD_PTR_MISMATCH = -21, /* NULL ptr with non-zero length */
+
+ ARGON2_MEMORY_ALLOCATION_ERROR = -22,
+
+ ARGON2_FREE_MEMORY_CBK_NULL = -23,
+ ARGON2_ALLOCATE_MEMORY_CBK_NULL = -24,
+
+ ARGON2_INCORRECT_PARAMETER = -25,
+ ARGON2_INCORRECT_TYPE = -26,
+
+ ARGON2_OUT_PTR_MISMATCH = -27,
+
+ ARGON2_THREADS_TOO_FEW = -28,
+ ARGON2_THREADS_TOO_MANY = -29,
+
+ ARGON2_MISSING_ARGS = -30,
+
+ ARGON2_ENCODING_FAIL = -31,
+
+ ARGON2_DECODING_FAIL = -32,
+
+ ARGON2_THREAD_FAIL = -33,
+
+ ARGON2_DECODING_LENGTH_FAIL = -34,
+
+ ARGON2_VERIFY_MISMATCH = -35
+} argon2_error_codes;
+
+/* Argon2 external data structures */
+
+/*
+ * Context: structure to hold Argon2 inputs:
+ * output array and its length,
+ * password and its length,
+ * salt and its length,
+ * secret and its length,
+ * associated data and its length,
+ * number of passes, amount of used memory (in KBytes, can be rounded up a bit)
+ * number of parallel threads that will be run.
+ * All the parameters above affect the output hash value.
+ * Additionally, two function pointers can be provided to allocate and
+ * deallocate the memory (if NULL, memory will be allocated internally).
+ * Also, three flags indicate whether to erase password, secret as soon as they
+ * are pre-hashed (and thus not needed anymore), and the entire memory
+ *****
+ * Simplest situation: you have output array out[8], password is stored in
+ * pwd[32], salt is stored in salt[16], you do not have keys nor associated
+ *data.
+ * You need to spend 1 GB of RAM and you run 5 passes of Argon2 with 4 parallel
+ *lanes.
+ * You want to erase the password, but you're OK with last pass not being
+ *erased.
+ * You want to use the default memory allocator.
+ * Then you initialize:
+ * Argon2_Context(out,8,pwd,32,salt,16,NULL,0,NULL,0,5,1<<20,4,4,NULL,NULL,true,false,false,false).
+ */
+typedef struct Argon2_Context {
+ uint8_t *out; /* output array */
+ uint32_t outlen; /* digest length */
+
+ uint8_t *pwd; /* password array */
+ uint32_t pwdlen; /* password length */
+
+ uint8_t *salt; /* salt array */
+ uint32_t saltlen; /* salt length */
+
+ uint8_t *secret; /* key array */
+ uint32_t secretlen; /* key length */
+
+ uint8_t *ad; /* associated data array */
+ uint32_t adlen; /* associated data length */
+
+ uint32_t t_cost; /* number of passes */
+ uint32_t m_cost; /* amount of memory requested (KB) */
+ uint32_t lanes; /* number of lanes */
+ uint32_t threads; /* maximum number of threads */
+
+ uint32_t flags; /* array of bool options */
+} argon2_context;
+
+/* Argon2 primitive type */
+typedef enum Argon2_type { Argon2_i = 1, Argon2_id = 2 } argon2_type;
+
+/*
+ * Function that performs memory-hard hashing with certain degree of parallelism
+ * @param context Pointer to the Argon2 internal structure
+ * @return Error code if smth is wrong, ARGON2_OK otherwise
+ */
+int argon2_ctx(argon2_context *context, argon2_type type);
+
+/**
+ * Hashes a password with Argon2i, producing an encoded hash
+ * @param t_cost Number of iterations
+ * @param m_cost Sets memory usage to m_cost kibibytes
+ * @param parallelism Number of threads and compute lanes
+ * @param pwd Pointer to password
+ * @param pwdlen Password size in bytes
+ * @param salt Pointer to salt
+ * @param saltlen Salt size in bytes
+ * @param hashlen Desired length of the hash in bytes
+ * @param encoded Buffer where to write the encoded hash
+ * @param encodedlen Size of the buffer (thus max size of the encoded hash)
+ * @pre Different parallelism levels will give different results
+ * @pre Returns ARGON2_OK if successful
+ */
+int argon2i_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt,
+ const size_t saltlen, const size_t hashlen,
+ char *encoded, const size_t encodedlen);
+
+/**
+ * Hashes a password with Argon2id, producing an encoded hash
+ * @param t_cost Number of iterations
+ * @param m_cost Sets memory usage to m_cost kibibytes
+ * @param parallelism Number of threads and compute lanes
+ * @param pwd Pointer to password
+ * @param pwdlen Password size in bytes
+ * @param salt Pointer to salt
+ * @param saltlen Salt size in bytes
+ * @param hashlen Desired length of the hash in bytes
+ * @param encoded Buffer where to write the encoded hash
+ * @param encodedlen Size of the buffer (thus max size of the encoded hash)
+ * @pre Different parallelism levels will give different results
+ * @pre Returns ARGON2_OK if successful
+ */
+int argon2id_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt,
+ const size_t saltlen, const size_t hashlen,
+ char *encoded, const size_t encodedlen);
+
+/**
+ * Hashes a password with Argon2i, producing a raw hash
+ * @param t_cost Number of iterations
+ * @param m_cost Sets memory usage to m_cost kibibytes
+ * @param parallelism Number of threads and compute lanes
+ * @param pwd Pointer to password
+ * @param pwdlen Password size in bytes
+ * @param salt Pointer to salt
+ * @param saltlen Salt size in bytes
+ * @param hash Buffer where to write the raw hash
+ * @param hashlen Desired length of the hash in bytes
+ * @pre Different parallelism levels will give different results
+ * @pre Returns ARGON2_OK if successful
+ */
+int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt,
+ const size_t saltlen, void *hash, const size_t hashlen);
+
+/**
+ * Hashes a password with Argon2id, producing a raw hash
+ * @param t_cost Number of iterations
+ * @param m_cost Sets memory usage to m_cost kibibytes
+ * @param parallelism Number of threads and compute lanes
+ * @param pwd Pointer to password
+ * @param pwdlen Password size in bytes
+ * @param salt Pointer to salt
+ * @param saltlen Salt size in bytes
+ * @param hash Buffer where to write the raw hash
+ * @param hashlen Desired length of the hash in bytes
+ * @pre Different parallelism levels will give different results
+ * @pre Returns ARGON2_OK if successful
+ */
+int argon2id_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt,
+ const size_t saltlen, void *hash, const size_t hashlen);
+
+/* generic function underlying the above ones */
+int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt, const size_t saltlen,
+ void *hash, const size_t hashlen, char *encoded,
+ const size_t encodedlen, argon2_type type);
+
+/**
+ * Verifies a password against an encoded string
+ * Encoded string is restricted as in validate_inputs()
+ * @param encoded String encoding parameters, salt, hash
+ * @param pwd Pointer to password
+ * @pre Returns ARGON2_OK if successful
+ */
+int argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen);
+
+/**
+ * Verifies a password against an encoded string
+ * Encoded string is restricted as in validate_inputs()
+ * @param encoded String encoding parameters, salt, hash
+ * @param pwd Pointer to password
+ * @pre Returns ARGON2_OK if successful
+ */
+int argon2id_verify(const char *encoded, const void *pwd, const size_t pwdlen);
+
+/* generic function underlying the above ones */
+int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
+ argon2_type type);
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/blake2b-long.c b/libs/libsodium/src/crypto_pwhash/argon2/blake2b-long.c
new file mode 100644
index 0000000000..f0364aca87
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/blake2b-long.c
@@ -0,0 +1,79 @@
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "crypto_generichash_blake2b.h"
+#include "private/common.h"
+#include "utils.h"
+
+#include "blake2b-long.h"
+
+int
+blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen)
+{
+ uint8_t *out = (uint8_t *) pout;
+ crypto_generichash_blake2b_state blake_state;
+ uint8_t outlen_bytes[4 /* sizeof(uint32_t) */] = { 0 };
+ int ret = -1;
+
+ if (outlen > UINT32_MAX) {
+ goto fail; /* LCOV_EXCL_LINE */
+ }
+
+ /* Ensure little-endian byte order! */
+ STORE32_LE(outlen_bytes, (uint32_t) outlen);
+
+#define TRY(statement) \
+ do { \
+ ret = statement; \
+ if (ret < 0) { \
+ goto fail; \
+ } \
+ } while ((void) 0, 0)
+
+ if (outlen <= crypto_generichash_blake2b_BYTES_MAX) {
+ TRY(crypto_generichash_blake2b_init(&blake_state, NULL, 0U, outlen));
+ TRY(crypto_generichash_blake2b_update(&blake_state, outlen_bytes,
+ sizeof(outlen_bytes)));
+ TRY(crypto_generichash_blake2b_update(
+ &blake_state, (const unsigned char *) in, inlen));
+ TRY(crypto_generichash_blake2b_final(&blake_state, out, outlen));
+ } else {
+ uint32_t toproduce;
+ uint8_t out_buffer[crypto_generichash_blake2b_BYTES_MAX];
+ uint8_t in_buffer[crypto_generichash_blake2b_BYTES_MAX];
+ TRY(crypto_generichash_blake2b_init(
+ &blake_state, NULL, 0U, crypto_generichash_blake2b_BYTES_MAX));
+ TRY(crypto_generichash_blake2b_update(&blake_state, outlen_bytes,
+ sizeof(outlen_bytes)));
+ TRY(crypto_generichash_blake2b_update(
+ &blake_state, (const unsigned char *) in, inlen));
+ TRY(crypto_generichash_blake2b_final(
+ &blake_state, out_buffer, crypto_generichash_blake2b_BYTES_MAX));
+ memcpy(out, out_buffer, crypto_generichash_blake2b_BYTES_MAX / 2);
+ out += crypto_generichash_blake2b_BYTES_MAX / 2;
+ toproduce =
+ (uint32_t) outlen - crypto_generichash_blake2b_BYTES_MAX / 2;
+
+ while (toproduce > crypto_generichash_blake2b_BYTES_MAX) {
+ memcpy(in_buffer, out_buffer, crypto_generichash_blake2b_BYTES_MAX);
+ TRY(crypto_generichash_blake2b(
+ out_buffer, crypto_generichash_blake2b_BYTES_MAX, in_buffer,
+ crypto_generichash_blake2b_BYTES_MAX, NULL, 0U));
+ memcpy(out, out_buffer, crypto_generichash_blake2b_BYTES_MAX / 2);
+ out += crypto_generichash_blake2b_BYTES_MAX / 2;
+ toproduce -= crypto_generichash_blake2b_BYTES_MAX / 2;
+ }
+
+ memcpy(in_buffer, out_buffer, crypto_generichash_blake2b_BYTES_MAX);
+ TRY(crypto_generichash_blake2b(out_buffer, toproduce, in_buffer,
+ crypto_generichash_blake2b_BYTES_MAX,
+ NULL, 0U));
+ memcpy(out, out_buffer, toproduce);
+ }
+fail:
+ sodium_memzero(&blake_state, sizeof(blake_state));
+ return ret;
+#undef TRY
+}
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/blake2b-long.h b/libs/libsodium/src/crypto_pwhash/argon2/blake2b-long.h
new file mode 100644
index 0000000000..3d6d775521
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/blake2b-long.h
@@ -0,0 +1,8 @@
+#ifndef blake2b_long_H
+#define blake2b_long_H
+
+#include <stddef.h>
+
+int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen);
+
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-avx2.h b/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-avx2.h
new file mode 100644
index 0000000000..f3dfa0f506
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-avx2.h
@@ -0,0 +1,150 @@
+#ifndef blamka_round_avx2_H
+#define blamka_round_avx2_H
+
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#define rotr32(x) _mm256_shuffle_epi32(x, _MM_SHUFFLE(2, 3, 0, 1))
+#define rotr24(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10, 3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
+#define rotr16(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9, 2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
+#define rotr63(x) _mm256_xor_si256(_mm256_srli_epi64((x), 63), _mm256_add_epi64((x), (x)))
+
+#define G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ __m256i ml = _mm256_mul_epu32(A0, B0); \
+ ml = _mm256_add_epi64(ml, ml); \
+ A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \
+ D0 = _mm256_xor_si256(D0, A0); \
+ D0 = rotr32(D0); \
+ \
+ ml = _mm256_mul_epu32(C0, D0); \
+ ml = _mm256_add_epi64(ml, ml); \
+ C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \
+ \
+ B0 = _mm256_xor_si256(B0, C0); \
+ B0 = rotr24(B0); \
+ \
+ ml = _mm256_mul_epu32(A1, B1); \
+ ml = _mm256_add_epi64(ml, ml); \
+ A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \
+ D1 = _mm256_xor_si256(D1, A1); \
+ D1 = rotr32(D1); \
+ \
+ ml = _mm256_mul_epu32(C1, D1); \
+ ml = _mm256_add_epi64(ml, ml); \
+ C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \
+ \
+ B1 = _mm256_xor_si256(B1, C1); \
+ B1 = rotr24(B1); \
+ } while((void)0, 0);
+
+#define G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ __m256i ml = _mm256_mul_epu32(A0, B0); \
+ ml = _mm256_add_epi64(ml, ml); \
+ A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \
+ D0 = _mm256_xor_si256(D0, A0); \
+ D0 = rotr16(D0); \
+ \
+ ml = _mm256_mul_epu32(C0, D0); \
+ ml = _mm256_add_epi64(ml, ml); \
+ C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \
+ B0 = _mm256_xor_si256(B0, C0); \
+ B0 = rotr63(B0); \
+ \
+ ml = _mm256_mul_epu32(A1, B1); \
+ ml = _mm256_add_epi64(ml, ml); \
+ A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \
+ D1 = _mm256_xor_si256(D1, A1); \
+ D1 = rotr16(D1); \
+ \
+ ml = _mm256_mul_epu32(C1, D1); \
+ ml = _mm256_add_epi64(ml, ml); \
+ C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \
+ B1 = _mm256_xor_si256(B1, C1); \
+ B1 = rotr63(B1); \
+ } while((void)0, 0);
+
+#define DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \
+ C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
+ D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \
+ \
+ B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \
+ C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
+ D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \
+ } while((void)0, 0);
+
+#define DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ __m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \
+ __m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \
+ B1 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
+ B0 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
+ \
+ tmp1 = C0; \
+ C0 = C1; \
+ C1 = tmp1; \
+ \
+ tmp1 = _mm256_blend_epi32(D0, D1, 0xCC); \
+ tmp2 = _mm256_blend_epi32(D0, D1, 0x33); \
+ D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
+ D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
+ } while(0);
+
+#define UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \
+ C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
+ D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \
+ \
+ B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \
+ C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
+ D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \
+ } while((void)0, 0);
+
+#define UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ __m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \
+ __m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \
+ B0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
+ B1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
+ \
+ tmp1 = C0; \
+ C0 = C1; \
+ C1 = tmp1; \
+ \
+ tmp1 = _mm256_blend_epi32(D0, D1, 0x33); \
+ tmp2 = _mm256_blend_epi32(D0, D1, 0xCC); \
+ D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
+ D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
+ } while((void)0, 0);
+
+#define BLAKE2_ROUND_1(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do{ \
+ G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ \
+ DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
+ \
+ G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ \
+ UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
+ } while((void)0, 0);
+
+#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do{ \
+ G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ \
+ DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ \
+ G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ \
+ UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ } while((void)0, 0);
+
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-avx512f.h b/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-avx512f.h
new file mode 100644
index 0000000000..9a822402d8
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-avx512f.h
@@ -0,0 +1,145 @@
+#ifndef blamka_round_avx512f_H
+#define blamka_round_avx512f_H
+
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#define ror64(x, n) _mm512_ror_epi64((x), (n))
+
+static inline __m512i
+muladd(__m512i x, __m512i y)
+{
+ __m512i z = _mm512_mul_epu32(x, y);
+
+ return _mm512_add_epi64(_mm512_add_epi64(x, y), _mm512_add_epi64(z, z));
+}
+
+#define G1_AVX512F(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ A0 = muladd(A0, B0); \
+ A1 = muladd(A1, B1); \
+ \
+ D0 = _mm512_xor_si512(D0, A0); \
+ D1 = _mm512_xor_si512(D1, A1); \
+ \
+ D0 = ror64(D0, 32); \
+ D1 = ror64(D1, 32); \
+ \
+ C0 = muladd(C0, D0); \
+ C1 = muladd(C1, D1); \
+ \
+ B0 = _mm512_xor_si512(B0, C0); \
+ B1 = _mm512_xor_si512(B1, C1); \
+ \
+ B0 = ror64(B0, 24); \
+ B1 = ror64(B1, 24); \
+ } while ((void)0, 0)
+
+#define G2_AVX512F(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ A0 = muladd(A0, B0); \
+ A1 = muladd(A1, B1); \
+ \
+ D0 = _mm512_xor_si512(D0, A0); \
+ D1 = _mm512_xor_si512(D1, A1); \
+ \
+ D0 = ror64(D0, 16); \
+ D1 = ror64(D1, 16); \
+ \
+ C0 = muladd(C0, D0); \
+ C1 = muladd(C1, D1); \
+ \
+ B0 = _mm512_xor_si512(B0, C0); \
+ B1 = _mm512_xor_si512(B1, C1); \
+ \
+ B0 = ror64(B0, 63); \
+ B1 = ror64(B1, 63); \
+ } while ((void)0, 0)
+
+#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \
+ B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \
+ \
+ C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
+ C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
+ \
+ D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \
+ D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \
+ } while ((void)0, 0)
+
+#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \
+ B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \
+ \
+ C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
+ C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
+ \
+ D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \
+ D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \
+ } while ((void)0, 0)
+
+#define BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ G1_AVX512F(A0, B0, C0, D0, A1, B1, C1, D1); \
+ G2_AVX512F(A0, B0, C0, D0, A1, B1, C1, D1); \
+ \
+ DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
+ \
+ G1_AVX512F(A0, B0, C0, D0, A1, B1, C1, D1); \
+ G2_AVX512F(A0, B0, C0, D0, A1, B1, C1, D1); \
+ \
+ UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
+ } while ((void)0, 0)
+
+#define SWAP_HALVES(A0, A1) \
+ do { \
+ __m512i t0, t1; \
+ t0 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(1, 0, 1, 0)); \
+ t1 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(3, 2, 3, 2)); \
+ A0 = t0; \
+ A1 = t1; \
+ } while((void)0, 0)
+
+#define SWAP_QUARTERS(A0, A1) \
+ do { \
+ SWAP_HALVES(A0, A1); \
+ A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \
+ A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \
+ } while((void)0, 0)
+
+#define UNSWAP_QUARTERS(A0, A1) \
+ do { \
+ A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \
+ A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \
+ SWAP_HALVES(A0, A1); \
+ } while((void)0, 0)
+
+#define BLAKE2_ROUND_1(A0, C0, B0, D0, A1, C1, B1, D1) \
+ do { \
+ SWAP_HALVES(A0, B0); \
+ SWAP_HALVES(C0, D0); \
+ SWAP_HALVES(A1, B1); \
+ SWAP_HALVES(C1, D1); \
+ BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \
+ SWAP_HALVES(A0, B0); \
+ SWAP_HALVES(C0, D0); \
+ SWAP_HALVES(A1, B1); \
+ SWAP_HALVES(C1, D1); \
+ } while ((void)0, 0)
+
+#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ SWAP_QUARTERS(A0, A1); \
+ SWAP_QUARTERS(B0, B1); \
+ SWAP_QUARTERS(C0, C1); \
+ SWAP_QUARTERS(D0, D1); \
+ BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \
+ UNSWAP_QUARTERS(A0, A1); \
+ UNSWAP_QUARTERS(B0, B1); \
+ UNSWAP_QUARTERS(C0, C1); \
+ UNSWAP_QUARTERS(D0, D1); \
+ } while ((void)0, 0)
+
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-ref.h b/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-ref.h
new file mode 100644
index 0000000000..7a2c6eb20e
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-ref.h
@@ -0,0 +1,40 @@
+#ifndef blamka_round_ref_H
+#define blamka_round_ref_H
+
+#include "private/common.h"
+
+/*designed by the Lyra PHC team */
+static inline uint64_t
+fBlaMka(uint64_t x, uint64_t y)
+{
+ const uint64_t m = UINT64_C(0xFFFFFFFF);
+ const uint64_t xy = (x & m) * (y & m);
+ return x + y + 2 * xy;
+}
+
+#define G(a, b, c, d) \
+ do { \
+ a = fBlaMka(a, b); \
+ d = ROTR64(d ^ a, 32); \
+ c = fBlaMka(c, d); \
+ b = ROTR64(b ^ c, 24); \
+ a = fBlaMka(a, b); \
+ d = ROTR64(d ^ a, 16); \
+ c = fBlaMka(c, d); \
+ b = ROTR64(b ^ c, 63); \
+ } while ((void) 0, 0)
+
+#define BLAKE2_ROUND_NOMSG(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, \
+ v12, v13, v14, v15) \
+ do { \
+ G(v0, v4, v8, v12); \
+ G(v1, v5, v9, v13); \
+ G(v2, v6, v10, v14); \
+ G(v3, v7, v11, v15); \
+ G(v0, v5, v10, v15); \
+ G(v1, v6, v11, v12); \
+ G(v2, v7, v8, v13); \
+ G(v3, v4, v9, v14); \
+ } while ((void) 0, 0)
+
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-ssse3.h b/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-ssse3.h
new file mode 100644
index 0000000000..98a47b93f8
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/blamka-round-ssse3.h
@@ -0,0 +1,120 @@
+#ifndef blamka_round_ssse3_H
+#define blamka_round_ssse3_H
+
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#define r16 \
+ (_mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
+#define r24 \
+ (_mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
+#define _mm_roti_epi64(x, c) \
+ (-(c) == 32) \
+ ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1)) \
+ : (-(c) == 24) \
+ ? _mm_shuffle_epi8((x), r24) \
+ : (-(c) == 16) \
+ ? _mm_shuffle_epi8((x), r16) \
+ : (-(c) == 63) \
+ ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
+ _mm_add_epi64((x), (x))) \
+ : _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
+ _mm_slli_epi64((x), 64 - (-(c))))
+
+static inline __m128i
+fBlaMka(__m128i x, __m128i y)
+{
+ const __m128i z = _mm_mul_epu32(x, y);
+ return _mm_add_epi64(_mm_add_epi64(x, y), _mm_add_epi64(z, z));
+}
+
+#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ A0 = fBlaMka(A0, B0); \
+ A1 = fBlaMka(A1, B1); \
+ \
+ D0 = _mm_xor_si128(D0, A0); \
+ D1 = _mm_xor_si128(D1, A1); \
+ \
+ D0 = _mm_roti_epi64(D0, -32); \
+ D1 = _mm_roti_epi64(D1, -32); \
+ \
+ C0 = fBlaMka(C0, D0); \
+ C1 = fBlaMka(C1, D1); \
+ \
+ B0 = _mm_xor_si128(B0, C0); \
+ B1 = _mm_xor_si128(B1, C1); \
+ \
+ B0 = _mm_roti_epi64(B0, -24); \
+ B1 = _mm_roti_epi64(B1, -24); \
+ } while ((void) 0, 0)
+
+#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ A0 = fBlaMka(A0, B0); \
+ A1 = fBlaMka(A1, B1); \
+ \
+ D0 = _mm_xor_si128(D0, A0); \
+ D1 = _mm_xor_si128(D1, A1); \
+ \
+ D0 = _mm_roti_epi64(D0, -16); \
+ D1 = _mm_roti_epi64(D1, -16); \
+ \
+ C0 = fBlaMka(C0, D0); \
+ C1 = fBlaMka(C1, D1); \
+ \
+ B0 = _mm_xor_si128(B0, C0); \
+ B1 = _mm_xor_si128(B1, C1); \
+ \
+ B0 = _mm_roti_epi64(B0, -63); \
+ B1 = _mm_roti_epi64(B1, -63); \
+ } while ((void) 0, 0)
+
+#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ __m128i t0 = _mm_alignr_epi8(B1, B0, 8); \
+ __m128i t1 = _mm_alignr_epi8(B0, B1, 8); \
+ B0 = t0; \
+ B1 = t1; \
+ \
+ t0 = C0; \
+ C0 = C1; \
+ C1 = t0; \
+ \
+ t0 = _mm_alignr_epi8(D1, D0, 8); \
+ t1 = _mm_alignr_epi8(D0, D1, 8); \
+ D0 = t1; \
+ D1 = t0; \
+ } while ((void) 0, 0)
+
+#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ __m128i t0 = _mm_alignr_epi8(B0, B1, 8); \
+ __m128i t1 = _mm_alignr_epi8(B1, B0, 8); \
+ B0 = t0; \
+ B1 = t1; \
+ \
+ t0 = C0; \
+ C0 = C1; \
+ C1 = t0; \
+ \
+ t0 = _mm_alignr_epi8(D0, D1, 8); \
+ t1 = _mm_alignr_epi8(D1, D0, 8); \
+ D0 = t1; \
+ D1 = t0; \
+ } while ((void) 0, 0)
+
+#define BLAKE2_ROUND(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ G1(A0, B0, C0, D0, A1, B1, C1, D1); \
+ G2(A0, B0, C0, D0, A1, B1, C1, D1); \
+ \
+ DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
+ \
+ G1(A0, B0, C0, D0, A1, B1, C1, D1); \
+ G2(A0, B0, C0, D0, A1, B1, C1, D1); \
+ \
+ UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
+ } while ((void) 0, 0)
+
+#endif
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/pwhash_argon2i.c b/libs/libsodium/src/crypto_pwhash/argon2/pwhash_argon2i.c
new file mode 100644
index 0000000000..0515bd6135
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/pwhash_argon2i.c
@@ -0,0 +1,290 @@
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "argon2-core.h"
+#include "argon2-encoding.h"
+#include "argon2.h"
+#include "crypto_pwhash.h"
+#include "crypto_pwhash_argon2i.h"
+#include "crypto_pwhash_argon2id.h"
+#include "private/common.h"
+#include "randombytes.h"
+#include "utils.h"
+
+#define STR_HASHBYTES 32U
+
+int
+crypto_pwhash_argon2i_alg_argon2i13(void)
+{
+ return crypto_pwhash_argon2i_ALG_ARGON2I13;
+}
+
+size_t
+crypto_pwhash_argon2i_bytes_min(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2i_BYTES_MIN >= ARGON2_MIN_OUTLEN);
+ return crypto_pwhash_argon2i_BYTES_MIN;
+}
+
+size_t
+crypto_pwhash_argon2i_bytes_max(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2i_BYTES_MAX <= ARGON2_MAX_OUTLEN);
+ return crypto_pwhash_argon2i_BYTES_MAX;
+}
+
+size_t
+crypto_pwhash_argon2i_passwd_min(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2i_PASSWD_MIN >= ARGON2_MIN_PWD_LENGTH);
+ return crypto_pwhash_argon2i_PASSWD_MIN;
+}
+
+size_t
+crypto_pwhash_argon2i_passwd_max(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2i_PASSWD_MAX <= ARGON2_MAX_PWD_LENGTH);
+ return crypto_pwhash_argon2i_PASSWD_MAX;
+}
+
+size_t
+crypto_pwhash_argon2i_saltbytes(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2i_SALTBYTES >= ARGON2_MIN_SALT_LENGTH);
+ COMPILER_ASSERT(crypto_pwhash_argon2i_SALTBYTES <= ARGON2_MAX_SALT_LENGTH);
+ return crypto_pwhash_argon2i_SALTBYTES;
+}
+
+size_t
+crypto_pwhash_argon2i_strbytes(void)
+{
+ return crypto_pwhash_argon2i_STRBYTES;
+}
+
+const char*
+crypto_pwhash_argon2i_strprefix(void)
+{
+ return crypto_pwhash_argon2i_STRPREFIX;
+}
+
+size_t
+crypto_pwhash_argon2i_opslimit_min(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2i_OPSLIMIT_MIN >= ARGON2_MIN_TIME);
+ return crypto_pwhash_argon2i_OPSLIMIT_MIN;
+}
+
+size_t
+crypto_pwhash_argon2i_opslimit_max(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2i_OPSLIMIT_MAX <= ARGON2_MAX_TIME);
+ return crypto_pwhash_argon2i_OPSLIMIT_MAX;
+}
+
+size_t
+crypto_pwhash_argon2i_memlimit_min(void)
+{
+ COMPILER_ASSERT((crypto_pwhash_argon2i_MEMLIMIT_MIN / 1024U) >= ARGON2_MIN_MEMORY);
+ return crypto_pwhash_argon2i_MEMLIMIT_MIN;
+}
+
+size_t
+crypto_pwhash_argon2i_memlimit_max(void)
+{
+ COMPILER_ASSERT((crypto_pwhash_argon2i_MEMLIMIT_MAX / 1024U) <= ARGON2_MAX_MEMORY);
+ return crypto_pwhash_argon2i_MEMLIMIT_MAX;
+}
+
+size_t
+crypto_pwhash_argon2i_opslimit_interactive(void)
+{
+ return crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_argon2i_memlimit_interactive(void)
+{
+ return crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_argon2i_opslimit_moderate(void)
+{
+ return crypto_pwhash_argon2i_OPSLIMIT_MODERATE;
+}
+
+size_t
+crypto_pwhash_argon2i_memlimit_moderate(void)
+{
+ return crypto_pwhash_argon2i_MEMLIMIT_MODERATE;
+}
+
+size_t
+crypto_pwhash_argon2i_opslimit_sensitive(void)
+{
+ return crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE;
+}
+
+size_t
+crypto_pwhash_argon2i_memlimit_sensitive(void)
+{
+ return crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE;
+}
+
+int
+crypto_pwhash_argon2i(unsigned char *const out, unsigned long long outlen,
+ const char *const passwd, unsigned long long passwdlen,
+ const unsigned char *const salt,
+ unsigned long long opslimit, size_t memlimit, int alg)
+{
+ memset(out, 0, outlen);
+ if (outlen > crypto_pwhash_argon2i_BYTES_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (outlen < crypto_pwhash_argon2i_BYTES_MIN) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX ||
+ opslimit > crypto_pwhash_argon2i_OPSLIMIT_MAX ||
+ memlimit > crypto_pwhash_argon2i_MEMLIMIT_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN ||
+ opslimit < crypto_pwhash_argon2i_OPSLIMIT_MIN ||
+ memlimit < crypto_pwhash_argon2i_MEMLIMIT_MIN) {
+ errno = EINVAL;
+ return -1;
+ }
+ switch (alg) {
+ case crypto_pwhash_argon2i_ALG_ARGON2I13:
+ if (argon2i_hash_raw((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
+ (uint32_t) 1U, passwd, (size_t) passwdlen, salt,
+ (size_t) crypto_pwhash_argon2i_SALTBYTES, out,
+ (size_t) outlen) != ARGON2_OK) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return 0;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+}
+
+int
+crypto_pwhash_argon2i_str(char out[crypto_pwhash_argon2i_STRBYTES],
+ const char *const passwd,
+ unsigned long long passwdlen,
+ unsigned long long opslimit, size_t memlimit)
+{
+ unsigned char salt[crypto_pwhash_argon2i_SALTBYTES];
+
+ memset(out, 0, crypto_pwhash_argon2i_STRBYTES);
+ if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX ||
+ opslimit > crypto_pwhash_argon2i_OPSLIMIT_MAX ||
+ memlimit > crypto_pwhash_argon2i_MEMLIMIT_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN ||
+ opslimit < crypto_pwhash_argon2i_OPSLIMIT_MIN ||
+ memlimit < crypto_pwhash_argon2i_MEMLIMIT_MIN) {
+ errno = EINVAL;
+ return -1;
+ }
+ randombytes_buf(salt, sizeof salt);
+ if (argon2i_hash_encoded((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
+ (uint32_t) 1U, passwd, (size_t) passwdlen, salt,
+ sizeof salt, STR_HASHBYTES, out,
+ crypto_pwhash_argon2i_STRBYTES) != ARGON2_OK) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return 0;
+}
+
+int
+crypto_pwhash_argon2i_str_verify(const char str[crypto_pwhash_argon2i_STRBYTES],
+ const char *const passwd,
+ unsigned long long passwdlen)
+{
+ int verify_ret;
+
+ if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ /* LCOV_EXCL_START */
+ if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN) {
+ errno = EINVAL;
+ return -1;
+ }
+ /* LCOV_EXCL_STOP */
+
+ verify_ret = argon2i_verify(str, passwd, (size_t) passwdlen);
+ if (verify_ret == ARGON2_OK) {
+ return 0;
+ }
+ if (verify_ret == ARGON2_VERIFY_MISMATCH) {
+ errno = EINVAL;
+ }
+ return -1;
+}
+
+static int
+_needs_rehash(const char *str, unsigned long long opslimit, size_t memlimit,
+ argon2_type type)
+{
+ unsigned char *fodder;
+ argon2_context ctx;
+ size_t fodder_len;
+ int ret = -1;
+
+ fodder_len = strlen(str);
+ memlimit /= 1024U;
+ if (opslimit > UINT32_MAX || memlimit > UINT32_MAX ||
+ fodder_len >= crypto_pwhash_STRBYTES) {
+ errno = EINVAL;
+ return -1;
+ }
+ memset(&ctx, 0, sizeof ctx);
+ if ((fodder = (unsigned char *) calloc(fodder_len, 1U)) == NULL) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ ctx.out = ctx.pwd = ctx.salt = fodder;
+ ctx.outlen = ctx.pwdlen = ctx.saltlen = (uint32_t) fodder_len;
+ ctx.ad = ctx.secret = NULL;
+ ctx.adlen = ctx.secretlen = 0U;
+ if (decode_string(&ctx, str, type) != 0) {
+ errno = EINVAL;
+ ret = -1;
+ } else if (ctx.t_cost != (uint32_t) opslimit ||
+ ctx.m_cost != (uint32_t) memlimit) {
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+ free(fodder);
+
+ return ret;
+}
+
+int
+crypto_pwhash_argon2i_str_needs_rehash(const char str[crypto_pwhash_argon2i_STRBYTES],
+ unsigned long long opslimit, size_t memlimit)
+{
+ return _needs_rehash(str, opslimit, memlimit, Argon2_i);
+}
+
+int
+crypto_pwhash_argon2id_str_needs_rehash(const char str[crypto_pwhash_argon2id_STRBYTES],
+ unsigned long long opslimit, size_t memlimit)
+{
+ return _needs_rehash(str, opslimit, memlimit, Argon2_id);
+}
diff --git a/libs/libsodium/src/crypto_pwhash/argon2/pwhash_argon2id.c b/libs/libsodium/src/crypto_pwhash/argon2/pwhash_argon2id.c
new file mode 100644
index 0000000000..99d3e219bf
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/argon2/pwhash_argon2id.c
@@ -0,0 +1,234 @@
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "argon2-core.h"
+#include "argon2.h"
+#include "crypto_pwhash_argon2id.h"
+#include "private/common.h"
+#include "randombytes.h"
+#include "utils.h"
+
+#define STR_HASHBYTES 32U
+
+int
+crypto_pwhash_argon2id_alg_argon2id13(void)
+{
+ return crypto_pwhash_argon2id_ALG_ARGON2ID13;
+}
+
+size_t
+crypto_pwhash_argon2id_bytes_min(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2id_BYTES_MIN >= ARGON2_MIN_OUTLEN);
+ return crypto_pwhash_argon2id_BYTES_MIN;
+}
+
+size_t
+crypto_pwhash_argon2id_bytes_max(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2id_BYTES_MAX <= ARGON2_MAX_OUTLEN);
+ return crypto_pwhash_argon2id_BYTES_MAX;
+}
+
+size_t
+crypto_pwhash_argon2id_passwd_min(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2id_PASSWD_MIN >= ARGON2_MIN_PWD_LENGTH);
+ return crypto_pwhash_argon2id_PASSWD_MIN;
+}
+
+size_t
+crypto_pwhash_argon2id_passwd_max(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2id_PASSWD_MAX <= ARGON2_MAX_PWD_LENGTH);
+ return crypto_pwhash_argon2id_PASSWD_MAX;
+}
+
+size_t
+crypto_pwhash_argon2id_saltbytes(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2id_SALTBYTES >= ARGON2_MIN_SALT_LENGTH);
+ COMPILER_ASSERT(crypto_pwhash_argon2id_SALTBYTES <= ARGON2_MAX_SALT_LENGTH);
+ return crypto_pwhash_argon2id_SALTBYTES;
+}
+
+size_t
+crypto_pwhash_argon2id_strbytes(void)
+{
+ return crypto_pwhash_argon2id_STRBYTES;
+}
+
+const char*
+crypto_pwhash_argon2id_strprefix(void)
+{
+ return crypto_pwhash_argon2id_STRPREFIX;
+}
+
+size_t
+crypto_pwhash_argon2id_opslimit_min(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2id_OPSLIMIT_MIN >= ARGON2_MIN_TIME);
+ return crypto_pwhash_argon2id_OPSLIMIT_MIN;
+}
+
+size_t
+crypto_pwhash_argon2id_opslimit_max(void)
+{
+ COMPILER_ASSERT(crypto_pwhash_argon2id_OPSLIMIT_MAX <= ARGON2_MAX_TIME);
+ return crypto_pwhash_argon2id_OPSLIMIT_MAX;
+}
+
+size_t
+crypto_pwhash_argon2id_memlimit_min(void)
+{
+ COMPILER_ASSERT((crypto_pwhash_argon2id_MEMLIMIT_MIN / 1024U) >= ARGON2_MIN_MEMORY);
+ return crypto_pwhash_argon2id_MEMLIMIT_MIN;
+}
+
+size_t
+crypto_pwhash_argon2id_memlimit_max(void)
+{
+ COMPILER_ASSERT((crypto_pwhash_argon2id_MEMLIMIT_MAX / 1024U) <= ARGON2_MAX_MEMORY);
+ return crypto_pwhash_argon2id_MEMLIMIT_MAX;
+}
+
+size_t
+crypto_pwhash_argon2id_opslimit_interactive(void)
+{
+ return crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_argon2id_memlimit_interactive(void)
+{
+ return crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_argon2id_opslimit_moderate(void)
+{
+ return crypto_pwhash_argon2id_OPSLIMIT_MODERATE;
+}
+
+size_t
+crypto_pwhash_argon2id_memlimit_moderate(void)
+{
+ return crypto_pwhash_argon2id_MEMLIMIT_MODERATE;
+}
+
+size_t
+crypto_pwhash_argon2id_opslimit_sensitive(void)
+{
+ return crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE;
+}
+
+size_t
+crypto_pwhash_argon2id_memlimit_sensitive(void)
+{
+ return crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE;
+}
+
+int
+crypto_pwhash_argon2id(unsigned char *const out, unsigned long long outlen,
+ const char *const passwd, unsigned long long passwdlen,
+ const unsigned char *const salt,
+ unsigned long long opslimit, size_t memlimit, int alg)
+{
+ memset(out, 0, outlen);
+ if (outlen > crypto_pwhash_argon2id_BYTES_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (outlen < crypto_pwhash_argon2id_BYTES_MIN) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX ||
+ opslimit > crypto_pwhash_argon2id_OPSLIMIT_MAX ||
+ memlimit > crypto_pwhash_argon2id_MEMLIMIT_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN ||
+ opslimit < crypto_pwhash_argon2id_OPSLIMIT_MIN ||
+ memlimit < crypto_pwhash_argon2id_MEMLIMIT_MIN) {
+ errno = EINVAL;
+ return -1;
+ }
+ switch (alg) {
+ case crypto_pwhash_argon2id_ALG_ARGON2ID13:
+ if (argon2id_hash_raw((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
+ (uint32_t) 1U, passwd, (size_t) passwdlen, salt,
+ (size_t) crypto_pwhash_argon2id_SALTBYTES, out,
+ (size_t) outlen) != ARGON2_OK) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return 0;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+}
+
+int
+crypto_pwhash_argon2id_str(char out[crypto_pwhash_argon2id_STRBYTES],
+ const char *const passwd,
+ unsigned long long passwdlen,
+ unsigned long long opslimit, size_t memlimit)
+{
+ unsigned char salt[crypto_pwhash_argon2id_SALTBYTES];
+
+ memset(out, 0, crypto_pwhash_argon2id_STRBYTES);
+ if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX ||
+ opslimit > crypto_pwhash_argon2id_OPSLIMIT_MAX ||
+ memlimit > crypto_pwhash_argon2id_MEMLIMIT_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN ||
+ opslimit < crypto_pwhash_argon2id_OPSLIMIT_MIN ||
+ memlimit < crypto_pwhash_argon2id_MEMLIMIT_MIN) {
+ errno = EINVAL;
+ return -1;
+ }
+ randombytes_buf(salt, sizeof salt);
+ if (argon2id_hash_encoded((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
+ (uint32_t) 1U, passwd, (size_t) passwdlen, salt,
+ sizeof salt, STR_HASHBYTES, out,
+ crypto_pwhash_argon2id_STRBYTES) != ARGON2_OK) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return 0;
+}
+
+int
+crypto_pwhash_argon2id_str_verify(const char str[crypto_pwhash_argon2id_STRBYTES],
+ const char *const passwd,
+ unsigned long long passwdlen)
+{
+ int verify_ret;
+
+ if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ /* LCOV_EXCL_START */
+ if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN) {
+ errno = EINVAL;
+ return -1;
+ }
+ /* LCOV_EXCL_STOP */
+
+ verify_ret = argon2id_verify(str, passwd, (size_t) passwdlen);
+ if (verify_ret == ARGON2_OK) {
+ return 0;
+ }
+ if (verify_ret == ARGON2_VERIFY_MISMATCH) {
+ errno = EINVAL;
+ }
+ return -1;
+}
diff --git a/libs/libsodium/src/crypto_pwhash/crypto_pwhash.c b/libs/libsodium/src/crypto_pwhash/crypto_pwhash.c
new file mode 100644
index 0000000000..8168f96216
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/crypto_pwhash.c
@@ -0,0 +1,211 @@
+
+#include <errno.h>
+#include <string.h>
+
+#include "core.h"
+#include "crypto_pwhash.h"
+
+int
+crypto_pwhash_alg_argon2i13(void)
+{
+ return crypto_pwhash_ALG_ARGON2I13;
+}
+
+int
+crypto_pwhash_alg_argon2id13(void)
+{
+ return crypto_pwhash_ALG_ARGON2ID13;
+}
+
+int
+crypto_pwhash_alg_default(void)
+{
+ return crypto_pwhash_ALG_DEFAULT;
+}
+
+size_t
+crypto_pwhash_bytes_min(void)
+{
+ return crypto_pwhash_BYTES_MIN;
+}
+
+size_t
+crypto_pwhash_bytes_max(void)
+{
+ return crypto_pwhash_BYTES_MAX;
+}
+
+size_t
+crypto_pwhash_passwd_min(void)
+{
+ return crypto_pwhash_PASSWD_MIN;
+}
+
+size_t
+crypto_pwhash_passwd_max(void)
+{
+ return crypto_pwhash_PASSWD_MAX;
+}
+
+size_t
+crypto_pwhash_saltbytes(void)
+{
+ return crypto_pwhash_SALTBYTES;
+}
+
+size_t
+crypto_pwhash_strbytes(void)
+{
+ return crypto_pwhash_STRBYTES;
+}
+
+const char *
+crypto_pwhash_strprefix(void)
+{
+ return crypto_pwhash_STRPREFIX;
+}
+
+size_t
+crypto_pwhash_opslimit_min(void)
+{
+ return crypto_pwhash_OPSLIMIT_MIN;
+}
+
+size_t
+crypto_pwhash_opslimit_max(void)
+{
+ return crypto_pwhash_OPSLIMIT_MAX;
+}
+
+size_t
+crypto_pwhash_memlimit_min(void)
+{
+ return crypto_pwhash_MEMLIMIT_MIN;
+}
+
+size_t
+crypto_pwhash_memlimit_max(void)
+{
+ return crypto_pwhash_MEMLIMIT_MAX;
+}
+
+size_t
+crypto_pwhash_opslimit_interactive(void)
+{
+ return crypto_pwhash_OPSLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_memlimit_interactive(void)
+{
+ return crypto_pwhash_MEMLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_opslimit_moderate(void)
+{
+ return crypto_pwhash_OPSLIMIT_MODERATE;
+}
+
+size_t
+crypto_pwhash_memlimit_moderate(void)
+{
+ return crypto_pwhash_MEMLIMIT_MODERATE;
+}
+
+size_t
+crypto_pwhash_opslimit_sensitive(void)
+{
+ return crypto_pwhash_OPSLIMIT_SENSITIVE;
+}
+
+size_t
+crypto_pwhash_memlimit_sensitive(void)
+{
+ return crypto_pwhash_MEMLIMIT_SENSITIVE;
+}
+
+int
+crypto_pwhash(unsigned char * const out, unsigned long long outlen,
+ const char * const passwd, unsigned long long passwdlen,
+ const unsigned char * const salt,
+ unsigned long long opslimit, size_t memlimit, int alg)
+{
+ switch (alg) {
+ case crypto_pwhash_ALG_ARGON2I13:
+ return crypto_pwhash_argon2i(out, outlen, passwd, passwdlen, salt,
+ opslimit, memlimit, alg);
+ case crypto_pwhash_ALG_ARGON2ID13:
+ return crypto_pwhash_argon2id(out, outlen, passwd, passwdlen, salt,
+ opslimit, memlimit, alg);
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+}
+
+int
+crypto_pwhash_str(char out[crypto_pwhash_STRBYTES],
+ const char * const passwd, unsigned long long passwdlen,
+ unsigned long long opslimit, size_t memlimit)
+{
+ return crypto_pwhash_argon2id_str(out, passwd, passwdlen,
+ opslimit, memlimit);
+}
+
+int
+crypto_pwhash_str_alg(char out[crypto_pwhash_STRBYTES],
+ const char * const passwd, unsigned long long passwdlen,
+ unsigned long long opslimit, size_t memlimit, int alg)
+{
+ switch (alg) {
+ case crypto_pwhash_ALG_ARGON2I13:
+ return crypto_pwhash_argon2i_str(out, passwd, passwdlen,
+ opslimit, memlimit);
+ case crypto_pwhash_ALG_ARGON2ID13:
+ return crypto_pwhash_argon2id_str(out, passwd, passwdlen,
+ opslimit, memlimit);
+ }
+ sodium_misuse();
+ /* NOTREACHED */
+}
+
+int
+crypto_pwhash_str_verify(const char str[crypto_pwhash_STRBYTES],
+ const char * const passwd,
+ unsigned long long passwdlen)
+{
+ if (strncmp(str, crypto_pwhash_argon2id_STRPREFIX,
+ sizeof crypto_pwhash_argon2id_STRPREFIX - 1) == 0) {
+ return crypto_pwhash_argon2id_str_verify(str, passwd, passwdlen);
+ }
+ if (strncmp(str, crypto_pwhash_argon2i_STRPREFIX,
+ sizeof crypto_pwhash_argon2i_STRPREFIX - 1) == 0) {
+ return crypto_pwhash_argon2i_str_verify(str, passwd, passwdlen);
+ }
+ errno = EINVAL;
+
+ return -1;
+}
+
+int
+crypto_pwhash_str_needs_rehash(const char str[crypto_pwhash_STRBYTES],
+ unsigned long long opslimit, size_t memlimit)
+{
+ if (strncmp(str, crypto_pwhash_argon2id_STRPREFIX,
+ sizeof crypto_pwhash_argon2id_STRPREFIX - 1) == 0) {
+ return crypto_pwhash_argon2id_str_needs_rehash(str, opslimit, memlimit);
+ }
+ if (strncmp(str, crypto_pwhash_argon2i_STRPREFIX,
+ sizeof crypto_pwhash_argon2i_STRPREFIX - 1) == 0) {
+ return crypto_pwhash_argon2i_str_needs_rehash(str, opslimit, memlimit);
+ }
+ errno = EINVAL;
+
+ return -1;
+}
+
+const char *
+crypto_pwhash_primitive(void) {
+ return crypto_pwhash_PRIMITIVE;
+}
diff --git a/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt-common.c b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt-common.c
new file mode 100644
index 0000000000..e15e12b294
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt-common.c
@@ -0,0 +1,263 @@
+/*-
+ * Copyright 2013 Alexander Peslyak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include "crypto_pwhash_scryptsalsa208sha256.h"
+#include "crypto_scrypt.h"
+#include "private/common.h"
+#include "runtime.h"
+#include "utils.h"
+
+static const char *const itoa64 =
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+static uint8_t *
+encode64_uint32(uint8_t *dst, size_t dstlen, uint32_t src, uint32_t srcbits)
+{
+ uint32_t bit;
+
+ for (bit = 0; bit < srcbits; bit += 6) {
+ if (dstlen < 1) {
+ return NULL; /* LCOV_EXCL_LINE */
+ }
+ *dst++ = itoa64[src & 0x3f];
+ dstlen--;
+ src >>= 6;
+ }
+ return dst;
+}
+
+static uint8_t *
+encode64(uint8_t *dst, size_t dstlen, const uint8_t *src, size_t srclen)
+{
+ size_t i;
+
+ for (i = 0; i < srclen;) {
+ uint8_t *dnext;
+ uint32_t value = 0, bits = 0;
+
+ do {
+ value |= (uint32_t) src[i++] << bits;
+ bits += 8;
+ } while (bits < 24 && i < srclen);
+
+ dnext = encode64_uint32(dst, dstlen, value, bits);
+ if (!dnext) {
+ return NULL; /* LCOV_EXCL_LINE */
+ }
+ dstlen -= dnext - dst;
+ dst = dnext;
+ }
+ return dst;
+}
+
+static int
+decode64_one(uint32_t *dst, uint8_t src)
+{
+ const char *ptr = strchr(itoa64, src);
+
+ if (ptr) {
+ *dst = (uint32_t)(ptr - itoa64);
+ return 0;
+ }
+ *dst = 0;
+
+ return -1;
+}
+
+static const uint8_t *
+decode64_uint32(uint32_t *dst, uint32_t dstbits, const uint8_t *src)
+{
+ uint32_t bit;
+ uint32_t value;
+
+ value = 0;
+ for (bit = 0; bit < dstbits; bit += 6) {
+ uint32_t one;
+ if (decode64_one(&one, *src)) {
+ *dst = 0;
+ return NULL;
+ }
+ src++;
+ value |= one << bit;
+ }
+ *dst = value;
+
+ return src;
+}
+
+const uint8_t *
+escrypt_parse_setting(const uint8_t *setting,
+ uint32_t *N_log2_p, uint32_t *r_p, uint32_t *p_p)
+{
+ const uint8_t *src;
+
+ if (setting[0] != '$' || setting[1] != '7' || setting[2] != '$') {
+ return NULL;
+ }
+ src = setting + 3;
+
+ if (decode64_one(N_log2_p, *src)) {
+ return NULL;
+ }
+ src++;
+
+ src = decode64_uint32(r_p, 30, src);
+ if (!src) {
+ return NULL;
+ }
+
+ src = decode64_uint32(p_p, 30, src);
+ if (!src) {
+ return NULL;
+ }
+ return src;
+}
+
+uint8_t *
+escrypt_r(escrypt_local_t *local, const uint8_t *passwd, size_t passwdlen,
+ const uint8_t *setting, uint8_t *buf, size_t buflen)
+{
+ uint8_t hash[crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES];
+ escrypt_kdf_t escrypt_kdf;
+ const uint8_t *src;
+ const uint8_t *salt;
+ uint8_t *dst;
+ size_t prefixlen;
+ size_t saltlen;
+ size_t need;
+ uint64_t N;
+ uint32_t N_log2;
+ uint32_t r;
+ uint32_t p;
+
+ src = escrypt_parse_setting(setting, &N_log2, &r, &p);
+ if (!src) {
+ return NULL;
+ }
+ N = (uint64_t) 1 << N_log2;
+ prefixlen = src - setting;
+
+ salt = src;
+ src = (uint8_t *) strrchr((char *) salt, '$');
+ if (src) {
+ saltlen = src - salt;
+ } else {
+ saltlen = strlen((char *) salt);
+ }
+ need = prefixlen + saltlen + 1 +
+ crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1;
+ if (need > buflen || need < saltlen) {
+ return NULL;
+ }
+#ifdef HAVE_EMMINTRIN_H
+ escrypt_kdf =
+ sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse;
+#else
+ escrypt_kdf = escrypt_kdf_nosse;
+#endif
+ if (escrypt_kdf(local, passwd, passwdlen, salt, saltlen, N, r, p, hash,
+ sizeof(hash))) {
+ return NULL;
+ }
+ dst = buf;
+ memcpy(dst, setting, prefixlen + saltlen);
+ dst += prefixlen + saltlen;
+ *dst++ = '$';
+
+ dst = encode64(dst, buflen - (dst - buf), hash, sizeof(hash));
+ sodium_memzero(hash, sizeof hash);
+ if (!dst || dst >= buf + buflen) {
+ return NULL; /* Can't happen LCOV_EXCL_LINE */
+ }
+ *dst = 0; /* NUL termination */
+
+ return buf;
+}
+
+uint8_t *
+escrypt_gensalt_r(uint32_t N_log2, uint32_t r, uint32_t p, const uint8_t *src,
+ size_t srclen, uint8_t *buf, size_t buflen)
+{
+ uint8_t *dst;
+ size_t prefixlen =
+ (sizeof "$7$" - 1U) + (1U /* N_log2 */) + (5U /* r */) + (5U /* p */);
+ size_t saltlen = BYTES2CHARS(srclen);
+ size_t need;
+
+ need = prefixlen + saltlen + 1;
+ if (need > buflen || need < saltlen || saltlen < srclen) {
+ return NULL; /* LCOV_EXCL_LINE */
+ }
+ if (N_log2 > 63 || ((uint64_t) r * (uint64_t) p >= (1U << 30))) {
+ return NULL; /* LCOV_EXCL_LINE */
+ }
+ dst = buf;
+ *dst++ = '$';
+ *dst++ = '7';
+ *dst++ = '$';
+
+ *dst++ = itoa64[N_log2];
+
+ dst = encode64_uint32(dst, buflen - (dst - buf), r, 30);
+ if (!dst) {
+ return NULL; /* Can't happen LCOV_EXCL_LINE */
+ }
+ dst = encode64_uint32(dst, buflen - (dst - buf), p, 30);
+ if (!dst) {
+ return NULL; /* Can't happen LCOV_EXCL_LINE */
+ }
+ dst = encode64(dst, buflen - (dst - buf), src, srclen);
+ if (!dst || dst >= buf + buflen) {
+ return NULL; /* Can't happen LCOV_EXCL_LINE */
+ }
+ *dst = 0; /* NUL termination */
+
+ return buf;
+}
+
+int
+crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t *passwd, size_t passwdlen,
+ const uint8_t *salt, size_t saltlen,
+ uint64_t N, uint32_t r, uint32_t p,
+ uint8_t *buf, size_t buflen)
+{
+ escrypt_kdf_t escrypt_kdf;
+ escrypt_local_t local;
+ int retval;
+
+ if (escrypt_init_local(&local)) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+#if defined(HAVE_EMMINTRIN_H)
+ escrypt_kdf =
+ sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse;
+#else
+ escrypt_kdf = escrypt_kdf_nosse;
+#endif
+ retval = escrypt_kdf(&local, passwd, passwdlen, salt, saltlen, N, r, p, buf,
+ buflen);
+ if (escrypt_free_local(&local)) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return retval;
+}
diff --git a/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt.h b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt.h
new file mode 100644
index 0000000000..83101967c3
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt.h
@@ -0,0 +1,98 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * Copyright 2013 Alexander Peslyak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#ifndef crypto_scrypt_H
+#define crypto_scrypt_H
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#if SIZE_MAX > 0xffffffffULL
+#define ARCH_BITS 64
+#else
+#define ARCH_BITS 32
+#endif
+
+#define crypto_pwhash_scryptsalsa208sha256_STRPREFIXBYTES 14
+#define crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES 57
+#define crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES 32
+#define crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES_ENCODED 43
+#define crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES 32
+#define crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED 43
+
+#define BYTES2CHARS(bytes) ((((bytes) *8) + 5) / 6)
+
+typedef struct {
+ void * base, *aligned;
+ size_t size;
+} escrypt_region_t;
+
+typedef union {
+ uint64_t d[8];
+ uint32_t w[16];
+} escrypt_block_t;
+
+typedef escrypt_region_t escrypt_local_t;
+
+extern int escrypt_init_local(escrypt_local_t *__local);
+
+extern int escrypt_free_local(escrypt_local_t *__local);
+
+extern void *alloc_region(escrypt_region_t *region, size_t size);
+extern int free_region(escrypt_region_t *region);
+
+typedef int (*escrypt_kdf_t)(escrypt_local_t *__local, const uint8_t *__passwd,
+ size_t __passwdlen, const uint8_t *__salt,
+ size_t __saltlen, uint64_t __N, uint32_t __r,
+ uint32_t __p, uint8_t *__buf, size_t __buflen);
+
+extern int escrypt_kdf_nosse(escrypt_local_t *__local, const uint8_t *__passwd,
+ size_t __passwdlen, const uint8_t *__salt,
+ size_t __saltlen, uint64_t __N, uint32_t __r,
+ uint32_t __p, uint8_t *__buf, size_t __buflen);
+
+extern int escrypt_kdf_sse(escrypt_local_t *__local, const uint8_t *__passwd,
+ size_t __passwdlen, const uint8_t *__salt,
+ size_t __saltlen, uint64_t __N, uint32_t __r,
+ uint32_t __p, uint8_t *__buf, size_t __buflen);
+
+extern uint8_t *escrypt_r(escrypt_local_t *__local, const uint8_t *__passwd,
+ size_t __passwdlen, const uint8_t *__setting,
+ uint8_t *__buf, size_t __buflen);
+
+extern uint8_t *escrypt_gensalt_r(uint32_t __N_log2, uint32_t __r, uint32_t __p,
+ const uint8_t *__src, size_t __srclen,
+ uint8_t *__buf, size_t __buflen);
+
+extern const uint8_t *escrypt_parse_setting(const uint8_t *setting,
+ uint32_t *N_log2_p, uint32_t *r_p,
+ uint32_t *p_p);
+
+#endif /* !_CRYPTO_SCRYPT_H_ */
diff --git a/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c
new file mode 100644
index 0000000000..9e31352dc2
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c
@@ -0,0 +1,375 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * Copyright 2013 Alexander Peslyak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../crypto_scrypt.h"
+#include "../pbkdf2-sha256.h"
+#include "private/common.h"
+
+static inline void
+blkcpy_64(escrypt_block_t *dest, const escrypt_block_t *src)
+{
+ int i;
+
+#if (ARCH_BITS == 32)
+ for (i = 0; i < 16; ++i) {
+ dest->w[i] = src->w[i];
+ }
+#else
+ for (i = 0; i < 8; ++i) {
+ dest->d[i] = src->d[i];
+ }
+#endif
+}
+
+static inline void
+blkxor_64(escrypt_block_t *dest, const escrypt_block_t *src)
+{
+ int i;
+
+#if (ARCH_BITS == 32)
+ for (i = 0; i < 16; ++i) {
+ dest->w[i] ^= src->w[i];
+ }
+#else
+ for (i = 0; i < 8; ++i) {
+ dest->d[i] ^= src->d[i];
+ }
+#endif
+}
+
+static inline void
+blkcpy(escrypt_block_t *dest, const escrypt_block_t *src, size_t len)
+{
+ size_t i, L;
+
+#if (ARCH_BITS == 32)
+ L = (len >> 2);
+ for (i = 0; i < L; ++i) {
+ dest->w[i] = src->w[i];
+ }
+#else
+ L = (len >> 3);
+ for (i = 0; i < L; ++i) {
+ dest->d[i] = src->d[i];
+ }
+#endif
+}
+
+static inline void
+blkxor(escrypt_block_t *dest, const escrypt_block_t *src, size_t len)
+{
+ size_t i, L;
+
+#if (ARCH_BITS == 32)
+ L = (len >> 2);
+ for (i = 0; i < L; ++i) {
+ dest->w[i] ^= src->w[i];
+ }
+#else
+ L = (len >> 3);
+ for (i = 0; i < L; ++i) {
+ dest->d[i] ^= src->d[i];
+ }
+#endif
+}
+
+/**
+ * salsa20_8(B):
+ * Apply the salsa20/8 core to the provided block.
+ */
+static void
+salsa20_8(uint32_t B[16])
+{
+ escrypt_block_t X;
+ uint32_t *x = X.w;
+ size_t i;
+
+ blkcpy_64(&X, (escrypt_block_t *) B);
+ for (i = 0; i < 8; i += 2) {
+#define R(a, b) (((a) << (b)) | ((a) >> (32 - (b))))
+ /* Operate on columns. */
+ x[4] ^= R(x[0] + x[12], 7);
+ x[8] ^= R(x[4] + x[0], 9);
+ x[12] ^= R(x[8] + x[4], 13);
+ x[0] ^= R(x[12] + x[8], 18);
+
+ x[9] ^= R(x[5] + x[1], 7);
+ x[13] ^= R(x[9] + x[5], 9);
+ x[1] ^= R(x[13] + x[9], 13);
+ x[5] ^= R(x[1] + x[13], 18);
+
+ x[14] ^= R(x[10] + x[6], 7);
+ x[2] ^= R(x[14] + x[10], 9);
+ x[6] ^= R(x[2] + x[14], 13);
+ x[10] ^= R(x[6] + x[2], 18);
+
+ x[3] ^= R(x[15] + x[11], 7);
+ x[7] ^= R(x[3] + x[15], 9);
+ x[11] ^= R(x[7] + x[3], 13);
+ x[15] ^= R(x[11] + x[7], 18);
+
+ /* Operate on rows. */
+ x[1] ^= R(x[0] + x[3], 7);
+ x[2] ^= R(x[1] + x[0], 9);
+ x[3] ^= R(x[2] + x[1], 13);
+ x[0] ^= R(x[3] + x[2], 18);
+
+ x[6] ^= R(x[5] + x[4], 7);
+ x[7] ^= R(x[6] + x[5], 9);
+ x[4] ^= R(x[7] + x[6], 13);
+ x[5] ^= R(x[4] + x[7], 18);
+
+ x[11] ^= R(x[10] + x[9], 7);
+ x[8] ^= R(x[11] + x[10], 9);
+ x[9] ^= R(x[8] + x[11], 13);
+ x[10] ^= R(x[9] + x[8], 18);
+
+ x[12] ^= R(x[15] + x[14], 7);
+ x[13] ^= R(x[12] + x[15], 9);
+ x[14] ^= R(x[13] + x[12], 13);
+ x[15] ^= R(x[14] + x[13], 18);
+#undef R
+ }
+ for (i = 0; i < 16; i++)
+ B[i] += x[i];
+}
+
+/**
+ * blockmix_salsa8(Bin, Bout, X, r):
+ * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
+ * bytes in length; the output Bout must also be the same size. The
+ * temporary space X must be 64 bytes.
+ */
+static void
+blockmix_salsa8(const uint32_t *Bin, uint32_t *Bout, uint32_t *X, size_t r)
+{
+ size_t i;
+
+ /* 1: X <-- B_{2r - 1} */
+ blkcpy_64((escrypt_block_t *) X,
+ (escrypt_block_t *) &Bin[(2 * r - 1) * 16]);
+
+ /* 2: for i = 0 to 2r - 1 do */
+ for (i = 0; i < 2 * r; i += 2) {
+ /* 3: X <-- H(X \xor B_i) */
+ blkxor_64((escrypt_block_t *) X, (escrypt_block_t *) &Bin[i * 16]);
+ salsa20_8(X);
+
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ blkcpy_64((escrypt_block_t *) &Bout[i * 8], (escrypt_block_t *) X);
+
+ /* 3: X <-- H(X \xor B_i) */
+ blkxor_64((escrypt_block_t *) X, (escrypt_block_t *) &Bin[i * 16 + 16]);
+ salsa20_8(X);
+
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ blkcpy_64((escrypt_block_t *) &Bout[i * 8 + r * 16],
+ (escrypt_block_t *) X);
+ }
+}
+
+/**
+ * integerify(B, r):
+ * Return the result of parsing B_{2r-1} as a little-endian integer.
+ */
+static inline uint64_t
+integerify(const void *B, size_t r)
+{
+ const uint32_t *X = (const uint32_t *) ((uintptr_t)(B) + (2 * r - 1) * 64);
+
+ return (((uint64_t)(X[1]) << 32) + X[0]);
+}
+
+/**
+ * smix(B, r, N, V, XY):
+ * Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
+ * the temporary storage V must be 128rN bytes in length; the temporary
+ * storage XY must be 256r + 64 bytes in length. The value N must be a
+ * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
+ * multiple of 64 bytes.
+ */
+static void
+smix(uint8_t *B, size_t r, uint64_t N, uint32_t *V, uint32_t *XY)
+{
+ uint32_t *X = XY;
+ uint32_t *Y = &XY[32 * r];
+ uint32_t *Z = &XY[64 * r];
+ uint64_t i;
+ uint64_t j;
+ size_t k;
+
+ /* 1: X <-- B */
+ for (k = 0; k < 32 * r; k++) {
+ X[k] = LOAD32_LE(&B[4 * k]);
+ }
+ /* 2: for i = 0 to N - 1 do */
+ for (i = 0; i < N; i += 2) {
+ /* 3: V_i <-- X */
+ blkcpy((escrypt_block_t *) &V[i * (32 * r)], (escrypt_block_t *) X,
+ 128 * r);
+
+ /* 4: X <-- H(X) */
+ blockmix_salsa8(X, Y, Z, r);
+
+ /* 3: V_i <-- X */
+ blkcpy((escrypt_block_t *) &V[(i + 1) * (32 * r)],
+ (escrypt_block_t *) Y, 128 * r);
+
+ /* 4: X <-- H(X) */
+ blockmix_salsa8(Y, X, Z, r);
+ }
+
+ /* 6: for i = 0 to N - 1 do */
+ for (i = 0; i < N; i += 2) {
+ /* 7: j <-- Integerify(X) mod N */
+ j = integerify(X, r) & (N - 1);
+
+ /* 8: X <-- H(X \xor V_j) */
+ blkxor((escrypt_block_t *) X, (escrypt_block_t *) &V[j * (32 * r)],
+ 128 * r);
+ blockmix_salsa8(X, Y, Z, r);
+
+ /* 7: j <-- Integerify(X) mod N */
+ j = integerify(Y, r) & (N - 1);
+
+ /* 8: X <-- H(X \xor V_j) */
+ blkxor((escrypt_block_t *) Y, (escrypt_block_t *) &V[j * (32 * r)],
+ 128 * r);
+ blockmix_salsa8(Y, X, Z, r);
+ }
+ /* 10: B' <-- X */
+ for (k = 0; k < 32 * r; k++) {
+ STORE32_LE(&B[4 * k], X[k]);
+ }
+}
+
+/**
+ * escrypt_kdf(local, passwd, passwdlen, salt, saltlen,
+ * N, r, p, buf, buflen):
+ * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
+ * p, buflen) and write the result into buf. The parameters r, p, and buflen
+ * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
+ * must be a power of 2 greater than 1.
+ *
+ * Return 0 on success; or -1 on error.
+ */
+int
+escrypt_kdf_nosse(escrypt_local_t *local, const uint8_t *passwd,
+ size_t passwdlen, const uint8_t *salt, size_t saltlen,
+ uint64_t N, uint32_t _r, uint32_t _p, uint8_t *buf,
+ size_t buflen)
+{
+ size_t B_size, V_size, XY_size, need;
+ uint8_t * B;
+ uint32_t *V, *XY;
+ size_t r = _r, p = _p;
+ uint32_t i;
+
+/* Sanity-check parameters. */
+#if SIZE_MAX > UINT32_MAX
+ if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
+ errno = EFBIG;
+ return -1;
+ }
+#endif
+ if ((uint64_t)(r) * (uint64_t)(p) >= ((uint64_t) 1 << 30)) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (N > UINT32_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (((N & (N - 1)) != 0) || (N < 2)) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (r == 0 || p == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ if ((r > SIZE_MAX / 128 / p) ||
+#if SIZE_MAX / 256 <= UINT32_MAX
+ (r > SIZE_MAX / 256) ||
+#endif
+ (N > SIZE_MAX / 128 / r)) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /* Allocate memory. */
+ B_size = (size_t) 128 * r * p;
+ V_size = (size_t) 128 * r * (size_t) N;
+ need = B_size + V_size;
+ if (need < V_size) {
+ errno = ENOMEM;
+ return -1;
+ }
+ XY_size = (size_t) 256 * r + 64;
+ need += XY_size;
+ if (need < XY_size) {
+ errno = ENOMEM;
+ return -1;
+ }
+ if (local->size < need) {
+ if (free_region(local)) {
+ return -1;
+ }
+ if (!alloc_region(local, need)) {
+ return -1;
+ }
+ }
+ B = (uint8_t *) local->aligned;
+ V = (uint32_t *) ((uint8_t *) B + B_size);
+ XY = (uint32_t *) ((uint8_t *) V + V_size);
+
+ /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
+ PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, B_size);
+
+ /* 2: for i = 0 to p - 1 do */
+ for (i = 0; i < p; i++) {
+ /* 3: B_i <-- MF(B_i, N) */
+ smix(&B[(size_t) 128 * i * r], r, N, V, XY);
+ }
+
+ /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
+ PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, buf, buflen);
+
+ /* Success! */
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.c b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.c
new file mode 100644
index 0000000000..42cab61fe2
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.c
@@ -0,0 +1,95 @@
+/*-
+ * Copyright 2005,2007,2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+
+#include "core.h"
+#include "crypto_auth_hmacsha256.h"
+#include "crypto_pwhash_scryptsalsa208sha256.h"
+#include "pbkdf2-sha256.h"
+#include "private/common.h"
+#include "utils.h"
+
+/**
+ * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
+ * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
+ * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
+ */
+void
+PBKDF2_SHA256(const uint8_t *passwd, size_t passwdlen, const uint8_t *salt,
+ size_t saltlen, uint64_t c, uint8_t *buf, size_t dkLen)
+{
+ crypto_auth_hmacsha256_state PShctx, hctx;
+ size_t i;
+ uint8_t ivec[4];
+ uint8_t U[32];
+ uint8_t T[32];
+ uint64_t j;
+ int k;
+ size_t clen;
+
+#if SIZE_MAX > 0x1fffffffe0ULL
+ COMPILER_ASSERT(crypto_pwhash_scryptsalsa208sha256_BYTES_MAX
+ <= 0x1fffffffe0ULL);
+ if (dkLen > 0x1fffffffe0ULL) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+#endif
+ crypto_auth_hmacsha256_init(&PShctx, passwd, passwdlen);
+ crypto_auth_hmacsha256_update(&PShctx, salt, saltlen);
+
+ for (i = 0; i * 32 < dkLen; i++) {
+ STORE32_BE(ivec, (uint32_t)(i + 1));
+ memcpy(&hctx, &PShctx, sizeof(crypto_auth_hmacsha256_state));
+ crypto_auth_hmacsha256_update(&hctx, ivec, 4);
+ crypto_auth_hmacsha256_final(&hctx, U);
+
+ memcpy(T, U, 32);
+ /* LCOV_EXCL_START */
+ for (j = 2; j <= c; j++) {
+ crypto_auth_hmacsha256_init(&hctx, passwd, passwdlen);
+ crypto_auth_hmacsha256_update(&hctx, U, 32);
+ crypto_auth_hmacsha256_final(&hctx, U);
+
+ for (k = 0; k < 32; k++) {
+ T[k] ^= U[k];
+ }
+ }
+ /* LCOV_EXCL_STOP */
+
+ clen = dkLen - i * 32;
+ if (clen > 32) {
+ clen = 32;
+ }
+ memcpy(&buf[i * 32], T, clen);
+ }
+ sodium_memzero((void *) &PShctx, sizeof PShctx);
+}
diff --git a/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.h b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.h
new file mode 100644
index 0000000000..f9598c87aa
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.h
@@ -0,0 +1,45 @@
+/*-
+ * Copyright 2005,2007,2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef pbkdf2_sha256_H
+#define pbkdf2_sha256_H
+
+#include <stdint.h>
+
+#include <sys/types.h>
+
+#include "crypto_auth_hmacsha256.h"
+
+/**
+ * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
+ * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
+ * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
+ */
+void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t,
+ uint8_t *, size_t);
+
+#endif /* !_SHA256_H_ */
diff --git a/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c
new file mode 100644
index 0000000000..d1afd91afe
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c
@@ -0,0 +1,285 @@
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "crypto_pwhash_scryptsalsa208sha256.h"
+#include "crypto_scrypt.h"
+#include "private/common.h"
+#include "randombytes.h"
+#include "utils.h"
+
+#define SETTING_SIZE(saltbytes) \
+ ((sizeof "$7$" - 1U) + (1U /* N_log2 */) + (5U /* r */) + (5U /* p */) + \
+ BYTES2CHARS(saltbytes))
+
+static int
+pickparams(unsigned long long opslimit, const size_t memlimit,
+ uint32_t *const N_log2, uint32_t *const p, uint32_t *const r)
+{
+ unsigned long long maxN;
+ unsigned long long maxrp;
+
+ if (opslimit < 32768) {
+ opslimit = 32768;
+ }
+ *r = 8;
+ if (opslimit < memlimit / 32) {
+ *p = 1;
+ maxN = opslimit / (*r * 4);
+ for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) {
+ if ((uint64_t)(1) << *N_log2 > maxN / 2) {
+ break;
+ }
+ }
+ } else {
+ maxN = memlimit / ((size_t) *r * 128);
+ for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) {
+ if ((uint64_t)(1) << *N_log2 > maxN / 2) {
+ break;
+ }
+ }
+ maxrp = (opslimit / 4) / ((uint64_t)(1) << *N_log2);
+ /* LCOV_EXCL_START */
+ if (maxrp > 0x3fffffff) {
+ maxrp = 0x3fffffff;
+ }
+ /* LCOV_EXCL_STOP */
+ *p = (uint32_t)(maxrp) / *r;
+ }
+ return 0;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_bytes_min(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_BYTES_MIN;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_bytes_max(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_BYTES_MAX;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_passwd_min(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_passwd_max(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_saltbytes(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_strbytes(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_STRBYTES;
+}
+
+const char *
+crypto_pwhash_scryptsalsa208sha256_strprefix(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_STRPREFIX;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_opslimit_min(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_opslimit_max(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_memlimit_min(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_memlimit_max(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE;
+}
+
+int
+crypto_pwhash_scryptsalsa208sha256(unsigned char *const out,
+ unsigned long long outlen,
+ const char *const passwd,
+ unsigned long long passwdlen,
+ const unsigned char *const salt,
+ unsigned long long opslimit, size_t memlimit)
+{
+ uint32_t N_log2;
+ uint32_t p;
+ uint32_t r;
+
+ memset(out, 0, outlen);
+ if (passwdlen > crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX ||
+ outlen > crypto_pwhash_scryptsalsa208sha256_BYTES_MAX) {
+ errno = EFBIG; /* LCOV_EXCL_LINE */
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ if (outlen < crypto_pwhash_scryptsalsa208sha256_BYTES_MIN ||
+ pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
+ errno = EINVAL; /* LCOV_EXCL_LINE */
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return crypto_pwhash_scryptsalsa208sha256_ll(
+ (const uint8_t *) passwd, (size_t) passwdlen, (const uint8_t *) salt,
+ crypto_pwhash_scryptsalsa208sha256_SALTBYTES, (uint64_t)(1) << N_log2,
+ r, p, out, (size_t) outlen);
+}
+
+int
+crypto_pwhash_scryptsalsa208sha256_str(
+ char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
+ const char *const passwd, unsigned long long passwdlen,
+ unsigned long long opslimit, size_t memlimit)
+{
+ uint8_t salt[crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES];
+ char setting[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U];
+ escrypt_local_t escrypt_local;
+ uint32_t N_log2;
+ uint32_t p;
+ uint32_t r;
+
+ memset(out, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES);
+ if (passwdlen > crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX) {
+ errno = EFBIG; /* LCOV_EXCL_LINE */
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ if (passwdlen < crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN ||
+ pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
+ errno = EINVAL; /* LCOV_EXCL_LINE */
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ randombytes_buf(salt, sizeof salt);
+ if (escrypt_gensalt_r(N_log2, r, p, salt, sizeof salt, (uint8_t *) setting,
+ sizeof setting) == NULL) {
+ errno = EINVAL; /* LCOV_EXCL_LINE */
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ if (escrypt_init_local(&escrypt_local) != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen,
+ (const uint8_t *) setting, (uint8_t *) out,
+ crypto_pwhash_scryptsalsa208sha256_STRBYTES) == NULL) {
+ /* LCOV_EXCL_START */
+ escrypt_free_local(&escrypt_local);
+ errno = EINVAL;
+ return -1;
+ /* LCOV_EXCL_STOP */
+ }
+ escrypt_free_local(&escrypt_local);
+
+ COMPILER_ASSERT(
+ SETTING_SIZE(crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES) ==
+ crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES);
+ COMPILER_ASSERT(
+ crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U +
+ crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1U ==
+ crypto_pwhash_scryptsalsa208sha256_STRBYTES);
+
+ return 0;
+}
+
+int
+crypto_pwhash_scryptsalsa208sha256_str_verify(
+ const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
+ const char *const passwd, unsigned long long passwdlen)
+{
+ char wanted[crypto_pwhash_scryptsalsa208sha256_STRBYTES];
+ escrypt_local_t escrypt_local;
+ int ret = -1;
+
+ if (memchr(str, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES) !=
+ &str[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U]) {
+ return -1;
+ }
+ if (escrypt_init_local(&escrypt_local) != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ memset(wanted, 0, sizeof wanted);
+ if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen,
+ (const uint8_t *) str, (uint8_t *) wanted,
+ sizeof wanted) == NULL) {
+ escrypt_free_local(&escrypt_local);
+ return -1;
+ }
+ escrypt_free_local(&escrypt_local);
+ ret = sodium_memcmp(wanted, str, sizeof wanted);
+ sodium_memzero(wanted, sizeof wanted);
+
+ return ret;
+}
+
+int
+crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(
+ const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
+ unsigned long long opslimit, size_t memlimit)
+{
+ uint32_t N_log2, N_log2_;
+ uint32_t p, p_;
+ uint32_t r, r_;
+
+ if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (memchr(str, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES) !=
+ &str[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U]) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (escrypt_parse_setting((const uint8_t *) str,
+ &N_log2_, &r_, &p_) == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (N_log2 != N_log2_ || r != r_ || p != p_) {
+ return 1;
+ }
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/scrypt_platform.c b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/scrypt_platform.c
new file mode 100644
index 0000000000..139a7df286
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/scrypt_platform.c
@@ -0,0 +1,108 @@
+/*-
+ * Copyright 2013 Alexander Peslyak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <errno.h>
+#include <stdlib.h>
+
+#include "crypto_scrypt.h"
+#include "runtime.h"
+
+#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
+# define MAP_ANON MAP_ANONYMOUS
+#endif
+#ifndef MAP_NOCORE
+# define MAP_NOCORE 0
+#endif
+#ifndef MAP_POPULATE
+# define MAP_POPULATE 0
+#endif
+
+void *
+alloc_region(escrypt_region_t *region, size_t size)
+{
+ uint8_t *base, *aligned;
+#if defined(MAP_ANON) && defined(HAVE_MMAP)
+ if ((base = (uint8_t *) mmap(NULL, size, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE | MAP_NOCORE | MAP_POPULATE,
+ -1, 0)) == MAP_FAILED) {
+ base = NULL; /* LCOV_EXCL_LINE */
+ } /* LCOV_EXCL_LINE */
+ aligned = base;
+#elif defined(HAVE_POSIX_MEMALIGN)
+ if ((errno = posix_memalign((void **) &base, 64, size)) != 0) {
+ base = NULL;
+ }
+ aligned = base;
+#else
+ base = aligned = NULL;
+ if (size + 63 < size)
+ errno = ENOMEM;
+ else if ((base = (uint8_t *) malloc(size + 63)) != NULL) {
+ aligned = base + 63;
+ aligned -= (uintptr_t) aligned & 63;
+ }
+#endif
+ region->base = base;
+ region->aligned = aligned;
+ region->size = base ? size : 0;
+
+ return aligned;
+}
+
+static inline void
+init_region(escrypt_region_t *region)
+{
+ region->base = region->aligned = NULL;
+ region->size = 0;
+}
+
+int
+free_region(escrypt_region_t *region)
+{
+ if (region->base) {
+#if defined(MAP_ANON) && defined(HAVE_MMAP)
+ if (munmap(region->base, region->size)) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+#else
+ free(region->base);
+#endif
+ }
+ init_region(region);
+
+ return 0;
+}
+
+int
+escrypt_init_local(escrypt_local_t *local)
+{
+ init_region(local);
+
+ return 0;
+}
+
+int
+escrypt_free_local(escrypt_local_t *local)
+{
+ return free_region(local);
+}
diff --git a/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c
new file mode 100644
index 0000000000..754a19fdb8
--- /dev/null
+++ b/libs/libsodium/src/crypto_pwhash/scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c
@@ -0,0 +1,400 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * Copyright 2012,2013 Alexander Peslyak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+
+#ifdef HAVE_EMMINTRIN_H
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# endif
+# include <emmintrin.h>
+# if defined(__XOP__) && defined(DISABLED)
+# include <x86intrin.h>
+# endif
+
+# include "../crypto_scrypt.h"
+# include "../pbkdf2-sha256.h"
+
+# if defined(__XOP__) && defined(DISABLED)
+# define ARX(out, in1, in2, s) \
+ out = _mm_xor_si128(out, _mm_roti_epi32(_mm_add_epi32(in1, in2), s));
+# else
+# define ARX(out, in1, in2, s) \
+ { \
+ __m128i T = _mm_add_epi32(in1, in2); \
+ out = _mm_xor_si128(out, _mm_slli_epi32(T, s)); \
+ out = _mm_xor_si128(out, _mm_srli_epi32(T, 32 - s)); \
+ }
+# endif
+
+# define SALSA20_2ROUNDS \
+ /* Operate on "columns". */ \
+ ARX(X1, X0, X3, 7) \
+ ARX(X2, X1, X0, 9) \
+ ARX(X3, X2, X1, 13) \
+ ARX(X0, X3, X2, 18) \
+ \
+ /* Rearrange data. */ \
+ X1 = _mm_shuffle_epi32(X1, 0x93); \
+ X2 = _mm_shuffle_epi32(X2, 0x4E); \
+ X3 = _mm_shuffle_epi32(X3, 0x39); \
+ \
+ /* Operate on "rows". */ \
+ ARX(X3, X0, X1, 7) \
+ ARX(X2, X3, X0, 9) \
+ ARX(X1, X2, X3, 13) \
+ ARX(X0, X1, X2, 18) \
+ \
+ /* Rearrange data. */ \
+ X1 = _mm_shuffle_epi32(X1, 0x39); \
+ X2 = _mm_shuffle_epi32(X2, 0x4E); \
+ X3 = _mm_shuffle_epi32(X3, 0x93);
+
+/**
+ * Apply the salsa20/8 core to the block provided in (X0 ... X3) ^ (Z0 ... Z3).
+ */
+# define SALSA20_8_XOR(in, out) \
+ { \
+ __m128i Y0 = X0 = _mm_xor_si128(X0, (in)[0]); \
+ __m128i Y1 = X1 = _mm_xor_si128(X1, (in)[1]); \
+ __m128i Y2 = X2 = _mm_xor_si128(X2, (in)[2]); \
+ __m128i Y3 = X3 = _mm_xor_si128(X3, (in)[3]); \
+ SALSA20_2ROUNDS \
+ SALSA20_2ROUNDS \
+ SALSA20_2ROUNDS \
+ SALSA20_2ROUNDS(out)[0] = X0 = _mm_add_epi32(X0, Y0); \
+ (out)[1] = X1 = _mm_add_epi32(X1, Y1); \
+ (out)[2] = X2 = _mm_add_epi32(X2, Y2); \
+ (out)[3] = X3 = _mm_add_epi32(X3, Y3); \
+ }
+
+/**
+ * blockmix_salsa8(Bin, Bout, r):
+ * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
+ * bytes in length; the output Bout must also be the same size.
+ */
+static inline void
+blockmix_salsa8(const __m128i *Bin, __m128i *Bout, size_t r)
+{
+ __m128i X0, X1, X2, X3;
+ size_t i;
+
+ /* 1: X <-- B_{2r - 1} */
+ X0 = Bin[8 * r - 4];
+ X1 = Bin[8 * r - 3];
+ X2 = Bin[8 * r - 2];
+ X3 = Bin[8 * r - 1];
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ SALSA20_8_XOR(Bin, Bout)
+
+ /* 2: for i = 0 to 2r - 1 do */
+ r--;
+ for (i = 0; i < r;) {
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ SALSA20_8_XOR(&Bin[i * 8 + 4], &Bout[(r + i) * 4 + 4])
+
+ i++;
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ SALSA20_8_XOR(&Bin[i * 8], &Bout[i * 4])
+ }
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ SALSA20_8_XOR(&Bin[i * 8 + 4], &Bout[(r + i) * 4 + 4])
+}
+
+# define XOR4(in) \
+ X0 = _mm_xor_si128(X0, (in)[0]); \
+ X1 = _mm_xor_si128(X1, (in)[1]); \
+ X2 = _mm_xor_si128(X2, (in)[2]); \
+ X3 = _mm_xor_si128(X3, (in)[3]);
+
+# define XOR4_2(in1, in2) \
+ X0 = _mm_xor_si128((in1)[0], (in2)[0]); \
+ X1 = _mm_xor_si128((in1)[1], (in2)[1]); \
+ X2 = _mm_xor_si128((in1)[2], (in2)[2]); \
+ X3 = _mm_xor_si128((in1)[3], (in2)[3]);
+
+static inline uint32_t
+blockmix_salsa8_xor(const __m128i *Bin1, const __m128i *Bin2, __m128i *Bout,
+ size_t r)
+{
+ __m128i X0, X1, X2, X3;
+ size_t i;
+
+ /* 1: X <-- B_{2r - 1} */
+ XOR4_2(&Bin1[8 * r - 4], &Bin2[8 * r - 4])
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ XOR4(Bin1)
+ SALSA20_8_XOR(Bin2, Bout)
+
+ /* 2: for i = 0 to 2r - 1 do */
+ r--;
+ for (i = 0; i < r;) {
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ XOR4(&Bin1[i * 8 + 4])
+ SALSA20_8_XOR(&Bin2[i * 8 + 4], &Bout[(r + i) * 4 + 4])
+
+ i++;
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ XOR4(&Bin1[i * 8])
+ SALSA20_8_XOR(&Bin2[i * 8], &Bout[i * 4])
+ }
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ XOR4(&Bin1[i * 8 + 4])
+ SALSA20_8_XOR(&Bin2[i * 8 + 4], &Bout[(r + i) * 4 + 4])
+
+ return _mm_cvtsi128_si32(X0);
+}
+
+# undef ARX
+# undef SALSA20_2ROUNDS
+# undef SALSA20_8_XOR
+# undef XOR4
+# undef XOR4_2
+
+/**
+ * integerify(B, r):
+ * Return the result of parsing B_{2r-1} as a little-endian integer.
+ * Note that B's layout is permuted compared to the generic implementation.
+ */
+static inline uint32_t
+integerify(const void *B, size_t r)
+{
+ return *(const uint32_t *) ((uintptr_t)(B) + (2 * r - 1) * 64);
+}
+
+/**
+ * smix(B, r, N, V, XY):
+ * Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
+ * the temporary storage V must be 128rN bytes in length; the temporary
+ * storage XY must be 256r + 64 bytes in length. The value N must be a
+ * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
+ * multiple of 64 bytes.
+ */
+static void
+smix(uint8_t *B, size_t r, uint32_t N, void *V, void *XY)
+{
+ size_t s = 128 * r;
+ __m128i * X = (__m128i *) V, *Y;
+ uint32_t *X32 = (uint32_t *) V;
+ uint32_t i, j;
+ size_t k;
+
+ /* 1: X <-- B */
+ /* 3: V_i <-- X */
+ for (k = 0; k < 2 * r; k++) {
+ for (i = 0; i < 16; i++) {
+ X32[k * 16 + i] = LOAD32_LE(&B[(k * 16 + (i * 5 % 16)) * 4]);
+ }
+ }
+
+ /* 2: for i = 0 to N - 1 do */
+ for (i = 1; i < N - 1; i += 2) {
+ /* 4: X <-- H(X) */
+ /* 3: V_i <-- X */
+ Y = (__m128i *) ((uintptr_t)(V) + i * s);
+ blockmix_salsa8(X, Y, r);
+
+ /* 4: X <-- H(X) */
+ /* 3: V_i <-- X */
+ X = (__m128i *) ((uintptr_t)(V) + (i + 1) * s);
+ blockmix_salsa8(Y, X, r);
+ }
+
+ /* 4: X <-- H(X) */
+ /* 3: V_i <-- X */
+ Y = (__m128i *) ((uintptr_t)(V) + i * s);
+ blockmix_salsa8(X, Y, r);
+
+ /* 4: X <-- H(X) */
+ /* 3: V_i <-- X */
+ X = (__m128i *) XY;
+ blockmix_salsa8(Y, X, r);
+
+ X32 = (uint32_t *) XY;
+ Y = (__m128i *) ((uintptr_t)(XY) + s);
+
+ /* 7: j <-- Integerify(X) mod N */
+ j = integerify(X, r) & (N - 1);
+
+ /* 6: for i = 0 to N - 1 do */
+ for (i = 0; i < N; i += 2) {
+ __m128i *V_j = (__m128i *) ((uintptr_t)(V) + j * s);
+
+ /* 8: X <-- H(X \xor V_j) */
+ /* 7: j <-- Integerify(X) mod N */
+ j = blockmix_salsa8_xor(X, V_j, Y, r) & (N - 1);
+ V_j = (__m128i *) ((uintptr_t)(V) + j * s);
+
+ /* 8: X <-- H(X \xor V_j) */
+ /* 7: j <-- Integerify(X) mod N */
+ j = blockmix_salsa8_xor(Y, V_j, X, r) & (N - 1);
+ }
+
+ /* 10: B' <-- X */
+ for (k = 0; k < 2 * r; k++) {
+ for (i = 0; i < 16; i++) {
+ STORE32_LE(&B[(k * 16 + (i * 5 % 16)) * 4], X32[k * 16 + i]);
+ }
+ }
+}
+
+/**
+ * escrypt_kdf(local, passwd, passwdlen, salt, saltlen,
+ * N, r, p, buf, buflen):
+ * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
+ * p, buflen) and write the result into buf. The parameters r, p, and buflen
+ * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
+ * must be a power of 2 greater than 1.
+ *
+ * Return 0 on success; or -1 on error.
+ */
+int
+escrypt_kdf_sse(escrypt_local_t *local, const uint8_t *passwd, size_t passwdlen,
+ const uint8_t *salt, size_t saltlen, uint64_t N, uint32_t _r,
+ uint32_t _p, uint8_t *buf, size_t buflen)
+{
+ size_t B_size, V_size, XY_size, need;
+ uint8_t * B;
+ uint32_t *V, *XY;
+ size_t r = _r, p = _p;
+ uint32_t i;
+
+/* Sanity-check parameters. */
+# if SIZE_MAX > UINT32_MAX
+/* LCOV_EXCL_START */
+ if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
+ errno = EFBIG;
+ return -1;
+ }
+/* LCOV_EXCL_END */
+# endif
+ if ((uint64_t)(r) * (uint64_t)(p) >= ((uint64_t) 1 << 30)) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (N > UINT32_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (((N & (N - 1)) != 0) || (N < 2)) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (r == 0 || p == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+/* LCOV_EXCL_START */
+ if ((r > SIZE_MAX / 128 / p) ||
+# if SIZE_MAX / 256 <= UINT32_MAX
+ (r > SIZE_MAX / 256) ||
+# endif
+ (N > SIZE_MAX / 128 / r)) {
+ errno = ENOMEM;
+ return -1;
+ }
+/* LCOV_EXCL_END */
+
+ /* Allocate memory. */
+ B_size = (size_t) 128 * r * p;
+ V_size = (size_t) 128 * r * N;
+ need = B_size + V_size;
+/* LCOV_EXCL_START */
+ if (need < V_size) {
+ errno = ENOMEM;
+ return -1;
+ }
+/* LCOV_EXCL_END */
+ XY_size = (size_t) 256 * r + 64;
+ need += XY_size;
+/* LCOV_EXCL_START */
+ if (need < XY_size) {
+ errno = ENOMEM;
+ return -1;
+ }
+/* LCOV_EXCL_END */
+ if (local->size < need) {
+ if (free_region(local)) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ if (!alloc_region(local, need)) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ }
+ B = (uint8_t *) local->aligned;
+ V = (uint32_t *) ((uint8_t *) B + B_size);
+ XY = (uint32_t *) ((uint8_t *) V + V_size);
+
+ /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
+ PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, B_size);
+
+ /* 2: for i = 0 to p - 1 do */
+ for (i = 0; i < p; i++) {
+ /* 3: B_i <-- MF(B_i, N) */
+ smix(&B[(size_t) 128 * i * r], r, (uint32_t) N, V, XY);
+ }
+
+ /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
+ PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, buf, buflen);
+
+ /* Success! */
+ return 0;
+}
+#endif
diff --git a/libs/libsodium/src/crypto_scalarmult/crypto_scalarmult.c b/libs/libsodium/src/crypto_scalarmult/crypto_scalarmult.c
new file mode 100644
index 0000000000..9afffce8a9
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/crypto_scalarmult.c
@@ -0,0 +1,33 @@
+
+#include "crypto_scalarmult.h"
+
+const char *
+crypto_scalarmult_primitive(void)
+{
+ return crypto_scalarmult_PRIMITIVE;
+}
+
+int
+crypto_scalarmult_base(unsigned char *q, const unsigned char *n)
+{
+ return crypto_scalarmult_curve25519_base(q, n);
+}
+
+int
+crypto_scalarmult(unsigned char *q, const unsigned char *n,
+ const unsigned char *p)
+{
+ return crypto_scalarmult_curve25519(q, n, p);
+}
+
+size_t
+crypto_scalarmult_bytes(void)
+{
+ return crypto_scalarmult_BYTES;
+}
+
+size_t
+crypto_scalarmult_scalarbytes(void)
+{
+ return crypto_scalarmult_SCALARBYTES;
+}
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/ref10/x25519_ref10.c b/libs/libsodium/src/crypto_scalarmult/curve25519/ref10/x25519_ref10.c
new file mode 100644
index 0000000000..7b93a7247b
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/ref10/x25519_ref10.c
@@ -0,0 +1,159 @@
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "../scalarmult_curve25519.h"
+#include "export.h"
+#include "private/ed25519_ref10.h"
+#include "utils.h"
+#include "x25519_ref10.h"
+
+/*
+ * Reject small order points early to mitigate the implications of
+ * unexpected optimizations that would affect the ref10 code.
+ * See https://eprint.iacr.org/2017/806.pdf for reference.
+ */
+static int
+has_small_order(const unsigned char s[32])
+{
+ CRYPTO_ALIGN(16)
+ static const unsigned char blacklist[][32] = {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00 },
+ { 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57 },
+ { 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
+ { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
+ { 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
+ { 0xcd, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x80 },
+ { 0x4c, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0xd7 },
+ { 0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
+ };
+ unsigned char c[12] = { 0 };
+ unsigned int k;
+ size_t i, j;
+
+ COMPILER_ASSERT(12 == sizeof blacklist / sizeof blacklist[0]);
+ for (j = 0; j < 32; j++) {
+ for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) {
+ c[i] |= s[j] ^ blacklist[i][j];
+ }
+ }
+ k = 0;
+ for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) {
+ k |= (c[i] - 1);
+ }
+ return (int) ((k >> 8) & 1);
+}
+
+static int
+crypto_scalarmult_curve25519_ref10(unsigned char *q,
+ const unsigned char *n,
+ const unsigned char *p)
+{
+ unsigned char *t = q;
+ unsigned int i;
+ fe25519 x1;
+ fe25519 x2;
+ fe25519 z2;
+ fe25519 x3;
+ fe25519 z3;
+ fe25519 tmp0;
+ fe25519 tmp1;
+ int pos;
+ unsigned int swap;
+ unsigned int b;
+
+ if (has_small_order(p)) {
+ return -1;
+ }
+ for (i = 0; i < 32; i++) {
+ t[i] = n[i];
+ }
+ t[0] &= 248;
+ t[31] &= 127;
+ t[31] |= 64;
+ fe25519_frombytes(x1, p);
+ fe25519_1(x2);
+ fe25519_0(z2);
+ fe25519_copy(x3, x1);
+ fe25519_1(z3);
+
+ swap = 0;
+ for (pos = 254; pos >= 0; --pos) {
+ b = t[pos / 8] >> (pos & 7);
+ b &= 1;
+ swap ^= b;
+ fe25519_cswap(x2, x3, swap);
+ fe25519_cswap(z2, z3, swap);
+ swap = b;
+ fe25519_sub(tmp0, x3, z3);
+ fe25519_sub(tmp1, x2, z2);
+ fe25519_add(x2, x2, z2);
+ fe25519_add(z2, x3, z3);
+ fe25519_mul(z3, tmp0, x2);
+ fe25519_mul(z2, z2, tmp1);
+ fe25519_sq(tmp0, tmp1);
+ fe25519_sq(tmp1, x2);
+ fe25519_add(x3, z3, z2);
+ fe25519_sub(z2, z3, z2);
+ fe25519_mul(x2, tmp1, tmp0);
+ fe25519_sub(tmp1, tmp1, tmp0);
+ fe25519_sq(z2, z2);
+ fe25519_scalar_product(z3, tmp1, 121666);
+ fe25519_sq(x3, x3);
+ fe25519_add(tmp0, tmp0, z3);
+ fe25519_mul(z3, x1, z2);
+ fe25519_mul(z2, tmp1, tmp0);
+ }
+ fe25519_cswap(x2, x3, swap);
+ fe25519_cswap(z2, z3, swap);
+
+ fe25519_invert(z2, z2);
+ fe25519_mul(x2, x2, z2);
+ fe25519_tobytes(q, x2);
+
+ return 0;
+}
+
+static void
+edwards_to_montgomery(fe25519 montgomeryX, const fe25519 edwardsY, const fe25519 edwardsZ)
+{
+ fe25519 tempX;
+ fe25519 tempZ;
+
+ fe25519_add(tempX, edwardsZ, edwardsY);
+ fe25519_sub(tempZ, edwardsZ, edwardsY);
+ fe25519_invert(tempZ, tempZ);
+ fe25519_mul(montgomeryX, tempX, tempZ);
+}
+
+static int
+crypto_scalarmult_curve25519_ref10_base(unsigned char *q,
+ const unsigned char *n)
+{
+ unsigned char *t = q;
+ ge25519_p3 A;
+ fe25519 pk;
+ unsigned int i;
+
+ for (i = 0; i < 32; i++) {
+ t[i] = n[i];
+ }
+ t[0] &= 248;
+ t[31] &= 127;
+ t[31] |= 64;
+ ge25519_scalarmult_base(&A, t);
+ edwards_to_montgomery(pk, A.Y, A.Z);
+ fe25519_tobytes(q, pk);
+
+ return 0;
+}
+
+struct crypto_scalarmult_curve25519_implementation
+ crypto_scalarmult_curve25519_ref10_implementation = {
+ SODIUM_C99(.mult =) crypto_scalarmult_curve25519_ref10,
+ SODIUM_C99(.mult_base =) crypto_scalarmult_curve25519_ref10_base
+ };
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/ref10/x25519_ref10.h b/libs/libsodium/src/crypto_scalarmult/curve25519/ref10/x25519_ref10.h
new file mode 100644
index 0000000000..ea52a62a69
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/ref10/x25519_ref10.h
@@ -0,0 +1,10 @@
+#ifndef x25519_ref10_H
+#define x25519_ref10_H
+
+#include "crypto_scalarmult_curve25519.h"
+#include "../scalarmult_curve25519.h"
+
+extern struct crypto_scalarmult_curve25519_implementation
+ crypto_scalarmult_curve25519_ref10_implementation;
+
+#endif
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/consts.S b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/consts.S
new file mode 100644
index 0000000000..67f1f0183e
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/consts.S
@@ -0,0 +1,25 @@
+#ifdef IN_SANDY2X
+
+/*
+ REDMASK51 is from amd64-51/consts.s.
+*/
+
+#include "consts_namespace.h"
+.data
+.p2align 4
+v0_0: .quad 0, 0
+v1_0: .quad 1, 0
+v2_1: .quad 2, 1
+v9_0: .quad 9, 0
+v9_9: .quad 9, 9
+v19_19: .quad 19, 19
+v38_1: .quad 38, 1
+v38_38: .quad 38, 38
+v121666_121666: .quad 121666, 121666
+m25: .quad 33554431, 33554431
+m26: .quad 67108863, 67108863
+subc0: .quad 0x07FFFFDA, 0x03FFFFFE
+subc2: .quad 0x07FFFFFE, 0x03FFFFFE
+REDMASK51: .quad 0x0007FFFFFFFFFFFF
+
+#endif
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/consts_namespace.h b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/consts_namespace.h
new file mode 100644
index 0000000000..9f81fa61c4
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/consts_namespace.h
@@ -0,0 +1,20 @@
+#ifndef consts_namespace_H
+#define consts_namespace_H
+
+#define v0_0 crypto_scalarmult_curve25519_sandy2x_v0_0
+#define v1_0 crypto_scalarmult_curve25519_sandy2x_v1_0
+#define v2_1 crypto_scalarmult_curve25519_sandy2x_v2_1
+#define v9_0 crypto_scalarmult_curve25519_sandy2x_v9_0
+#define v9_9 crypto_scalarmult_curve25519_sandy2x_v9_9
+#define v19_19 crypto_scalarmult_curve25519_sandy2x_v19_19
+#define v38_1 crypto_scalarmult_curve25519_sandy2x_v38_1
+#define v38_38 crypto_scalarmult_curve25519_sandy2x_v38_38
+#define v121666_121666 crypto_scalarmult_curve25519_sandy2x_v121666_121666
+#define m25 crypto_scalarmult_curve25519_sandy2x_m25
+#define m26 crypto_scalarmult_curve25519_sandy2x_m26
+#define subc0 crypto_scalarmult_curve25519_sandy2x_subc0
+#define subc2 crypto_scalarmult_curve25519_sandy2x_subc2
+#define REDMASK51 crypto_scalarmult_curve25519_sandy2x_REDMASK51
+
+#endif /* ifndef consts_namespace_H */
+
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/curve25519_sandy2x.c b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/curve25519_sandy2x.c
new file mode 100644
index 0000000000..98b7cf79e5
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/curve25519_sandy2x.c
@@ -0,0 +1,114 @@
+/*
+ This file is adapted from ref10/scalarmult.c:
+ The code for Mongomery ladder is replace by the ladder assembly function;
+ Inversion is done in the same way as amd64-51/.
+ (fe is first converted into fe51 after Mongomery ladder)
+*/
+
+#include <stddef.h>
+
+#ifdef HAVE_AVX_ASM
+
+#include "utils.h"
+#include "curve25519_sandy2x.h"
+#include "../scalarmult_curve25519.h"
+#include "fe.h"
+#include "fe51.h"
+#include "ladder.h"
+#include "ladder_base.h"
+
+#define x1 var[0]
+#define x2 var[1]
+#define z2 var[2]
+
+static int
+crypto_scalarmult_curve25519_sandy2x(unsigned char *q, const unsigned char *n,
+ const unsigned char *p)
+{
+ unsigned char *t = q;
+ fe var[3];
+ fe51 x_51;
+ fe51 z_51;
+ unsigned int i;
+
+ for (i = 0; i < 32; i++) {
+ t[i] = n[i];
+ }
+ t[0] &= 248;
+ t[31] &= 127;
+ t[31] |= 64;
+
+ fe_frombytes(x1, p);
+
+ ladder(var, t);
+
+ z_51.v[0] = (z2[1] << 26) + z2[0];
+ z_51.v[1] = (z2[3] << 26) + z2[2];
+ z_51.v[2] = (z2[5] << 26) + z2[4];
+ z_51.v[3] = (z2[7] << 26) + z2[6];
+ z_51.v[4] = (z2[9] << 26) + z2[8];
+
+ x_51.v[0] = (x2[1] << 26) + x2[0];
+ x_51.v[1] = (x2[3] << 26) + x2[2];
+ x_51.v[2] = (x2[5] << 26) + x2[4];
+ x_51.v[3] = (x2[7] << 26) + x2[6];
+ x_51.v[4] = (x2[9] << 26) + x2[8];
+
+ fe51_invert(&z_51, &z_51);
+ fe51_mul(&x_51, &x_51, &z_51);
+ fe51_pack(q, &x_51);
+
+ return 0;
+}
+
+#undef x2
+#undef z2
+
+#define x2 var[0]
+#define z2 var[1]
+
+static int
+crypto_scalarmult_curve25519_sandy2x_base(unsigned char *q,
+ const unsigned char *n)
+{
+ unsigned char *t = q;
+ fe var[3];
+ fe51 x_51;
+ fe51 z_51;
+ unsigned int i;
+
+ for (i = 0;i < 32; i++) {
+ t[i] = n[i];
+ }
+ t[0] &= 248;
+ t[31] &= 127;
+ t[31] |= 64;
+
+ ladder_base(var, t);
+
+ z_51.v[0] = (z2[1] << 26) + z2[0];
+ z_51.v[1] = (z2[3] << 26) + z2[2];
+ z_51.v[2] = (z2[5] << 26) + z2[4];
+ z_51.v[3] = (z2[7] << 26) + z2[6];
+ z_51.v[4] = (z2[9] << 26) + z2[8];
+
+ x_51.v[0] = (x2[1] << 26) + x2[0];
+ x_51.v[1] = (x2[3] << 26) + x2[2];
+ x_51.v[2] = (x2[5] << 26) + x2[4];
+ x_51.v[3] = (x2[7] << 26) + x2[6];
+ x_51.v[4] = (x2[9] << 26) + x2[8];
+
+ fe51_invert(&z_51, &z_51);
+ fe51_mul(&x_51, &x_51, &z_51);
+ fe51_pack(q, &x_51);
+
+ return 0;
+}
+
+struct crypto_scalarmult_curve25519_implementation
+crypto_scalarmult_curve25519_sandy2x_implementation = {
+ SODIUM_C99(.mult = ) crypto_scalarmult_curve25519_sandy2x,
+ SODIUM_C99(.mult_base = ) crypto_scalarmult_curve25519_sandy2x_base
+};
+
+#endif
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/curve25519_sandy2x.h b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/curve25519_sandy2x.h
new file mode 100644
index 0000000000..f02d980187
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/curve25519_sandy2x.h
@@ -0,0 +1,9 @@
+#ifndef curve25519_sandy2x_H
+#define curve25519_sandy2x_H
+
+#include "crypto_scalarmult_curve25519.h"
+
+extern struct crypto_scalarmult_curve25519_implementation
+ crypto_scalarmult_curve25519_sandy2x_implementation;
+
+#endif
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe.h b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe.h
new file mode 100644
index 0000000000..b1115f8691
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe.h
@@ -0,0 +1,26 @@
+/*
+ This file is adapted from ref10/fe.h:
+ All the redundant functions are removed.
+*/
+
+#ifndef fe_H
+#define fe_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+typedef uint64_t fe[10];
+
+/*
+fe means field element.
+Here the field is \Z/(2^255-19).
+An element t, entries t[0]...t[9], represents the integer
+t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9].
+Bounds on each t[i] vary depending on context.
+*/
+
+#define fe_frombytes crypto_scalarmult_curve25519_sandy2x_fe_frombytes
+
+extern void fe_frombytes(fe, const unsigned char *);
+
+#endif
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51.h b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51.h
new file mode 100644
index 0000000000..8e3f199b24
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51.h
@@ -0,0 +1,35 @@
+/*
+ This file is adapted from amd64-51/fe25519.h:
+ 'fe25519' is renamed as 'fe51';
+ All the redundant functions are removed;
+ New function fe51_nsquare is introduced.
+*/
+
+#ifndef fe51_H
+#define fe51_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "fe51_namespace.h"
+
+typedef struct
+{
+ uint64_t v[5];
+}
+fe51;
+
+extern void fe51_pack(unsigned char *, const fe51 *);
+extern void fe51_mul(fe51 *, const fe51 *, const fe51 *);
+extern void fe51_nsquare(fe51 *, const fe51 *, int);
+extern void fe51_invert(fe51 *, const fe51 *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_invert.c b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_invert.c
new file mode 100644
index 0000000000..ec9bb1a91f
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_invert.c
@@ -0,0 +1,58 @@
+/*
+ This file is adapted from amd64-51/fe25519_invert.c:
+ Loops of squares are replaced by nsquares for better performance.
+*/
+
+#include "fe51.h"
+
+#ifdef HAVE_AVX_ASM
+
+#define fe51_square(x, y) fe51_nsquare(x, y, 1)
+
+void
+fe51_invert(fe51 *r, const fe51 *x)
+{
+ fe51 z2;
+ fe51 z9;
+ fe51 z11;
+ fe51 z2_5_0;
+ fe51 z2_10_0;
+ fe51 z2_20_0;
+ fe51 z2_50_0;
+ fe51 z2_100_0;
+ fe51 t;
+
+ /* 2 */ fe51_square(&z2,x);
+ /* 4 */ fe51_square(&t,&z2);
+ /* 8 */ fe51_square(&t,&t);
+ /* 9 */ fe51_mul(&z9,&t,x);
+ /* 11 */ fe51_mul(&z11,&z9,&z2);
+ /* 22 */ fe51_square(&t,&z11);
+ /* 2^5 - 2^0 = 31 */ fe51_mul(&z2_5_0,&t,&z9);
+
+ /* 2^10 - 2^5 */ fe51_nsquare(&t,&z2_5_0, 5);
+ /* 2^10 - 2^0 */ fe51_mul(&z2_10_0,&t,&z2_5_0);
+
+ /* 2^20 - 2^10 */ fe51_nsquare(&t,&z2_10_0, 10);
+ /* 2^20 - 2^0 */ fe51_mul(&z2_20_0,&t,&z2_10_0);
+
+ /* 2^40 - 2^20 */ fe51_nsquare(&t,&z2_20_0, 20);
+ /* 2^40 - 2^0 */ fe51_mul(&t,&t,&z2_20_0);
+
+ /* 2^50 - 2^10 */ fe51_nsquare(&t,&t,10);
+ /* 2^50 - 2^0 */ fe51_mul(&z2_50_0,&t,&z2_10_0);
+
+ /* 2^100 - 2^50 */ fe51_nsquare(&t,&z2_50_0, 50);
+ /* 2^100 - 2^0 */ fe51_mul(&z2_100_0,&t,&z2_50_0);
+
+ /* 2^200 - 2^100 */ fe51_nsquare(&t,&z2_100_0, 100);
+ /* 2^200 - 2^0 */ fe51_mul(&t,&t,&z2_100_0);
+
+ /* 2^250 - 2^50 */ fe51_nsquare(&t,&t, 50);
+ /* 2^250 - 2^0 */ fe51_mul(&t,&t,&z2_50_0);
+
+ /* 2^255 - 2^5 */ fe51_nsquare(&t,&t,5);
+ /* 2^255 - 21 */ fe51_mul(r,&t,&z11);
+}
+
+#endif
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_mul.S b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_mul.S
new file mode 100644
index 0000000000..83501b0395
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_mul.S
@@ -0,0 +1,197 @@
+#ifdef IN_SANDY2X
+
+/*
+ This file is basically amd64-51/fe25519_mul.s.
+*/
+#include "fe51_namespace.h"
+#include "consts_namespace.h"
+.text
+.p2align 5
+#ifdef ASM_HIDE_SYMBOL
+ASM_HIDE_SYMBOL fe51_mul
+ASM_HIDE_SYMBOL _fe51_mul
+#endif
+.globl fe51_mul
+.globl _fe51_mul
+#ifdef __ELF__
+.type fe51_mul, @function
+.type _fe51_mul, @function
+#endif
+fe51_mul:
+_fe51_mul:
+mov %rsp,%r11
+and $31,%r11
+add $96,%r11
+sub %r11,%rsp
+movq %r11,0(%rsp)
+movq %r12,8(%rsp)
+movq %r13,16(%rsp)
+movq %r14,24(%rsp)
+movq %r15,32(%rsp)
+movq %rbx,40(%rsp)
+movq %rbp,48(%rsp)
+movq %rdi,56(%rsp)
+mov %rdx,%rcx
+movq 24(%rsi),%rdx
+imulq $19,%rdx,%rax
+movq %rax,64(%rsp)
+mulq 16(%rcx)
+mov %rax,%r8
+mov %rdx,%r9
+movq 32(%rsi),%rdx
+imulq $19,%rdx,%rax
+movq %rax,72(%rsp)
+mulq 8(%rcx)
+add %rax,%r8
+adc %rdx,%r9
+movq 0(%rsi),%rax
+mulq 0(%rcx)
+add %rax,%r8
+adc %rdx,%r9
+movq 0(%rsi),%rax
+mulq 8(%rcx)
+mov %rax,%r10
+mov %rdx,%r11
+movq 0(%rsi),%rax
+mulq 16(%rcx)
+mov %rax,%r12
+mov %rdx,%r13
+movq 0(%rsi),%rax
+mulq 24(%rcx)
+mov %rax,%r14
+mov %rdx,%r15
+movq 0(%rsi),%rax
+mulq 32(%rcx)
+mov %rax,%rbx
+mov %rdx,%rbp
+movq 8(%rsi),%rax
+mulq 0(%rcx)
+add %rax,%r10
+adc %rdx,%r11
+movq 8(%rsi),%rax
+mulq 8(%rcx)
+add %rax,%r12
+adc %rdx,%r13
+movq 8(%rsi),%rax
+mulq 16(%rcx)
+add %rax,%r14
+adc %rdx,%r15
+movq 8(%rsi),%rax
+mulq 24(%rcx)
+add %rax,%rbx
+adc %rdx,%rbp
+movq 8(%rsi),%rdx
+imulq $19,%rdx,%rax
+mulq 32(%rcx)
+add %rax,%r8
+adc %rdx,%r9
+movq 16(%rsi),%rax
+mulq 0(%rcx)
+add %rax,%r12
+adc %rdx,%r13
+movq 16(%rsi),%rax
+mulq 8(%rcx)
+add %rax,%r14
+adc %rdx,%r15
+movq 16(%rsi),%rax
+mulq 16(%rcx)
+add %rax,%rbx
+adc %rdx,%rbp
+movq 16(%rsi),%rdx
+imulq $19,%rdx,%rax
+mulq 24(%rcx)
+add %rax,%r8
+adc %rdx,%r9
+movq 16(%rsi),%rdx
+imulq $19,%rdx,%rax
+mulq 32(%rcx)
+add %rax,%r10
+adc %rdx,%r11
+movq 24(%rsi),%rax
+mulq 0(%rcx)
+add %rax,%r14
+adc %rdx,%r15
+movq 24(%rsi),%rax
+mulq 8(%rcx)
+add %rax,%rbx
+adc %rdx,%rbp
+movq 64(%rsp),%rax
+mulq 24(%rcx)
+add %rax,%r10
+adc %rdx,%r11
+movq 64(%rsp),%rax
+mulq 32(%rcx)
+add %rax,%r12
+adc %rdx,%r13
+movq 32(%rsi),%rax
+mulq 0(%rcx)
+add %rax,%rbx
+adc %rdx,%rbp
+movq 72(%rsp),%rax
+mulq 16(%rcx)
+add %rax,%r10
+adc %rdx,%r11
+movq 72(%rsp),%rax
+mulq 24(%rcx)
+add %rax,%r12
+adc %rdx,%r13
+movq 72(%rsp),%rax
+mulq 32(%rcx)
+add %rax,%r14
+adc %rdx,%r15
+movq REDMASK51(%rip),%rsi
+shld $13,%r8,%r9
+and %rsi,%r8
+shld $13,%r10,%r11
+and %rsi,%r10
+add %r9,%r10
+shld $13,%r12,%r13
+and %rsi,%r12
+add %r11,%r12
+shld $13,%r14,%r15
+and %rsi,%r14
+add %r13,%r14
+shld $13,%rbx,%rbp
+and %rsi,%rbx
+add %r15,%rbx
+imulq $19,%rbp,%rdx
+add %rdx,%r8
+mov %r8,%rdx
+shr $51,%rdx
+add %r10,%rdx
+mov %rdx,%rcx
+shr $51,%rdx
+and %rsi,%r8
+add %r12,%rdx
+mov %rdx,%r9
+shr $51,%rdx
+and %rsi,%rcx
+add %r14,%rdx
+mov %rdx,%rax
+shr $51,%rdx
+and %rsi,%r9
+add %rbx,%rdx
+mov %rdx,%r10
+shr $51,%rdx
+and %rsi,%rax
+imulq $19,%rdx,%rdx
+add %rdx,%r8
+and %rsi,%r10
+movq %r8,0(%rdi)
+movq %rcx,8(%rdi)
+movq %r9,16(%rdi)
+movq %rax,24(%rdi)
+movq %r10,32(%rdi)
+movq 0(%rsp),%r11
+movq 8(%rsp),%r12
+movq 16(%rsp),%r13
+movq 24(%rsp),%r14
+movq 32(%rsp),%r15
+movq 40(%rsp),%rbx
+movq 48(%rsp),%rbp
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
+
+#endif
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_namespace.h b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_namespace.h
new file mode 100644
index 0000000000..057f242ca1
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_namespace.h
@@ -0,0 +1,16 @@
+#ifndef fe51_namespace_H
+#define fe51_namespace_H
+
+#define fe51 crypto_scalarmult_curve25519_sandy2x_fe51
+#define _fe51 _crypto_scalarmult_curve25519_sandy2x_fe51
+#define fe51_pack crypto_scalarmult_curve25519_sandy2x_fe51_pack
+#define _fe51_pack _crypto_scalarmult_curve25519_sandy2x_fe51_pack
+#define fe51_mul crypto_scalarmult_curve25519_sandy2x_fe51_mul
+#define _fe51_mul _crypto_scalarmult_curve25519_sandy2x_fe51_mul
+#define fe51_nsquare crypto_scalarmult_curve25519_sandy2x_fe51_nsquare
+#define _fe51_nsquare _crypto_scalarmult_curve25519_sandy2x_fe51_nsquare
+
+#define fe51_invert crypto_scalarmult_curve25519_sandy2x_fe51_invert
+
+#endif /* ifndef fe51_namespace_H */
+
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_nsquare.S b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_nsquare.S
new file mode 100644
index 0000000000..41c3054805
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_nsquare.S
@@ -0,0 +1,172 @@
+#ifdef IN_SANDY2X
+
+/*
+ This file is adapted from amd64-51/fe25519_square.s:
+ Adding loop to perform n squares.
+*/
+#include "fe51_namespace.h"
+#include "consts_namespace.h"
+.p2align 5
+
+#ifdef ASM_HIDE_SYMBOL
+ASM_HIDE_SYMBOL fe51_nsquare
+ASM_HIDE_SYMBOL _fe51_nsquare
+#endif
+.globl fe51_nsquare
+.globl _fe51_nsquare
+#ifdef __ELF__
+.type fe51_nsquare, @function
+.type _fe51_nsquare, @function
+#endif
+fe51_nsquare:
+_fe51_nsquare:
+
+mov %rsp,%r11
+and $31,%r11
+add $64,%r11
+sub %r11,%rsp
+movq %r11,0(%rsp)
+movq %r12,8(%rsp)
+movq %r13,16(%rsp)
+movq %r14,24(%rsp)
+movq %r15,32(%rsp)
+movq %rbx,40(%rsp)
+movq %rbp,48(%rsp)
+movq 0(%rsi),%rcx
+movq 8(%rsi),%r8
+movq 16(%rsi),%r9
+movq 24(%rsi),%rax
+movq 32(%rsi),%rsi
+movq %r9,16(%rdi)
+movq %rax,24(%rdi)
+movq %rsi,32(%rdi)
+mov %rdx,%rsi
+
+.p2align 4
+._loop:
+sub $1,%rsi
+mov %rcx,%rax
+mul %rcx
+add %rcx,%rcx
+mov %rax,%r9
+mov %rdx,%r10
+mov %rcx,%rax
+mul %r8
+mov %rax,%r11
+mov %rdx,%r12
+mov %rcx,%rax
+mulq 16(%rdi)
+mov %rax,%r13
+mov %rdx,%r14
+mov %rcx,%rax
+mulq 24(%rdi)
+mov %rax,%r15
+mov %rdx,%rbx
+mov %rcx,%rax
+mulq 32(%rdi)
+mov %rax,%rcx
+mov %rdx,%rbp
+mov %r8,%rax
+mul %r8
+add %r8,%r8
+add %rax,%r13
+adc %rdx,%r14
+mov %r8,%rax
+mulq 16(%rdi)
+add %rax,%r15
+adc %rdx,%rbx
+mov %r8,%rax
+imulq $19, %r8,%r8
+mulq 24(%rdi)
+add %rax,%rcx
+adc %rdx,%rbp
+mov %r8,%rax
+mulq 32(%rdi)
+add %rax,%r9
+adc %rdx,%r10
+movq 16(%rdi),%rax
+mulq 16(%rdi)
+add %rax,%rcx
+adc %rdx,%rbp
+shld $13,%rcx,%rbp
+movq 16(%rdi),%rax
+imulq $38, %rax,%rax
+mulq 24(%rdi)
+add %rax,%r9
+adc %rdx,%r10
+shld $13,%r9,%r10
+movq 16(%rdi),%rax
+imulq $38, %rax,%rax
+mulq 32(%rdi)
+add %rax,%r11
+adc %rdx,%r12
+movq 24(%rdi),%rax
+imulq $19, %rax,%rax
+mulq 24(%rdi)
+add %rax,%r11
+adc %rdx,%r12
+shld $13,%r11,%r12
+movq 24(%rdi),%rax
+imulq $38, %rax,%rax
+mulq 32(%rdi)
+add %rax,%r13
+adc %rdx,%r14
+shld $13,%r13,%r14
+movq 32(%rdi),%rax
+imulq $19, %rax,%rax
+mulq 32(%rdi)
+add %rax,%r15
+adc %rdx,%rbx
+shld $13,%r15,%rbx
+movq REDMASK51(%rip),%rdx
+and %rdx,%rcx
+add %rbx,%rcx
+and %rdx,%r9
+and %rdx,%r11
+add %r10,%r11
+and %rdx,%r13
+add %r12,%r13
+and %rdx,%r15
+add %r14,%r15
+imulq $19, %rbp,%rbp
+lea (%r9,%rbp),%r9
+mov %r9,%rax
+shr $51,%r9
+add %r11,%r9
+and %rdx,%rax
+mov %r9,%r8
+shr $51,%r9
+add %r13,%r9
+and %rdx,%r8
+mov %r9,%r10
+shr $51,%r9
+add %r15,%r9
+and %rdx,%r10
+movq %r10,16(%rdi)
+mov %r9,%r10
+shr $51,%r9
+add %rcx,%r9
+and %rdx,%r10
+movq %r10,24(%rdi)
+mov %r9,%r10
+shr $51,%r9
+imulq $19, %r9,%r9
+lea (%rax,%r9),%rcx
+and %rdx,%r10
+movq %r10,32(%rdi)
+cmp $0,%rsi
+jne ._loop
+
+movq %rcx,0(%rdi)
+movq %r8,8(%rdi)
+movq 0(%rsp),%r11
+movq 8(%rsp),%r12
+movq 16(%rsp),%r13
+movq 24(%rsp),%r14
+movq 32(%rsp),%r15
+movq 40(%rsp),%rbx
+movq 48(%rsp),%rbp
+add %r11,%rsp
+ret
+
+#endif
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_pack.S b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_pack.S
new file mode 100644
index 0000000000..500c858476
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe51_pack.S
@@ -0,0 +1,226 @@
+#ifdef IN_SANDY2X
+
+/*
+ This file is the result of merging
+ amd64-51/fe25519_pack.c and amd64-51/fe25519_freeze.s.
+*/
+#include "fe51_namespace.h"
+#include "consts_namespace.h"
+.p2align 5
+
+#ifdef ASM_HIDE_SYMBOL
+ASM_HIDE_SYMBOL fe51_pack
+ASM_HIDE_SYMBOL _fe51_pack
+#endif
+.globl fe51_pack
+.globl _fe51_pack
+#ifdef __ELF__
+.type fe51_pack, @function
+.type _fe51_pack, @function
+#endif
+fe51_pack:
+_fe51_pack:
+
+mov %rsp,%r11
+and $31,%r11
+add $32,%r11
+sub %r11,%rsp
+movq %r11,0(%rsp)
+movq %r12,8(%rsp)
+movq 0(%rsi),%rdx
+movq 8(%rsi),%rcx
+movq 16(%rsi),%r8
+movq 24(%rsi),%r9
+movq 32(%rsi),%rsi
+movq REDMASK51(%rip),%rax
+lea -18(%rax),%r10
+mov $3,%r11
+
+.p2align 4
+._reduceloop:
+mov %rdx,%r12
+shr $51,%r12
+and %rax,%rdx
+add %r12,%rcx
+mov %rcx,%r12
+shr $51,%r12
+and %rax,%rcx
+add %r12,%r8
+mov %r8,%r12
+shr $51,%r12
+and %rax,%r8
+add %r12,%r9
+mov %r9,%r12
+shr $51,%r12
+and %rax,%r9
+add %r12,%rsi
+mov %rsi,%r12
+shr $51,%r12
+and %rax,%rsi
+imulq $19, %r12,%r12
+add %r12,%rdx
+sub $1,%r11
+ja ._reduceloop
+
+mov $1,%r12
+cmp %r10,%rdx
+cmovl %r11,%r12
+cmp %rax,%rcx
+cmovne %r11,%r12
+cmp %rax,%r8
+cmovne %r11,%r12
+cmp %rax,%r9
+cmovne %r11,%r12
+cmp %rax,%rsi
+cmovne %r11,%r12
+neg %r12
+and %r12,%rax
+and %r12,%r10
+sub %r10,%rdx
+sub %rax,%rcx
+sub %rax,%r8
+sub %rax,%r9
+sub %rax,%rsi
+mov %rdx,%rax
+and $0xFF,%eax
+movb %al,0(%rdi)
+mov %rdx,%rax
+shr $8,%rax
+and $0xFF,%eax
+movb %al,1(%rdi)
+mov %rdx,%rax
+shr $16,%rax
+and $0xFF,%eax
+movb %al,2(%rdi)
+mov %rdx,%rax
+shr $24,%rax
+and $0xFF,%eax
+movb %al,3(%rdi)
+mov %rdx,%rax
+shr $32,%rax
+and $0xFF,%eax
+movb %al,4(%rdi)
+mov %rdx,%rax
+shr $40,%rax
+and $0xFF,%eax
+movb %al,5(%rdi)
+mov %rdx,%rdx
+shr $48,%rdx
+mov %rcx,%rax
+shl $3,%rax
+and $0xF8,%eax
+xor %rdx,%rax
+movb %al,6(%rdi)
+mov %rcx,%rdx
+shr $5,%rdx
+and $0xFF,%edx
+movb %dl,7(%rdi)
+mov %rcx,%rdx
+shr $13,%rdx
+and $0xFF,%edx
+movb %dl,8(%rdi)
+mov %rcx,%rdx
+shr $21,%rdx
+and $0xFF,%edx
+movb %dl,9(%rdi)
+mov %rcx,%rdx
+shr $29,%rdx
+and $0xFF,%edx
+movb %dl,10(%rdi)
+mov %rcx,%rdx
+shr $37,%rdx
+and $0xFF,%edx
+movb %dl,11(%rdi)
+mov %rcx,%rdx
+shr $45,%rdx
+mov %r8,%rcx
+shl $6,%rcx
+and $0xC0,%ecx
+xor %rdx,%rcx
+movb %cl,12(%rdi)
+mov %r8,%rdx
+shr $2,%rdx
+and $0xFF,%edx
+movb %dl,13(%rdi)
+mov %r8,%rdx
+shr $10,%rdx
+and $0xFF,%edx
+movb %dl,14(%rdi)
+mov %r8,%rdx
+shr $18,%rdx
+and $0xFF,%edx
+movb %dl,15(%rdi)
+mov %r8,%rdx
+shr $26,%rdx
+and $0xFF,%edx
+movb %dl,16(%rdi)
+mov %r8,%rdx
+shr $34,%rdx
+and $0xFF,%edx
+movb %dl,17(%rdi)
+mov %r8,%rdx
+shr $42,%rdx
+movb %dl,18(%rdi)
+mov %r8,%rdx
+shr $50,%rdx
+mov %r9,%rcx
+shl $1,%rcx
+and $0xFE,%ecx
+xor %rdx,%rcx
+movb %cl,19(%rdi)
+mov %r9,%rdx
+shr $7,%rdx
+and $0xFF,%edx
+movb %dl,20(%rdi)
+mov %r9,%rdx
+shr $15,%rdx
+and $0xFF,%edx
+movb %dl,21(%rdi)
+mov %r9,%rdx
+shr $23,%rdx
+and $0xFF,%edx
+movb %dl,22(%rdi)
+mov %r9,%rdx
+shr $31,%rdx
+and $0xFF,%edx
+movb %dl,23(%rdi)
+mov %r9,%rdx
+shr $39,%rdx
+and $0xFF,%edx
+movb %dl,24(%rdi)
+mov %r9,%rdx
+shr $47,%rdx
+mov %rsi,%rcx
+shl $4,%rcx
+and $0xF0,%ecx
+xor %rdx,%rcx
+movb %cl,25(%rdi)
+mov %rsi,%rdx
+shr $4,%rdx
+and $0xFF,%edx
+movb %dl,26(%rdi)
+mov %rsi,%rdx
+shr $12,%rdx
+and $0xFF,%edx
+movb %dl,27(%rdi)
+mov %rsi,%rdx
+shr $20,%rdx
+and $0xFF,%edx
+movb %dl,28(%rdi)
+mov %rsi,%rdx
+shr $28,%rdx
+and $0xFF,%edx
+movb %dl,29(%rdi)
+mov %rsi,%rdx
+shr $36,%rdx
+and $0xFF,%edx
+movb %dl,30(%rdi)
+mov %rsi,%rsi
+shr $44,%rsi
+movb %sil,31(%rdi)
+movq 0(%rsp),%r11
+movq 8(%rsp),%r12
+add %r11,%rsp
+ret
+
+#endif
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe_frombytes_sandy2x.c b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe_frombytes_sandy2x.c
new file mode 100644
index 0000000000..2fe081ee2a
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/fe_frombytes_sandy2x.c
@@ -0,0 +1,78 @@
+/*
+ This file is basically ref10/fe_frombytes.h.
+*/
+
+#include "fe.h"
+
+#ifdef HAVE_AVX_ASM
+
+static uint64_t
+load_3(const unsigned char *in)
+{
+ uint64_t result;
+ result = (uint64_t) in[0];
+ result |= ((uint64_t) in[1]) << 8;
+ result |= ((uint64_t) in[2]) << 16;
+ return result;
+}
+
+static uint64_t
+load_4(const unsigned char *in)
+{
+ uint64_t result;
+ result = (uint64_t) in[0];
+ result |= ((uint64_t) in[1]) << 8;
+ result |= ((uint64_t) in[2]) << 16;
+ result |= ((uint64_t) in[3]) << 24;
+ return result;
+}
+
+void
+fe_frombytes(fe h, const unsigned char *s)
+{
+ uint64_t h0 = load_4(s);
+ uint64_t h1 = load_3(s + 4) << 6;
+ uint64_t h2 = load_3(s + 7) << 5;
+ uint64_t h3 = load_3(s + 10) << 3;
+ uint64_t h4 = load_3(s + 13) << 2;
+ uint64_t h5 = load_4(s + 16);
+ uint64_t h6 = load_3(s + 20) << 7;
+ uint64_t h7 = load_3(s + 23) << 5;
+ uint64_t h8 = load_3(s + 26) << 4;
+ uint64_t h9 = (load_3(s + 29) & 8388607) << 2;
+ uint64_t carry0;
+ uint64_t carry1;
+ uint64_t carry2;
+ uint64_t carry3;
+ uint64_t carry4;
+ uint64_t carry5;
+ uint64_t carry6;
+ uint64_t carry7;
+ uint64_t carry8;
+ uint64_t carry9;
+
+ carry9 = h9 >> 25; h0 += carry9 * 19; h9 &= 0x1FFFFFF;
+ carry1 = h1 >> 25; h2 += carry1; h1 &= 0x1FFFFFF;
+ carry3 = h3 >> 25; h4 += carry3; h3 &= 0x1FFFFFF;
+ carry5 = h5 >> 25; h6 += carry5; h5 &= 0x1FFFFFF;
+ carry7 = h7 >> 25; h8 += carry7; h7 &= 0x1FFFFFF;
+
+ carry0 = h0 >> 26; h1 += carry0; h0 &= 0x3FFFFFF;
+ carry2 = h2 >> 26; h3 += carry2; h2 &= 0x3FFFFFF;
+ carry4 = h4 >> 26; h5 += carry4; h4 &= 0x3FFFFFF;
+ carry6 = h6 >> 26; h7 += carry6; h6 &= 0x3FFFFFF;
+ carry8 = h8 >> 26; h9 += carry8; h8 &= 0x3FFFFFF;
+
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+ h[5] = h5;
+ h[6] = h6;
+ h[7] = h7;
+ h[8] = h8;
+ h[9] = h9;
+}
+
+#endif
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder.S b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder.S
new file mode 100644
index 0000000000..c5c06021d8
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder.S
@@ -0,0 +1,1440 @@
+#ifdef IN_SANDY2X
+
+#include "ladder_namespace.h"
+#include "consts_namespace.h"
+.p2align 5
+
+#ifdef ASM_HIDE_SYMBOL
+ASM_HIDE_SYMBOL ladder
+ASM_HIDE_SYMBOL _ladder
+#endif
+.globl ladder
+.globl _ladder
+#ifdef __ELF__
+.type ladder, @function
+.type _ladder, @function
+#endif
+ladder:
+_ladder:
+
+mov %rsp,%r11
+and $31,%r11
+add $1856,%r11
+sub %r11,%rsp
+movq %r11,1824(%rsp)
+movq %r12,1832(%rsp)
+movq %r13,1840(%rsp)
+movq %r14,1848(%rsp)
+vmovdqa v0_0(%rip),%xmm0
+vmovdqa v1_0(%rip),%xmm1
+vmovdqu 0(%rdi),%xmm2
+vmovdqa %xmm2,0(%rsp)
+vmovdqu 16(%rdi),%xmm2
+vmovdqa %xmm2,16(%rsp)
+vmovdqu 32(%rdi),%xmm2
+vmovdqa %xmm2,32(%rsp)
+vmovdqu 48(%rdi),%xmm2
+vmovdqa %xmm2,48(%rsp)
+vmovdqu 64(%rdi),%xmm2
+vmovdqa %xmm2,64(%rsp)
+vmovdqa %xmm1,80(%rsp)
+vmovdqa %xmm0,96(%rsp)
+vmovdqa %xmm0,112(%rsp)
+vmovdqa %xmm0,128(%rsp)
+vmovdqa %xmm0,144(%rsp)
+vmovdqa %xmm1,%xmm0
+vpxor %xmm1,%xmm1,%xmm1
+vpxor %xmm2,%xmm2,%xmm2
+vpxor %xmm3,%xmm3,%xmm3
+vpxor %xmm4,%xmm4,%xmm4
+vpxor %xmm5,%xmm5,%xmm5
+vpxor %xmm6,%xmm6,%xmm6
+vpxor %xmm7,%xmm7,%xmm7
+vpxor %xmm8,%xmm8,%xmm8
+vpxor %xmm9,%xmm9,%xmm9
+vmovdqu 0(%rdi),%xmm10
+vmovdqa %xmm10,160(%rsp)
+vmovdqu 16(%rdi),%xmm10
+vmovdqa %xmm10,176(%rsp)
+vpmuludq v19_19(%rip),%xmm10,%xmm10
+vmovdqa %xmm10,192(%rsp)
+vmovdqu 32(%rdi),%xmm10
+vmovdqa %xmm10,208(%rsp)
+vpmuludq v19_19(%rip),%xmm10,%xmm10
+vmovdqa %xmm10,224(%rsp)
+vmovdqu 48(%rdi),%xmm10
+vmovdqa %xmm10,240(%rsp)
+vpmuludq v19_19(%rip),%xmm10,%xmm10
+vmovdqa %xmm10,256(%rsp)
+vmovdqu 64(%rdi),%xmm10
+vmovdqa %xmm10,272(%rsp)
+vpmuludq v19_19(%rip),%xmm10,%xmm10
+vmovdqa %xmm10,288(%rsp)
+vmovdqu 8(%rdi),%xmm10
+vpmuludq v2_1(%rip),%xmm10,%xmm10
+vmovdqa %xmm10,304(%rsp)
+vpmuludq v19_19(%rip),%xmm10,%xmm10
+vmovdqa %xmm10,320(%rsp)
+vmovdqu 24(%rdi),%xmm10
+vpmuludq v2_1(%rip),%xmm10,%xmm10
+vmovdqa %xmm10,336(%rsp)
+vpmuludq v19_19(%rip),%xmm10,%xmm10
+vmovdqa %xmm10,352(%rsp)
+vmovdqu 40(%rdi),%xmm10
+vpmuludq v2_1(%rip),%xmm10,%xmm10
+vmovdqa %xmm10,368(%rsp)
+vpmuludq v19_19(%rip),%xmm10,%xmm10
+vmovdqa %xmm10,384(%rsp)
+vmovdqu 56(%rdi),%xmm10
+vpmuludq v2_1(%rip),%xmm10,%xmm10
+vmovdqa %xmm10,400(%rsp)
+vpmuludq v19_19(%rip),%xmm10,%xmm10
+vmovdqa %xmm10,416(%rsp)
+vmovdqu 0(%rdi),%xmm10
+vmovdqu 64(%rdi),%xmm11
+vblendps $12, %xmm11, %xmm10, %xmm10
+vpshufd $2,%xmm10,%xmm10
+vpmuludq v38_1(%rip),%xmm10,%xmm10
+vmovdqa %xmm10,432(%rsp)
+movq 0(%rsi),%rdx
+movq 8(%rsi),%rcx
+movq 16(%rsi),%r8
+movq 24(%rsi),%r9
+shrd $1,%rcx,%rdx
+shrd $1,%r8,%rcx
+shrd $1,%r9,%r8
+shr $1,%r9
+xorq 0(%rsi),%rdx
+xorq 8(%rsi),%rcx
+xorq 16(%rsi),%r8
+xorq 24(%rsi),%r9
+leaq 800(%rsp),%rsi
+mov $64,%rax
+
+.p2align 4
+._ladder_small_loop:
+mov %rdx,%r10
+mov %rcx,%r11
+mov %r8,%r12
+mov %r9,%r13
+shr $1,%rdx
+shr $1,%rcx
+shr $1,%r8
+shr $1,%r9
+and $1,%r10d
+and $1,%r11d
+and $1,%r12d
+and $1,%r13d
+neg %r10
+neg %r11
+neg %r12
+neg %r13
+movl %r10d,0(%rsi)
+movl %r11d,256(%rsi)
+movl %r12d,512(%rsi)
+movl %r13d,768(%rsi)
+add $4,%rsi
+sub $1,%rax
+jne ._ladder_small_loop
+mov $255,%rdx
+add $760,%rsi
+
+.p2align 4
+._ladder_loop:
+sub $1,%rdx
+vbroadcastss 0(%rsi),%xmm10
+sub $4,%rsi
+vmovdqa 0(%rsp),%xmm11
+vmovdqa 80(%rsp),%xmm12
+vpxor %xmm11,%xmm0,%xmm13
+vpand %xmm10,%xmm13,%xmm13
+vpxor %xmm13,%xmm0,%xmm0
+vpxor %xmm13,%xmm11,%xmm11
+vpxor %xmm12,%xmm1,%xmm13
+vpand %xmm10,%xmm13,%xmm13
+vpxor %xmm13,%xmm1,%xmm1
+vpxor %xmm13,%xmm12,%xmm12
+vmovdqa 16(%rsp),%xmm13
+vmovdqa 96(%rsp),%xmm14
+vpxor %xmm13,%xmm2,%xmm15
+vpand %xmm10,%xmm15,%xmm15
+vpxor %xmm15,%xmm2,%xmm2
+vpxor %xmm15,%xmm13,%xmm13
+vpxor %xmm14,%xmm3,%xmm15
+vpand %xmm10,%xmm15,%xmm15
+vpxor %xmm15,%xmm3,%xmm3
+vpxor %xmm15,%xmm14,%xmm14
+vmovdqa %xmm13,0(%rsp)
+vmovdqa %xmm14,16(%rsp)
+vmovdqa 32(%rsp),%xmm13
+vmovdqa 112(%rsp),%xmm14
+vpxor %xmm13,%xmm4,%xmm15
+vpand %xmm10,%xmm15,%xmm15
+vpxor %xmm15,%xmm4,%xmm4
+vpxor %xmm15,%xmm13,%xmm13
+vpxor %xmm14,%xmm5,%xmm15
+vpand %xmm10,%xmm15,%xmm15
+vpxor %xmm15,%xmm5,%xmm5
+vpxor %xmm15,%xmm14,%xmm14
+vmovdqa %xmm13,32(%rsp)
+vmovdqa %xmm14,80(%rsp)
+vmovdqa 48(%rsp),%xmm13
+vmovdqa 128(%rsp),%xmm14
+vpxor %xmm13,%xmm6,%xmm15
+vpand %xmm10,%xmm15,%xmm15
+vpxor %xmm15,%xmm6,%xmm6
+vpxor %xmm15,%xmm13,%xmm13
+vpxor %xmm14,%xmm7,%xmm15
+vpand %xmm10,%xmm15,%xmm15
+vpxor %xmm15,%xmm7,%xmm7
+vpxor %xmm15,%xmm14,%xmm14
+vmovdqa %xmm13,48(%rsp)
+vmovdqa %xmm14,96(%rsp)
+vmovdqa 64(%rsp),%xmm13
+vmovdqa 144(%rsp),%xmm14
+vpxor %xmm13,%xmm8,%xmm15
+vpand %xmm10,%xmm15,%xmm15
+vpxor %xmm15,%xmm8,%xmm8
+vpxor %xmm15,%xmm13,%xmm13
+vpxor %xmm14,%xmm9,%xmm15
+vpand %xmm10,%xmm15,%xmm15
+vpxor %xmm15,%xmm9,%xmm9
+vpxor %xmm15,%xmm14,%xmm14
+vmovdqa %xmm13,64(%rsp)
+vmovdqa %xmm14,112(%rsp)
+vpaddq subc0(%rip),%xmm11,%xmm10
+vpsubq %xmm12,%xmm10,%xmm10
+vpaddq %xmm12,%xmm11,%xmm11
+vpunpckhqdq %xmm10,%xmm11,%xmm12
+vpunpcklqdq %xmm10,%xmm11,%xmm10
+vpaddq %xmm1,%xmm0,%xmm11
+vpaddq subc0(%rip),%xmm0,%xmm0
+vpsubq %xmm1,%xmm0,%xmm0
+vpunpckhqdq %xmm11,%xmm0,%xmm1
+vpunpcklqdq %xmm11,%xmm0,%xmm0
+vpmuludq %xmm0,%xmm10,%xmm11
+vpmuludq %xmm1,%xmm10,%xmm13
+vmovdqa %xmm1,128(%rsp)
+vpaddq %xmm1,%xmm1,%xmm1
+vpmuludq %xmm0,%xmm12,%xmm14
+vmovdqa %xmm0,144(%rsp)
+vpaddq %xmm14,%xmm13,%xmm13
+vpmuludq %xmm1,%xmm12,%xmm0
+vmovdqa %xmm1,448(%rsp)
+vpaddq %xmm3,%xmm2,%xmm1
+vpaddq subc2(%rip),%xmm2,%xmm2
+vpsubq %xmm3,%xmm2,%xmm2
+vpunpckhqdq %xmm1,%xmm2,%xmm3
+vpunpcklqdq %xmm1,%xmm2,%xmm1
+vpmuludq %xmm1,%xmm10,%xmm2
+vpaddq %xmm2,%xmm0,%xmm0
+vpmuludq %xmm3,%xmm10,%xmm2
+vmovdqa %xmm3,464(%rsp)
+vpaddq %xmm3,%xmm3,%xmm3
+vpmuludq %xmm1,%xmm12,%xmm14
+vmovdqa %xmm1,480(%rsp)
+vpaddq %xmm14,%xmm2,%xmm2
+vpmuludq %xmm3,%xmm12,%xmm1
+vmovdqa %xmm3,496(%rsp)
+vpaddq %xmm5,%xmm4,%xmm3
+vpaddq subc2(%rip),%xmm4,%xmm4
+vpsubq %xmm5,%xmm4,%xmm4
+vpunpckhqdq %xmm3,%xmm4,%xmm5
+vpunpcklqdq %xmm3,%xmm4,%xmm3
+vpmuludq %xmm3,%xmm10,%xmm4
+vpaddq %xmm4,%xmm1,%xmm1
+vpmuludq %xmm5,%xmm10,%xmm4
+vmovdqa %xmm5,512(%rsp)
+vpaddq %xmm5,%xmm5,%xmm5
+vpmuludq %xmm3,%xmm12,%xmm14
+vmovdqa %xmm3,528(%rsp)
+vpaddq %xmm14,%xmm4,%xmm4
+vpaddq %xmm7,%xmm6,%xmm3
+vpaddq subc2(%rip),%xmm6,%xmm6
+vpsubq %xmm7,%xmm6,%xmm6
+vpunpckhqdq %xmm3,%xmm6,%xmm7
+vpunpcklqdq %xmm3,%xmm6,%xmm3
+vpmuludq %xmm3,%xmm10,%xmm6
+vpmuludq %xmm5,%xmm12,%xmm14
+vmovdqa %xmm5,544(%rsp)
+vpmuludq v19_19(%rip),%xmm5,%xmm5
+vmovdqa %xmm5,560(%rsp)
+vpaddq %xmm14,%xmm6,%xmm6
+vpmuludq %xmm7,%xmm10,%xmm5
+vmovdqa %xmm7,576(%rsp)
+vpaddq %xmm7,%xmm7,%xmm7
+vpmuludq %xmm3,%xmm12,%xmm14
+vmovdqa %xmm3,592(%rsp)
+vpaddq %xmm14,%xmm5,%xmm5
+vpmuludq v19_19(%rip),%xmm3,%xmm3
+vmovdqa %xmm3,608(%rsp)
+vpaddq %xmm9,%xmm8,%xmm3
+vpaddq subc2(%rip),%xmm8,%xmm8
+vpsubq %xmm9,%xmm8,%xmm8
+vpunpckhqdq %xmm3,%xmm8,%xmm9
+vpunpcklqdq %xmm3,%xmm8,%xmm3
+vmovdqa %xmm3,624(%rsp)
+vpmuludq %xmm7,%xmm12,%xmm8
+vmovdqa %xmm7,640(%rsp)
+vpmuludq v19_19(%rip),%xmm7,%xmm7
+vmovdqa %xmm7,656(%rsp)
+vpmuludq %xmm3,%xmm10,%xmm7
+vpaddq %xmm7,%xmm8,%xmm8
+vpmuludq %xmm9,%xmm10,%xmm7
+vmovdqa %xmm9,672(%rsp)
+vpaddq %xmm9,%xmm9,%xmm9
+vpmuludq %xmm3,%xmm12,%xmm10
+vpaddq %xmm10,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm3,%xmm3
+vmovdqa %xmm3,688(%rsp)
+vpmuludq v19_19(%rip),%xmm12,%xmm12
+vpmuludq %xmm9,%xmm12,%xmm3
+vmovdqa %xmm9,704(%rsp)
+vpaddq %xmm3,%xmm11,%xmm11
+vmovdqa 0(%rsp),%xmm3
+vmovdqa 16(%rsp),%xmm9
+vpaddq subc2(%rip),%xmm3,%xmm10
+vpsubq %xmm9,%xmm10,%xmm10
+vpaddq %xmm9,%xmm3,%xmm3
+vpunpckhqdq %xmm10,%xmm3,%xmm9
+vpunpcklqdq %xmm10,%xmm3,%xmm3
+vpmuludq 144(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm0,%xmm0
+vpmuludq 128(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm2,%xmm2
+vpmuludq 480(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm1,%xmm1
+vpmuludq 464(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm4,%xmm4
+vpmuludq 528(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm6,%xmm6
+vpmuludq 512(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm5,%xmm5
+vpmuludq 592(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm8,%xmm8
+vpmuludq 576(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm3,%xmm3
+vpmuludq 624(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm11,%xmm11
+vpmuludq 672(%rsp),%xmm3,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpmuludq 144(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm2,%xmm2
+vpmuludq 448(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm1,%xmm1
+vpmuludq 480(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm4,%xmm4
+vpmuludq 496(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpmuludq 528(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm5,%xmm5
+vpmuludq 544(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm8,%xmm8
+vpmuludq 592(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm9,%xmm9
+vpmuludq 640(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm11,%xmm11
+vpmuludq 624(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpmuludq 704(%rsp),%xmm9,%xmm9
+vpaddq %xmm9,%xmm0,%xmm0
+vmovdqa 32(%rsp),%xmm3
+vmovdqa 80(%rsp),%xmm9
+vpaddq subc2(%rip),%xmm3,%xmm10
+vpsubq %xmm9,%xmm10,%xmm10
+vpaddq %xmm9,%xmm3,%xmm3
+vpunpckhqdq %xmm10,%xmm3,%xmm9
+vpunpcklqdq %xmm10,%xmm3,%xmm3
+vpmuludq 144(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm1,%xmm1
+vpmuludq 128(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm4,%xmm4
+vpmuludq 480(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm6,%xmm6
+vpmuludq 464(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm5,%xmm5
+vpmuludq 528(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm8,%xmm8
+vpmuludq 512(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm3,%xmm3
+vpmuludq 592(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm11,%xmm11
+vpmuludq 576(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm13,%xmm13
+vpmuludq 624(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm0,%xmm0
+vpmuludq 672(%rsp),%xmm3,%xmm3
+vpaddq %xmm3,%xmm2,%xmm2
+vpmuludq 144(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm4,%xmm4
+vpmuludq 448(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpmuludq 480(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm5,%xmm5
+vpmuludq 496(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm8,%xmm8
+vpmuludq 528(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm9,%xmm9
+vpmuludq 544(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm11,%xmm11
+vpmuludq 592(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpmuludq 640(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm0,%xmm0
+vpmuludq 624(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm2,%xmm2
+vpmuludq 704(%rsp),%xmm9,%xmm9
+vpaddq %xmm9,%xmm1,%xmm1
+vmovdqa 48(%rsp),%xmm3
+vmovdqa 96(%rsp),%xmm9
+vpaddq subc2(%rip),%xmm3,%xmm10
+vpsubq %xmm9,%xmm10,%xmm10
+vpaddq %xmm9,%xmm3,%xmm3
+vpunpckhqdq %xmm10,%xmm3,%xmm9
+vpunpcklqdq %xmm10,%xmm3,%xmm3
+vpmuludq 144(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm6,%xmm6
+vpmuludq 128(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm5,%xmm5
+vpmuludq 480(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm8,%xmm8
+vpmuludq 464(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm3,%xmm3
+vpmuludq 528(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm11,%xmm11
+vpmuludq 512(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm13,%xmm13
+vpmuludq 592(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm0,%xmm0
+vpmuludq 576(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm2,%xmm2
+vpmuludq 624(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm1,%xmm1
+vpmuludq 672(%rsp),%xmm3,%xmm3
+vpaddq %xmm3,%xmm4,%xmm4
+vpmuludq 144(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm5,%xmm5
+vpmuludq 448(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm8,%xmm8
+vpmuludq 480(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm9,%xmm9
+vpmuludq 496(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm11,%xmm11
+vpmuludq 528(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpmuludq 544(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm0,%xmm0
+vpmuludq 592(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm2,%xmm2
+vpmuludq 640(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm1,%xmm1
+vpmuludq 624(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm4,%xmm4
+vpmuludq 704(%rsp),%xmm9,%xmm9
+vpaddq %xmm9,%xmm6,%xmm6
+vmovdqa 64(%rsp),%xmm3
+vmovdqa 112(%rsp),%xmm9
+vpaddq subc2(%rip),%xmm3,%xmm10
+vpsubq %xmm9,%xmm10,%xmm10
+vpaddq %xmm9,%xmm3,%xmm3
+vpunpckhqdq %xmm10,%xmm3,%xmm9
+vpunpcklqdq %xmm10,%xmm3,%xmm3
+vpmuludq 144(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm8,%xmm8
+vpmuludq 128(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm3,%xmm3
+vpmuludq 480(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm11,%xmm11
+vpmuludq 464(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm13,%xmm13
+vpmuludq 528(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm0,%xmm0
+vpmuludq 512(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm2,%xmm2
+vpmuludq 592(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm1,%xmm1
+vpmuludq 576(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm4,%xmm4
+vpmuludq 624(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm6,%xmm6
+vpmuludq 672(%rsp),%xmm3,%xmm3
+vpaddq %xmm3,%xmm5,%xmm5
+vpmuludq 144(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm9,%xmm9
+vpmuludq 448(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm11,%xmm11
+vpmuludq 480(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpmuludq 496(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm0,%xmm0
+vpmuludq 528(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm2,%xmm2
+vpmuludq 544(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm1,%xmm1
+vpmuludq 592(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm4,%xmm4
+vpmuludq 640(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpmuludq 624(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm5,%xmm5
+vpmuludq 704(%rsp),%xmm9,%xmm9
+vpaddq %xmm9,%xmm8,%xmm8
+vpsrlq $25,%xmm4,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpand m25(%rip),%xmm4,%xmm4
+vpsrlq $26,%xmm11,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpand m26(%rip),%xmm11,%xmm11
+vpsrlq $26,%xmm6,%xmm3
+vpaddq %xmm3,%xmm5,%xmm5
+vpand m26(%rip),%xmm6,%xmm6
+vpsrlq $25,%xmm13,%xmm3
+vpaddq %xmm3,%xmm0,%xmm0
+vpand m25(%rip),%xmm13,%xmm13
+vpsrlq $25,%xmm5,%xmm3
+vpaddq %xmm3,%xmm8,%xmm8
+vpand m25(%rip),%xmm5,%xmm5
+vpsrlq $26,%xmm0,%xmm3
+vpaddq %xmm3,%xmm2,%xmm2
+vpand m26(%rip),%xmm0,%xmm0
+vpsrlq $26,%xmm8,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpand m26(%rip),%xmm8,%xmm8
+vpsrlq $25,%xmm2,%xmm3
+vpaddq %xmm3,%xmm1,%xmm1
+vpand m25(%rip),%xmm2,%xmm2
+vpsrlq $25,%xmm7,%xmm3
+vpsllq $4,%xmm3,%xmm9
+vpaddq %xmm3,%xmm11,%xmm11
+vpsllq $1,%xmm3,%xmm3
+vpaddq %xmm3,%xmm9,%xmm9
+vpaddq %xmm9,%xmm11,%xmm11
+vpand m25(%rip),%xmm7,%xmm7
+vpsrlq $26,%xmm1,%xmm3
+vpaddq %xmm3,%xmm4,%xmm4
+vpand m26(%rip),%xmm1,%xmm1
+vpsrlq $26,%xmm11,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpand m26(%rip),%xmm11,%xmm11
+vpsrlq $25,%xmm4,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpand m25(%rip),%xmm4,%xmm4
+vpunpcklqdq %xmm13,%xmm11,%xmm3
+vpunpckhqdq %xmm13,%xmm11,%xmm9
+vpaddq subc0(%rip),%xmm9,%xmm10
+vpsubq %xmm3,%xmm10,%xmm10
+vpaddq %xmm9,%xmm3,%xmm3
+vpunpckhqdq %xmm3,%xmm10,%xmm9
+vpunpcklqdq %xmm3,%xmm10,%xmm10
+vpmuludq %xmm10,%xmm10,%xmm3
+vpaddq %xmm10,%xmm10,%xmm10
+vpmuludq %xmm9,%xmm10,%xmm11
+vpunpcklqdq %xmm2,%xmm0,%xmm12
+vpunpckhqdq %xmm2,%xmm0,%xmm0
+vpaddq subc2(%rip),%xmm0,%xmm2
+vpsubq %xmm12,%xmm2,%xmm2
+vpaddq %xmm0,%xmm12,%xmm12
+vpunpckhqdq %xmm12,%xmm2,%xmm0
+vpunpcklqdq %xmm12,%xmm2,%xmm2
+vpmuludq %xmm2,%xmm10,%xmm12
+vpaddq %xmm9,%xmm9,%xmm13
+vpmuludq %xmm13,%xmm9,%xmm9
+vpaddq %xmm9,%xmm12,%xmm12
+vpmuludq %xmm0,%xmm10,%xmm9
+vpmuludq %xmm2,%xmm13,%xmm14
+vpaddq %xmm14,%xmm9,%xmm9
+vpunpcklqdq %xmm4,%xmm1,%xmm14
+vpunpckhqdq %xmm4,%xmm1,%xmm1
+vpaddq subc2(%rip),%xmm1,%xmm4
+vpsubq %xmm14,%xmm4,%xmm4
+vpaddq %xmm1,%xmm14,%xmm14
+vpunpckhqdq %xmm14,%xmm4,%xmm1
+vpunpcklqdq %xmm14,%xmm4,%xmm4
+vmovdqa %xmm1,0(%rsp)
+vpaddq %xmm1,%xmm1,%xmm1
+vmovdqa %xmm1,16(%rsp)
+vpmuludq v19_19(%rip),%xmm1,%xmm1
+vmovdqa %xmm1,32(%rsp)
+vpmuludq %xmm4,%xmm10,%xmm1
+vpmuludq %xmm2,%xmm2,%xmm14
+vpaddq %xmm14,%xmm1,%xmm1
+vpmuludq 0(%rsp),%xmm10,%xmm14
+vpmuludq %xmm4,%xmm13,%xmm15
+vpaddq %xmm15,%xmm14,%xmm14
+vpunpcklqdq %xmm5,%xmm6,%xmm15
+vpunpckhqdq %xmm5,%xmm6,%xmm5
+vpaddq subc2(%rip),%xmm5,%xmm6
+vpsubq %xmm15,%xmm6,%xmm6
+vpaddq %xmm5,%xmm15,%xmm15
+vpunpckhqdq %xmm15,%xmm6,%xmm5
+vpunpcklqdq %xmm15,%xmm6,%xmm6
+vmovdqa %xmm6,48(%rsp)
+vpmuludq v19_19(%rip),%xmm6,%xmm6
+vmovdqa %xmm6,64(%rsp)
+vmovdqa %xmm5,80(%rsp)
+vpmuludq v38_38(%rip),%xmm5,%xmm5
+vmovdqa %xmm5,96(%rsp)
+vpmuludq 48(%rsp),%xmm10,%xmm5
+vpaddq %xmm0,%xmm0,%xmm6
+vpmuludq %xmm6,%xmm0,%xmm0
+vpaddq %xmm0,%xmm5,%xmm5
+vpmuludq 80(%rsp),%xmm10,%xmm0
+vpmuludq %xmm4,%xmm6,%xmm15
+vpaddq %xmm15,%xmm0,%xmm0
+vpmuludq %xmm6,%xmm13,%xmm15
+vpaddq %xmm15,%xmm1,%xmm1
+vpmuludq %xmm6,%xmm2,%xmm15
+vpaddq %xmm15,%xmm14,%xmm14
+vpunpcklqdq %xmm7,%xmm8,%xmm15
+vpunpckhqdq %xmm7,%xmm8,%xmm7
+vpaddq subc2(%rip),%xmm7,%xmm8
+vpsubq %xmm15,%xmm8,%xmm8
+vpaddq %xmm7,%xmm15,%xmm15
+vpunpckhqdq %xmm15,%xmm8,%xmm7
+vpunpcklqdq %xmm15,%xmm8,%xmm8
+vmovdqa %xmm8,112(%rsp)
+vpmuludq v19_19(%rip),%xmm8,%xmm8
+vmovdqa %xmm8,448(%rsp)
+vpmuludq 112(%rsp),%xmm10,%xmm8
+vpmuludq %xmm7,%xmm10,%xmm10
+vpmuludq v38_38(%rip),%xmm7,%xmm15
+vpmuludq %xmm15,%xmm7,%xmm7
+vpaddq %xmm7,%xmm8,%xmm8
+vpmuludq %xmm15,%xmm13,%xmm7
+vpaddq %xmm7,%xmm3,%xmm3
+vpmuludq %xmm15,%xmm2,%xmm7
+vpaddq %xmm7,%xmm11,%xmm11
+vpmuludq 80(%rsp),%xmm13,%xmm7
+vpaddq %xmm7,%xmm7,%xmm7
+vpaddq %xmm7,%xmm8,%xmm8
+vpmuludq 16(%rsp),%xmm13,%xmm7
+vpaddq %xmm7,%xmm5,%xmm5
+vpmuludq 48(%rsp),%xmm13,%xmm7
+vpaddq %xmm7,%xmm0,%xmm0
+vpmuludq 112(%rsp),%xmm13,%xmm7
+vpaddq %xmm7,%xmm10,%xmm10
+vpmuludq %xmm15,%xmm6,%xmm7
+vpaddq %xmm7,%xmm12,%xmm12
+vpmuludq %xmm15,%xmm4,%xmm7
+vpaddq %xmm7,%xmm9,%xmm9
+vpaddq %xmm2,%xmm2,%xmm2
+vpmuludq %xmm4,%xmm2,%xmm7
+vpaddq %xmm7,%xmm5,%xmm5
+vpmuludq 448(%rsp),%xmm2,%xmm7
+vpaddq %xmm7,%xmm3,%xmm3
+vpmuludq 448(%rsp),%xmm6,%xmm7
+vpaddq %xmm7,%xmm11,%xmm11
+vpmuludq 0(%rsp),%xmm2,%xmm7
+vpaddq %xmm7,%xmm0,%xmm0
+vpmuludq 48(%rsp),%xmm2,%xmm7
+vpaddq %xmm7,%xmm8,%xmm8
+vpmuludq 80(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpmuludq 96(%rsp),%xmm4,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpmuludq %xmm4,%xmm4,%xmm2
+vpaddq %xmm2,%xmm8,%xmm8
+vpaddq %xmm4,%xmm4,%xmm2
+vpmuludq 448(%rsp),%xmm2,%xmm4
+vpaddq %xmm4,%xmm12,%xmm12
+vpmuludq 16(%rsp),%xmm15,%xmm4
+vpaddq %xmm4,%xmm1,%xmm1
+vpmuludq 48(%rsp),%xmm15,%xmm4
+vpaddq %xmm4,%xmm14,%xmm14
+vpmuludq 96(%rsp),%xmm6,%xmm4
+vpaddq %xmm4,%xmm3,%xmm3
+vmovdqa 16(%rsp),%xmm4
+vpmuludq 448(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm9,%xmm9
+vpmuludq 16(%rsp),%xmm6,%xmm4
+vpaddq %xmm4,%xmm8,%xmm8
+vpmuludq 48(%rsp),%xmm6,%xmm4
+vpaddq %xmm4,%xmm10,%xmm10
+vpmuludq 80(%rsp),%xmm15,%xmm4
+vpaddq %xmm4,%xmm4,%xmm4
+vpaddq %xmm4,%xmm5,%xmm5
+vpmuludq 112(%rsp),%xmm15,%xmm4
+vpaddq %xmm4,%xmm0,%xmm0
+vmovdqa 48(%rsp),%xmm4
+vpaddq %xmm4,%xmm4,%xmm4
+vpmuludq 448(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm1,%xmm1
+vmovdqa 80(%rsp),%xmm4
+vpaddq %xmm4,%xmm4,%xmm4
+vpmuludq 448(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm14,%xmm14
+vpmuludq 64(%rsp),%xmm2,%xmm4
+vpaddq %xmm4,%xmm3,%xmm3
+vmovdqa 16(%rsp),%xmm4
+vpmuludq 64(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm11,%xmm11
+vmovdqa 16(%rsp),%xmm4
+vpmuludq 96(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm12,%xmm12
+vmovdqa 48(%rsp),%xmm4
+vpmuludq 96(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm9,%xmm9
+vpmuludq 0(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vmovdqa 32(%rsp),%xmm2
+vpmuludq 0(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm3,%xmm3
+vmovdqa 64(%rsp),%xmm2
+vpmuludq 48(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vmovdqa 96(%rsp),%xmm2
+vpmuludq 80(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm1,%xmm1
+vmovdqa 448(%rsp),%xmm2
+vpmuludq 112(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpsrlq $26,%xmm3,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpand m26(%rip),%xmm3,%xmm3
+vpsrlq $25,%xmm14,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpand m25(%rip),%xmm14,%xmm14
+vpsrlq $25,%xmm11,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpand m25(%rip),%xmm11,%xmm11
+vpsrlq $26,%xmm5,%xmm2
+vpaddq %xmm2,%xmm0,%xmm0
+vpand m26(%rip),%xmm5,%xmm5
+vpsrlq $26,%xmm12,%xmm2
+vpaddq %xmm2,%xmm9,%xmm9
+vpand m26(%rip),%xmm12,%xmm12
+vpsrlq $25,%xmm0,%xmm2
+vpaddq %xmm2,%xmm8,%xmm8
+vpand m25(%rip),%xmm0,%xmm0
+vpsrlq $25,%xmm9,%xmm2
+vpaddq %xmm2,%xmm1,%xmm1
+vpand m25(%rip),%xmm9,%xmm9
+vpsrlq $26,%xmm8,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpand m26(%rip),%xmm8,%xmm8
+vpsrlq $26,%xmm1,%xmm2
+vpaddq %xmm2,%xmm14,%xmm14
+vpand m26(%rip),%xmm1,%xmm1
+vpsrlq $25,%xmm10,%xmm2
+vpsllq $4,%xmm2,%xmm4
+vpaddq %xmm2,%xmm3,%xmm3
+vpsllq $1,%xmm2,%xmm2
+vpaddq %xmm2,%xmm4,%xmm4
+vpaddq %xmm4,%xmm3,%xmm3
+vpand m25(%rip),%xmm10,%xmm10
+vpsrlq $25,%xmm14,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpand m25(%rip),%xmm14,%xmm14
+vpsrlq $26,%xmm3,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpand m26(%rip),%xmm3,%xmm3
+vpunpckhqdq %xmm11,%xmm3,%xmm2
+vmovdqa %xmm2,0(%rsp)
+vpshufd $0,%xmm3,%xmm2
+vpshufd $0,%xmm11,%xmm3
+vpmuludq 160(%rsp),%xmm2,%xmm4
+vpmuludq 432(%rsp),%xmm3,%xmm6
+vpaddq %xmm6,%xmm4,%xmm4
+vpmuludq 176(%rsp),%xmm2,%xmm6
+vpmuludq 304(%rsp),%xmm3,%xmm7
+vpaddq %xmm7,%xmm6,%xmm6
+vpmuludq 208(%rsp),%xmm2,%xmm7
+vpmuludq 336(%rsp),%xmm3,%xmm11
+vpaddq %xmm11,%xmm7,%xmm7
+vpmuludq 240(%rsp),%xmm2,%xmm11
+vpmuludq 368(%rsp),%xmm3,%xmm13
+vpaddq %xmm13,%xmm11,%xmm11
+vpmuludq 272(%rsp),%xmm2,%xmm2
+vpmuludq 400(%rsp),%xmm3,%xmm3
+vpaddq %xmm3,%xmm2,%xmm2
+vpunpckhqdq %xmm9,%xmm12,%xmm3
+vmovdqa %xmm3,16(%rsp)
+vpshufd $0,%xmm12,%xmm3
+vpshufd $0,%xmm9,%xmm9
+vpmuludq 288(%rsp),%xmm3,%xmm12
+vpaddq %xmm12,%xmm4,%xmm4
+vpmuludq 416(%rsp),%xmm9,%xmm12
+vpaddq %xmm12,%xmm4,%xmm4
+vpmuludq 160(%rsp),%xmm3,%xmm12
+vpaddq %xmm12,%xmm6,%xmm6
+vpmuludq 432(%rsp),%xmm9,%xmm12
+vpaddq %xmm12,%xmm6,%xmm6
+vpmuludq 176(%rsp),%xmm3,%xmm12
+vpaddq %xmm12,%xmm7,%xmm7
+vpmuludq 304(%rsp),%xmm9,%xmm12
+vpaddq %xmm12,%xmm7,%xmm7
+vpmuludq 208(%rsp),%xmm3,%xmm12
+vpaddq %xmm12,%xmm11,%xmm11
+vpmuludq 336(%rsp),%xmm9,%xmm12
+vpaddq %xmm12,%xmm11,%xmm11
+vpmuludq 240(%rsp),%xmm3,%xmm3
+vpaddq %xmm3,%xmm2,%xmm2
+vpmuludq 368(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm2,%xmm2
+vpunpckhqdq %xmm14,%xmm1,%xmm3
+vmovdqa %xmm3,32(%rsp)
+vpshufd $0,%xmm1,%xmm1
+vpshufd $0,%xmm14,%xmm3
+vpmuludq 256(%rsp),%xmm1,%xmm9
+vpaddq %xmm9,%xmm4,%xmm4
+vpmuludq 384(%rsp),%xmm3,%xmm9
+vpaddq %xmm9,%xmm4,%xmm4
+vpmuludq 288(%rsp),%xmm1,%xmm9
+vpaddq %xmm9,%xmm6,%xmm6
+vpmuludq 416(%rsp),%xmm3,%xmm9
+vpaddq %xmm9,%xmm6,%xmm6
+vpmuludq 160(%rsp),%xmm1,%xmm9
+vpaddq %xmm9,%xmm7,%xmm7
+vpmuludq 432(%rsp),%xmm3,%xmm9
+vpaddq %xmm9,%xmm7,%xmm7
+vpmuludq 176(%rsp),%xmm1,%xmm9
+vpaddq %xmm9,%xmm11,%xmm11
+vpmuludq 304(%rsp),%xmm3,%xmm9
+vpaddq %xmm9,%xmm11,%xmm11
+vpmuludq 208(%rsp),%xmm1,%xmm1
+vpaddq %xmm1,%xmm2,%xmm2
+vpmuludq 336(%rsp),%xmm3,%xmm1
+vpaddq %xmm1,%xmm2,%xmm2
+vpunpckhqdq %xmm0,%xmm5,%xmm1
+vmovdqa %xmm1,48(%rsp)
+vpshufd $0,%xmm5,%xmm1
+vpshufd $0,%xmm0,%xmm0
+vpmuludq 224(%rsp),%xmm1,%xmm3
+vpaddq %xmm3,%xmm4,%xmm4
+vpmuludq 352(%rsp),%xmm0,%xmm3
+vpaddq %xmm3,%xmm4,%xmm4
+vpmuludq 256(%rsp),%xmm1,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpmuludq 384(%rsp),%xmm0,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpmuludq 288(%rsp),%xmm1,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpmuludq 416(%rsp),%xmm0,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpmuludq 160(%rsp),%xmm1,%xmm3
+vpaddq %xmm3,%xmm11,%xmm11
+vpmuludq 432(%rsp),%xmm0,%xmm3
+vpaddq %xmm3,%xmm11,%xmm11
+vpmuludq 176(%rsp),%xmm1,%xmm1
+vpaddq %xmm1,%xmm2,%xmm2
+vpmuludq 304(%rsp),%xmm0,%xmm0
+vpaddq %xmm0,%xmm2,%xmm2
+vpunpckhqdq %xmm10,%xmm8,%xmm0
+vmovdqa %xmm0,64(%rsp)
+vpshufd $0,%xmm8,%xmm0
+vpshufd $0,%xmm10,%xmm1
+vpmuludq 192(%rsp),%xmm0,%xmm3
+vpaddq %xmm3,%xmm4,%xmm4
+vpmuludq 320(%rsp),%xmm1,%xmm3
+vpaddq %xmm3,%xmm4,%xmm4
+vpmuludq 224(%rsp),%xmm0,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpmuludq 352(%rsp),%xmm1,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpmuludq 256(%rsp),%xmm0,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpmuludq 384(%rsp),%xmm1,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpmuludq 288(%rsp),%xmm0,%xmm3
+vpaddq %xmm3,%xmm11,%xmm11
+vpmuludq 416(%rsp),%xmm1,%xmm3
+vpaddq %xmm3,%xmm11,%xmm11
+vpmuludq 160(%rsp),%xmm0,%xmm0
+vpaddq %xmm0,%xmm2,%xmm2
+vpmuludq 432(%rsp),%xmm1,%xmm0
+vpaddq %xmm0,%xmm2,%xmm2
+vmovdqa %xmm4,80(%rsp)
+vmovdqa %xmm6,96(%rsp)
+vmovdqa %xmm7,112(%rsp)
+vmovdqa %xmm11,448(%rsp)
+vmovdqa %xmm2,496(%rsp)
+vmovdqa 144(%rsp),%xmm0
+vpmuludq %xmm0,%xmm0,%xmm1
+vpaddq %xmm0,%xmm0,%xmm0
+vmovdqa 128(%rsp),%xmm2
+vpmuludq %xmm2,%xmm0,%xmm3
+vmovdqa 480(%rsp),%xmm4
+vpmuludq %xmm4,%xmm0,%xmm5
+vmovdqa 464(%rsp),%xmm6
+vpmuludq %xmm6,%xmm0,%xmm7
+vmovdqa 528(%rsp),%xmm8
+vpmuludq %xmm8,%xmm0,%xmm9
+vpmuludq 512(%rsp),%xmm0,%xmm10
+vpmuludq 592(%rsp),%xmm0,%xmm11
+vpmuludq 576(%rsp),%xmm0,%xmm12
+vpmuludq 624(%rsp),%xmm0,%xmm13
+vmovdqa 672(%rsp),%xmm14
+vpmuludq %xmm14,%xmm0,%xmm0
+vpmuludq v38_38(%rip),%xmm14,%xmm15
+vpmuludq %xmm15,%xmm14,%xmm14
+vpaddq %xmm14,%xmm13,%xmm13
+vpaddq %xmm6,%xmm6,%xmm14
+vpmuludq %xmm14,%xmm6,%xmm6
+vpaddq %xmm6,%xmm11,%xmm11
+vpaddq %xmm2,%xmm2,%xmm6
+vpmuludq %xmm6,%xmm2,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpmuludq %xmm15,%xmm6,%xmm2
+vpaddq %xmm2,%xmm1,%xmm1
+vpmuludq %xmm15,%xmm4,%xmm2
+vpaddq %xmm2,%xmm3,%xmm3
+vpmuludq 544(%rsp),%xmm6,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpmuludq 592(%rsp),%xmm6,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpmuludq 640(%rsp),%xmm6,%xmm2
+vpaddq %xmm2,%xmm13,%xmm13
+vpmuludq 624(%rsp),%xmm6,%xmm2
+vpaddq %xmm2,%xmm0,%xmm0
+vpmuludq %xmm4,%xmm6,%xmm2
+vpaddq %xmm2,%xmm7,%xmm7
+vpmuludq %xmm14,%xmm6,%xmm2
+vpaddq %xmm2,%xmm9,%xmm9
+vpmuludq %xmm8,%xmm6,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpmuludq %xmm15,%xmm14,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpmuludq %xmm15,%xmm8,%xmm2
+vpaddq %xmm2,%xmm7,%xmm7
+vpmuludq %xmm4,%xmm4,%xmm2
+vpaddq %xmm2,%xmm9,%xmm9
+vpmuludq %xmm14,%xmm4,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpaddq %xmm4,%xmm4,%xmm2
+vpmuludq %xmm8,%xmm2,%xmm4
+vpaddq %xmm4,%xmm11,%xmm11
+vpmuludq 688(%rsp),%xmm2,%xmm4
+vpaddq %xmm4,%xmm1,%xmm1
+vpmuludq 688(%rsp),%xmm14,%xmm4
+vpaddq %xmm4,%xmm3,%xmm3
+vpmuludq 512(%rsp),%xmm2,%xmm4
+vpaddq %xmm4,%xmm12,%xmm12
+vpmuludq 592(%rsp),%xmm2,%xmm4
+vpaddq %xmm4,%xmm13,%xmm13
+vpmuludq 576(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm0,%xmm0
+vpmuludq 656(%rsp),%xmm8,%xmm2
+vpaddq %xmm2,%xmm3,%xmm3
+vpmuludq %xmm8,%xmm14,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpmuludq %xmm8,%xmm8,%xmm2
+vpaddq %xmm2,%xmm13,%xmm13
+vpaddq %xmm8,%xmm8,%xmm2
+vpmuludq 688(%rsp),%xmm2,%xmm4
+vpaddq %xmm4,%xmm5,%xmm5
+vpmuludq 544(%rsp),%xmm15,%xmm4
+vpaddq %xmm4,%xmm9,%xmm9
+vpmuludq 592(%rsp),%xmm15,%xmm4
+vpaddq %xmm4,%xmm10,%xmm10
+vpmuludq 656(%rsp),%xmm14,%xmm4
+vpaddq %xmm4,%xmm1,%xmm1
+vmovdqa 544(%rsp),%xmm4
+vpmuludq 688(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm7,%xmm7
+vpmuludq 544(%rsp),%xmm14,%xmm4
+vpaddq %xmm4,%xmm13,%xmm13
+vpmuludq 592(%rsp),%xmm14,%xmm4
+vpaddq %xmm4,%xmm0,%xmm0
+vpmuludq 640(%rsp),%xmm15,%xmm4
+vpaddq %xmm4,%xmm11,%xmm11
+vpmuludq 624(%rsp),%xmm15,%xmm4
+vpaddq %xmm4,%xmm12,%xmm12
+vmovdqa 592(%rsp),%xmm4
+vpaddq %xmm4,%xmm4,%xmm4
+vpmuludq 688(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm9,%xmm9
+vpmuludq 608(%rsp),%xmm2,%xmm4
+vpaddq %xmm4,%xmm1,%xmm1
+vmovdqa 544(%rsp),%xmm4
+vpmuludq 608(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm3,%xmm3
+vmovdqa 544(%rsp),%xmm4
+vpmuludq 656(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm5,%xmm5
+vmovdqa 592(%rsp),%xmm4
+vpmuludq 656(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm7,%xmm7
+vmovdqa 640(%rsp),%xmm4
+vpmuludq 688(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm10,%xmm10
+vpmuludq 512(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm0,%xmm0
+vmovdqa 560(%rsp),%xmm2
+vpmuludq 512(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm1,%xmm1
+vmovdqa 608(%rsp),%xmm2
+vpmuludq 592(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vmovdqa 656(%rsp),%xmm2
+vpmuludq 576(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm9,%xmm9
+vmovdqa 688(%rsp),%xmm2
+vpmuludq 624(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpsrlq $26,%xmm1,%xmm2
+vpaddq %xmm2,%xmm3,%xmm3
+vpand m26(%rip),%xmm1,%xmm1
+vpsrlq $25,%xmm10,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpand m25(%rip),%xmm10,%xmm10
+vpsrlq $25,%xmm3,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpand m25(%rip),%xmm3,%xmm3
+vpsrlq $26,%xmm11,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpand m26(%rip),%xmm11,%xmm11
+vpsrlq $26,%xmm5,%xmm2
+vpaddq %xmm2,%xmm7,%xmm7
+vpand m26(%rip),%xmm5,%xmm5
+vpsrlq $25,%xmm12,%xmm2
+vpaddq %xmm2,%xmm13,%xmm13
+vpand m25(%rip),%xmm12,%xmm12
+vpsrlq $25,%xmm7,%xmm2
+vpaddq %xmm2,%xmm9,%xmm9
+vpand m25(%rip),%xmm7,%xmm7
+vpsrlq $26,%xmm13,%xmm2
+vpaddq %xmm2,%xmm0,%xmm0
+vpand m26(%rip),%xmm13,%xmm13
+vpsrlq $26,%xmm9,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpand m26(%rip),%xmm9,%xmm9
+vpsrlq $25,%xmm0,%xmm2
+vpsllq $4,%xmm2,%xmm4
+vpaddq %xmm2,%xmm1,%xmm1
+vpsllq $1,%xmm2,%xmm2
+vpaddq %xmm2,%xmm4,%xmm4
+vpaddq %xmm4,%xmm1,%xmm1
+vpand m25(%rip),%xmm0,%xmm0
+vpsrlq $25,%xmm10,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpand m25(%rip),%xmm10,%xmm10
+vpsrlq $26,%xmm1,%xmm2
+vpaddq %xmm2,%xmm3,%xmm3
+vpand m26(%rip),%xmm1,%xmm1
+vpunpckhqdq %xmm3,%xmm1,%xmm2
+vpunpcklqdq %xmm3,%xmm1,%xmm1
+vmovdqa %xmm1,464(%rsp)
+vpaddq subc0(%rip),%xmm2,%xmm3
+vpsubq %xmm1,%xmm3,%xmm3
+vpunpckhqdq %xmm3,%xmm2,%xmm1
+vpunpcklqdq %xmm3,%xmm2,%xmm2
+vmovdqa %xmm2,480(%rsp)
+vmovdqa %xmm1,512(%rsp)
+vpsllq $1,%xmm1,%xmm1
+vmovdqa %xmm1,528(%rsp)
+vpmuludq v121666_121666(%rip),%xmm3,%xmm3
+vmovdqa 80(%rsp),%xmm1
+vpunpcklqdq %xmm1,%xmm3,%xmm2
+vpunpckhqdq %xmm1,%xmm3,%xmm1
+vpunpckhqdq %xmm7,%xmm5,%xmm3
+vpunpcklqdq %xmm7,%xmm5,%xmm4
+vmovdqa %xmm4,544(%rsp)
+vpaddq subc2(%rip),%xmm3,%xmm5
+vpsubq %xmm4,%xmm5,%xmm5
+vpunpckhqdq %xmm5,%xmm3,%xmm4
+vpunpcklqdq %xmm5,%xmm3,%xmm3
+vmovdqa %xmm3,560(%rsp)
+vmovdqa %xmm4,576(%rsp)
+vpsllq $1,%xmm4,%xmm4
+vmovdqa %xmm4,592(%rsp)
+vpmuludq v121666_121666(%rip),%xmm5,%xmm5
+vmovdqa 96(%rsp),%xmm3
+vpunpcklqdq %xmm3,%xmm5,%xmm4
+vpunpckhqdq %xmm3,%xmm5,%xmm3
+vpunpckhqdq %xmm10,%xmm9,%xmm5
+vpunpcklqdq %xmm10,%xmm9,%xmm6
+vmovdqa %xmm6,608(%rsp)
+vpaddq subc2(%rip),%xmm5,%xmm7
+vpsubq %xmm6,%xmm7,%xmm7
+vpunpckhqdq %xmm7,%xmm5,%xmm6
+vpunpcklqdq %xmm7,%xmm5,%xmm5
+vmovdqa %xmm5,624(%rsp)
+vmovdqa %xmm6,640(%rsp)
+vpsllq $1,%xmm6,%xmm6
+vmovdqa %xmm6,656(%rsp)
+vpmuludq v121666_121666(%rip),%xmm7,%xmm7
+vmovdqa 112(%rsp),%xmm5
+vpunpcklqdq %xmm5,%xmm7,%xmm6
+vpunpckhqdq %xmm5,%xmm7,%xmm5
+vpunpckhqdq %xmm12,%xmm11,%xmm7
+vpunpcklqdq %xmm12,%xmm11,%xmm8
+vmovdqa %xmm8,672(%rsp)
+vpaddq subc2(%rip),%xmm7,%xmm9
+vpsubq %xmm8,%xmm9,%xmm9
+vpunpckhqdq %xmm9,%xmm7,%xmm8
+vpunpcklqdq %xmm9,%xmm7,%xmm7
+vmovdqa %xmm7,688(%rsp)
+vmovdqa %xmm8,704(%rsp)
+vpsllq $1,%xmm8,%xmm8
+vmovdqa %xmm8,720(%rsp)
+vpmuludq v121666_121666(%rip),%xmm9,%xmm9
+vmovdqa 448(%rsp),%xmm7
+vpunpcklqdq %xmm7,%xmm9,%xmm8
+vpunpckhqdq %xmm7,%xmm9,%xmm7
+vpunpckhqdq %xmm0,%xmm13,%xmm9
+vpunpcklqdq %xmm0,%xmm13,%xmm0
+vmovdqa %xmm0,448(%rsp)
+vpaddq subc2(%rip),%xmm9,%xmm10
+vpsubq %xmm0,%xmm10,%xmm10
+vpunpckhqdq %xmm10,%xmm9,%xmm0
+vpunpcklqdq %xmm10,%xmm9,%xmm9
+vmovdqa %xmm9,736(%rsp)
+vmovdqa %xmm0,752(%rsp)
+vpsllq $1,%xmm0,%xmm0
+vmovdqa %xmm0,768(%rsp)
+vpmuludq v121666_121666(%rip),%xmm10,%xmm10
+vmovdqa 496(%rsp),%xmm0
+vpunpcklqdq %xmm0,%xmm10,%xmm9
+vpunpckhqdq %xmm0,%xmm10,%xmm0
+vpsrlq $26,%xmm2,%xmm10
+vpaddq %xmm10,%xmm1,%xmm1
+vpand m26(%rip),%xmm2,%xmm2
+vpsrlq $25,%xmm5,%xmm10
+vpaddq %xmm10,%xmm8,%xmm8
+vpand m25(%rip),%xmm5,%xmm5
+vpsrlq $25,%xmm1,%xmm10
+vpaddq %xmm10,%xmm4,%xmm4
+vpand m25(%rip),%xmm1,%xmm1
+vpsrlq $26,%xmm8,%xmm10
+vpaddq %xmm10,%xmm7,%xmm7
+vpand m26(%rip),%xmm8,%xmm8
+vpsrlq $26,%xmm4,%xmm10
+vpaddq %xmm10,%xmm3,%xmm3
+vpand m26(%rip),%xmm4,%xmm4
+vpsrlq $25,%xmm7,%xmm10
+vpaddq %xmm10,%xmm9,%xmm9
+vpand m25(%rip),%xmm7,%xmm7
+vpsrlq $25,%xmm3,%xmm10
+vpaddq %xmm10,%xmm6,%xmm6
+vpand m25(%rip),%xmm3,%xmm3
+vpsrlq $26,%xmm9,%xmm10
+vpaddq %xmm10,%xmm0,%xmm0
+vpand m26(%rip),%xmm9,%xmm9
+vpsrlq $26,%xmm6,%xmm10
+vpaddq %xmm10,%xmm5,%xmm5
+vpand m26(%rip),%xmm6,%xmm6
+vpsrlq $25,%xmm0,%xmm10
+vpsllq $4,%xmm10,%xmm11
+vpaddq %xmm10,%xmm2,%xmm2
+vpsllq $1,%xmm10,%xmm10
+vpaddq %xmm10,%xmm11,%xmm11
+vpaddq %xmm11,%xmm2,%xmm2
+vpand m25(%rip),%xmm0,%xmm0
+vpsrlq $25,%xmm5,%xmm10
+vpaddq %xmm10,%xmm8,%xmm8
+vpand m25(%rip),%xmm5,%xmm5
+vpsrlq $26,%xmm2,%xmm10
+vpaddq %xmm10,%xmm1,%xmm1
+vpand m26(%rip),%xmm2,%xmm2
+vpunpckhqdq %xmm1,%xmm2,%xmm10
+vmovdqa %xmm10,80(%rsp)
+vpunpcklqdq %xmm1,%xmm2,%xmm1
+vpunpckhqdq %xmm3,%xmm4,%xmm2
+vmovdqa %xmm2,96(%rsp)
+vpunpcklqdq %xmm3,%xmm4,%xmm2
+vpunpckhqdq %xmm5,%xmm6,%xmm3
+vmovdqa %xmm3,112(%rsp)
+vpunpcklqdq %xmm5,%xmm6,%xmm3
+vpunpckhqdq %xmm7,%xmm8,%xmm4
+vmovdqa %xmm4,128(%rsp)
+vpunpcklqdq %xmm7,%xmm8,%xmm4
+vpunpckhqdq %xmm0,%xmm9,%xmm5
+vmovdqa %xmm5,144(%rsp)
+vpunpcklqdq %xmm0,%xmm9,%xmm0
+vmovdqa 464(%rsp),%xmm5
+vpaddq %xmm5,%xmm1,%xmm1
+vpunpcklqdq %xmm1,%xmm5,%xmm6
+vpunpckhqdq %xmm1,%xmm5,%xmm1
+vpmuludq 512(%rsp),%xmm6,%xmm5
+vpmuludq 480(%rsp),%xmm1,%xmm7
+vpaddq %xmm7,%xmm5,%xmm5
+vpmuludq 560(%rsp),%xmm6,%xmm7
+vpmuludq 528(%rsp),%xmm1,%xmm8
+vpaddq %xmm8,%xmm7,%xmm7
+vpmuludq 576(%rsp),%xmm6,%xmm8
+vpmuludq 560(%rsp),%xmm1,%xmm9
+vpaddq %xmm9,%xmm8,%xmm8
+vpmuludq 624(%rsp),%xmm6,%xmm9
+vpmuludq 592(%rsp),%xmm1,%xmm10
+vpaddq %xmm10,%xmm9,%xmm9
+vpmuludq 640(%rsp),%xmm6,%xmm10
+vpmuludq 624(%rsp),%xmm1,%xmm11
+vpaddq %xmm11,%xmm10,%xmm10
+vpmuludq 688(%rsp),%xmm6,%xmm11
+vpmuludq 656(%rsp),%xmm1,%xmm12
+vpaddq %xmm12,%xmm11,%xmm11
+vpmuludq 704(%rsp),%xmm6,%xmm12
+vpmuludq 688(%rsp),%xmm1,%xmm13
+vpaddq %xmm13,%xmm12,%xmm12
+vpmuludq 736(%rsp),%xmm6,%xmm13
+vpmuludq 720(%rsp),%xmm1,%xmm14
+vpaddq %xmm14,%xmm13,%xmm13
+vpmuludq 752(%rsp),%xmm6,%xmm14
+vpmuludq 736(%rsp),%xmm1,%xmm15
+vpaddq %xmm15,%xmm14,%xmm14
+vpmuludq 480(%rsp),%xmm6,%xmm6
+vpmuludq v19_19(%rip),%xmm1,%xmm1
+vpmuludq 768(%rsp),%xmm1,%xmm1
+vpaddq %xmm1,%xmm6,%xmm6
+vmovdqa 544(%rsp),%xmm1
+vpaddq %xmm1,%xmm2,%xmm2
+vpunpcklqdq %xmm2,%xmm1,%xmm15
+vpunpckhqdq %xmm2,%xmm1,%xmm1
+vpmuludq 480(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm7,%xmm7
+vpmuludq 512(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm8,%xmm8
+vpmuludq 560(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm9,%xmm9
+vpmuludq 576(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpmuludq 624(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpmuludq 640(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpmuludq 688(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm13,%xmm13
+vpmuludq 704(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm14,%xmm14
+vpmuludq v19_19(%rip),%xmm15,%xmm15
+vpmuludq 736(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm6,%xmm6
+vpmuludq 752(%rsp),%xmm15,%xmm15
+vpaddq %xmm15,%xmm5,%xmm5
+vpmuludq 480(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm8,%xmm8
+vpmuludq 528(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm9,%xmm9
+vpmuludq 560(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpmuludq 592(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpmuludq 624(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpmuludq 656(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm13,%xmm13
+vpmuludq 688(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm14,%xmm14
+vpmuludq v19_19(%rip),%xmm1,%xmm1
+vpmuludq 720(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm6,%xmm6
+vpmuludq 736(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpmuludq 768(%rsp),%xmm1,%xmm1
+vpaddq %xmm1,%xmm7,%xmm7
+vmovdqa 608(%rsp),%xmm1
+vpaddq %xmm1,%xmm3,%xmm3
+vpunpcklqdq %xmm3,%xmm1,%xmm2
+vpunpckhqdq %xmm3,%xmm1,%xmm1
+vpmuludq 480(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm9,%xmm9
+vpmuludq 512(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm10,%xmm10
+vpmuludq 560(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm11,%xmm11
+vpmuludq 576(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm12,%xmm12
+vpmuludq 624(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpmuludq 640(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm14,%xmm14
+vpmuludq v19_19(%rip),%xmm2,%xmm2
+vpmuludq 688(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpmuludq 704(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm5,%xmm5
+vpmuludq 736(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpmuludq 752(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm8,%xmm8
+vpmuludq 480(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpmuludq 528(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpmuludq 560(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpmuludq 592(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm13,%xmm13
+vpmuludq 624(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm14,%xmm14
+vpmuludq v19_19(%rip),%xmm1,%xmm1
+vpmuludq 656(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm6,%xmm6
+vpmuludq 688(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpmuludq 720(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm7,%xmm7
+vpmuludq 736(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm8,%xmm8
+vpmuludq 768(%rsp),%xmm1,%xmm1
+vpaddq %xmm1,%xmm9,%xmm9
+vmovdqa 672(%rsp),%xmm1
+vpaddq %xmm1,%xmm4,%xmm4
+vpunpcklqdq %xmm4,%xmm1,%xmm2
+vpunpckhqdq %xmm4,%xmm1,%xmm1
+vpmuludq 480(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm11,%xmm11
+vpmuludq 512(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm12,%xmm12
+vpmuludq 560(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpmuludq 576(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm14,%xmm14
+vpmuludq v19_19(%rip),%xmm2,%xmm2
+vpmuludq 624(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpmuludq 640(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm5,%xmm5
+vpmuludq 688(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpmuludq 704(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm8,%xmm8
+vpmuludq 736(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm9,%xmm9
+vpmuludq 752(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpmuludq 480(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpmuludq 528(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm13,%xmm13
+vpmuludq 560(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm14,%xmm14
+vpmuludq v19_19(%rip),%xmm1,%xmm1
+vpmuludq 592(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm6,%xmm6
+vpmuludq 624(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpmuludq 656(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm7,%xmm7
+vpmuludq 688(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm8,%xmm8
+vpmuludq 720(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm9,%xmm9
+vpmuludq 736(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpmuludq 768(%rsp),%xmm1,%xmm1
+vpaddq %xmm1,%xmm11,%xmm11
+vmovdqa 448(%rsp),%xmm1
+vpaddq %xmm1,%xmm0,%xmm0
+vpunpcklqdq %xmm0,%xmm1,%xmm2
+vpunpckhqdq %xmm0,%xmm1,%xmm0
+vpmuludq 480(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm13,%xmm13
+vpmuludq 512(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm14,%xmm14
+vpmuludq v19_19(%rip),%xmm2,%xmm2
+vpmuludq 560(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm6,%xmm6
+vpmuludq 576(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm5,%xmm5
+vpmuludq 624(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm7,%xmm7
+vpmuludq 640(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm8,%xmm8
+vpmuludq 688(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm9,%xmm9
+vpmuludq 704(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm10,%xmm10
+vpmuludq 736(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm11,%xmm11
+vpmuludq 752(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpmuludq 480(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm14,%xmm14
+vpmuludq v19_19(%rip),%xmm0,%xmm0
+vpmuludq 528(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm6,%xmm6
+vpmuludq 560(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm5,%xmm5
+vpmuludq 592(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm7,%xmm7
+vpmuludq 624(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm8,%xmm8
+vpmuludq 656(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm9,%xmm9
+vpmuludq 688(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm10,%xmm10
+vpmuludq 720(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm11,%xmm11
+vpmuludq 736(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm12,%xmm12
+vpmuludq 768(%rsp),%xmm0,%xmm0
+vpaddq %xmm0,%xmm13,%xmm13
+vpsrlq $26,%xmm6,%xmm0
+vpaddq %xmm0,%xmm5,%xmm5
+vpand m26(%rip),%xmm6,%xmm6
+vpsrlq $25,%xmm10,%xmm0
+vpaddq %xmm0,%xmm11,%xmm11
+vpand m25(%rip),%xmm10,%xmm10
+vpsrlq $25,%xmm5,%xmm0
+vpaddq %xmm0,%xmm7,%xmm7
+vpand m25(%rip),%xmm5,%xmm5
+vpsrlq $26,%xmm11,%xmm0
+vpaddq %xmm0,%xmm12,%xmm12
+vpand m26(%rip),%xmm11,%xmm11
+vpsrlq $26,%xmm7,%xmm0
+vpaddq %xmm0,%xmm8,%xmm8
+vpand m26(%rip),%xmm7,%xmm7
+vpsrlq $25,%xmm12,%xmm0
+vpaddq %xmm0,%xmm13,%xmm13
+vpand m25(%rip),%xmm12,%xmm12
+vpsrlq $25,%xmm8,%xmm0
+vpaddq %xmm0,%xmm9,%xmm9
+vpand m25(%rip),%xmm8,%xmm8
+vpsrlq $26,%xmm13,%xmm0
+vpaddq %xmm0,%xmm14,%xmm14
+vpand m26(%rip),%xmm13,%xmm13
+vpsrlq $26,%xmm9,%xmm0
+vpaddq %xmm0,%xmm10,%xmm10
+vpand m26(%rip),%xmm9,%xmm9
+vpsrlq $25,%xmm14,%xmm0
+vpsllq $4,%xmm0,%xmm1
+vpaddq %xmm0,%xmm6,%xmm6
+vpsllq $1,%xmm0,%xmm0
+vpaddq %xmm0,%xmm1,%xmm1
+vpaddq %xmm1,%xmm6,%xmm6
+vpand m25(%rip),%xmm14,%xmm14
+vpsrlq $25,%xmm10,%xmm0
+vpaddq %xmm0,%xmm11,%xmm11
+vpand m25(%rip),%xmm10,%xmm10
+vpsrlq $26,%xmm6,%xmm0
+vpaddq %xmm0,%xmm5,%xmm5
+vpand m26(%rip),%xmm6,%xmm6
+vpunpckhqdq %xmm5,%xmm6,%xmm1
+vpunpcklqdq %xmm5,%xmm6,%xmm0
+vpunpckhqdq %xmm8,%xmm7,%xmm3
+vpunpcklqdq %xmm8,%xmm7,%xmm2
+vpunpckhqdq %xmm10,%xmm9,%xmm5
+vpunpcklqdq %xmm10,%xmm9,%xmm4
+vpunpckhqdq %xmm12,%xmm11,%xmm7
+vpunpcklqdq %xmm12,%xmm11,%xmm6
+vpunpckhqdq %xmm14,%xmm13,%xmm9
+vpunpcklqdq %xmm14,%xmm13,%xmm8
+cmp $0,%rdx
+jne ._ladder_loop
+vmovdqu %xmm1,160(%rdi)
+vmovdqu %xmm0,80(%rdi)
+vmovdqu %xmm3,176(%rdi)
+vmovdqu %xmm2,96(%rdi)
+vmovdqu %xmm5,192(%rdi)
+vmovdqu %xmm4,112(%rdi)
+vmovdqu %xmm7,208(%rdi)
+vmovdqu %xmm6,128(%rdi)
+vmovdqu %xmm9,224(%rdi)
+vmovdqu %xmm8,144(%rdi)
+movq 1824(%rsp),%r11
+movq 1832(%rsp),%r12
+movq 1840(%rsp),%r13
+movq 1848(%rsp),%r14
+add %r11,%rsp
+ret
+
+#endif
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder.h b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder.h
new file mode 100644
index 0000000000..ccf4ecaecd
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder.h
@@ -0,0 +1,18 @@
+#ifndef ladder_H
+#define ladder_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "fe.h"
+#include "ladder_namespace.h"
+
+extern void ladder(fe *, const unsigned char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef ladder_H */
+
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder_base.S b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder_base.S
new file mode 100644
index 0000000000..f290d2565e
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder_base.S
@@ -0,0 +1,1295 @@
+#ifdef IN_SANDY2X
+
+#include "ladder_base_namespace.h"
+#include "consts_namespace.h"
+.p2align 5
+
+#ifdef ASM_HIDE_SYMBOL
+ASM_HIDE_SYMBOL ladder_base
+ASM_HIDE_SYMBOL _ladder_base
+#endif
+.globl ladder_base
+.globl _ladder_base
+#ifdef __ELF__
+.type ladder_base, @function
+.type _ladder_base, @function
+#endif
+ladder_base:
+_ladder_base:
+
+mov %rsp,%r11
+and $31,%r11
+add $1568,%r11
+sub %r11,%rsp
+movq %r11,1536(%rsp)
+movq %r12,1544(%rsp)
+movq %r13,1552(%rsp)
+vmovdqa v0_0(%rip),%xmm0
+vmovdqa v1_0(%rip),%xmm1
+vmovdqa v9_0(%rip),%xmm2
+vmovdqa %xmm2,0(%rsp)
+vmovdqa %xmm0,16(%rsp)
+vmovdqa %xmm0,32(%rsp)
+vmovdqa %xmm0,48(%rsp)
+vmovdqa %xmm0,64(%rsp)
+vmovdqa %xmm1,80(%rsp)
+vmovdqa %xmm0,96(%rsp)
+vmovdqa %xmm0,112(%rsp)
+vmovdqa %xmm0,128(%rsp)
+vmovdqa %xmm0,144(%rsp)
+vmovdqa %xmm1,%xmm0
+vpxor %xmm1,%xmm1,%xmm1
+vpxor %xmm2,%xmm2,%xmm2
+vpxor %xmm3,%xmm3,%xmm3
+vpxor %xmm4,%xmm4,%xmm4
+vpxor %xmm5,%xmm5,%xmm5
+vpxor %xmm6,%xmm6,%xmm6
+vpxor %xmm7,%xmm7,%xmm7
+vpxor %xmm8,%xmm8,%xmm8
+vpxor %xmm9,%xmm9,%xmm9
+movq 0(%rsi),%rdx
+movq 8(%rsi),%rcx
+movq 16(%rsi),%r8
+movq 24(%rsi),%r9
+shrd $1,%rcx,%rdx
+shrd $1,%r8,%rcx
+shrd $1,%r9,%r8
+shr $1,%r9
+xorq 0(%rsi),%rdx
+xorq 8(%rsi),%rcx
+xorq 16(%rsi),%r8
+xorq 24(%rsi),%r9
+leaq 512(%rsp),%rsi
+mov $64,%rax
+
+.p2align 4
+._ladder_base_small_loop:
+mov %rdx,%r10
+mov %rcx,%r11
+mov %r8,%r12
+mov %r9,%r13
+shr $1,%rdx
+shr $1,%rcx
+shr $1,%r8
+shr $1,%r9
+and $1,%r10d
+and $1,%r11d
+and $1,%r12d
+and $1,%r13d
+neg %r10
+neg %r11
+neg %r12
+neg %r13
+movl %r10d,0(%rsi)
+movl %r11d,256(%rsi)
+movl %r12d,512(%rsi)
+movl %r13d,768(%rsi)
+add $4,%rsi
+sub $1,%rax
+jne ._ladder_base_small_loop
+mov $255,%rdx
+add $760,%rsi
+
+.p2align 4
+._ladder_base_loop:
+sub $1,%rdx
+vbroadcastss 0(%rsi),%xmm10
+sub $4,%rsi
+vmovdqa 0(%rsp),%xmm11
+vmovdqa 80(%rsp),%xmm12
+vpxor %xmm11,%xmm0,%xmm13
+vpand %xmm10,%xmm13,%xmm13
+vpxor %xmm13,%xmm0,%xmm0
+vpxor %xmm13,%xmm11,%xmm11
+vpxor %xmm12,%xmm1,%xmm13
+vpand %xmm10,%xmm13,%xmm13
+vpxor %xmm13,%xmm1,%xmm1
+vpxor %xmm13,%xmm12,%xmm12
+vmovdqa 16(%rsp),%xmm13
+vmovdqa 96(%rsp),%xmm14
+vpxor %xmm13,%xmm2,%xmm15
+vpand %xmm10,%xmm15,%xmm15
+vpxor %xmm15,%xmm2,%xmm2
+vpxor %xmm15,%xmm13,%xmm13
+vpxor %xmm14,%xmm3,%xmm15
+vpand %xmm10,%xmm15,%xmm15
+vpxor %xmm15,%xmm3,%xmm3
+vpxor %xmm15,%xmm14,%xmm14
+vmovdqa %xmm13,0(%rsp)
+vmovdqa %xmm14,16(%rsp)
+vmovdqa 32(%rsp),%xmm13
+vmovdqa 112(%rsp),%xmm14
+vpxor %xmm13,%xmm4,%xmm15
+vpand %xmm10,%xmm15,%xmm15
+vpxor %xmm15,%xmm4,%xmm4
+vpxor %xmm15,%xmm13,%xmm13
+vpxor %xmm14,%xmm5,%xmm15
+vpand %xmm10,%xmm15,%xmm15
+vpxor %xmm15,%xmm5,%xmm5
+vpxor %xmm15,%xmm14,%xmm14
+vmovdqa %xmm13,32(%rsp)
+vmovdqa %xmm14,80(%rsp)
+vmovdqa 48(%rsp),%xmm13
+vmovdqa 128(%rsp),%xmm14
+vpxor %xmm13,%xmm6,%xmm15
+vpand %xmm10,%xmm15,%xmm15
+vpxor %xmm15,%xmm6,%xmm6
+vpxor %xmm15,%xmm13,%xmm13
+vpxor %xmm14,%xmm7,%xmm15
+vpand %xmm10,%xmm15,%xmm15
+vpxor %xmm15,%xmm7,%xmm7
+vpxor %xmm15,%xmm14,%xmm14
+vmovdqa %xmm13,48(%rsp)
+vmovdqa %xmm14,96(%rsp)
+vmovdqa 64(%rsp),%xmm13
+vmovdqa 144(%rsp),%xmm14
+vpxor %xmm13,%xmm8,%xmm15
+vpand %xmm10,%xmm15,%xmm15
+vpxor %xmm15,%xmm8,%xmm8
+vpxor %xmm15,%xmm13,%xmm13
+vpxor %xmm14,%xmm9,%xmm15
+vpand %xmm10,%xmm15,%xmm15
+vpxor %xmm15,%xmm9,%xmm9
+vpxor %xmm15,%xmm14,%xmm14
+vmovdqa %xmm13,64(%rsp)
+vmovdqa %xmm14,112(%rsp)
+vpaddq subc0(%rip),%xmm11,%xmm10
+vpsubq %xmm12,%xmm10,%xmm10
+vpaddq %xmm12,%xmm11,%xmm11
+vpunpckhqdq %xmm10,%xmm11,%xmm12
+vpunpcklqdq %xmm10,%xmm11,%xmm10
+vpaddq %xmm1,%xmm0,%xmm11
+vpaddq subc0(%rip),%xmm0,%xmm0
+vpsubq %xmm1,%xmm0,%xmm0
+vpunpckhqdq %xmm11,%xmm0,%xmm1
+vpunpcklqdq %xmm11,%xmm0,%xmm0
+vpmuludq %xmm0,%xmm10,%xmm11
+vpmuludq %xmm1,%xmm10,%xmm13
+vmovdqa %xmm1,128(%rsp)
+vpaddq %xmm1,%xmm1,%xmm1
+vpmuludq %xmm0,%xmm12,%xmm14
+vmovdqa %xmm0,144(%rsp)
+vpaddq %xmm14,%xmm13,%xmm13
+vpmuludq %xmm1,%xmm12,%xmm0
+vmovdqa %xmm1,160(%rsp)
+vpaddq %xmm3,%xmm2,%xmm1
+vpaddq subc2(%rip),%xmm2,%xmm2
+vpsubq %xmm3,%xmm2,%xmm2
+vpunpckhqdq %xmm1,%xmm2,%xmm3
+vpunpcklqdq %xmm1,%xmm2,%xmm1
+vpmuludq %xmm1,%xmm10,%xmm2
+vpaddq %xmm2,%xmm0,%xmm0
+vpmuludq %xmm3,%xmm10,%xmm2
+vmovdqa %xmm3,176(%rsp)
+vpaddq %xmm3,%xmm3,%xmm3
+vpmuludq %xmm1,%xmm12,%xmm14
+vmovdqa %xmm1,192(%rsp)
+vpaddq %xmm14,%xmm2,%xmm2
+vpmuludq %xmm3,%xmm12,%xmm1
+vmovdqa %xmm3,208(%rsp)
+vpaddq %xmm5,%xmm4,%xmm3
+vpaddq subc2(%rip),%xmm4,%xmm4
+vpsubq %xmm5,%xmm4,%xmm4
+vpunpckhqdq %xmm3,%xmm4,%xmm5
+vpunpcklqdq %xmm3,%xmm4,%xmm3
+vpmuludq %xmm3,%xmm10,%xmm4
+vpaddq %xmm4,%xmm1,%xmm1
+vpmuludq %xmm5,%xmm10,%xmm4
+vmovdqa %xmm5,224(%rsp)
+vpaddq %xmm5,%xmm5,%xmm5
+vpmuludq %xmm3,%xmm12,%xmm14
+vmovdqa %xmm3,240(%rsp)
+vpaddq %xmm14,%xmm4,%xmm4
+vpaddq %xmm7,%xmm6,%xmm3
+vpaddq subc2(%rip),%xmm6,%xmm6
+vpsubq %xmm7,%xmm6,%xmm6
+vpunpckhqdq %xmm3,%xmm6,%xmm7
+vpunpcklqdq %xmm3,%xmm6,%xmm3
+vpmuludq %xmm3,%xmm10,%xmm6
+vpmuludq %xmm5,%xmm12,%xmm14
+vmovdqa %xmm5,256(%rsp)
+vpmuludq v19_19(%rip),%xmm5,%xmm5
+vmovdqa %xmm5,272(%rsp)
+vpaddq %xmm14,%xmm6,%xmm6
+vpmuludq %xmm7,%xmm10,%xmm5
+vmovdqa %xmm7,288(%rsp)
+vpaddq %xmm7,%xmm7,%xmm7
+vpmuludq %xmm3,%xmm12,%xmm14
+vmovdqa %xmm3,304(%rsp)
+vpaddq %xmm14,%xmm5,%xmm5
+vpmuludq v19_19(%rip),%xmm3,%xmm3
+vmovdqa %xmm3,320(%rsp)
+vpaddq %xmm9,%xmm8,%xmm3
+vpaddq subc2(%rip),%xmm8,%xmm8
+vpsubq %xmm9,%xmm8,%xmm8
+vpunpckhqdq %xmm3,%xmm8,%xmm9
+vpunpcklqdq %xmm3,%xmm8,%xmm3
+vmovdqa %xmm3,336(%rsp)
+vpmuludq %xmm7,%xmm12,%xmm8
+vmovdqa %xmm7,352(%rsp)
+vpmuludq v19_19(%rip),%xmm7,%xmm7
+vmovdqa %xmm7,368(%rsp)
+vpmuludq %xmm3,%xmm10,%xmm7
+vpaddq %xmm7,%xmm8,%xmm8
+vpmuludq %xmm9,%xmm10,%xmm7
+vmovdqa %xmm9,384(%rsp)
+vpaddq %xmm9,%xmm9,%xmm9
+vpmuludq %xmm3,%xmm12,%xmm10
+vpaddq %xmm10,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm3,%xmm3
+vmovdqa %xmm3,400(%rsp)
+vpmuludq v19_19(%rip),%xmm12,%xmm12
+vpmuludq %xmm9,%xmm12,%xmm3
+vmovdqa %xmm9,416(%rsp)
+vpaddq %xmm3,%xmm11,%xmm11
+vmovdqa 0(%rsp),%xmm3
+vmovdqa 16(%rsp),%xmm9
+vpaddq subc2(%rip),%xmm3,%xmm10
+vpsubq %xmm9,%xmm10,%xmm10
+vpaddq %xmm9,%xmm3,%xmm3
+vpunpckhqdq %xmm10,%xmm3,%xmm9
+vpunpcklqdq %xmm10,%xmm3,%xmm3
+vpmuludq 144(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm0,%xmm0
+vpmuludq 128(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm2,%xmm2
+vpmuludq 192(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm1,%xmm1
+vpmuludq 176(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm4,%xmm4
+vpmuludq 240(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm6,%xmm6
+vpmuludq 224(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm5,%xmm5
+vpmuludq 304(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm8,%xmm8
+vpmuludq 288(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm3,%xmm3
+vpmuludq 336(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm11,%xmm11
+vpmuludq 384(%rsp),%xmm3,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpmuludq 144(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm2,%xmm2
+vpmuludq 160(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm1,%xmm1
+vpmuludq 192(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm4,%xmm4
+vpmuludq 208(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpmuludq 240(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm5,%xmm5
+vpmuludq 256(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm8,%xmm8
+vpmuludq 304(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm9,%xmm9
+vpmuludq 352(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm11,%xmm11
+vpmuludq 336(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpmuludq 416(%rsp),%xmm9,%xmm9
+vpaddq %xmm9,%xmm0,%xmm0
+vmovdqa 32(%rsp),%xmm3
+vmovdqa 80(%rsp),%xmm9
+vpaddq subc2(%rip),%xmm3,%xmm10
+vpsubq %xmm9,%xmm10,%xmm10
+vpaddq %xmm9,%xmm3,%xmm3
+vpunpckhqdq %xmm10,%xmm3,%xmm9
+vpunpcklqdq %xmm10,%xmm3,%xmm3
+vpmuludq 144(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm1,%xmm1
+vpmuludq 128(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm4,%xmm4
+vpmuludq 192(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm6,%xmm6
+vpmuludq 176(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm5,%xmm5
+vpmuludq 240(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm8,%xmm8
+vpmuludq 224(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm3,%xmm3
+vpmuludq 304(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm11,%xmm11
+vpmuludq 288(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm13,%xmm13
+vpmuludq 336(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm0,%xmm0
+vpmuludq 384(%rsp),%xmm3,%xmm3
+vpaddq %xmm3,%xmm2,%xmm2
+vpmuludq 144(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm4,%xmm4
+vpmuludq 160(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpmuludq 192(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm5,%xmm5
+vpmuludq 208(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm8,%xmm8
+vpmuludq 240(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm9,%xmm9
+vpmuludq 256(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm11,%xmm11
+vpmuludq 304(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpmuludq 352(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm0,%xmm0
+vpmuludq 336(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm2,%xmm2
+vpmuludq 416(%rsp),%xmm9,%xmm9
+vpaddq %xmm9,%xmm1,%xmm1
+vmovdqa 48(%rsp),%xmm3
+vmovdqa 96(%rsp),%xmm9
+vpaddq subc2(%rip),%xmm3,%xmm10
+vpsubq %xmm9,%xmm10,%xmm10
+vpaddq %xmm9,%xmm3,%xmm3
+vpunpckhqdq %xmm10,%xmm3,%xmm9
+vpunpcklqdq %xmm10,%xmm3,%xmm3
+vpmuludq 144(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm6,%xmm6
+vpmuludq 128(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm5,%xmm5
+vpmuludq 192(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm8,%xmm8
+vpmuludq 176(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm3,%xmm3
+vpmuludq 240(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm11,%xmm11
+vpmuludq 224(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm13,%xmm13
+vpmuludq 304(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm0,%xmm0
+vpmuludq 288(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm2,%xmm2
+vpmuludq 336(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm1,%xmm1
+vpmuludq 384(%rsp),%xmm3,%xmm3
+vpaddq %xmm3,%xmm4,%xmm4
+vpmuludq 144(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm5,%xmm5
+vpmuludq 160(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm8,%xmm8
+vpmuludq 192(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm9,%xmm9
+vpmuludq 208(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm11,%xmm11
+vpmuludq 240(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpmuludq 256(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm0,%xmm0
+vpmuludq 304(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm2,%xmm2
+vpmuludq 352(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm1,%xmm1
+vpmuludq 336(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm4,%xmm4
+vpmuludq 416(%rsp),%xmm9,%xmm9
+vpaddq %xmm9,%xmm6,%xmm6
+vmovdqa 64(%rsp),%xmm3
+vmovdqa 112(%rsp),%xmm9
+vpaddq subc2(%rip),%xmm3,%xmm10
+vpsubq %xmm9,%xmm10,%xmm10
+vpaddq %xmm9,%xmm3,%xmm3
+vpunpckhqdq %xmm10,%xmm3,%xmm9
+vpunpcklqdq %xmm10,%xmm3,%xmm3
+vpmuludq 144(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm8,%xmm8
+vpmuludq 128(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm3,%xmm3
+vpmuludq 192(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm11,%xmm11
+vpmuludq 176(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm13,%xmm13
+vpmuludq 240(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm0,%xmm0
+vpmuludq 224(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm2,%xmm2
+vpmuludq 304(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm1,%xmm1
+vpmuludq 288(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm4,%xmm4
+vpmuludq 336(%rsp),%xmm3,%xmm10
+vpaddq %xmm10,%xmm6,%xmm6
+vpmuludq 384(%rsp),%xmm3,%xmm3
+vpaddq %xmm3,%xmm5,%xmm5
+vpmuludq 144(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpmuludq v19_19(%rip),%xmm9,%xmm9
+vpmuludq 160(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm11,%xmm11
+vpmuludq 192(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpmuludq 208(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm0,%xmm0
+vpmuludq 240(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm2,%xmm2
+vpmuludq 256(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm1,%xmm1
+vpmuludq 304(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm4,%xmm4
+vpmuludq 352(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpmuludq 336(%rsp),%xmm9,%xmm3
+vpaddq %xmm3,%xmm5,%xmm5
+vpmuludq 416(%rsp),%xmm9,%xmm9
+vpaddq %xmm9,%xmm8,%xmm8
+vpsrlq $25,%xmm4,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpand m25(%rip),%xmm4,%xmm4
+vpsrlq $26,%xmm11,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpand m26(%rip),%xmm11,%xmm11
+vpsrlq $26,%xmm6,%xmm3
+vpaddq %xmm3,%xmm5,%xmm5
+vpand m26(%rip),%xmm6,%xmm6
+vpsrlq $25,%xmm13,%xmm3
+vpaddq %xmm3,%xmm0,%xmm0
+vpand m25(%rip),%xmm13,%xmm13
+vpsrlq $25,%xmm5,%xmm3
+vpaddq %xmm3,%xmm8,%xmm8
+vpand m25(%rip),%xmm5,%xmm5
+vpsrlq $26,%xmm0,%xmm3
+vpaddq %xmm3,%xmm2,%xmm2
+vpand m26(%rip),%xmm0,%xmm0
+vpsrlq $26,%xmm8,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpand m26(%rip),%xmm8,%xmm8
+vpsrlq $25,%xmm2,%xmm3
+vpaddq %xmm3,%xmm1,%xmm1
+vpand m25(%rip),%xmm2,%xmm2
+vpsrlq $25,%xmm7,%xmm3
+vpsllq $4,%xmm3,%xmm9
+vpaddq %xmm3,%xmm11,%xmm11
+vpsllq $1,%xmm3,%xmm3
+vpaddq %xmm3,%xmm9,%xmm9
+vpaddq %xmm9,%xmm11,%xmm11
+vpand m25(%rip),%xmm7,%xmm7
+vpsrlq $26,%xmm1,%xmm3
+vpaddq %xmm3,%xmm4,%xmm4
+vpand m26(%rip),%xmm1,%xmm1
+vpsrlq $26,%xmm11,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpand m26(%rip),%xmm11,%xmm11
+vpsrlq $25,%xmm4,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpand m25(%rip),%xmm4,%xmm4
+vpunpcklqdq %xmm13,%xmm11,%xmm3
+vpunpckhqdq %xmm13,%xmm11,%xmm9
+vpaddq subc0(%rip),%xmm9,%xmm10
+vpsubq %xmm3,%xmm10,%xmm10
+vpaddq %xmm9,%xmm3,%xmm3
+vpunpckhqdq %xmm3,%xmm10,%xmm9
+vpunpcklqdq %xmm3,%xmm10,%xmm10
+vpmuludq %xmm10,%xmm10,%xmm3
+vpaddq %xmm10,%xmm10,%xmm10
+vpmuludq %xmm9,%xmm10,%xmm11
+vpunpcklqdq %xmm2,%xmm0,%xmm12
+vpunpckhqdq %xmm2,%xmm0,%xmm0
+vpaddq subc2(%rip),%xmm0,%xmm2
+vpsubq %xmm12,%xmm2,%xmm2
+vpaddq %xmm0,%xmm12,%xmm12
+vpunpckhqdq %xmm12,%xmm2,%xmm0
+vpunpcklqdq %xmm12,%xmm2,%xmm2
+vpmuludq %xmm2,%xmm10,%xmm12
+vpaddq %xmm9,%xmm9,%xmm13
+vpmuludq %xmm13,%xmm9,%xmm9
+vpaddq %xmm9,%xmm12,%xmm12
+vpmuludq %xmm0,%xmm10,%xmm9
+vpmuludq %xmm2,%xmm13,%xmm14
+vpaddq %xmm14,%xmm9,%xmm9
+vpunpcklqdq %xmm4,%xmm1,%xmm14
+vpunpckhqdq %xmm4,%xmm1,%xmm1
+vpaddq subc2(%rip),%xmm1,%xmm4
+vpsubq %xmm14,%xmm4,%xmm4
+vpaddq %xmm1,%xmm14,%xmm14
+vpunpckhqdq %xmm14,%xmm4,%xmm1
+vpunpcklqdq %xmm14,%xmm4,%xmm4
+vmovdqa %xmm1,0(%rsp)
+vpaddq %xmm1,%xmm1,%xmm1
+vmovdqa %xmm1,16(%rsp)
+vpmuludq v19_19(%rip),%xmm1,%xmm1
+vmovdqa %xmm1,32(%rsp)
+vpmuludq %xmm4,%xmm10,%xmm1
+vpmuludq %xmm2,%xmm2,%xmm14
+vpaddq %xmm14,%xmm1,%xmm1
+vpmuludq 0(%rsp),%xmm10,%xmm14
+vpmuludq %xmm4,%xmm13,%xmm15
+vpaddq %xmm15,%xmm14,%xmm14
+vpunpcklqdq %xmm5,%xmm6,%xmm15
+vpunpckhqdq %xmm5,%xmm6,%xmm5
+vpaddq subc2(%rip),%xmm5,%xmm6
+vpsubq %xmm15,%xmm6,%xmm6
+vpaddq %xmm5,%xmm15,%xmm15
+vpunpckhqdq %xmm15,%xmm6,%xmm5
+vpunpcklqdq %xmm15,%xmm6,%xmm6
+vmovdqa %xmm6,48(%rsp)
+vpmuludq v19_19(%rip),%xmm6,%xmm6
+vmovdqa %xmm6,64(%rsp)
+vmovdqa %xmm5,80(%rsp)
+vpmuludq v38_38(%rip),%xmm5,%xmm5
+vmovdqa %xmm5,96(%rsp)
+vpmuludq 48(%rsp),%xmm10,%xmm5
+vpaddq %xmm0,%xmm0,%xmm6
+vpmuludq %xmm6,%xmm0,%xmm0
+vpaddq %xmm0,%xmm5,%xmm5
+vpmuludq 80(%rsp),%xmm10,%xmm0
+vpmuludq %xmm4,%xmm6,%xmm15
+vpaddq %xmm15,%xmm0,%xmm0
+vpmuludq %xmm6,%xmm13,%xmm15
+vpaddq %xmm15,%xmm1,%xmm1
+vpmuludq %xmm6,%xmm2,%xmm15
+vpaddq %xmm15,%xmm14,%xmm14
+vpunpcklqdq %xmm7,%xmm8,%xmm15
+vpunpckhqdq %xmm7,%xmm8,%xmm7
+vpaddq subc2(%rip),%xmm7,%xmm8
+vpsubq %xmm15,%xmm8,%xmm8
+vpaddq %xmm7,%xmm15,%xmm15
+vpunpckhqdq %xmm15,%xmm8,%xmm7
+vpunpcklqdq %xmm15,%xmm8,%xmm8
+vmovdqa %xmm8,112(%rsp)
+vpmuludq v19_19(%rip),%xmm8,%xmm8
+vmovdqa %xmm8,160(%rsp)
+vpmuludq 112(%rsp),%xmm10,%xmm8
+vpmuludq %xmm7,%xmm10,%xmm10
+vpmuludq v38_38(%rip),%xmm7,%xmm15
+vpmuludq %xmm15,%xmm7,%xmm7
+vpaddq %xmm7,%xmm8,%xmm8
+vpmuludq %xmm15,%xmm13,%xmm7
+vpaddq %xmm7,%xmm3,%xmm3
+vpmuludq %xmm15,%xmm2,%xmm7
+vpaddq %xmm7,%xmm11,%xmm11
+vpmuludq 80(%rsp),%xmm13,%xmm7
+vpaddq %xmm7,%xmm7,%xmm7
+vpaddq %xmm7,%xmm8,%xmm8
+vpmuludq 16(%rsp),%xmm13,%xmm7
+vpaddq %xmm7,%xmm5,%xmm5
+vpmuludq 48(%rsp),%xmm13,%xmm7
+vpaddq %xmm7,%xmm0,%xmm0
+vpmuludq 112(%rsp),%xmm13,%xmm7
+vpaddq %xmm7,%xmm10,%xmm10
+vpmuludq %xmm15,%xmm6,%xmm7
+vpaddq %xmm7,%xmm12,%xmm12
+vpmuludq %xmm15,%xmm4,%xmm7
+vpaddq %xmm7,%xmm9,%xmm9
+vpaddq %xmm2,%xmm2,%xmm2
+vpmuludq %xmm4,%xmm2,%xmm7
+vpaddq %xmm7,%xmm5,%xmm5
+vpmuludq 160(%rsp),%xmm2,%xmm7
+vpaddq %xmm7,%xmm3,%xmm3
+vpmuludq 160(%rsp),%xmm6,%xmm7
+vpaddq %xmm7,%xmm11,%xmm11
+vpmuludq 0(%rsp),%xmm2,%xmm7
+vpaddq %xmm7,%xmm0,%xmm0
+vpmuludq 48(%rsp),%xmm2,%xmm7
+vpaddq %xmm7,%xmm8,%xmm8
+vpmuludq 80(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpmuludq 96(%rsp),%xmm4,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpmuludq %xmm4,%xmm4,%xmm2
+vpaddq %xmm2,%xmm8,%xmm8
+vpaddq %xmm4,%xmm4,%xmm2
+vpmuludq 160(%rsp),%xmm2,%xmm4
+vpaddq %xmm4,%xmm12,%xmm12
+vpmuludq 16(%rsp),%xmm15,%xmm4
+vpaddq %xmm4,%xmm1,%xmm1
+vpmuludq 48(%rsp),%xmm15,%xmm4
+vpaddq %xmm4,%xmm14,%xmm14
+vpmuludq 96(%rsp),%xmm6,%xmm4
+vpaddq %xmm4,%xmm3,%xmm3
+vmovdqa 16(%rsp),%xmm4
+vpmuludq 160(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm9,%xmm9
+vpmuludq 16(%rsp),%xmm6,%xmm4
+vpaddq %xmm4,%xmm8,%xmm8
+vpmuludq 48(%rsp),%xmm6,%xmm4
+vpaddq %xmm4,%xmm10,%xmm10
+vpmuludq 80(%rsp),%xmm15,%xmm4
+vpaddq %xmm4,%xmm4,%xmm4
+vpaddq %xmm4,%xmm5,%xmm5
+vpmuludq 112(%rsp),%xmm15,%xmm4
+vpaddq %xmm4,%xmm0,%xmm0
+vmovdqa 48(%rsp),%xmm4
+vpaddq %xmm4,%xmm4,%xmm4
+vpmuludq 160(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm1,%xmm1
+vmovdqa 80(%rsp),%xmm4
+vpaddq %xmm4,%xmm4,%xmm4
+vpmuludq 160(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm14,%xmm14
+vpmuludq 64(%rsp),%xmm2,%xmm4
+vpaddq %xmm4,%xmm3,%xmm3
+vmovdqa 16(%rsp),%xmm4
+vpmuludq 64(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm11,%xmm11
+vmovdqa 16(%rsp),%xmm4
+vpmuludq 96(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm12,%xmm12
+vmovdqa 48(%rsp),%xmm4
+vpmuludq 96(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm9,%xmm9
+vpmuludq 0(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vmovdqa 32(%rsp),%xmm2
+vpmuludq 0(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm3,%xmm3
+vmovdqa 64(%rsp),%xmm2
+vpmuludq 48(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vmovdqa 96(%rsp),%xmm2
+vpmuludq 80(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm1,%xmm1
+vmovdqa 160(%rsp),%xmm2
+vpmuludq 112(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpsrlq $26,%xmm3,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpand m26(%rip),%xmm3,%xmm3
+vpsrlq $25,%xmm14,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpand m25(%rip),%xmm14,%xmm14
+vpsrlq $25,%xmm11,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpand m25(%rip),%xmm11,%xmm11
+vpsrlq $26,%xmm5,%xmm2
+vpaddq %xmm2,%xmm0,%xmm0
+vpand m26(%rip),%xmm5,%xmm5
+vpsrlq $26,%xmm12,%xmm2
+vpaddq %xmm2,%xmm9,%xmm9
+vpand m26(%rip),%xmm12,%xmm12
+vpsrlq $25,%xmm0,%xmm2
+vpaddq %xmm2,%xmm8,%xmm8
+vpand m25(%rip),%xmm0,%xmm0
+vpsrlq $25,%xmm9,%xmm2
+vpaddq %xmm2,%xmm1,%xmm1
+vpand m25(%rip),%xmm9,%xmm9
+vpsrlq $26,%xmm8,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpand m26(%rip),%xmm8,%xmm8
+vpsrlq $26,%xmm1,%xmm2
+vpaddq %xmm2,%xmm14,%xmm14
+vpand m26(%rip),%xmm1,%xmm1
+vpsrlq $25,%xmm10,%xmm2
+vpsllq $4,%xmm2,%xmm4
+vpaddq %xmm2,%xmm3,%xmm3
+vpsllq $1,%xmm2,%xmm2
+vpaddq %xmm2,%xmm4,%xmm4
+vpaddq %xmm4,%xmm3,%xmm3
+vpand m25(%rip),%xmm10,%xmm10
+vpsrlq $25,%xmm14,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpand m25(%rip),%xmm14,%xmm14
+vpsrlq $26,%xmm3,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpand m26(%rip),%xmm3,%xmm3
+vpunpckhqdq %xmm11,%xmm3,%xmm2
+vmovdqa %xmm2,0(%rsp)
+vpunpcklqdq %xmm11,%xmm3,%xmm2
+vpmuludq v9_9(%rip),%xmm2,%xmm2
+vmovdqa %xmm2,80(%rsp)
+vpunpckhqdq %xmm9,%xmm12,%xmm2
+vmovdqa %xmm2,16(%rsp)
+vpunpcklqdq %xmm9,%xmm12,%xmm2
+vpmuludq v9_9(%rip),%xmm2,%xmm2
+vmovdqa %xmm2,96(%rsp)
+vpunpckhqdq %xmm14,%xmm1,%xmm2
+vmovdqa %xmm2,32(%rsp)
+vpunpcklqdq %xmm14,%xmm1,%xmm1
+vpmuludq v9_9(%rip),%xmm1,%xmm1
+vmovdqa %xmm1,112(%rsp)
+vpunpckhqdq %xmm0,%xmm5,%xmm1
+vmovdqa %xmm1,48(%rsp)
+vpunpcklqdq %xmm0,%xmm5,%xmm0
+vpmuludq v9_9(%rip),%xmm0,%xmm0
+vmovdqa %xmm0,160(%rsp)
+vpunpckhqdq %xmm10,%xmm8,%xmm0
+vmovdqa %xmm0,64(%rsp)
+vpunpcklqdq %xmm10,%xmm8,%xmm0
+vpmuludq v9_9(%rip),%xmm0,%xmm0
+vmovdqa %xmm0,208(%rsp)
+vmovdqa 144(%rsp),%xmm0
+vpmuludq %xmm0,%xmm0,%xmm1
+vpaddq %xmm0,%xmm0,%xmm0
+vmovdqa 128(%rsp),%xmm2
+vpmuludq %xmm2,%xmm0,%xmm3
+vmovdqa 192(%rsp),%xmm4
+vpmuludq %xmm4,%xmm0,%xmm5
+vmovdqa 176(%rsp),%xmm6
+vpmuludq %xmm6,%xmm0,%xmm7
+vmovdqa 240(%rsp),%xmm8
+vpmuludq %xmm8,%xmm0,%xmm9
+vpmuludq 224(%rsp),%xmm0,%xmm10
+vpmuludq 304(%rsp),%xmm0,%xmm11
+vpmuludq 288(%rsp),%xmm0,%xmm12
+vpmuludq 336(%rsp),%xmm0,%xmm13
+vmovdqa 384(%rsp),%xmm14
+vpmuludq %xmm14,%xmm0,%xmm0
+vpmuludq v38_38(%rip),%xmm14,%xmm15
+vpmuludq %xmm15,%xmm14,%xmm14
+vpaddq %xmm14,%xmm13,%xmm13
+vpaddq %xmm6,%xmm6,%xmm14
+vpmuludq %xmm14,%xmm6,%xmm6
+vpaddq %xmm6,%xmm11,%xmm11
+vpaddq %xmm2,%xmm2,%xmm6
+vpmuludq %xmm6,%xmm2,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpmuludq %xmm15,%xmm6,%xmm2
+vpaddq %xmm2,%xmm1,%xmm1
+vpmuludq %xmm15,%xmm4,%xmm2
+vpaddq %xmm2,%xmm3,%xmm3
+vpmuludq 256(%rsp),%xmm6,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpmuludq 304(%rsp),%xmm6,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpmuludq 352(%rsp),%xmm6,%xmm2
+vpaddq %xmm2,%xmm13,%xmm13
+vpmuludq 336(%rsp),%xmm6,%xmm2
+vpaddq %xmm2,%xmm0,%xmm0
+vpmuludq %xmm4,%xmm6,%xmm2
+vpaddq %xmm2,%xmm7,%xmm7
+vpmuludq %xmm14,%xmm6,%xmm2
+vpaddq %xmm2,%xmm9,%xmm9
+vpmuludq %xmm8,%xmm6,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpmuludq %xmm15,%xmm14,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpmuludq %xmm15,%xmm8,%xmm2
+vpaddq %xmm2,%xmm7,%xmm7
+vpmuludq %xmm4,%xmm4,%xmm2
+vpaddq %xmm2,%xmm9,%xmm9
+vpmuludq %xmm14,%xmm4,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpaddq %xmm4,%xmm4,%xmm2
+vpmuludq %xmm8,%xmm2,%xmm4
+vpaddq %xmm4,%xmm11,%xmm11
+vpmuludq 400(%rsp),%xmm2,%xmm4
+vpaddq %xmm4,%xmm1,%xmm1
+vpmuludq 400(%rsp),%xmm14,%xmm4
+vpaddq %xmm4,%xmm3,%xmm3
+vpmuludq 224(%rsp),%xmm2,%xmm4
+vpaddq %xmm4,%xmm12,%xmm12
+vpmuludq 304(%rsp),%xmm2,%xmm4
+vpaddq %xmm4,%xmm13,%xmm13
+vpmuludq 288(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm0,%xmm0
+vpmuludq 368(%rsp),%xmm8,%xmm2
+vpaddq %xmm2,%xmm3,%xmm3
+vpmuludq %xmm8,%xmm14,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpmuludq %xmm8,%xmm8,%xmm2
+vpaddq %xmm2,%xmm13,%xmm13
+vpaddq %xmm8,%xmm8,%xmm2
+vpmuludq 400(%rsp),%xmm2,%xmm4
+vpaddq %xmm4,%xmm5,%xmm5
+vpmuludq 256(%rsp),%xmm15,%xmm4
+vpaddq %xmm4,%xmm9,%xmm9
+vpmuludq 304(%rsp),%xmm15,%xmm4
+vpaddq %xmm4,%xmm10,%xmm10
+vpmuludq 368(%rsp),%xmm14,%xmm4
+vpaddq %xmm4,%xmm1,%xmm1
+vmovdqa 256(%rsp),%xmm4
+vpmuludq 400(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm7,%xmm7
+vpmuludq 256(%rsp),%xmm14,%xmm4
+vpaddq %xmm4,%xmm13,%xmm13
+vpmuludq 304(%rsp),%xmm14,%xmm4
+vpaddq %xmm4,%xmm0,%xmm0
+vpmuludq 352(%rsp),%xmm15,%xmm4
+vpaddq %xmm4,%xmm11,%xmm11
+vpmuludq 336(%rsp),%xmm15,%xmm4
+vpaddq %xmm4,%xmm12,%xmm12
+vmovdqa 304(%rsp),%xmm4
+vpaddq %xmm4,%xmm4,%xmm4
+vpmuludq 400(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm9,%xmm9
+vpmuludq 320(%rsp),%xmm2,%xmm4
+vpaddq %xmm4,%xmm1,%xmm1
+vmovdqa 256(%rsp),%xmm4
+vpmuludq 320(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm3,%xmm3
+vmovdqa 256(%rsp),%xmm4
+vpmuludq 368(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm5,%xmm5
+vmovdqa 304(%rsp),%xmm4
+vpmuludq 368(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm7,%xmm7
+vmovdqa 352(%rsp),%xmm4
+vpmuludq 400(%rsp),%xmm4,%xmm4
+vpaddq %xmm4,%xmm10,%xmm10
+vpmuludq 224(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm0,%xmm0
+vmovdqa 272(%rsp),%xmm2
+vpmuludq 224(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm1,%xmm1
+vmovdqa 320(%rsp),%xmm2
+vpmuludq 304(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vmovdqa 368(%rsp),%xmm2
+vpmuludq 288(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm9,%xmm9
+vmovdqa 400(%rsp),%xmm2
+vpmuludq 336(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpsrlq $26,%xmm1,%xmm2
+vpaddq %xmm2,%xmm3,%xmm3
+vpand m26(%rip),%xmm1,%xmm1
+vpsrlq $25,%xmm10,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpand m25(%rip),%xmm10,%xmm10
+vpsrlq $25,%xmm3,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpand m25(%rip),%xmm3,%xmm3
+vpsrlq $26,%xmm11,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpand m26(%rip),%xmm11,%xmm11
+vpsrlq $26,%xmm5,%xmm2
+vpaddq %xmm2,%xmm7,%xmm7
+vpand m26(%rip),%xmm5,%xmm5
+vpsrlq $25,%xmm12,%xmm2
+vpaddq %xmm2,%xmm13,%xmm13
+vpand m25(%rip),%xmm12,%xmm12
+vpsrlq $25,%xmm7,%xmm2
+vpaddq %xmm2,%xmm9,%xmm9
+vpand m25(%rip),%xmm7,%xmm7
+vpsrlq $26,%xmm13,%xmm2
+vpaddq %xmm2,%xmm0,%xmm0
+vpand m26(%rip),%xmm13,%xmm13
+vpsrlq $26,%xmm9,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpand m26(%rip),%xmm9,%xmm9
+vpsrlq $25,%xmm0,%xmm2
+vpsllq $4,%xmm2,%xmm4
+vpaddq %xmm2,%xmm1,%xmm1
+vpsllq $1,%xmm2,%xmm2
+vpaddq %xmm2,%xmm4,%xmm4
+vpaddq %xmm4,%xmm1,%xmm1
+vpand m25(%rip),%xmm0,%xmm0
+vpsrlq $25,%xmm10,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpand m25(%rip),%xmm10,%xmm10
+vpsrlq $26,%xmm1,%xmm2
+vpaddq %xmm2,%xmm3,%xmm3
+vpand m26(%rip),%xmm1,%xmm1
+vpunpckhqdq %xmm3,%xmm1,%xmm2
+vpunpcklqdq %xmm3,%xmm1,%xmm1
+vmovdqa %xmm1,176(%rsp)
+vpaddq subc0(%rip),%xmm2,%xmm3
+vpsubq %xmm1,%xmm3,%xmm3
+vpunpckhqdq %xmm3,%xmm2,%xmm1
+vpunpcklqdq %xmm3,%xmm2,%xmm2
+vmovdqa %xmm2,192(%rsp)
+vmovdqa %xmm1,224(%rsp)
+vpsllq $1,%xmm1,%xmm1
+vmovdqa %xmm1,240(%rsp)
+vpmuludq v121666_121666(%rip),%xmm3,%xmm3
+vmovdqa 80(%rsp),%xmm1
+vpunpcklqdq %xmm1,%xmm3,%xmm2
+vpunpckhqdq %xmm1,%xmm3,%xmm1
+vpunpckhqdq %xmm7,%xmm5,%xmm3
+vpunpcklqdq %xmm7,%xmm5,%xmm4
+vmovdqa %xmm4,256(%rsp)
+vpaddq subc2(%rip),%xmm3,%xmm5
+vpsubq %xmm4,%xmm5,%xmm5
+vpunpckhqdq %xmm5,%xmm3,%xmm4
+vpunpcklqdq %xmm5,%xmm3,%xmm3
+vmovdqa %xmm3,272(%rsp)
+vmovdqa %xmm4,288(%rsp)
+vpsllq $1,%xmm4,%xmm4
+vmovdqa %xmm4,304(%rsp)
+vpmuludq v121666_121666(%rip),%xmm5,%xmm5
+vmovdqa 96(%rsp),%xmm3
+vpunpcklqdq %xmm3,%xmm5,%xmm4
+vpunpckhqdq %xmm3,%xmm5,%xmm3
+vpunpckhqdq %xmm10,%xmm9,%xmm5
+vpunpcklqdq %xmm10,%xmm9,%xmm6
+vmovdqa %xmm6,320(%rsp)
+vpaddq subc2(%rip),%xmm5,%xmm7
+vpsubq %xmm6,%xmm7,%xmm7
+vpunpckhqdq %xmm7,%xmm5,%xmm6
+vpunpcklqdq %xmm7,%xmm5,%xmm5
+vmovdqa %xmm5,336(%rsp)
+vmovdqa %xmm6,352(%rsp)
+vpsllq $1,%xmm6,%xmm6
+vmovdqa %xmm6,368(%rsp)
+vpmuludq v121666_121666(%rip),%xmm7,%xmm7
+vmovdqa 112(%rsp),%xmm5
+vpunpcklqdq %xmm5,%xmm7,%xmm6
+vpunpckhqdq %xmm5,%xmm7,%xmm5
+vpunpckhqdq %xmm12,%xmm11,%xmm7
+vpunpcklqdq %xmm12,%xmm11,%xmm8
+vmovdqa %xmm8,384(%rsp)
+vpaddq subc2(%rip),%xmm7,%xmm9
+vpsubq %xmm8,%xmm9,%xmm9
+vpunpckhqdq %xmm9,%xmm7,%xmm8
+vpunpcklqdq %xmm9,%xmm7,%xmm7
+vmovdqa %xmm7,400(%rsp)
+vmovdqa %xmm8,416(%rsp)
+vpsllq $1,%xmm8,%xmm8
+vmovdqa %xmm8,432(%rsp)
+vpmuludq v121666_121666(%rip),%xmm9,%xmm9
+vmovdqa 160(%rsp),%xmm7
+vpunpcklqdq %xmm7,%xmm9,%xmm8
+vpunpckhqdq %xmm7,%xmm9,%xmm7
+vpunpckhqdq %xmm0,%xmm13,%xmm9
+vpunpcklqdq %xmm0,%xmm13,%xmm0
+vmovdqa %xmm0,160(%rsp)
+vpaddq subc2(%rip),%xmm9,%xmm10
+vpsubq %xmm0,%xmm10,%xmm10
+vpunpckhqdq %xmm10,%xmm9,%xmm0
+vpunpcklqdq %xmm10,%xmm9,%xmm9
+vmovdqa %xmm9,448(%rsp)
+vmovdqa %xmm0,464(%rsp)
+vpsllq $1,%xmm0,%xmm0
+vmovdqa %xmm0,480(%rsp)
+vpmuludq v121666_121666(%rip),%xmm10,%xmm10
+vmovdqa 208(%rsp),%xmm0
+vpunpcklqdq %xmm0,%xmm10,%xmm9
+vpunpckhqdq %xmm0,%xmm10,%xmm0
+vpsrlq $26,%xmm2,%xmm10
+vpaddq %xmm10,%xmm1,%xmm1
+vpand m26(%rip),%xmm2,%xmm2
+vpsrlq $25,%xmm5,%xmm10
+vpaddq %xmm10,%xmm8,%xmm8
+vpand m25(%rip),%xmm5,%xmm5
+vpsrlq $25,%xmm1,%xmm10
+vpaddq %xmm10,%xmm4,%xmm4
+vpand m25(%rip),%xmm1,%xmm1
+vpsrlq $26,%xmm8,%xmm10
+vpaddq %xmm10,%xmm7,%xmm7
+vpand m26(%rip),%xmm8,%xmm8
+vpsrlq $26,%xmm4,%xmm10
+vpaddq %xmm10,%xmm3,%xmm3
+vpand m26(%rip),%xmm4,%xmm4
+vpsrlq $25,%xmm7,%xmm10
+vpaddq %xmm10,%xmm9,%xmm9
+vpand m25(%rip),%xmm7,%xmm7
+vpsrlq $25,%xmm3,%xmm10
+vpaddq %xmm10,%xmm6,%xmm6
+vpand m25(%rip),%xmm3,%xmm3
+vpsrlq $26,%xmm9,%xmm10
+vpaddq %xmm10,%xmm0,%xmm0
+vpand m26(%rip),%xmm9,%xmm9
+vpsrlq $26,%xmm6,%xmm10
+vpaddq %xmm10,%xmm5,%xmm5
+vpand m26(%rip),%xmm6,%xmm6
+vpsrlq $25,%xmm0,%xmm10
+vpsllq $4,%xmm10,%xmm11
+vpaddq %xmm10,%xmm2,%xmm2
+vpsllq $1,%xmm10,%xmm10
+vpaddq %xmm10,%xmm11,%xmm11
+vpaddq %xmm11,%xmm2,%xmm2
+vpand m25(%rip),%xmm0,%xmm0
+vpsrlq $25,%xmm5,%xmm10
+vpaddq %xmm10,%xmm8,%xmm8
+vpand m25(%rip),%xmm5,%xmm5
+vpsrlq $26,%xmm2,%xmm10
+vpaddq %xmm10,%xmm1,%xmm1
+vpand m26(%rip),%xmm2,%xmm2
+vpunpckhqdq %xmm1,%xmm2,%xmm10
+vmovdqa %xmm10,80(%rsp)
+vpunpcklqdq %xmm1,%xmm2,%xmm1
+vpunpckhqdq %xmm3,%xmm4,%xmm2
+vmovdqa %xmm2,96(%rsp)
+vpunpcklqdq %xmm3,%xmm4,%xmm2
+vpunpckhqdq %xmm5,%xmm6,%xmm3
+vmovdqa %xmm3,112(%rsp)
+vpunpcklqdq %xmm5,%xmm6,%xmm3
+vpunpckhqdq %xmm7,%xmm8,%xmm4
+vmovdqa %xmm4,128(%rsp)
+vpunpcklqdq %xmm7,%xmm8,%xmm4
+vpunpckhqdq %xmm0,%xmm9,%xmm5
+vmovdqa %xmm5,144(%rsp)
+vpunpcklqdq %xmm0,%xmm9,%xmm0
+vmovdqa 176(%rsp),%xmm5
+vpaddq %xmm5,%xmm1,%xmm1
+vpunpcklqdq %xmm1,%xmm5,%xmm6
+vpunpckhqdq %xmm1,%xmm5,%xmm1
+vpmuludq 224(%rsp),%xmm6,%xmm5
+vpmuludq 192(%rsp),%xmm1,%xmm7
+vpaddq %xmm7,%xmm5,%xmm5
+vpmuludq 272(%rsp),%xmm6,%xmm7
+vpmuludq 240(%rsp),%xmm1,%xmm8
+vpaddq %xmm8,%xmm7,%xmm7
+vpmuludq 288(%rsp),%xmm6,%xmm8
+vpmuludq 272(%rsp),%xmm1,%xmm9
+vpaddq %xmm9,%xmm8,%xmm8
+vpmuludq 336(%rsp),%xmm6,%xmm9
+vpmuludq 304(%rsp),%xmm1,%xmm10
+vpaddq %xmm10,%xmm9,%xmm9
+vpmuludq 352(%rsp),%xmm6,%xmm10
+vpmuludq 336(%rsp),%xmm1,%xmm11
+vpaddq %xmm11,%xmm10,%xmm10
+vpmuludq 400(%rsp),%xmm6,%xmm11
+vpmuludq 368(%rsp),%xmm1,%xmm12
+vpaddq %xmm12,%xmm11,%xmm11
+vpmuludq 416(%rsp),%xmm6,%xmm12
+vpmuludq 400(%rsp),%xmm1,%xmm13
+vpaddq %xmm13,%xmm12,%xmm12
+vpmuludq 448(%rsp),%xmm6,%xmm13
+vpmuludq 432(%rsp),%xmm1,%xmm14
+vpaddq %xmm14,%xmm13,%xmm13
+vpmuludq 464(%rsp),%xmm6,%xmm14
+vpmuludq 448(%rsp),%xmm1,%xmm15
+vpaddq %xmm15,%xmm14,%xmm14
+vpmuludq 192(%rsp),%xmm6,%xmm6
+vpmuludq v19_19(%rip),%xmm1,%xmm1
+vpmuludq 480(%rsp),%xmm1,%xmm1
+vpaddq %xmm1,%xmm6,%xmm6
+vmovdqa 256(%rsp),%xmm1
+vpaddq %xmm1,%xmm2,%xmm2
+vpunpcklqdq %xmm2,%xmm1,%xmm15
+vpunpckhqdq %xmm2,%xmm1,%xmm1
+vpmuludq 192(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm7,%xmm7
+vpmuludq 224(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm8,%xmm8
+vpmuludq 272(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm9,%xmm9
+vpmuludq 288(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpmuludq 336(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpmuludq 352(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpmuludq 400(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm13,%xmm13
+vpmuludq 416(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm14,%xmm14
+vpmuludq v19_19(%rip),%xmm15,%xmm15
+vpmuludq 448(%rsp),%xmm15,%xmm2
+vpaddq %xmm2,%xmm6,%xmm6
+vpmuludq 464(%rsp),%xmm15,%xmm15
+vpaddq %xmm15,%xmm5,%xmm5
+vpmuludq 192(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm8,%xmm8
+vpmuludq 240(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm9,%xmm9
+vpmuludq 272(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpmuludq 304(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpmuludq 336(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpmuludq 368(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm13,%xmm13
+vpmuludq 400(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm14,%xmm14
+vpmuludq v19_19(%rip),%xmm1,%xmm1
+vpmuludq 432(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm6,%xmm6
+vpmuludq 448(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpmuludq 480(%rsp),%xmm1,%xmm1
+vpaddq %xmm1,%xmm7,%xmm7
+vmovdqa 320(%rsp),%xmm1
+vpaddq %xmm1,%xmm3,%xmm3
+vpunpcklqdq %xmm3,%xmm1,%xmm2
+vpunpckhqdq %xmm3,%xmm1,%xmm1
+vpmuludq 192(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm9,%xmm9
+vpmuludq 224(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm10,%xmm10
+vpmuludq 272(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm11,%xmm11
+vpmuludq 288(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm12,%xmm12
+vpmuludq 336(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpmuludq 352(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm14,%xmm14
+vpmuludq v19_19(%rip),%xmm2,%xmm2
+vpmuludq 400(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpmuludq 416(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm5,%xmm5
+vpmuludq 448(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpmuludq 464(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm8,%xmm8
+vpmuludq 192(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpmuludq 240(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm11,%xmm11
+vpmuludq 272(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpmuludq 304(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm13,%xmm13
+vpmuludq 336(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm14,%xmm14
+vpmuludq v19_19(%rip),%xmm1,%xmm1
+vpmuludq 368(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm6,%xmm6
+vpmuludq 400(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpmuludq 432(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm7,%xmm7
+vpmuludq 448(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm8,%xmm8
+vpmuludq 480(%rsp),%xmm1,%xmm1
+vpaddq %xmm1,%xmm9,%xmm9
+vmovdqa 384(%rsp),%xmm1
+vpaddq %xmm1,%xmm4,%xmm4
+vpunpcklqdq %xmm4,%xmm1,%xmm2
+vpunpckhqdq %xmm4,%xmm1,%xmm1
+vpmuludq 192(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm11,%xmm11
+vpmuludq 224(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm12,%xmm12
+vpmuludq 272(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm13,%xmm13
+vpmuludq 288(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm14,%xmm14
+vpmuludq v19_19(%rip),%xmm2,%xmm2
+vpmuludq 336(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm6,%xmm6
+vpmuludq 352(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm5,%xmm5
+vpmuludq 400(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm7,%xmm7
+vpmuludq 416(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm8,%xmm8
+vpmuludq 448(%rsp),%xmm2,%xmm3
+vpaddq %xmm3,%xmm9,%xmm9
+vpmuludq 464(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpmuludq 192(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpmuludq 240(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm13,%xmm13
+vpmuludq 272(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm14,%xmm14
+vpmuludq v19_19(%rip),%xmm1,%xmm1
+vpmuludq 304(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm6,%xmm6
+vpmuludq 336(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm5,%xmm5
+vpmuludq 368(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm7,%xmm7
+vpmuludq 400(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm8,%xmm8
+vpmuludq 432(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm9,%xmm9
+vpmuludq 448(%rsp),%xmm1,%xmm2
+vpaddq %xmm2,%xmm10,%xmm10
+vpmuludq 480(%rsp),%xmm1,%xmm1
+vpaddq %xmm1,%xmm11,%xmm11
+vmovdqa 160(%rsp),%xmm1
+vpaddq %xmm1,%xmm0,%xmm0
+vpunpcklqdq %xmm0,%xmm1,%xmm2
+vpunpckhqdq %xmm0,%xmm1,%xmm0
+vpmuludq 192(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm13,%xmm13
+vpmuludq 224(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm14,%xmm14
+vpmuludq v19_19(%rip),%xmm2,%xmm2
+vpmuludq 272(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm6,%xmm6
+vpmuludq 288(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm5,%xmm5
+vpmuludq 336(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm7,%xmm7
+vpmuludq 352(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm8,%xmm8
+vpmuludq 400(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm9,%xmm9
+vpmuludq 416(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm10,%xmm10
+vpmuludq 448(%rsp),%xmm2,%xmm1
+vpaddq %xmm1,%xmm11,%xmm11
+vpmuludq 464(%rsp),%xmm2,%xmm2
+vpaddq %xmm2,%xmm12,%xmm12
+vpmuludq 192(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm14,%xmm14
+vpmuludq v19_19(%rip),%xmm0,%xmm0
+vpmuludq 240(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm6,%xmm6
+vpmuludq 272(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm5,%xmm5
+vpmuludq 304(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm7,%xmm7
+vpmuludq 336(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm8,%xmm8
+vpmuludq 368(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm9,%xmm9
+vpmuludq 400(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm10,%xmm10
+vpmuludq 432(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm11,%xmm11
+vpmuludq 448(%rsp),%xmm0,%xmm1
+vpaddq %xmm1,%xmm12,%xmm12
+vpmuludq 480(%rsp),%xmm0,%xmm0
+vpaddq %xmm0,%xmm13,%xmm13
+vpsrlq $26,%xmm6,%xmm0
+vpaddq %xmm0,%xmm5,%xmm5
+vpand m26(%rip),%xmm6,%xmm6
+vpsrlq $25,%xmm10,%xmm0
+vpaddq %xmm0,%xmm11,%xmm11
+vpand m25(%rip),%xmm10,%xmm10
+vpsrlq $25,%xmm5,%xmm0
+vpaddq %xmm0,%xmm7,%xmm7
+vpand m25(%rip),%xmm5,%xmm5
+vpsrlq $26,%xmm11,%xmm0
+vpaddq %xmm0,%xmm12,%xmm12
+vpand m26(%rip),%xmm11,%xmm11
+vpsrlq $26,%xmm7,%xmm0
+vpaddq %xmm0,%xmm8,%xmm8
+vpand m26(%rip),%xmm7,%xmm7
+vpsrlq $25,%xmm12,%xmm0
+vpaddq %xmm0,%xmm13,%xmm13
+vpand m25(%rip),%xmm12,%xmm12
+vpsrlq $25,%xmm8,%xmm0
+vpaddq %xmm0,%xmm9,%xmm9
+vpand m25(%rip),%xmm8,%xmm8
+vpsrlq $26,%xmm13,%xmm0
+vpaddq %xmm0,%xmm14,%xmm14
+vpand m26(%rip),%xmm13,%xmm13
+vpsrlq $26,%xmm9,%xmm0
+vpaddq %xmm0,%xmm10,%xmm10
+vpand m26(%rip),%xmm9,%xmm9
+vpsrlq $25,%xmm14,%xmm0
+vpsllq $4,%xmm0,%xmm1
+vpaddq %xmm0,%xmm6,%xmm6
+vpsllq $1,%xmm0,%xmm0
+vpaddq %xmm0,%xmm1,%xmm1
+vpaddq %xmm1,%xmm6,%xmm6
+vpand m25(%rip),%xmm14,%xmm14
+vpsrlq $25,%xmm10,%xmm0
+vpaddq %xmm0,%xmm11,%xmm11
+vpand m25(%rip),%xmm10,%xmm10
+vpsrlq $26,%xmm6,%xmm0
+vpaddq %xmm0,%xmm5,%xmm5
+vpand m26(%rip),%xmm6,%xmm6
+vpunpckhqdq %xmm5,%xmm6,%xmm1
+vpunpcklqdq %xmm5,%xmm6,%xmm0
+vpunpckhqdq %xmm8,%xmm7,%xmm3
+vpunpcklqdq %xmm8,%xmm7,%xmm2
+vpunpckhqdq %xmm10,%xmm9,%xmm5
+vpunpcklqdq %xmm10,%xmm9,%xmm4
+vpunpckhqdq %xmm12,%xmm11,%xmm7
+vpunpcklqdq %xmm12,%xmm11,%xmm6
+vpunpckhqdq %xmm14,%xmm13,%xmm9
+vpunpcklqdq %xmm14,%xmm13,%xmm8
+cmp $0,%rdx
+jne ._ladder_base_loop
+vmovdqu %xmm1,80(%rdi)
+vmovdqu %xmm0,0(%rdi)
+vmovdqu %xmm3,96(%rdi)
+vmovdqu %xmm2,16(%rdi)
+vmovdqu %xmm5,112(%rdi)
+vmovdqu %xmm4,32(%rdi)
+vmovdqu %xmm7,128(%rdi)
+vmovdqu %xmm6,48(%rdi)
+vmovdqu %xmm9,144(%rdi)
+vmovdqu %xmm8,64(%rdi)
+movq 1536(%rsp),%r11
+movq 1544(%rsp),%r12
+movq 1552(%rsp),%r13
+add %r11,%rsp
+ret
+
+#endif
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder_base.h b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder_base.h
new file mode 100644
index 0000000000..a69be13f0d
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder_base.h
@@ -0,0 +1,18 @@
+#ifndef ladder_base_H
+#define ladder_base_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "fe.h"
+#include "ladder_base_namespace.h"
+
+extern void ladder_base(fe *, const unsigned char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef ladder_base_H */
+
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder_base_namespace.h b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder_base_namespace.h
new file mode 100644
index 0000000000..304546a185
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder_base_namespace.h
@@ -0,0 +1,8 @@
+#ifndef ladder_base_namespace_H
+#define ladder_base_namespace_H
+
+#define ladder_base crypto_scalarmult_curve25519_sandy2x_ladder_base
+#define _ladder_base _crypto_scalarmult_curve25519_sandy2x_ladder_base
+
+#endif /* ifndef ladder_base_namespace_H */
+
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder_namespace.h b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder_namespace.h
new file mode 100644
index 0000000000..6637074bec
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/ladder_namespace.h
@@ -0,0 +1,8 @@
+#ifndef ladder_namespace_H
+#define ladder_namespace_H
+
+#define ladder crypto_scalarmult_curve25519_sandy2x_ladder
+#define _ladder _crypto_scalarmult_curve25519_sandy2x_ladder
+
+#endif /* ifndef ladder_namespace_H */
+
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/sandy2x.S b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/sandy2x.S
new file mode 100644
index 0000000000..1fd632057b
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/sandy2x/sandy2x.S
@@ -0,0 +1,17 @@
+
+#ifdef HAVE_AVX_ASM
+
+#define IN_SANDY2X
+
+#include "consts.S"
+#include "fe51_mul.S"
+#include "fe51_nsquare.S"
+#include "fe51_pack.S"
+#include "ladder.S"
+#include "ladder_base.S"
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
+
+#endif
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/scalarmult_curve25519.c b/libs/libsodium/src/crypto_scalarmult/curve25519/scalarmult_curve25519.c
new file mode 100644
index 0000000000..2d3ffc0563
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/scalarmult_curve25519.c
@@ -0,0 +1,59 @@
+
+#include "crypto_scalarmult_curve25519.h"
+#include "private/implementations.h"
+#include "scalarmult_curve25519.h"
+#include "runtime.h"
+
+#ifdef HAVE_AVX_ASM
+# include "sandy2x/curve25519_sandy2x.h"
+#endif
+#include "ref10/x25519_ref10.h"
+static const crypto_scalarmult_curve25519_implementation *implementation =
+ &crypto_scalarmult_curve25519_ref10_implementation;
+
+int
+crypto_scalarmult_curve25519(unsigned char *q, const unsigned char *n,
+ const unsigned char *p)
+{
+ size_t i;
+ volatile unsigned char d = 0;
+
+ if (implementation->mult(q, n, p) != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ for (i = 0; i < crypto_scalarmult_curve25519_BYTES; i++) {
+ d |= q[i];
+ }
+ return -(1 & ((d - 1) >> 8));
+}
+
+int
+crypto_scalarmult_curve25519_base(unsigned char *q, const unsigned char *n)
+{
+ return implementation->mult_base(q, n);
+}
+
+size_t
+crypto_scalarmult_curve25519_bytes(void)
+{
+ return crypto_scalarmult_curve25519_BYTES;
+}
+
+size_t
+crypto_scalarmult_curve25519_scalarbytes(void)
+{
+ return crypto_scalarmult_curve25519_SCALARBYTES;
+}
+
+int
+_crypto_scalarmult_curve25519_pick_best_implementation(void)
+{
+ implementation = &crypto_scalarmult_curve25519_ref10_implementation;
+
+#ifdef HAVE_AVX_ASM
+ if (sodium_runtime_has_avx()) {
+ implementation = &crypto_scalarmult_curve25519_sandy2x_implementation;
+ }
+#endif
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_scalarmult/curve25519/scalarmult_curve25519.h b/libs/libsodium/src/crypto_scalarmult/curve25519/scalarmult_curve25519.h
new file mode 100644
index 0000000000..66edbf6a8a
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/curve25519/scalarmult_curve25519.h
@@ -0,0 +1,11 @@
+
+#ifndef scalarmult_poly1305_H
+#define scalarmult_poly1305_H
+
+typedef struct crypto_scalarmult_curve25519_implementation {
+ int (*mult)(unsigned char *q, const unsigned char *n,
+ const unsigned char *p);
+ int (*mult_base)(unsigned char *q, const unsigned char *n);
+} crypto_scalarmult_curve25519_implementation;
+
+#endif
diff --git a/libs/libsodium/src/crypto_scalarmult/ed25519/ref10/scalarmult_ed25519_ref10.c b/libs/libsodium/src/crypto_scalarmult/ed25519/ref10/scalarmult_ed25519_ref10.c
new file mode 100644
index 0000000000..0e317cf7cc
--- /dev/null
+++ b/libs/libsodium/src/crypto_scalarmult/ed25519/ref10/scalarmult_ed25519_ref10.c
@@ -0,0 +1,86 @@
+
+#include <string.h>
+
+#include "crypto_scalarmult_ed25519.h"
+#include "private/ed25519_ref10.h"
+#include "utils.h"
+
+static int
+_crypto_scalarmult_ed25519_is_inf(const unsigned char s[32])
+{
+ unsigned char c;
+ unsigned int i;
+
+ c = s[0] ^ 0x01;
+ for (i = 1; i < 31; i++) {
+ c |= s[i];
+ }
+ c |= s[31] & 0x7f;
+
+ return ((((unsigned int) c) - 1U) >> 8) & 1;
+}
+
+static inline void
+_crypto_scalarmult_ed25519_clamp(unsigned char k[32])
+{
+ k[0] &= 248;
+ k[31] &= 127;
+ k[31] |= 64;
+}
+
+int
+crypto_scalarmult_ed25519(unsigned char *q, const unsigned char *n,
+ const unsigned char *p)
+{
+ unsigned char *t = q;
+ ge25519_p3 Q;
+ ge25519_p3 P;
+ unsigned int i;
+
+ if (ge25519_is_canonical(p) == 0 || ge25519_has_small_order(p) != 0 ||
+ ge25519_frombytes(&P, p) != 0 || ge25519_is_on_main_subgroup(&P) == 0) {
+ return -1;
+ }
+ for (i = 0; i < 32; ++i) {
+ t[i] = n[i];
+ }
+ _crypto_scalarmult_ed25519_clamp(t);
+ ge25519_scalarmult(&Q, t, &P);
+ ge25519_p3_tobytes(q, &Q);
+ if (_crypto_scalarmult_ed25519_is_inf(q) != 0 || sodium_is_zero(n, 32)) {
+ return -1;
+ }
+ return 0;
+}
+
+int
+crypto_scalarmult_ed25519_base(unsigned char *q,
+ const unsigned char *n)
+{
+ unsigned char *t = q;
+ ge25519_p3 Q;
+ unsigned int i;
+
+ for (i = 0; i < 32; ++i) {
+ t[i] = n[i];
+ }
+ _crypto_scalarmult_ed25519_clamp(t);
+ ge25519_scalarmult_base(&Q, t);
+ ge25519_p3_tobytes(q, &Q);
+ if (sodium_is_zero(n, 32) != 0) {
+ return -1;
+ }
+ return 0;
+}
+
+size_t
+crypto_scalarmult_ed25519_bytes(void)
+{
+ return crypto_scalarmult_ed25519_BYTES;
+}
+
+size_t
+crypto_scalarmult_ed25519_scalarbytes(void)
+{
+ return crypto_scalarmult_ed25519_SCALARBYTES;
+}
diff --git a/libs/libsodium/src/crypto_secretbox/crypto_secretbox.c b/libs/libsodium/src/crypto_secretbox/crypto_secretbox.c
new file mode 100644
index 0000000000..45f678ecdf
--- /dev/null
+++ b/libs/libsodium/src/crypto_secretbox/crypto_secretbox.c
@@ -0,0 +1,67 @@
+
+#include "crypto_secretbox.h"
+#include "randombytes.h"
+
+size_t
+crypto_secretbox_keybytes(void)
+{
+ return crypto_secretbox_KEYBYTES;
+}
+
+size_t
+crypto_secretbox_noncebytes(void)
+{
+ return crypto_secretbox_NONCEBYTES;
+}
+
+size_t
+crypto_secretbox_zerobytes(void)
+{
+ return crypto_secretbox_ZEROBYTES;
+}
+
+size_t
+crypto_secretbox_boxzerobytes(void)
+{
+ return crypto_secretbox_BOXZEROBYTES;
+}
+
+size_t
+crypto_secretbox_macbytes(void)
+{
+ return crypto_secretbox_MACBYTES;
+}
+
+size_t
+crypto_secretbox_messagebytes_max(void)
+{
+ return crypto_secretbox_MESSAGEBYTES_MAX;
+}
+
+const char *
+crypto_secretbox_primitive(void)
+{
+ return crypto_secretbox_PRIMITIVE;
+}
+
+int
+crypto_secretbox(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k)
+{
+ return crypto_secretbox_xsalsa20poly1305(c, m, mlen, n, k);
+}
+
+int
+crypto_secretbox_open(unsigned char *m, const unsigned char *c,
+ unsigned long long clen, const unsigned char *n,
+ const unsigned char *k)
+{
+ return crypto_secretbox_xsalsa20poly1305_open(m, c, clen, n, k);
+}
+
+void
+crypto_secretbox_keygen(unsigned char k[crypto_secretbox_KEYBYTES])
+{
+ randombytes_buf(k, crypto_secretbox_KEYBYTES);
+}
diff --git a/libs/libsodium/src/crypto_secretbox/crypto_secretbox_easy.c b/libs/libsodium/src/crypto_secretbox/crypto_secretbox_easy.c
new file mode 100644
index 0000000000..b1203849f2
--- /dev/null
+++ b/libs/libsodium/src/crypto_secretbox/crypto_secretbox_easy.c
@@ -0,0 +1,144 @@
+
+#include <assert.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "core.h"
+#include "crypto_core_hsalsa20.h"
+#include "crypto_onetimeauth_poly1305.h"
+#include "crypto_secretbox.h"
+#include "crypto_stream_salsa20.h"
+#include "private/common.h"
+#include "utils.h"
+
+int
+crypto_secretbox_detached(unsigned char *c, unsigned char *mac,
+ const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k)
+{
+ crypto_onetimeauth_poly1305_state state;
+ unsigned char block0[64U];
+ unsigned char subkey[crypto_stream_salsa20_KEYBYTES];
+ unsigned long long i;
+ unsigned long long mlen0;
+
+ crypto_core_hsalsa20(subkey, n, k, NULL);
+
+ if (((uintptr_t) c > (uintptr_t) m &&
+ (uintptr_t) c - (uintptr_t) m < mlen) ||
+ ((uintptr_t) m > (uintptr_t) c &&
+ (uintptr_t) m - (uintptr_t) c < mlen)) { /* LCOV_EXCL_LINE */
+ memmove(c, m, mlen);
+ m = c;
+ }
+ memset(block0, 0U, crypto_secretbox_ZEROBYTES);
+ COMPILER_ASSERT(64U >= crypto_secretbox_ZEROBYTES);
+ mlen0 = mlen;
+ if (mlen0 > 64U - crypto_secretbox_ZEROBYTES) {
+ mlen0 = 64U - crypto_secretbox_ZEROBYTES;
+ }
+ for (i = 0U; i < mlen0; i++) {
+ block0[i + crypto_secretbox_ZEROBYTES] = m[i];
+ }
+ crypto_stream_salsa20_xor(block0, block0,
+ mlen0 + crypto_secretbox_ZEROBYTES,
+ n + 16, subkey);
+ COMPILER_ASSERT(crypto_secretbox_ZEROBYTES >=
+ crypto_onetimeauth_poly1305_KEYBYTES);
+ crypto_onetimeauth_poly1305_init(&state, block0);
+
+ for (i = 0U; i < mlen0; i++) {
+ c[i] = block0[crypto_secretbox_ZEROBYTES + i];
+ }
+ sodium_memzero(block0, sizeof block0);
+ if (mlen > mlen0) {
+ crypto_stream_salsa20_xor_ic(c + mlen0, m + mlen0, mlen - mlen0,
+ n + 16, 1U, subkey);
+ }
+ sodium_memzero(subkey, sizeof subkey);
+
+ crypto_onetimeauth_poly1305_update(&state, c, mlen);
+ crypto_onetimeauth_poly1305_final(&state, mac);
+ sodium_memzero(&state, sizeof state);
+
+ return 0;
+}
+
+int
+crypto_secretbox_easy(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k)
+{
+ if (mlen > crypto_secretbox_MESSAGEBYTES_MAX) {
+ sodium_misuse();
+ }
+ return crypto_secretbox_detached(c + crypto_secretbox_MACBYTES,
+ c, m, mlen, n, k);
+}
+
+int
+crypto_secretbox_open_detached(unsigned char *m, const unsigned char *c,
+ const unsigned char *mac,
+ unsigned long long clen,
+ const unsigned char *n,
+ const unsigned char *k)
+{
+ unsigned char block0[64U];
+ unsigned char subkey[crypto_stream_salsa20_KEYBYTES];
+ unsigned long long i;
+ unsigned long long mlen0;
+
+ crypto_core_hsalsa20(subkey, n, k, NULL);
+ crypto_stream_salsa20(block0, crypto_stream_salsa20_KEYBYTES,
+ n + 16, subkey);
+ if (crypto_onetimeauth_poly1305_verify(mac, c, clen, block0) != 0) {
+ sodium_memzero(subkey, sizeof subkey);
+ return -1;
+ }
+ if (m == NULL) {
+ return 0;
+ }
+ if (((uintptr_t) c >= (uintptr_t) m &&
+ (uintptr_t) c - (uintptr_t) m < clen) ||
+ ((uintptr_t) m >= (uintptr_t) c &&
+ (uintptr_t) m - (uintptr_t) c < clen)) { /* LCOV_EXCL_LINE */
+ memmove(m, c, clen);
+ c = m;
+ }
+ mlen0 = clen;
+ if (mlen0 > 64U - crypto_secretbox_ZEROBYTES) {
+ mlen0 = 64U - crypto_secretbox_ZEROBYTES;
+ }
+ for (i = 0U; i < mlen0; i++) {
+ block0[crypto_secretbox_ZEROBYTES + i] = c[i];
+ }
+ crypto_stream_salsa20_xor(block0, block0,
+ crypto_secretbox_ZEROBYTES + mlen0,
+ n + 16, subkey);
+ for (i = 0U; i < mlen0; i++) {
+ m[i] = block0[i + crypto_secretbox_ZEROBYTES];
+ }
+ if (clen > mlen0) {
+ crypto_stream_salsa20_xor_ic(m + mlen0, c + mlen0, clen - mlen0,
+ n + 16, 1U, subkey);
+ }
+ sodium_memzero(subkey, sizeof subkey);
+
+ return 0;
+}
+
+int
+crypto_secretbox_open_easy(unsigned char *m, const unsigned char *c,
+ unsigned long long clen, const unsigned char *n,
+ const unsigned char *k)
+{
+ if (clen < crypto_secretbox_MACBYTES) {
+ return -1;
+ }
+ return crypto_secretbox_open_detached(m, c + crypto_secretbox_MACBYTES, c,
+ clen - crypto_secretbox_MACBYTES,
+ n, k);
+}
diff --git a/libs/libsodium/src/crypto_secretbox/xchacha20poly1305/secretbox_xchacha20poly1305.c b/libs/libsodium/src/crypto_secretbox/xchacha20poly1305/secretbox_xchacha20poly1305.c
new file mode 100644
index 0000000000..e76167d2ee
--- /dev/null
+++ b/libs/libsodium/src/crypto_secretbox/xchacha20poly1305/secretbox_xchacha20poly1305.c
@@ -0,0 +1,177 @@
+
+#include <assert.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "core.h"
+#include "crypto_core_hchacha20.h"
+#include "crypto_onetimeauth_poly1305.h"
+#include "crypto_secretbox_xchacha20poly1305.h"
+#include "crypto_stream_chacha20.h"
+#include "private/common.h"
+#include "utils.h"
+
+#define crypto_secretbox_xchacha20poly1305_ZEROBYTES 32U
+
+int
+crypto_secretbox_xchacha20poly1305_detached(unsigned char *c,
+ unsigned char *mac,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n,
+ const unsigned char *k)
+{
+ crypto_onetimeauth_poly1305_state state;
+ unsigned char block0[64U];
+ unsigned char subkey[crypto_stream_chacha20_KEYBYTES];
+ unsigned long long i;
+ unsigned long long mlen0;
+
+ crypto_core_hchacha20(subkey, n, k, NULL);
+
+ if (((uintptr_t) c > (uintptr_t) m &&
+ (uintptr_t) c - (uintptr_t) m < mlen) ||
+ ((uintptr_t) m > (uintptr_t) c &&
+ (uintptr_t) m - (uintptr_t) c < mlen)) { /* LCOV_EXCL_LINE */
+ memmove(c, m, mlen);
+ m = c;
+ }
+ memset(block0, 0U, crypto_secretbox_xchacha20poly1305_ZEROBYTES);
+ COMPILER_ASSERT(64U >= crypto_secretbox_xchacha20poly1305_ZEROBYTES);
+ mlen0 = mlen;
+ if (mlen0 > 64U - crypto_secretbox_xchacha20poly1305_ZEROBYTES) {
+ mlen0 = 64U - crypto_secretbox_xchacha20poly1305_ZEROBYTES;
+ }
+ for (i = 0U; i < mlen0; i++) {
+ block0[i + crypto_secretbox_xchacha20poly1305_ZEROBYTES] = m[i];
+ }
+ crypto_stream_chacha20_xor(block0, block0,
+ mlen0 + crypto_secretbox_xchacha20poly1305_ZEROBYTES,
+ n + 16, subkey);
+ COMPILER_ASSERT(crypto_secretbox_xchacha20poly1305_ZEROBYTES >=
+ crypto_onetimeauth_poly1305_KEYBYTES);
+ crypto_onetimeauth_poly1305_init(&state, block0);
+
+ for (i = 0U; i < mlen0; i++) {
+ c[i] = block0[crypto_secretbox_xchacha20poly1305_ZEROBYTES + i];
+ }
+ sodium_memzero(block0, sizeof block0);
+ if (mlen > mlen0) {
+ crypto_stream_chacha20_xor_ic(c + mlen0, m + mlen0, mlen - mlen0,
+ n + 16, 1U, subkey);
+ }
+ sodium_memzero(subkey, sizeof subkey);
+
+ crypto_onetimeauth_poly1305_update(&state, c, mlen);
+ crypto_onetimeauth_poly1305_final(&state, mac);
+ sodium_memzero(&state, sizeof state);
+
+ return 0;
+}
+
+int
+crypto_secretbox_xchacha20poly1305_easy(unsigned char *c,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n,
+ const unsigned char *k)
+{
+ if (mlen > crypto_secretbox_xchacha20poly1305_MESSAGEBYTES_MAX) {
+ sodium_misuse();
+ }
+ return crypto_secretbox_xchacha20poly1305_detached
+ (c + crypto_secretbox_xchacha20poly1305_MACBYTES, c, m, mlen, n, k);
+}
+
+int
+crypto_secretbox_xchacha20poly1305_open_detached(unsigned char *m,
+ const unsigned char *c,
+ const unsigned char *mac,
+ unsigned long long clen,
+ const unsigned char *n,
+ const unsigned char *k)
+{
+ unsigned char block0[64U];
+ unsigned char subkey[crypto_stream_chacha20_KEYBYTES];
+ unsigned long long i;
+ unsigned long long mlen0;
+
+ crypto_core_hchacha20(subkey, n, k, NULL);
+ crypto_stream_chacha20(block0, crypto_stream_chacha20_KEYBYTES,
+ n + 16, subkey);
+ if (crypto_onetimeauth_poly1305_verify(mac, c, clen, block0) != 0) {
+ sodium_memzero(subkey, sizeof subkey);
+ return -1;
+ }
+ if (m == NULL) {
+ return 0;
+ }
+ if (((uintptr_t) c >= (uintptr_t) m &&
+ (uintptr_t) c - (uintptr_t) m < clen) ||
+ ((uintptr_t) m >= (uintptr_t) c &&
+ (uintptr_t) m - (uintptr_t) c < clen)) { /* LCOV_EXCL_LINE */
+ memmove(m, c, clen);
+ c = m;
+ }
+ mlen0 = clen;
+ if (mlen0 > 64U - crypto_secretbox_xchacha20poly1305_ZEROBYTES) {
+ mlen0 = 64U - crypto_secretbox_xchacha20poly1305_ZEROBYTES;
+ }
+ for (i = 0U; i < mlen0; i++) {
+ block0[crypto_secretbox_xchacha20poly1305_ZEROBYTES + i] = c[i];
+ }
+ crypto_stream_chacha20_xor(block0, block0,
+ crypto_secretbox_xchacha20poly1305_ZEROBYTES + mlen0,
+ n + 16, subkey);
+ for (i = 0U; i < mlen0; i++) {
+ m[i] = block0[i + crypto_secretbox_xchacha20poly1305_ZEROBYTES];
+ }
+ if (clen > mlen0) {
+ crypto_stream_chacha20_xor_ic(m + mlen0, c + mlen0, clen - mlen0,
+ n + 16, 1U, subkey);
+ }
+ sodium_memzero(subkey, sizeof subkey);
+
+ return 0;
+}
+
+int
+crypto_secretbox_xchacha20poly1305_open_easy(unsigned char *m,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *n,
+ const unsigned char *k)
+{
+ if (clen < crypto_secretbox_xchacha20poly1305_MACBYTES) {
+ return -1;
+ }
+ return crypto_secretbox_xchacha20poly1305_open_detached
+ (m, c + crypto_secretbox_xchacha20poly1305_MACBYTES, c,
+ clen - crypto_secretbox_xchacha20poly1305_MACBYTES, n, k);
+}
+
+size_t
+crypto_secretbox_xchacha20poly1305_keybytes(void)
+{
+ return crypto_secretbox_xchacha20poly1305_KEYBYTES;
+}
+
+size_t
+crypto_secretbox_xchacha20poly1305_noncebytes(void)
+{
+ return crypto_secretbox_xchacha20poly1305_NONCEBYTES;
+}
+
+size_t
+crypto_secretbox_xchacha20poly1305_macbytes(void)
+{
+ return crypto_secretbox_xchacha20poly1305_MACBYTES;
+}
+
+size_t
+crypto_secretbox_xchacha20poly1305_messagebytes_max(void)
+{
+ return crypto_secretbox_xchacha20poly1305_MESSAGEBYTES_MAX;
+}
diff --git a/libs/libsodium/src/crypto_secretbox/xsalsa20poly1305/secretbox_xsalsa20poly1305.c b/libs/libsodium/src/crypto_secretbox/xsalsa20poly1305/secretbox_xsalsa20poly1305.c
new file mode 100644
index 0000000000..7240050dfd
--- /dev/null
+++ b/libs/libsodium/src/crypto_secretbox/xsalsa20poly1305/secretbox_xsalsa20poly1305.c
@@ -0,0 +1,89 @@
+#include "crypto_onetimeauth_poly1305.h"
+#include "crypto_secretbox_xsalsa20poly1305.h"
+#include "crypto_stream_xsalsa20.h"
+#include "randombytes.h"
+
+int
+crypto_secretbox_xsalsa20poly1305(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n,
+ const unsigned char *k)
+{
+ int i;
+
+ if (mlen < 32) {
+ return -1;
+ }
+ crypto_stream_xsalsa20_xor(c, m, mlen, n, k);
+ crypto_onetimeauth_poly1305(c + 16, c + 32, mlen - 32, c);
+ for (i = 0; i < 16; ++i) {
+ c[i] = 0;
+ }
+ return 0;
+}
+
+int
+crypto_secretbox_xsalsa20poly1305_open(unsigned char *m, const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *n,
+ const unsigned char *k)
+{
+ unsigned char subkey[32];
+ int i;
+
+ if (clen < 32) {
+ return -1;
+ }
+ crypto_stream_xsalsa20(subkey, 32, n, k);
+ if (crypto_onetimeauth_poly1305_verify(c + 16, c + 32,
+ clen - 32, subkey) != 0) {
+ return -1;
+ }
+ crypto_stream_xsalsa20_xor(m, c, clen, n, k);
+ for (i = 0; i < 32; ++i) {
+ m[i] = 0;
+ }
+ return 0;
+}
+
+size_t
+crypto_secretbox_xsalsa20poly1305_keybytes(void)
+{
+ return crypto_secretbox_xsalsa20poly1305_KEYBYTES;
+}
+
+size_t
+crypto_secretbox_xsalsa20poly1305_noncebytes(void)
+{
+ return crypto_secretbox_xsalsa20poly1305_NONCEBYTES;
+}
+
+size_t
+crypto_secretbox_xsalsa20poly1305_zerobytes(void)
+{
+ return crypto_secretbox_xsalsa20poly1305_ZEROBYTES;
+}
+
+size_t
+crypto_secretbox_xsalsa20poly1305_boxzerobytes(void)
+{
+ return crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES;
+}
+
+size_t
+crypto_secretbox_xsalsa20poly1305_macbytes(void)
+{
+ return crypto_secretbox_xsalsa20poly1305_MACBYTES;
+}
+
+size_t
+crypto_secretbox_xsalsa20poly1305_messagebytes_max(void)
+{
+ return crypto_secretbox_xsalsa20poly1305_MESSAGEBYTES_MAX;
+}
+
+void
+crypto_secretbox_xsalsa20poly1305_keygen(unsigned char k[crypto_secretbox_xsalsa20poly1305_KEYBYTES])
+{
+ randombytes_buf(k, crypto_secretbox_xsalsa20poly1305_KEYBYTES);
+}
diff --git a/libs/libsodium/src/crypto_secretstream/xchacha20poly1305/secretstream_xchacha20poly1305.c b/libs/libsodium/src/crypto_secretstream/xchacha20poly1305/secretstream_xchacha20poly1305.c
new file mode 100644
index 0000000000..ef000d16c7
--- /dev/null
+++ b/libs/libsodium/src/crypto_secretstream/xchacha20poly1305/secretstream_xchacha20poly1305.c
@@ -0,0 +1,311 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+
+#include "core.h"
+#include "crypto_aead_chacha20poly1305.h"
+#include "crypto_aead_xchacha20poly1305.h"
+#include "crypto_core_hchacha20.h"
+#include "crypto_onetimeauth_poly1305.h"
+#include "crypto_secretstream_xchacha20poly1305.h"
+#include "randombytes.h"
+#include "utils.h"
+
+#include "private/common.h"
+
+#define crypto_secretstream_xchacha20poly1305_COUNTERBYTES 4U
+#define crypto_secretstream_xchacha20poly1305_INONCEBYTES 8U
+
+#define STATE_COUNTER(STATE) ((STATE)->nonce)
+#define STATE_INONCE(STATE) ((STATE)->nonce + \
+ crypto_secretstream_xchacha20poly1305_COUNTERBYTES)
+
+static const unsigned char _pad0[16] = { 0 };
+
+static inline void
+_crypto_secretstream_xchacha20poly1305_counter_reset
+ (crypto_secretstream_xchacha20poly1305_state *state)
+{
+ memset(STATE_COUNTER(state), 0,
+ crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
+ STATE_COUNTER(state)[0] = 1;
+}
+
+void
+crypto_secretstream_xchacha20poly1305_keygen
+ (unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
+{
+ randombytes_buf(k, crypto_secretstream_xchacha20poly1305_KEYBYTES);
+}
+
+int
+crypto_secretstream_xchacha20poly1305_init_push
+ (crypto_secretstream_xchacha20poly1305_state *state,
+ unsigned char out[crypto_secretstream_xchacha20poly1305_HEADERBYTES],
+ const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
+{
+ COMPILER_ASSERT(crypto_secretstream_xchacha20poly1305_HEADERBYTES ==
+ crypto_core_hchacha20_INPUTBYTES +
+ crypto_secretstream_xchacha20poly1305_INONCEBYTES);
+ COMPILER_ASSERT(crypto_secretstream_xchacha20poly1305_HEADERBYTES ==
+ crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
+ COMPILER_ASSERT(sizeof state->nonce ==
+ crypto_secretstream_xchacha20poly1305_INONCEBYTES +
+ crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
+
+ randombytes_buf(out, crypto_secretstream_xchacha20poly1305_HEADERBYTES);
+ crypto_core_hchacha20(state->k, out, k, NULL);
+ _crypto_secretstream_xchacha20poly1305_counter_reset(state);
+ memcpy(STATE_INONCE(state), out + crypto_core_hchacha20_INPUTBYTES,
+ crypto_secretstream_xchacha20poly1305_INONCEBYTES);
+ memset(state->_pad, 0, sizeof state->_pad);
+
+ return 0;
+}
+
+int
+crypto_secretstream_xchacha20poly1305_init_pull
+ (crypto_secretstream_xchacha20poly1305_state *state,
+ const unsigned char in[crypto_secretstream_xchacha20poly1305_HEADERBYTES],
+ const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
+{
+ crypto_core_hchacha20(state->k, in, k, NULL);
+ _crypto_secretstream_xchacha20poly1305_counter_reset(state);
+ memcpy(STATE_INONCE(state), in + crypto_core_hchacha20_INPUTBYTES,
+ crypto_secretstream_xchacha20poly1305_INONCEBYTES);
+ memset(state->_pad, 0, sizeof state->_pad);
+
+ return 0;
+}
+
+void
+crypto_secretstream_xchacha20poly1305_rekey
+ (crypto_secretstream_xchacha20poly1305_state *state)
+{
+ unsigned char new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES +
+ crypto_secretstream_xchacha20poly1305_INONCEBYTES];
+ size_t i;
+
+ for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
+ new_key_and_inonce[i] = state->k[i];
+ }
+ for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
+ new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i] =
+ STATE_INONCE(state)[i];
+ }
+ crypto_stream_chacha20_ietf_xor(new_key_and_inonce, new_key_and_inonce,
+ sizeof new_key_and_inonce,
+ state->nonce, state->k);
+ for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
+ state->k[i] = new_key_and_inonce[i];
+ }
+ for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
+ STATE_INONCE(state)[i] =
+ new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i];
+ }
+ _crypto_secretstream_xchacha20poly1305_counter_reset(state);
+}
+
+int
+crypto_secretstream_xchacha20poly1305_push
+ (crypto_secretstream_xchacha20poly1305_state *state,
+ unsigned char *out, unsigned long long *outlen_p,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *ad, unsigned long long adlen, unsigned char tag)
+{
+ crypto_onetimeauth_poly1305_state poly1305_state;
+ unsigned char block[64U];
+ unsigned char slen[8U];
+ unsigned char *c;
+ unsigned char *mac;
+
+ if (outlen_p != NULL) {
+ *outlen_p = 0U;
+ }
+ if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
+ sodium_misuse();
+ }
+ crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);
+ crypto_onetimeauth_poly1305_init(&poly1305_state, block);
+ sodium_memzero(block, sizeof block);
+
+ crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
+ (0x10 - adlen) & 0xf);
+ memset(block, 0, sizeof block);
+ block[0] = tag;
+
+ crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
+ state->nonce, 1U, state->k);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
+ out[0] = block[0];
+
+ c = out + (sizeof tag);
+ crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, state->nonce, 2U, state->k);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
+ crypto_onetimeauth_poly1305_update
+ (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
+
+ STORE64_LE(slen, (uint64_t) adlen);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
+ STORE64_LE(slen, (sizeof block) + mlen);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
+
+ mac = c + mlen;
+ crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
+ sodium_memzero(&poly1305_state, sizeof poly1305_state);
+
+ COMPILER_ASSERT(crypto_onetimeauth_poly1305_BYTES >=
+ crypto_secretstream_xchacha20poly1305_INONCEBYTES);
+ XOR_BUF(STATE_INONCE(state), mac,
+ crypto_secretstream_xchacha20poly1305_INONCEBYTES);
+ sodium_increment(STATE_COUNTER(state),
+ crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
+ if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
+ sodium_is_zero(STATE_COUNTER(state),
+ crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
+ crypto_secretstream_xchacha20poly1305_rekey(state);
+ }
+ if (outlen_p != NULL) {
+ *outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES + mlen;
+ }
+ return 0;
+}
+
+int
+crypto_secretstream_xchacha20poly1305_pull
+ (crypto_secretstream_xchacha20poly1305_state *state,
+ unsigned char *m, unsigned long long *mlen_p, unsigned char *tag_p,
+ const unsigned char *in, unsigned long long inlen,
+ const unsigned char *ad, unsigned long long adlen)
+{
+ crypto_onetimeauth_poly1305_state poly1305_state;
+ unsigned char block[64U];
+ unsigned char slen[8U];
+ unsigned char mac[crypto_onetimeauth_poly1305_BYTES];
+ const unsigned char *c;
+ const unsigned char *stored_mac;
+ unsigned long long mlen;
+ unsigned char tag;
+
+ if (mlen_p != NULL) {
+ *mlen_p = 0U;
+ }
+ if (tag_p != NULL) {
+ *tag_p = 0xff;
+ }
+ if (inlen < crypto_secretstream_xchacha20poly1305_ABYTES) {
+ return -1;
+ }
+ mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES;
+ if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
+ sodium_misuse();
+ }
+ crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);
+ crypto_onetimeauth_poly1305_init(&poly1305_state, block);
+ sodium_memzero(block, sizeof block);
+
+ crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
+ (0x10 - adlen) & 0xf);
+
+ memset(block, 0, sizeof block);
+ block[0] = in[0];
+ crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
+ state->nonce, 1U, state->k);
+ tag = block[0];
+ block[0] = in[0];
+ crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
+
+ c = in + (sizeof tag);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
+ crypto_onetimeauth_poly1305_update
+ (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
+
+ STORE64_LE(slen, (uint64_t) adlen);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
+ STORE64_LE(slen, (sizeof block) + mlen);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
+
+ crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
+ sodium_memzero(&poly1305_state, sizeof poly1305_state);
+
+ stored_mac = c + mlen;
+ if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) {
+ sodium_memzero(mac, sizeof mac);
+ return -1;
+ }
+
+ crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, state->nonce, 2U, state->k);
+ XOR_BUF(STATE_INONCE(state), mac,
+ crypto_secretstream_xchacha20poly1305_INONCEBYTES);
+ sodium_increment(STATE_COUNTER(state),
+ crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
+ if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
+ sodium_is_zero(STATE_COUNTER(state),
+ crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
+ crypto_secretstream_xchacha20poly1305_rekey(state);
+ }
+ if (mlen_p != NULL) {
+ *mlen_p = mlen;
+ }
+ if (tag_p != NULL) {
+ *tag_p = tag;
+ }
+ return 0;
+}
+
+size_t
+crypto_secretstream_xchacha20poly1305_statebytes(void)
+{
+ return sizeof(crypto_secretstream_xchacha20poly1305_state);
+}
+
+size_t
+crypto_secretstream_xchacha20poly1305_abytes(void)
+{
+ return crypto_secretstream_xchacha20poly1305_ABYTES;
+}
+
+size_t
+crypto_secretstream_xchacha20poly1305_headerbytes(void)
+{
+ return crypto_secretstream_xchacha20poly1305_HEADERBYTES;
+}
+
+size_t
+crypto_secretstream_xchacha20poly1305_keybytes(void)
+{
+ return crypto_secretstream_xchacha20poly1305_KEYBYTES;
+}
+
+size_t
+crypto_secretstream_xchacha20poly1305_messagebytes_max(void)
+{
+ return crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX;
+}
+
+unsigned char
+crypto_secretstream_xchacha20poly1305_tag_message(void)
+{
+ return crypto_secretstream_xchacha20poly1305_TAG_MESSAGE;
+}
+
+unsigned char
+crypto_secretstream_xchacha20poly1305_tag_push(void)
+{
+ return crypto_secretstream_xchacha20poly1305_TAG_PUSH;
+}
+
+unsigned char
+crypto_secretstream_xchacha20poly1305_tag_rekey(void)
+{
+ return crypto_secretstream_xchacha20poly1305_TAG_REKEY;
+}
+
+unsigned char
+crypto_secretstream_xchacha20poly1305_tag_final(void)
+{
+ return crypto_secretstream_xchacha20poly1305_TAG_FINAL;
+}
diff --git a/libs/libsodium/src/crypto_shorthash/crypto_shorthash.c b/libs/libsodium/src/crypto_shorthash/crypto_shorthash.c
new file mode 100644
index 0000000000..95f52f83ba
--- /dev/null
+++ b/libs/libsodium/src/crypto_shorthash/crypto_shorthash.c
@@ -0,0 +1,34 @@
+
+#include "crypto_shorthash.h"
+#include "randombytes.h"
+
+size_t
+crypto_shorthash_bytes(void)
+{
+ return crypto_shorthash_BYTES;
+}
+
+size_t
+crypto_shorthash_keybytes(void)
+{
+ return crypto_shorthash_KEYBYTES;
+}
+
+const char *
+crypto_shorthash_primitive(void)
+{
+ return crypto_shorthash_PRIMITIVE;
+}
+
+int
+crypto_shorthash(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k)
+{
+ return crypto_shorthash_siphash24(out, in, inlen, k);
+}
+
+void
+crypto_shorthash_keygen(unsigned char k[crypto_shorthash_KEYBYTES])
+{
+ randombytes_buf(k, crypto_shorthash_KEYBYTES);
+}
diff --git a/libs/libsodium/src/crypto_shorthash/siphash24/ref/shorthash_siphash24_ref.c b/libs/libsodium/src/crypto_shorthash/siphash24/ref/shorthash_siphash24_ref.c
new file mode 100644
index 0000000000..0c173d4c89
--- /dev/null
+++ b/libs/libsodium/src/crypto_shorthash/siphash24/ref/shorthash_siphash24_ref.c
@@ -0,0 +1,65 @@
+#include "crypto_shorthash_siphash24.h"
+#include "private/common.h"
+#include "shorthash_siphash_ref.h"
+
+int
+crypto_shorthash_siphash24(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k)
+{
+ /* "somepseudorandomlygeneratedbytes" */
+ uint64_t v0 = 0x736f6d6570736575ULL;
+ uint64_t v1 = 0x646f72616e646f6dULL;
+ uint64_t v2 = 0x6c7967656e657261ULL;
+ uint64_t v3 = 0x7465646279746573ULL;
+ uint64_t b;
+ uint64_t k0 = LOAD64_LE(k);
+ uint64_t k1 = LOAD64_LE(k + 8);
+ uint64_t m;
+ const uint8_t *end = in + inlen - (inlen % sizeof(uint64_t));
+ const int left = inlen & 7;
+
+ b = ((uint64_t) inlen) << 56;
+ v3 ^= k1;
+ v2 ^= k0;
+ v1 ^= k1;
+ v0 ^= k0;
+ for (; in != end; in += 8) {
+ m = LOAD64_LE(in);
+ v3 ^= m;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= m;
+ }
+ switch (left) {
+ case 7:
+ b |= ((uint64_t) in[6]) << 48;
+ case 6:
+ b |= ((uint64_t) in[5]) << 40;
+ case 5:
+ b |= ((uint64_t) in[4]) << 32;
+ case 4:
+ b |= ((uint64_t) in[3]) << 24;
+ case 3:
+ b |= ((uint64_t) in[2]) << 16;
+ case 2:
+ b |= ((uint64_t) in[1]) << 8;
+ case 1:
+ b |= ((uint64_t) in[0]);
+ break;
+ case 0:
+ break;
+ }
+ v3 ^= b;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= b;
+ v2 ^= 0xff;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ b = v0 ^ v1 ^ v2 ^ v3;
+ STORE64_LE(out, b);
+
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_shorthash/siphash24/ref/shorthash_siphash_ref.h b/libs/libsodium/src/crypto_shorthash/siphash24/ref/shorthash_siphash_ref.h
new file mode 100644
index 0000000000..3f9a38b510
--- /dev/null
+++ b/libs/libsodium/src/crypto_shorthash/siphash24/ref/shorthash_siphash_ref.h
@@ -0,0 +1,24 @@
+#ifndef shorthash_siphash_H
+#define shorthash_siphash_H
+
+#include "private/common.h"
+
+#define SIPROUND \
+ do { \
+ v0 += v1; \
+ v1 = ROTL64(v1, 13); \
+ v1 ^= v0; \
+ v0 = ROTL64(v0, 32); \
+ v2 += v3; \
+ v3 = ROTL64(v3, 16); \
+ v3 ^= v2; \
+ v0 += v3; \
+ v3 = ROTL64(v3, 21); \
+ v3 ^= v0; \
+ v2 += v1; \
+ v1 = ROTL64(v1, 17); \
+ v1 ^= v2; \
+ v2 = ROTL64(v2, 32); \
+ } while (0)
+
+#endif
diff --git a/libs/libsodium/src/crypto_shorthash/siphash24/ref/shorthash_siphashx24_ref.c b/libs/libsodium/src/crypto_shorthash/siphash24/ref/shorthash_siphashx24_ref.c
new file mode 100644
index 0000000000..20480d0d5f
--- /dev/null
+++ b/libs/libsodium/src/crypto_shorthash/siphash24/ref/shorthash_siphashx24_ref.c
@@ -0,0 +1,71 @@
+#include "crypto_shorthash_siphash24.h"
+#include "private/common.h"
+#include "shorthash_siphash_ref.h"
+
+int
+crypto_shorthash_siphashx24(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k)
+{
+ uint64_t v0 = 0x736f6d6570736575ULL;
+ uint64_t v1 = 0x646f72616e646f83ULL;
+ uint64_t v2 = 0x6c7967656e657261ULL;
+ uint64_t v3 = 0x7465646279746573ULL;
+ uint64_t b;
+ uint64_t k0 = LOAD64_LE(k);
+ uint64_t k1 = LOAD64_LE(k + 8);
+ uint64_t m;
+ const uint8_t *end = in + inlen - (inlen % sizeof(uint64_t));
+ const int left = inlen & 7;
+
+ b = ((uint64_t) inlen) << 56;
+ v3 ^= k1;
+ v2 ^= k0;
+ v1 ^= k1;
+ v0 ^= k0;
+ for (; in != end; in += 8) {
+ m = LOAD64_LE(in);
+ v3 ^= m;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= m;
+ }
+ switch (left) {
+ case 7:
+ b |= ((uint64_t) in[6]) << 48;
+ case 6:
+ b |= ((uint64_t) in[5]) << 40;
+ case 5:
+ b |= ((uint64_t) in[4]) << 32;
+ case 4:
+ b |= ((uint64_t) in[3]) << 24;
+ case 3:
+ b |= ((uint64_t) in[2]) << 16;
+ case 2:
+ b |= ((uint64_t) in[1]) << 8;
+ case 1:
+ b |= ((uint64_t) in[0]);
+ break;
+ case 0:
+ break;
+ }
+ v3 ^= b;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= b;
+ v2 ^= 0xee;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ b = v0 ^ v1 ^ v2 ^ v3;
+ STORE64_LE(out, b);
+ v1 ^= 0xdd;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ b = v0 ^ v1 ^ v2 ^ v3;
+ STORE64_LE(out + 8, b);
+
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_shorthash/siphash24/shorthash_siphash24.c b/libs/libsodium/src/crypto_shorthash/siphash24/shorthash_siphash24.c
new file mode 100644
index 0000000000..e2cea7761e
--- /dev/null
+++ b/libs/libsodium/src/crypto_shorthash/siphash24/shorthash_siphash24.c
@@ -0,0 +1,11 @@
+#include "crypto_shorthash_siphash24.h"
+
+size_t
+crypto_shorthash_siphash24_bytes(void) {
+ return crypto_shorthash_siphash24_BYTES;
+}
+
+size_t
+crypto_shorthash_siphash24_keybytes(void) {
+ return crypto_shorthash_siphash24_KEYBYTES;
+}
diff --git a/libs/libsodium/src/crypto_shorthash/siphash24/shorthash_siphashx24.c b/libs/libsodium/src/crypto_shorthash/siphash24/shorthash_siphashx24.c
new file mode 100644
index 0000000000..2d487dbb6f
--- /dev/null
+++ b/libs/libsodium/src/crypto_shorthash/siphash24/shorthash_siphashx24.c
@@ -0,0 +1,11 @@
+#include "crypto_shorthash_siphash24.h"
+
+size_t
+crypto_shorthash_siphashx24_bytes(void) {
+ return crypto_shorthash_siphashx24_BYTES;
+}
+
+size_t
+crypto_shorthash_siphashx24_keybytes(void) {
+ return crypto_shorthash_siphashx24_KEYBYTES;
+}
diff --git a/libs/libsodium/src/crypto_sign/crypto_sign.c b/libs/libsodium/src/crypto_sign/crypto_sign.c
new file mode 100644
index 0000000000..127072f726
--- /dev/null
+++ b/libs/libsodium/src/crypto_sign/crypto_sign.c
@@ -0,0 +1,115 @@
+
+#include "crypto_sign.h"
+
+size_t
+crypto_sign_statebytes(void)
+{
+ return sizeof(crypto_sign_state);
+}
+
+size_t
+crypto_sign_bytes(void)
+{
+ return crypto_sign_BYTES;
+}
+
+size_t
+crypto_sign_seedbytes(void)
+{
+ return crypto_sign_SEEDBYTES;
+}
+
+size_t
+crypto_sign_publickeybytes(void)
+{
+ return crypto_sign_PUBLICKEYBYTES;
+}
+
+size_t
+crypto_sign_secretkeybytes(void)
+{
+ return crypto_sign_SECRETKEYBYTES;
+}
+
+size_t
+crypto_sign_messagebytes_max(void)
+{
+ return crypto_sign_MESSAGEBYTES_MAX;
+}
+
+const char *
+crypto_sign_primitive(void)
+{
+ return crypto_sign_PRIMITIVE;
+}
+
+int
+crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk,
+ const unsigned char *seed)
+{
+ return crypto_sign_ed25519_seed_keypair(pk, sk, seed);
+}
+
+int
+crypto_sign_keypair(unsigned char *pk, unsigned char *sk)
+{
+ return crypto_sign_ed25519_keypair(pk, sk);
+}
+
+int
+crypto_sign(unsigned char *sm, unsigned long long *smlen_p,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *sk)
+{
+ return crypto_sign_ed25519(sm, smlen_p, m, mlen, sk);
+}
+
+int
+crypto_sign_open(unsigned char *m, unsigned long long *mlen_p,
+ const unsigned char *sm, unsigned long long smlen,
+ const unsigned char *pk)
+{
+ return crypto_sign_ed25519_open(m, mlen_p, sm, smlen, pk);
+}
+
+int
+crypto_sign_detached(unsigned char *sig, unsigned long long *siglen_p,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *sk)
+{
+ return crypto_sign_ed25519_detached(sig, siglen_p, m, mlen, sk);
+}
+
+int
+crypto_sign_verify_detached(const unsigned char *sig, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *pk)
+{
+ return crypto_sign_ed25519_verify_detached(sig, m, mlen, pk);
+}
+
+int
+crypto_sign_init(crypto_sign_state *state)
+{
+ return crypto_sign_ed25519ph_init(state);
+}
+
+int
+crypto_sign_update(crypto_sign_state *state, const unsigned char *m,
+ unsigned long long mlen)
+{
+ return crypto_sign_ed25519ph_update(state, m, mlen);
+}
+
+int
+crypto_sign_final_create(crypto_sign_state *state, unsigned char *sig,
+ unsigned long long *siglen_p, const unsigned char *sk)
+{
+ return crypto_sign_ed25519ph_final_create(state, sig, siglen_p, sk);
+}
+
+int
+crypto_sign_final_verify(crypto_sign_state *state, unsigned char *sig,
+ const unsigned char *pk)
+{
+ return crypto_sign_ed25519ph_final_verify(state, sig, pk);
+}
diff --git a/libs/libsodium/src/crypto_sign/ed25519/ref10/keypair.c b/libs/libsodium/src/crypto_sign/ed25519/ref10/keypair.c
new file mode 100644
index 0000000000..8bf3cec8fd
--- /dev/null
+++ b/libs/libsodium/src/crypto_sign/ed25519/ref10/keypair.c
@@ -0,0 +1,91 @@
+
+#include <string.h>
+
+#include "crypto_hash_sha512.h"
+#include "crypto_scalarmult_curve25519.h"
+#include "crypto_sign_ed25519.h"
+#include "sign_ed25519_ref10.h"
+#include "private/ed25519_ref10.h"
+#include "randombytes.h"
+#include "utils.h"
+
+int
+crypto_sign_ed25519_seed_keypair(unsigned char *pk, unsigned char *sk,
+ const unsigned char *seed)
+{
+ ge25519_p3 A;
+
+#ifdef ED25519_NONDETERMINISTIC
+ memmove(sk, seed, 32);
+#else
+ crypto_hash_sha512(sk, seed, 32);
+#endif
+ sk[0] &= 248;
+ sk[31] &= 127;
+ sk[31] |= 64;
+
+ ge25519_scalarmult_base(&A, sk);
+ ge25519_p3_tobytes(pk, &A);
+
+ memmove(sk, seed, 32);
+ memmove(sk + 32, pk, 32);
+
+ return 0;
+}
+
+int
+crypto_sign_ed25519_keypair(unsigned char *pk, unsigned char *sk)
+{
+ unsigned char seed[32];
+ int ret;
+
+ randombytes_buf(seed, sizeof seed);
+ ret = crypto_sign_ed25519_seed_keypair(pk, sk, seed);
+ sodium_memzero(seed, sizeof seed);
+
+ return ret;
+}
+
+int
+crypto_sign_ed25519_pk_to_curve25519(unsigned char *curve25519_pk,
+ const unsigned char *ed25519_pk)
+{
+ ge25519_p3 A;
+ fe25519 x;
+ fe25519 one_minus_y;
+
+ if (ge25519_has_small_order(ed25519_pk) != 0 ||
+ ge25519_frombytes_negate_vartime(&A, ed25519_pk) != 0 ||
+ ge25519_is_on_main_subgroup(&A) == 0) {
+ return -1;
+ }
+ fe25519_1(one_minus_y);
+ fe25519_sub(one_minus_y, one_minus_y, A.Y);
+ fe25519_invert(one_minus_y, one_minus_y);
+ fe25519_1(x);
+ fe25519_add(x, x, A.Y);
+ fe25519_mul(x, x, one_minus_y);
+ fe25519_tobytes(curve25519_pk, x);
+
+ return 0;
+}
+
+int
+crypto_sign_ed25519_sk_to_curve25519(unsigned char *curve25519_sk,
+ const unsigned char *ed25519_sk)
+{
+ unsigned char h[crypto_hash_sha512_BYTES];
+
+#ifdef ED25519_NONDETERMINISTIC
+ memcpy(h, ed25519_sk, 32);
+#else
+ crypto_hash_sha512(h, ed25519_sk, 32);
+#endif
+ h[0] &= 248;
+ h[31] &= 127;
+ h[31] |= 64;
+ memcpy(curve25519_sk, h, crypto_scalarmult_curve25519_BYTES);
+ sodium_memzero(h, sizeof h);
+
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_sign/ed25519/ref10/obsolete.c b/libs/libsodium/src/crypto_sign/ed25519/ref10/obsolete.c
new file mode 100644
index 0000000000..03440cfa75
--- /dev/null
+++ b/libs/libsodium/src/crypto_sign/ed25519/ref10/obsolete.c
@@ -0,0 +1,116 @@
+
+#include <limits.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "crypto_hash_sha512.h"
+#include "crypto_sign_edwards25519sha512batch.h"
+#include "crypto_verify_32.h"
+#include "private/ed25519_ref10.h"
+#include "randombytes.h"
+#include "utils.h"
+
+int
+crypto_sign_edwards25519sha512batch_keypair(unsigned char *pk,
+ unsigned char *sk)
+{
+ ge25519_p3 A;
+
+ randombytes_buf(sk, 32);
+ crypto_hash_sha512(sk, sk, 32);
+ sk[0] &= 248;
+ sk[31] &= 127;
+ sk[31] |= 64;
+ ge25519_scalarmult_base(&A, sk);
+ ge25519_p3_tobytes(pk, &A);
+
+ return 0;
+}
+
+int
+crypto_sign_edwards25519sha512batch(unsigned char *sm,
+ unsigned long long *smlen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *sk)
+{
+ crypto_hash_sha512_state hs;
+ unsigned char nonce[64];
+ unsigned char hram[64];
+ unsigned char sig[64];
+ ge25519_p3 A;
+ ge25519_p3 R;
+
+ crypto_hash_sha512_init(&hs);
+ crypto_hash_sha512_update(&hs, sk + 32, 32);
+ crypto_hash_sha512_update(&hs, m, mlen);
+ crypto_hash_sha512_final(&hs, nonce);
+ ge25519_scalarmult_base(&A, sk);
+ ge25519_p3_tobytes(sig + 32, &A);
+ sc25519_reduce(nonce);
+ ge25519_scalarmult_base(&R, nonce);
+ ge25519_p3_tobytes(sig, &R);
+ crypto_hash_sha512_init(&hs);
+ crypto_hash_sha512_update(&hs, sig, 32);
+ crypto_hash_sha512_update(&hs, m, mlen);
+ crypto_hash_sha512_final(&hs, hram);
+ sc25519_reduce(hram);
+ sc25519_muladd(sig + 32, hram, nonce, sk);
+ sodium_memzero(hram, sizeof hram);
+ memmove(sm + 32, m, (size_t) mlen);
+ memcpy(sm, sig, 32);
+ memcpy(sm + 32 + mlen, sig + 32, 32);
+ *smlen_p = mlen + 64U;
+
+ return 0;
+}
+
+int
+crypto_sign_edwards25519sha512batch_open(unsigned char *m,
+ unsigned long long *mlen_p,
+ const unsigned char *sm,
+ unsigned long long smlen,
+ const unsigned char *pk)
+{
+ unsigned char h[64];
+ unsigned char t1[32], t2[32];
+ unsigned long long mlen;
+ ge25519_cached Ai;
+ ge25519_p1p1 csa;
+ ge25519_p2 cs;
+ ge25519_p3 A;
+ ge25519_p3 R;
+ ge25519_p3 cs3;
+
+ *mlen_p = 0;
+ if (smlen < 64 || smlen - 64 > crypto_sign_edwards25519sha512batch_MESSAGEBYTES_MAX) {
+ return -1;
+ }
+ mlen = smlen - 64;
+ if (sm[smlen - 1] & 224) {
+ return -1;
+ }
+ if (ge25519_has_small_order(pk) != 0 ||
+ ge25519_frombytes_negate_vartime(&A, pk) != 0 ||
+ ge25519_has_small_order(sm) != 0 ||
+ ge25519_frombytes_negate_vartime(&R, sm) != 0) {
+ return -1;
+ }
+ ge25519_p3_to_cached(&Ai, &A);
+ crypto_hash_sha512(h, sm, mlen + 32);
+ sc25519_reduce(h);
+ ge25519_scalarmult(&cs3, h, &R);
+ ge25519_add(&csa, &cs3, &Ai);
+ ge25519_p1p1_to_p2(&cs, &csa);
+ ge25519_tobytes(t1, &cs);
+ t1[31] ^= 1 << 7;
+ ge25519_scalarmult_base(&R, sm + 32 + mlen);
+ ge25519_p3_tobytes(t2, &R);
+ if (crypto_verify_32(t1, t2) != 0) {
+ return -1;
+ }
+ *mlen_p = mlen;
+ memmove(m, sm + 32, mlen);
+
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_sign/ed25519/ref10/open.c b/libs/libsodium/src/crypto_sign/ed25519/ref10/open.c
new file mode 100644
index 0000000000..c9e8843c1e
--- /dev/null
+++ b/libs/libsodium/src/crypto_sign/ed25519/ref10/open.c
@@ -0,0 +1,93 @@
+
+#include <limits.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "crypto_hash_sha512.h"
+#include "crypto_sign_ed25519.h"
+#include "crypto_verify_32.h"
+#include "sign_ed25519_ref10.h"
+#include "private/ed25519_ref10.h"
+#include "utils.h"
+
+int
+_crypto_sign_ed25519_verify_detached(const unsigned char *sig,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *pk,
+ int prehashed)
+{
+ crypto_hash_sha512_state hs;
+ unsigned char h[64];
+ unsigned char rcheck[32];
+ ge25519_p3 A;
+ ge25519_p2 R;
+
+#ifndef ED25519_COMPAT
+ if (sc25519_is_canonical(sig + 32) == 0 ||
+ ge25519_has_small_order(sig) != 0) {
+ return -1;
+ }
+ if (ge25519_is_canonical(pk) == 0) {
+ return -1;
+ }
+#else
+ if (sig[63] & 224) {
+ return -1;
+ }
+#endif
+ if (ge25519_has_small_order(pk) != 0 ||
+ ge25519_frombytes_negate_vartime(&A, pk) != 0) {
+ return -1;
+ }
+ _crypto_sign_ed25519_ref10_hinit(&hs, prehashed);
+ crypto_hash_sha512_update(&hs, sig, 32);
+ crypto_hash_sha512_update(&hs, pk, 32);
+ crypto_hash_sha512_update(&hs, m, mlen);
+ crypto_hash_sha512_final(&hs, h);
+ sc25519_reduce(h);
+
+ ge25519_double_scalarmult_vartime(&R, h, &A, sig + 32);
+ ge25519_tobytes(rcheck, &R);
+
+ return crypto_verify_32(rcheck, sig) | (-(rcheck == sig)) |
+ sodium_memcmp(sig, rcheck, 32);
+}
+
+int
+crypto_sign_ed25519_verify_detached(const unsigned char *sig,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *pk)
+{
+ return _crypto_sign_ed25519_verify_detached(sig, m, mlen, pk, 0);
+}
+
+int
+crypto_sign_ed25519_open(unsigned char *m, unsigned long long *mlen_p,
+ const unsigned char *sm, unsigned long long smlen,
+ const unsigned char *pk)
+{
+ unsigned long long mlen;
+
+ if (smlen < 64 || smlen - 64 > crypto_sign_ed25519_MESSAGEBYTES_MAX) {
+ goto badsig;
+ }
+ mlen = smlen - 64;
+ if (crypto_sign_ed25519_verify_detached(sm, sm + 64, mlen, pk) != 0) {
+ memset(m, 0, mlen);
+ goto badsig;
+ }
+ if (mlen_p != NULL) {
+ *mlen_p = mlen;
+ }
+ memmove(m, sm + 64, mlen);
+
+ return 0;
+
+badsig:
+ if (mlen_p != NULL) {
+ *mlen_p = 0;
+ }
+ return -1;
+}
diff --git a/libs/libsodium/src/crypto_sign/ed25519/ref10/sign.c b/libs/libsodium/src/crypto_sign/ed25519/ref10/sign.c
new file mode 100644
index 0000000000..4df90bddd9
--- /dev/null
+++ b/libs/libsodium/src/crypto_sign/ed25519/ref10/sign.c
@@ -0,0 +1,144 @@
+
+#include <string.h>
+
+#include "crypto_hash_sha512.h"
+#include "crypto_sign_ed25519.h"
+#include "sign_ed25519_ref10.h"
+#include "private/ed25519_ref10.h"
+#include "randombytes.h"
+#include "utils.h"
+
+void
+_crypto_sign_ed25519_ref10_hinit(crypto_hash_sha512_state *hs, int prehashed)
+{
+ static const unsigned char DOM2PREFIX[32 + 2] = {
+ 'S', 'i', 'g', 'E', 'd', '2', '5', '5', '1', '9', ' ',
+ 'n', 'o', ' ',
+ 'E', 'd', '2', '5', '5', '1', '9', ' ',
+ 'c', 'o', 'l', 'l', 'i', 's', 'i', 'o', 'n', 's', 1, 0
+ };
+
+ crypto_hash_sha512_init(hs);
+ if (prehashed) {
+ crypto_hash_sha512_update(hs, DOM2PREFIX, sizeof DOM2PREFIX);
+ }
+}
+
+static inline void
+_crypto_sign_ed25519_clamp(unsigned char k[32])
+{
+ k[0] &= 248;
+ k[31] &= 127;
+ k[31] |= 64;
+}
+
+#ifdef ED25519_NONDETERMINISTIC
+/* r = hash(B || empty_labelset || Z || pad1 || k || pad2 || empty_labelset || K || extra || M) (mod q) */
+static void
+_crypto_sign_ed25519_synthetic_r_hv(crypto_hash_sha512_state *hs,
+ unsigned char Z[32],
+ const unsigned char sk[64])
+{
+ static const unsigned char B[32] = {
+ 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ };
+ static const unsigned char zeros[128] = { 0x00 };
+ static const unsigned char empty_labelset[3] = { 0x02, 0x00, 0x00 };
+
+ crypto_hash_sha512_update(hs, B, 32);
+ crypto_hash_sha512_update(hs, empty_labelset, 3);
+ randombytes_buf(Z, 32);
+ crypto_hash_sha512_update(hs, Z, 32);
+ crypto_hash_sha512_update(hs, zeros, 128 - (32 + 3 + 32) % 128);
+ crypto_hash_sha512_update(hs, sk, 32);
+ crypto_hash_sha512_update(hs, zeros, 128 - 32 % 128);
+ crypto_hash_sha512_update(hs, empty_labelset, 3);
+ crypto_hash_sha512_update(hs, sk + 32, 32);
+ /* empty extra */
+}
+#endif
+
+int
+_crypto_sign_ed25519_detached(unsigned char *sig, unsigned long long *siglen_p,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *sk, int prehashed)
+{
+ crypto_hash_sha512_state hs;
+ unsigned char az[64];
+ unsigned char nonce[64];
+ unsigned char hram[64];
+ ge25519_p3 R;
+
+ _crypto_sign_ed25519_ref10_hinit(&hs, prehashed);
+
+#ifdef ED25519_NONDETERMINISTIC
+ memcpy(az, sk, 32);
+ _crypto_sign_ed25519_synthetic_r_hv(&hs, nonce, az);
+#else
+ crypto_hash_sha512(az, sk, 32);
+ crypto_hash_sha512_update(&hs, az + 32, 32);
+#endif
+
+ crypto_hash_sha512_update(&hs, m, mlen);
+ crypto_hash_sha512_final(&hs, nonce);
+
+ memmove(sig + 32, sk + 32, 32);
+
+ sc25519_reduce(nonce);
+ ge25519_scalarmult_base(&R, nonce);
+ ge25519_p3_tobytes(sig, &R);
+
+ _crypto_sign_ed25519_ref10_hinit(&hs, prehashed);
+ crypto_hash_sha512_update(&hs, sig, 64);
+ crypto_hash_sha512_update(&hs, m, mlen);
+ crypto_hash_sha512_final(&hs, hram);
+
+ sc25519_reduce(hram);
+ _crypto_sign_ed25519_clamp(az);
+ sc25519_muladd(sig + 32, hram, az, nonce);
+
+ sodium_memzero(az, sizeof az);
+ sodium_memzero(nonce, sizeof nonce);
+
+ if (siglen_p != NULL) {
+ *siglen_p = 64U;
+ }
+ return 0;
+}
+
+int
+crypto_sign_ed25519_detached(unsigned char *sig, unsigned long long *siglen_p,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *sk)
+{
+ return _crypto_sign_ed25519_detached(sig, siglen_p, m, mlen, sk, 0);
+}
+
+int
+crypto_sign_ed25519(unsigned char *sm, unsigned long long *smlen_p,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *sk)
+{
+ unsigned long long siglen;
+
+ memmove(sm + crypto_sign_ed25519_BYTES, m, mlen);
+ /* LCOV_EXCL_START */
+ if (crypto_sign_ed25519_detached(
+ sm, &siglen, sm + crypto_sign_ed25519_BYTES, mlen, sk) != 0 ||
+ siglen != crypto_sign_ed25519_BYTES) {
+ if (smlen_p != NULL) {
+ *smlen_p = 0;
+ }
+ memset(sm, 0, mlen + crypto_sign_ed25519_BYTES);
+ return -1;
+ }
+ /* LCOV_EXCL_STOP */
+
+ if (smlen_p != NULL) {
+ *smlen_p = mlen + siglen;
+ }
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_sign/ed25519/ref10/sign_ed25519_ref10.h b/libs/libsodium/src/crypto_sign/ed25519/ref10/sign_ed25519_ref10.h
new file mode 100644
index 0000000000..29f45a8544
--- /dev/null
+++ b/libs/libsodium/src/crypto_sign/ed25519/ref10/sign_ed25519_ref10.h
@@ -0,0 +1,18 @@
+#ifndef sign_ed25519_ref10_H
+#define sign_ed25519_ref10_H
+
+void _crypto_sign_ed25519_ref10_hinit(crypto_hash_sha512_state *hs,
+ int prehashed);
+
+int _crypto_sign_ed25519_detached(unsigned char *sig,
+ unsigned long long *siglen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *sk, int prehashed);
+
+int _crypto_sign_ed25519_verify_detached(const unsigned char *sig,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *pk,
+ int prehashed);
+#endif
diff --git a/libs/libsodium/src/crypto_sign/ed25519/sign_ed25519.c b/libs/libsodium/src/crypto_sign/ed25519/sign_ed25519.c
new file mode 100644
index 0000000000..8a69513ede
--- /dev/null
+++ b/libs/libsodium/src/crypto_sign/ed25519/sign_ed25519.c
@@ -0,0 +1,97 @@
+
+#include <string.h>
+
+#include "crypto_hash_sha512.h"
+#include "crypto_sign_ed25519.h"
+#include "ref10/sign_ed25519_ref10.h"
+
+size_t
+crypto_sign_ed25519ph_statebytes(void)
+{
+ return sizeof(crypto_sign_ed25519ph_state);
+}
+
+size_t
+crypto_sign_ed25519_bytes(void)
+{
+ return crypto_sign_ed25519_BYTES;
+}
+
+size_t
+crypto_sign_ed25519_seedbytes(void)
+{
+ return crypto_sign_ed25519_SEEDBYTES;
+}
+
+size_t
+crypto_sign_ed25519_publickeybytes(void)
+{
+ return crypto_sign_ed25519_PUBLICKEYBYTES;
+}
+
+size_t
+crypto_sign_ed25519_secretkeybytes(void)
+{
+ return crypto_sign_ed25519_SECRETKEYBYTES;
+}
+
+size_t
+crypto_sign_ed25519_messagebytes_max(void)
+{
+ return crypto_sign_ed25519_MESSAGEBYTES_MAX;
+}
+
+int
+crypto_sign_ed25519_sk_to_seed(unsigned char *seed, const unsigned char *sk)
+{
+ memmove(seed, sk, crypto_sign_ed25519_SEEDBYTES);
+
+ return 0;
+}
+
+int
+crypto_sign_ed25519_sk_to_pk(unsigned char *pk, const unsigned char *sk)
+{
+ memmove(pk, sk + crypto_sign_ed25519_SEEDBYTES,
+ crypto_sign_ed25519_PUBLICKEYBYTES);
+ return 0;
+}
+
+int
+crypto_sign_ed25519ph_init(crypto_sign_ed25519ph_state *state)
+{
+ crypto_hash_sha512_init(&state->hs);
+ return 0;
+}
+
+int
+crypto_sign_ed25519ph_update(crypto_sign_ed25519ph_state *state,
+ const unsigned char *m, unsigned long long mlen)
+{
+ return crypto_hash_sha512_update(&state->hs, m, mlen);
+}
+
+int
+crypto_sign_ed25519ph_final_create(crypto_sign_ed25519ph_state *state,
+ unsigned char *sig,
+ unsigned long long *siglen_p,
+ const unsigned char *sk)
+{
+ unsigned char ph[crypto_hash_sha512_BYTES];
+
+ crypto_hash_sha512_final(&state->hs, ph);
+
+ return _crypto_sign_ed25519_detached(sig, siglen_p, ph, sizeof ph, sk, 1);
+}
+
+int
+crypto_sign_ed25519ph_final_verify(crypto_sign_ed25519ph_state *state,
+ unsigned char *sig,
+ const unsigned char *pk)
+{
+ unsigned char ph[crypto_hash_sha512_BYTES];
+
+ crypto_hash_sha512_final(&state->hs, ph);
+
+ return _crypto_sign_ed25519_verify_detached(sig, ph, sizeof ph, pk, 1);
+}
diff --git a/libs/libsodium/src/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-avx2.c b/libs/libsodium/src/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-avx2.c
new file mode 100644
index 0000000000..6149af3942
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-avx2.c
@@ -0,0 +1,180 @@
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "core.h"
+#include "crypto_stream_chacha20.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+#include "utils.h"
+
+#if defined(HAVE_AVX2INTRIN_H) && defined(HAVE_EMMINTRIN_H) && \
+ defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# pragma GCC target("ssse3")
+# pragma GCC target("sse4.1")
+# pragma GCC target("avx2")
+# endif
+
+# include <emmintrin.h>
+# include <immintrin.h>
+# include <smmintrin.h>
+# include <tmmintrin.h>
+
+# include "../stream_chacha20.h"
+# include "chacha20_dolbeau-avx2.h"
+
+# define ROUNDS 20
+
+typedef struct chacha_ctx {
+ uint32_t input[16];
+} chacha_ctx;
+
+static void
+chacha_keysetup(chacha_ctx *ctx, const uint8_t *k)
+{
+ ctx->input[0] = 0x61707865;
+ ctx->input[1] = 0x3320646e;
+ ctx->input[2] = 0x79622d32;
+ ctx->input[3] = 0x6b206574;
+ ctx->input[4] = LOAD32_LE(k + 0);
+ ctx->input[5] = LOAD32_LE(k + 4);
+ ctx->input[6] = LOAD32_LE(k + 8);
+ ctx->input[7] = LOAD32_LE(k + 12);
+ ctx->input[8] = LOAD32_LE(k + 16);
+ ctx->input[9] = LOAD32_LE(k + 20);
+ ctx->input[10] = LOAD32_LE(k + 24);
+ ctx->input[11] = LOAD32_LE(k + 28);
+}
+
+static void
+chacha_ivsetup(chacha_ctx *ctx, const uint8_t *iv, const uint8_t *counter)
+{
+ ctx->input[12] = counter == NULL ? 0 : LOAD32_LE(counter + 0);
+ ctx->input[13] = counter == NULL ? 0 : LOAD32_LE(counter + 4);
+ ctx->input[14] = LOAD32_LE(iv + 0);
+ ctx->input[15] = LOAD32_LE(iv + 4);
+}
+
+static void
+chacha_ietf_ivsetup(chacha_ctx *ctx, const uint8_t *iv, const uint8_t *counter)
+{
+ ctx->input[12] = counter == NULL ? 0 : LOAD32_LE(counter);
+ ctx->input[13] = LOAD32_LE(iv + 0);
+ ctx->input[14] = LOAD32_LE(iv + 4);
+ ctx->input[15] = LOAD32_LE(iv + 8);
+}
+
+static void
+chacha20_encrypt_bytes(chacha_ctx *ctx, const uint8_t *m, uint8_t *c,
+ unsigned long long bytes)
+{
+ uint32_t * const x = &ctx->input[0];
+
+ if (!bytes) {
+ return; /* LCOV_EXCL_LINE */
+ }
+ if (bytes > crypto_stream_chacha20_MESSAGEBYTES_MAX) {
+ sodium_misuse();
+ }
+# include "u8.h"
+# include "u4.h"
+# include "u1.h"
+# include "u0.h"
+}
+
+static int
+stream_ref(unsigned char *c, unsigned long long clen, const unsigned char *n,
+ const unsigned char *k)
+{
+ struct chacha_ctx ctx;
+
+ if (!clen) {
+ return 0;
+ }
+ COMPILER_ASSERT(crypto_stream_chacha20_KEYBYTES == 256 / 8);
+ chacha_keysetup(&ctx, k);
+ chacha_ivsetup(&ctx, n, NULL);
+ memset(c, 0, clen);
+ chacha20_encrypt_bytes(&ctx, c, c, clen);
+ sodium_memzero(&ctx, sizeof ctx);
+
+ return 0;
+}
+
+static int
+stream_ietf_ref(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k)
+{
+ struct chacha_ctx ctx;
+
+ if (!clen) {
+ return 0;
+ }
+ COMPILER_ASSERT(crypto_stream_chacha20_KEYBYTES == 256 / 8);
+ chacha_keysetup(&ctx, k);
+ chacha_ietf_ivsetup(&ctx, n, NULL);
+ memset(c, 0, clen);
+ chacha20_encrypt_bytes(&ctx, c, c, clen);
+ sodium_memzero(&ctx, sizeof ctx);
+
+ return 0;
+}
+
+static int
+stream_ref_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n, uint64_t ic,
+ const unsigned char *k)
+{
+ struct chacha_ctx ctx;
+ uint8_t ic_bytes[8];
+ uint32_t ic_high;
+ uint32_t ic_low;
+
+ if (!mlen) {
+ return 0;
+ }
+ ic_high = (uint32_t) (ic >> 32);
+ ic_low = (uint32_t) ic;
+ STORE32_LE(&ic_bytes[0], ic_low);
+ STORE32_LE(&ic_bytes[4], ic_high);
+ chacha_keysetup(&ctx, k);
+ chacha_ivsetup(&ctx, n, ic_bytes);
+ chacha20_encrypt_bytes(&ctx, m, c, mlen);
+ sodium_memzero(&ctx, sizeof ctx);
+
+ return 0;
+}
+
+static int
+stream_ietf_ref_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ uint32_t ic, const unsigned char *k)
+{
+ struct chacha_ctx ctx;
+ uint8_t ic_bytes[4];
+
+ if (!mlen) {
+ return 0;
+ }
+ STORE32_LE(ic_bytes, ic);
+ chacha_keysetup(&ctx, k);
+ chacha_ietf_ivsetup(&ctx, n, ic_bytes);
+ chacha20_encrypt_bytes(&ctx, m, c, mlen);
+ sodium_memzero(&ctx, sizeof ctx);
+
+ return 0;
+}
+
+struct crypto_stream_chacha20_implementation
+ crypto_stream_chacha20_dolbeau_avx2_implementation = {
+ SODIUM_C99(.stream =) stream_ref,
+ SODIUM_C99(.stream_ietf =) stream_ietf_ref,
+ SODIUM_C99(.stream_xor_ic =) stream_ref_xor_ic,
+ SODIUM_C99(.stream_ietf_xor_ic =) stream_ietf_ref_xor_ic
+ };
+
+#endif
diff --git a/libs/libsodium/src/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-avx2.h b/libs/libsodium/src/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-avx2.h
new file mode 100644
index 0000000000..45eb98d797
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-avx2.h
@@ -0,0 +1,8 @@
+
+#include <stdint.h>
+
+#include "../stream_chacha20.h"
+#include "crypto_stream_chacha20.h"
+
+extern struct crypto_stream_chacha20_implementation
+ crypto_stream_chacha20_dolbeau_avx2_implementation;
diff --git a/libs/libsodium/src/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-ssse3.c b/libs/libsodium/src/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-ssse3.c
new file mode 100644
index 0000000000..b7b9aa4ad3
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-ssse3.c
@@ -0,0 +1,174 @@
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "core.h"
+#include "crypto_stream_chacha20.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+#include "utils.h"
+
+#if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# pragma GCC target("ssse3")
+# endif
+
+# include <emmintrin.h>
+# include <tmmintrin.h>
+
+# include "../stream_chacha20.h"
+# include "chacha20_dolbeau-ssse3.h"
+
+# define ROUNDS 20
+
+typedef struct chacha_ctx {
+ uint32_t input[16];
+} chacha_ctx;
+
+static void
+chacha_keysetup(chacha_ctx *ctx, const uint8_t *k)
+{
+ ctx->input[0] = 0x61707865;
+ ctx->input[1] = 0x3320646e;
+ ctx->input[2] = 0x79622d32;
+ ctx->input[3] = 0x6b206574;
+ ctx->input[4] = LOAD32_LE(k + 0);
+ ctx->input[5] = LOAD32_LE(k + 4);
+ ctx->input[6] = LOAD32_LE(k + 8);
+ ctx->input[7] = LOAD32_LE(k + 12);
+ ctx->input[8] = LOAD32_LE(k + 16);
+ ctx->input[9] = LOAD32_LE(k + 20);
+ ctx->input[10] = LOAD32_LE(k + 24);
+ ctx->input[11] = LOAD32_LE(k + 28);
+}
+
+static void
+chacha_ivsetup(chacha_ctx *ctx, const uint8_t *iv, const uint8_t *counter)
+{
+ ctx->input[12] = counter == NULL ? 0 : LOAD32_LE(counter + 0);
+ ctx->input[13] = counter == NULL ? 0 : LOAD32_LE(counter + 4);
+ ctx->input[14] = LOAD32_LE(iv + 0);
+ ctx->input[15] = LOAD32_LE(iv + 4);
+}
+
+static void
+chacha_ietf_ivsetup(chacha_ctx *ctx, const uint8_t *iv, const uint8_t *counter)
+{
+ ctx->input[12] = counter == NULL ? 0 : LOAD32_LE(counter);
+ ctx->input[13] = LOAD32_LE(iv + 0);
+ ctx->input[14] = LOAD32_LE(iv + 4);
+ ctx->input[15] = LOAD32_LE(iv + 8);
+}
+
+static void
+chacha20_encrypt_bytes(chacha_ctx *ctx, const uint8_t *m, uint8_t *c,
+ unsigned long long bytes)
+{
+ uint32_t * const x = &ctx->input[0];
+
+ if (!bytes) {
+ return; /* LCOV_EXCL_LINE */
+ }
+ if (bytes > crypto_stream_chacha20_MESSAGEBYTES_MAX) {
+ sodium_misuse();
+ }
+# include "u4.h"
+# include "u1.h"
+# include "u0.h"
+}
+
+static int
+stream_ref(unsigned char *c, unsigned long long clen, const unsigned char *n,
+ const unsigned char *k)
+{
+ struct chacha_ctx ctx;
+
+ if (!clen) {
+ return 0;
+ }
+ COMPILER_ASSERT(crypto_stream_chacha20_KEYBYTES == 256 / 8);
+ chacha_keysetup(&ctx, k);
+ chacha_ivsetup(&ctx, n, NULL);
+ memset(c, 0, clen);
+ chacha20_encrypt_bytes(&ctx, c, c, clen);
+ sodium_memzero(&ctx, sizeof ctx);
+
+ return 0;
+}
+
+static int
+stream_ietf_ref(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k)
+{
+ struct chacha_ctx ctx;
+
+ if (!clen) {
+ return 0;
+ }
+ COMPILER_ASSERT(crypto_stream_chacha20_KEYBYTES == 256 / 8);
+ chacha_keysetup(&ctx, k);
+ chacha_ietf_ivsetup(&ctx, n, NULL);
+ memset(c, 0, clen);
+ chacha20_encrypt_bytes(&ctx, c, c, clen);
+ sodium_memzero(&ctx, sizeof ctx);
+
+ return 0;
+}
+
+static int
+stream_ref_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n, uint64_t ic,
+ const unsigned char *k)
+{
+ struct chacha_ctx ctx;
+ uint8_t ic_bytes[8];
+ uint32_t ic_high;
+ uint32_t ic_low;
+
+ if (!mlen) {
+ return 0;
+ }
+ ic_high = (uint32_t) (ic >> 32);
+ ic_low = (uint32_t) ic;
+ STORE32_LE(&ic_bytes[0], ic_low);
+ STORE32_LE(&ic_bytes[4], ic_high);
+ chacha_keysetup(&ctx, k);
+ chacha_ivsetup(&ctx, n, ic_bytes);
+ chacha20_encrypt_bytes(&ctx, m, c, mlen);
+ sodium_memzero(&ctx, sizeof ctx);
+
+ return 0;
+}
+
+static int
+stream_ietf_ref_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ uint32_t ic, const unsigned char *k)
+{
+ struct chacha_ctx ctx;
+ uint8_t ic_bytes[4];
+
+ if (!mlen) {
+ return 0;
+ }
+ STORE32_LE(ic_bytes, ic);
+ chacha_keysetup(&ctx, k);
+ chacha_ietf_ivsetup(&ctx, n, ic_bytes);
+ chacha20_encrypt_bytes(&ctx, m, c, mlen);
+ sodium_memzero(&ctx, sizeof ctx);
+
+ return 0;
+}
+
+struct crypto_stream_chacha20_implementation
+ crypto_stream_chacha20_dolbeau_ssse3_implementation = {
+ SODIUM_C99(.stream =) stream_ref,
+ SODIUM_C99(.stream_ietf =) stream_ietf_ref,
+ SODIUM_C99(.stream_xor_ic =) stream_ref_xor_ic,
+ SODIUM_C99(.stream_ietf_xor_ic =) stream_ietf_ref_xor_ic
+ };
+
+#endif
diff --git a/libs/libsodium/src/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-ssse3.h b/libs/libsodium/src/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-ssse3.h
new file mode 100644
index 0000000000..d67630f6a9
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-ssse3.h
@@ -0,0 +1,8 @@
+
+#include <stdint.h>
+
+#include "../stream_chacha20.h"
+#include "crypto_stream_chacha20.h"
+
+extern struct crypto_stream_chacha20_implementation
+ crypto_stream_chacha20_dolbeau_ssse3_implementation;
diff --git a/libs/libsodium/src/crypto_stream/chacha20/dolbeau/u0.h b/libs/libsodium/src/crypto_stream/chacha20/dolbeau/u0.h
new file mode 100644
index 0000000000..17c3ff8e08
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/chacha20/dolbeau/u0.h
@@ -0,0 +1,86 @@
+if (bytes > 0) {
+ __m128i x_0, x_1, x_2, x_3;
+ __m128i t_1;
+ const __m128i rot16 =
+ _mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2);
+ const __m128i rot8 =
+ _mm_set_epi8(14, 13, 12, 15, 10, 9, 8, 11, 6, 5, 4, 7, 2, 1, 0, 3);
+ uint8_t partialblock[64];
+
+ unsigned int i;
+
+ x_0 = _mm_loadu_si128((__m128i*) (x + 0));
+ x_1 = _mm_loadu_si128((__m128i*) (x + 4));
+ x_2 = _mm_loadu_si128((__m128i*) (x + 8));
+ x_3 = _mm_loadu_si128((__m128i*) (x + 12));
+
+ for (i = 0; i < ROUNDS; i += 2) {
+ x_0 = _mm_add_epi32(x_0, x_1);
+ x_3 = _mm_xor_si128(x_3, x_0);
+ x_3 = _mm_shuffle_epi8(x_3, rot16);
+
+ x_2 = _mm_add_epi32(x_2, x_3);
+ x_1 = _mm_xor_si128(x_1, x_2);
+
+ t_1 = x_1;
+ x_1 = _mm_slli_epi32(x_1, 12);
+ t_1 = _mm_srli_epi32(t_1, 20);
+ x_1 = _mm_xor_si128(x_1, t_1);
+
+ x_0 = _mm_add_epi32(x_0, x_1);
+ x_3 = _mm_xor_si128(x_3, x_0);
+ x_0 = _mm_shuffle_epi32(x_0, 0x93);
+ x_3 = _mm_shuffle_epi8(x_3, rot8);
+
+ x_2 = _mm_add_epi32(x_2, x_3);
+ x_3 = _mm_shuffle_epi32(x_3, 0x4e);
+ x_1 = _mm_xor_si128(x_1, x_2);
+ x_2 = _mm_shuffle_epi32(x_2, 0x39);
+
+ t_1 = x_1;
+ x_1 = _mm_slli_epi32(x_1, 7);
+ t_1 = _mm_srli_epi32(t_1, 25);
+ x_1 = _mm_xor_si128(x_1, t_1);
+
+ x_0 = _mm_add_epi32(x_0, x_1);
+ x_3 = _mm_xor_si128(x_3, x_0);
+ x_3 = _mm_shuffle_epi8(x_3, rot16);
+
+ x_2 = _mm_add_epi32(x_2, x_3);
+ x_1 = _mm_xor_si128(x_1, x_2);
+
+ t_1 = x_1;
+ x_1 = _mm_slli_epi32(x_1, 12);
+ t_1 = _mm_srli_epi32(t_1, 20);
+ x_1 = _mm_xor_si128(x_1, t_1);
+
+ x_0 = _mm_add_epi32(x_0, x_1);
+ x_3 = _mm_xor_si128(x_3, x_0);
+ x_0 = _mm_shuffle_epi32(x_0, 0x39);
+ x_3 = _mm_shuffle_epi8(x_3, rot8);
+
+ x_2 = _mm_add_epi32(x_2, x_3);
+ x_3 = _mm_shuffle_epi32(x_3, 0x4e);
+ x_1 = _mm_xor_si128(x_1, x_2);
+ x_2 = _mm_shuffle_epi32(x_2, 0x93);
+
+ t_1 = x_1;
+ x_1 = _mm_slli_epi32(x_1, 7);
+ t_1 = _mm_srli_epi32(t_1, 25);
+ x_1 = _mm_xor_si128(x_1, t_1);
+ }
+ x_0 = _mm_add_epi32(x_0, _mm_loadu_si128((__m128i*) (x + 0)));
+ x_1 = _mm_add_epi32(x_1, _mm_loadu_si128((__m128i*) (x + 4)));
+ x_2 = _mm_add_epi32(x_2, _mm_loadu_si128((__m128i*) (x + 8)));
+ x_3 = _mm_add_epi32(x_3, _mm_loadu_si128((__m128i*) (x + 12)));
+ _mm_storeu_si128((__m128i*) (partialblock + 0), x_0);
+ _mm_storeu_si128((__m128i*) (partialblock + 16), x_1);
+ _mm_storeu_si128((__m128i*) (partialblock + 32), x_2);
+ _mm_storeu_si128((__m128i*) (partialblock + 48), x_3);
+
+ for (i = 0; i < bytes; i++) {
+ c[i] = m[i] ^ partialblock[i];
+ }
+
+ sodium_memzero(partialblock, sizeof partialblock);
+}
diff --git a/libs/libsodium/src/crypto_stream/chacha20/dolbeau/u1.h b/libs/libsodium/src/crypto_stream/chacha20/dolbeau/u1.h
new file mode 100644
index 0000000000..867b44bcf2
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/chacha20/dolbeau/u1.h
@@ -0,0 +1,98 @@
+while (bytes >= 64) {
+ __m128i x_0, x_1, x_2, x_3;
+ __m128i t_1;
+ const __m128i rot16 =
+ _mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2);
+ const __m128i rot8 =
+ _mm_set_epi8(14, 13, 12, 15, 10, 9, 8, 11, 6, 5, 4, 7, 2, 1, 0, 3);
+
+ uint32_t in12;
+ uint32_t in13;
+ int i;
+
+ x_0 = _mm_loadu_si128((__m128i*) (x + 0));
+ x_1 = _mm_loadu_si128((__m128i*) (x + 4));
+ x_2 = _mm_loadu_si128((__m128i*) (x + 8));
+ x_3 = _mm_loadu_si128((__m128i*) (x + 12));
+
+ for (i = 0; i < ROUNDS; i += 2) {
+ x_0 = _mm_add_epi32(x_0, x_1);
+ x_3 = _mm_xor_si128(x_3, x_0);
+ x_3 = _mm_shuffle_epi8(x_3, rot16);
+
+ x_2 = _mm_add_epi32(x_2, x_3);
+ x_1 = _mm_xor_si128(x_1, x_2);
+
+ t_1 = x_1;
+ x_1 = _mm_slli_epi32(x_1, 12);
+ t_1 = _mm_srli_epi32(t_1, 20);
+ x_1 = _mm_xor_si128(x_1, t_1);
+
+ x_0 = _mm_add_epi32(x_0, x_1);
+ x_3 = _mm_xor_si128(x_3, x_0);
+ x_0 = _mm_shuffle_epi32(x_0, 0x93);
+ x_3 = _mm_shuffle_epi8(x_3, rot8);
+
+ x_2 = _mm_add_epi32(x_2, x_3);
+ x_3 = _mm_shuffle_epi32(x_3, 0x4e);
+ x_1 = _mm_xor_si128(x_1, x_2);
+ x_2 = _mm_shuffle_epi32(x_2, 0x39);
+
+ t_1 = x_1;
+ x_1 = _mm_slli_epi32(x_1, 7);
+ t_1 = _mm_srli_epi32(t_1, 25);
+ x_1 = _mm_xor_si128(x_1, t_1);
+
+ x_0 = _mm_add_epi32(x_0, x_1);
+ x_3 = _mm_xor_si128(x_3, x_0);
+ x_3 = _mm_shuffle_epi8(x_3, rot16);
+
+ x_2 = _mm_add_epi32(x_2, x_3);
+ x_1 = _mm_xor_si128(x_1, x_2);
+
+ t_1 = x_1;
+ x_1 = _mm_slli_epi32(x_1, 12);
+ t_1 = _mm_srli_epi32(t_1, 20);
+ x_1 = _mm_xor_si128(x_1, t_1);
+
+ x_0 = _mm_add_epi32(x_0, x_1);
+ x_3 = _mm_xor_si128(x_3, x_0);
+ x_0 = _mm_shuffle_epi32(x_0, 0x39);
+ x_3 = _mm_shuffle_epi8(x_3, rot8);
+
+ x_2 = _mm_add_epi32(x_2, x_3);
+ x_3 = _mm_shuffle_epi32(x_3, 0x4e);
+ x_1 = _mm_xor_si128(x_1, x_2);
+ x_2 = _mm_shuffle_epi32(x_2, 0x93);
+
+ t_1 = x_1;
+ x_1 = _mm_slli_epi32(x_1, 7);
+ t_1 = _mm_srli_epi32(t_1, 25);
+ x_1 = _mm_xor_si128(x_1, t_1);
+ }
+ x_0 = _mm_add_epi32(x_0, _mm_loadu_si128((__m128i*) (x + 0)));
+ x_1 = _mm_add_epi32(x_1, _mm_loadu_si128((__m128i*) (x + 4)));
+ x_2 = _mm_add_epi32(x_2, _mm_loadu_si128((__m128i*) (x + 8)));
+ x_3 = _mm_add_epi32(x_3, _mm_loadu_si128((__m128i*) (x + 12)));
+ x_0 = _mm_xor_si128(x_0, _mm_loadu_si128((__m128i*) (m + 0)));
+ x_1 = _mm_xor_si128(x_1, _mm_loadu_si128((__m128i*) (m + 16)));
+ x_2 = _mm_xor_si128(x_2, _mm_loadu_si128((__m128i*) (m + 32)));
+ x_3 = _mm_xor_si128(x_3, _mm_loadu_si128((__m128i*) (m + 48)));
+ _mm_storeu_si128((__m128i*) (c + 0), x_0);
+ _mm_storeu_si128((__m128i*) (c + 16), x_1);
+ _mm_storeu_si128((__m128i*) (c + 32), x_2);
+ _mm_storeu_si128((__m128i*) (c + 48), x_3);
+
+ in12 = x[12];
+ in13 = x[13];
+ in12++;
+ if (in12 == 0) {
+ in13++;
+ }
+ x[12] = in12;
+ x[13] = in13;
+
+ bytes -= 64;
+ c += 64;
+ m += 64;
+}
diff --git a/libs/libsodium/src/crypto_stream/chacha20/dolbeau/u4.h b/libs/libsodium/src/crypto_stream/chacha20/dolbeau/u4.h
new file mode 100644
index 0000000000..3ff8342609
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/chacha20/dolbeau/u4.h
@@ -0,0 +1,175 @@
+
+#define VEC4_ROT(A, IMM) \
+ _mm_or_si128(_mm_slli_epi32(A, IMM), _mm_srli_epi32(A, (32 - IMM)))
+
+/* same, but replace 2 of the shift/shift/or "rotation" by byte shuffles (8 &
+ * 16) (better) */
+#define VEC4_QUARTERROUND_SHUFFLE(A, B, C, D) \
+ x_##A = _mm_add_epi32(x_##A, x_##B); \
+ t_##A = _mm_xor_si128(x_##D, x_##A); \
+ x_##D = _mm_shuffle_epi8(t_##A, rot16); \
+ x_##C = _mm_add_epi32(x_##C, x_##D); \
+ t_##C = _mm_xor_si128(x_##B, x_##C); \
+ x_##B = VEC4_ROT(t_##C, 12); \
+ x_##A = _mm_add_epi32(x_##A, x_##B); \
+ t_##A = _mm_xor_si128(x_##D, x_##A); \
+ x_##D = _mm_shuffle_epi8(t_##A, rot8); \
+ x_##C = _mm_add_epi32(x_##C, x_##D); \
+ t_##C = _mm_xor_si128(x_##B, x_##C); \
+ x_##B = VEC4_ROT(t_##C, 7)
+
+#define VEC4_QUARTERROUND(A, B, C, D) VEC4_QUARTERROUND_SHUFFLE(A, B, C, D)
+
+if (bytes >= 256) {
+ /* constant for shuffling bytes (replacing multiple-of-8 rotates) */
+ __m128i rot16 =
+ _mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2);
+ __m128i rot8 =
+ _mm_set_epi8(14, 13, 12, 15, 10, 9, 8, 11, 6, 5, 4, 7, 2, 1, 0, 3);
+
+ __m128i x_0 = _mm_set1_epi32(x[0]);
+ __m128i x_1 = _mm_set1_epi32(x[1]);
+ __m128i x_2 = _mm_set1_epi32(x[2]);
+ __m128i x_3 = _mm_set1_epi32(x[3]);
+ __m128i x_4 = _mm_set1_epi32(x[4]);
+ __m128i x_5 = _mm_set1_epi32(x[5]);
+ __m128i x_6 = _mm_set1_epi32(x[6]);
+ __m128i x_7 = _mm_set1_epi32(x[7]);
+ __m128i x_8 = _mm_set1_epi32(x[8]);
+ __m128i x_9 = _mm_set1_epi32(x[9]);
+ __m128i x_10 = _mm_set1_epi32(x[10]);
+ __m128i x_11 = _mm_set1_epi32(x[11]);
+ __m128i x_12;
+ __m128i x_13;
+ __m128i x_14 = _mm_set1_epi32(x[14]);
+ __m128i x_15 = _mm_set1_epi32(x[15]);
+ __m128i orig0 = x_0;
+ __m128i orig1 = x_1;
+ __m128i orig2 = x_2;
+ __m128i orig3 = x_3;
+ __m128i orig4 = x_4;
+ __m128i orig5 = x_5;
+ __m128i orig6 = x_6;
+ __m128i orig7 = x_7;
+ __m128i orig8 = x_8;
+ __m128i orig9 = x_9;
+ __m128i orig10 = x_10;
+ __m128i orig11 = x_11;
+ __m128i orig12;
+ __m128i orig13;
+ __m128i orig14 = x_14;
+ __m128i orig15 = x_15;
+ __m128i t_0, t_1, t_2, t_3, t_4, t_5, t_6, t_7, t_8, t_9, t_10, t_11, t_12,
+ t_13, t_14, t_15;
+
+ uint32_t in12, in13;
+ int i;
+
+ while (bytes >= 256) {
+ const __m128i addv12 = _mm_set_epi64x(1, 0);
+ const __m128i addv13 = _mm_set_epi64x(3, 2);
+ __m128i t12, t13;
+ uint64_t in1213;
+
+ x_0 = orig0;
+ x_1 = orig1;
+ x_2 = orig2;
+ x_3 = orig3;
+ x_4 = orig4;
+ x_5 = orig5;
+ x_6 = orig6;
+ x_7 = orig7;
+ x_8 = orig8;
+ x_9 = orig9;
+ x_10 = orig10;
+ x_11 = orig11;
+ x_14 = orig14;
+ x_15 = orig15;
+
+ in12 = x[12];
+ in13 = x[13];
+ in1213 = ((uint64_t) in12) | (((uint64_t) in13) << 32);
+ t12 = _mm_set1_epi64x(in1213);
+ t13 = _mm_set1_epi64x(in1213);
+
+ x_12 = _mm_add_epi64(addv12, t12);
+ x_13 = _mm_add_epi64(addv13, t13);
+
+ t12 = _mm_unpacklo_epi32(x_12, x_13);
+ t13 = _mm_unpackhi_epi32(x_12, x_13);
+
+ x_12 = _mm_unpacklo_epi32(t12, t13);
+ x_13 = _mm_unpackhi_epi32(t12, t13);
+
+ orig12 = x_12;
+ orig13 = x_13;
+
+ in1213 += 4;
+
+ x[12] = in1213 & 0xFFFFFFFF;
+ x[13] = (in1213 >> 32) & 0xFFFFFFFF;
+
+ for (i = 0; i < ROUNDS; i += 2) {
+ VEC4_QUARTERROUND(0, 4, 8, 12);
+ VEC4_QUARTERROUND(1, 5, 9, 13);
+ VEC4_QUARTERROUND(2, 6, 10, 14);
+ VEC4_QUARTERROUND(3, 7, 11, 15);
+ VEC4_QUARTERROUND(0, 5, 10, 15);
+ VEC4_QUARTERROUND(1, 6, 11, 12);
+ VEC4_QUARTERROUND(2, 7, 8, 13);
+ VEC4_QUARTERROUND(3, 4, 9, 14);
+ }
+
+#define ONEQUAD_TRANSPOSE(A, B, C, D) \
+ { \
+ __m128i t0, t1, t2, t3; \
+ \
+ x_##A = _mm_add_epi32(x_##A, orig##A); \
+ x_##B = _mm_add_epi32(x_##B, orig##B); \
+ x_##C = _mm_add_epi32(x_##C, orig##C); \
+ x_##D = _mm_add_epi32(x_##D, orig##D); \
+ t_##A = _mm_unpacklo_epi32(x_##A, x_##B); \
+ t_##B = _mm_unpacklo_epi32(x_##C, x_##D); \
+ t_##C = _mm_unpackhi_epi32(x_##A, x_##B); \
+ t_##D = _mm_unpackhi_epi32(x_##C, x_##D); \
+ x_##A = _mm_unpacklo_epi64(t_##A, t_##B); \
+ x_##B = _mm_unpackhi_epi64(t_##A, t_##B); \
+ x_##C = _mm_unpacklo_epi64(t_##C, t_##D); \
+ x_##D = _mm_unpackhi_epi64(t_##C, t_##D); \
+ \
+ t0 = _mm_xor_si128(x_##A, _mm_loadu_si128((__m128i*) (m + 0))); \
+ _mm_storeu_si128((__m128i*) (c + 0), t0); \
+ t1 = _mm_xor_si128(x_##B, _mm_loadu_si128((__m128i*) (m + 64))); \
+ _mm_storeu_si128((__m128i*) (c + 64), t1); \
+ t2 = _mm_xor_si128(x_##C, _mm_loadu_si128((__m128i*) (m + 128))); \
+ _mm_storeu_si128((__m128i*) (c + 128), t2); \
+ t3 = _mm_xor_si128(x_##D, _mm_loadu_si128((__m128i*) (m + 192))); \
+ _mm_storeu_si128((__m128i*) (c + 192), t3); \
+ }
+
+#define ONEQUAD(A, B, C, D) ONEQUAD_TRANSPOSE(A, B, C, D)
+
+ ONEQUAD(0, 1, 2, 3);
+ m += 16;
+ c += 16;
+ ONEQUAD(4, 5, 6, 7);
+ m += 16;
+ c += 16;
+ ONEQUAD(8, 9, 10, 11);
+ m += 16;
+ c += 16;
+ ONEQUAD(12, 13, 14, 15);
+ m -= 48;
+ c -= 48;
+
+#undef ONEQUAD
+#undef ONEQUAD_TRANSPOSE
+
+ bytes -= 256;
+ c += 256;
+ m += 256;
+ }
+}
+#undef VEC4_ROT
+#undef VEC4_QUARTERROUND
+#undef VEC4_QUARTERROUND_SHUFFLE
diff --git a/libs/libsodium/src/crypto_stream/chacha20/dolbeau/u8.h b/libs/libsodium/src/crypto_stream/chacha20/dolbeau/u8.h
new file mode 100644
index 0000000000..22bf9fcfa1
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/chacha20/dolbeau/u8.h
@@ -0,0 +1,357 @@
+
+#define VEC8_ROT(A, IMM) \
+ _mm256_or_si256(_mm256_slli_epi32(A, IMM), _mm256_srli_epi32(A, (32 - IMM)))
+
+/* implements a vector quarter round by-the-book (naive!) */
+#define VEC8_QUARTERROUND_NAIVE(A, B, C, D) \
+ x_##A = _mm256_add_epi32(x_##A, x_##B); \
+ t_##A = _mm256_xor_si256(x_##D, x_##A); \
+ x_##D = VEC8_ROT(t_##A, 16); \
+ x_##C = _mm256_add_epi32(x_##C, x_##D); \
+ t_##C = _mm256_xor_si256(x_##B, x_##C); \
+ x_##B = VEC8_ROT(t_##C, 12); \
+ x_##A = _mm256_add_epi32(x_##A, x_##B); \
+ t_##A = _mm256_xor_si256(x_##D, x_##A); \
+ x_##D = VEC8_ROT(t_##A, 8); \
+ x_##C = _mm256_add_epi32(x_##C, x_##D); \
+ t_##C = _mm256_xor_si256(x_##B, x_##C); \
+ x_##B = VEC8_ROT(t_##C, 7)
+
+/* same, but replace 2 of the shift/shift/or "rotation" by byte shuffles (8 &
+ * 16) (better) */
+#define VEC8_QUARTERROUND_SHUFFLE(A, B, C, D) \
+ x_##A = _mm256_add_epi32(x_##A, x_##B); \
+ t_##A = _mm256_xor_si256(x_##D, x_##A); \
+ x_##D = _mm256_shuffle_epi8(t_##A, rot16); \
+ x_##C = _mm256_add_epi32(x_##C, x_##D); \
+ t_##C = _mm256_xor_si256(x_##B, x_##C); \
+ x_##B = VEC8_ROT(t_##C, 12); \
+ x_##A = _mm256_add_epi32(x_##A, x_##B); \
+ t_##A = _mm256_xor_si256(x_##D, x_##A); \
+ x_##D = _mm256_shuffle_epi8(t_##A, rot8); \
+ x_##C = _mm256_add_epi32(x_##C, x_##D); \
+ t_##C = _mm256_xor_si256(x_##B, x_##C); \
+ x_##B = VEC8_ROT(t_##C, 7)
+
+/* same, but replace 2 of the shift/shift/or "rotation" by byte & word shuffles
+ * (8 & 16) (not as good as previous) */
+#define VEC8_QUARTERROUND_SHUFFLE2(A, B, C, D) \
+ x_##A = _mm256_add_epi32(x_##A, x_##B); \
+ t_##A = _mm256_xor_si256(x_##D, x_##A); \
+ x_##D = _mm256_shufflehi_epi16(_mm256_shufflelo_epi16(t_##A, 0xb1), 0xb1); \
+ x_##C = _mm256_add_epi32(x_##C, x_##D); \
+ t_##C = _mm256_xor_si256(x_##B, x_##C); \
+ x_##B = VEC8_ROT(t_##C, 12); \
+ x_##A = _mm256_add_epi32(x_##A, x_##B); \
+ t_##A = _mm256_xor_si256(x_##D, x_##A); \
+ x_##D = _mm256_shuffle_epi8(t_##A, rot8); \
+ x_##C = _mm256_add_epi32(x_##C, x_##D); \
+ t_##C = _mm256_xor_si256(x_##B, x_##C); \
+ x_##B = VEC8_ROT(t_##C, 7)
+
+#define VEC8_QUARTERROUND(A, B, C, D) VEC8_QUARTERROUND_SHUFFLE(A, B, C, D)
+
+#define VEC8_LINE1(A, B, C, D) \
+ x_##A = _mm256_add_epi32(x_##A, x_##B); \
+ x_##D = _mm256_shuffle_epi8(_mm256_xor_si256(x_##D, x_##A), rot16)
+#define VEC8_LINE2(A, B, C, D) \
+ x_##C = _mm256_add_epi32(x_##C, x_##D); \
+ x_##B = VEC8_ROT(_mm256_xor_si256(x_##B, x_##C), 12)
+#define VEC8_LINE3(A, B, C, D) \
+ x_##A = _mm256_add_epi32(x_##A, x_##B); \
+ x_##D = _mm256_shuffle_epi8(_mm256_xor_si256(x_##D, x_##A), rot8)
+#define VEC8_LINE4(A, B, C, D) \
+ x_##C = _mm256_add_epi32(x_##C, x_##D); \
+ x_##B = VEC8_ROT(_mm256_xor_si256(x_##B, x_##C), 7)
+
+#define VEC8_ROUND_SEQ(A1, B1, C1, D1, A2, B2, C2, D2, A3, B3, C3, D3, A4, B4, \
+ C4, D4) \
+ VEC8_LINE1(A1, B1, C1, D1); \
+ VEC8_LINE1(A2, B2, C2, D2); \
+ VEC8_LINE1(A3, B3, C3, D3); \
+ VEC8_LINE1(A4, B4, C4, D4); \
+ VEC8_LINE2(A1, B1, C1, D1); \
+ VEC8_LINE2(A2, B2, C2, D2); \
+ VEC8_LINE2(A3, B3, C3, D3); \
+ VEC8_LINE2(A4, B4, C4, D4); \
+ VEC8_LINE3(A1, B1, C1, D1); \
+ VEC8_LINE3(A2, B2, C2, D2); \
+ VEC8_LINE3(A3, B3, C3, D3); \
+ VEC8_LINE3(A4, B4, C4, D4); \
+ VEC8_LINE4(A1, B1, C1, D1); \
+ VEC8_LINE4(A2, B2, C2, D2); \
+ VEC8_LINE4(A3, B3, C3, D3); \
+ VEC8_LINE4(A4, B4, C4, D4)
+
+#define VEC8_ROUND_HALF(A1, B1, C1, D1, A2, B2, C2, D2, A3, B3, C3, D3, A4, \
+ B4, C4, D4) \
+ VEC8_LINE1(A1, B1, C1, D1); \
+ VEC8_LINE1(A2, B2, C2, D2); \
+ VEC8_LINE2(A1, B1, C1, D1); \
+ VEC8_LINE2(A2, B2, C2, D2); \
+ VEC8_LINE3(A1, B1, C1, D1); \
+ VEC8_LINE3(A2, B2, C2, D2); \
+ VEC8_LINE4(A1, B1, C1, D1); \
+ VEC8_LINE4(A2, B2, C2, D2); \
+ VEC8_LINE1(A3, B3, C3, D3); \
+ VEC8_LINE1(A4, B4, C4, D4); \
+ VEC8_LINE2(A3, B3, C3, D3); \
+ VEC8_LINE2(A4, B4, C4, D4); \
+ VEC8_LINE3(A3, B3, C3, D3); \
+ VEC8_LINE3(A4, B4, C4, D4); \
+ VEC8_LINE4(A3, B3, C3, D3); \
+ VEC8_LINE4(A4, B4, C4, D4)
+
+#define VEC8_ROUND_HALFANDHALF(A1, B1, C1, D1, A2, B2, C2, D2, A3, B3, C3, D3, \
+ A4, B4, C4, D4) \
+ VEC8_LINE1(A1, B1, C1, D1); \
+ VEC8_LINE1(A2, B2, C2, D2); \
+ VEC8_LINE2(A1, B1, C1, D1); \
+ VEC8_LINE2(A2, B2, C2, D2); \
+ VEC8_LINE1(A3, B3, C3, D3); \
+ VEC8_LINE1(A4, B4, C4, D4); \
+ VEC8_LINE2(A3, B3, C3, D3); \
+ VEC8_LINE2(A4, B4, C4, D4); \
+ VEC8_LINE3(A1, B1, C1, D1); \
+ VEC8_LINE3(A2, B2, C2, D2); \
+ VEC8_LINE4(A1, B1, C1, D1); \
+ VEC8_LINE4(A2, B2, C2, D2); \
+ VEC8_LINE3(A3, B3, C3, D3); \
+ VEC8_LINE3(A4, B4, C4, D4); \
+ VEC8_LINE4(A3, B3, C3, D3); \
+ VEC8_LINE4(A4, B4, C4, D4)
+
+#define VEC8_ROUND(A1, B1, C1, D1, A2, B2, C2, D2, A3, B3, C3, D3, A4, B4, C4, \
+ D4) \
+ VEC8_ROUND_SEQ(A1, B1, C1, D1, A2, B2, C2, D2, A3, B3, C3, D3, A4, B4, C4, \
+ D4)
+
+if (bytes >= 512) {
+ /* constant for shuffling bytes (replacing multiple-of-8 rotates) */
+ __m256i rot16 =
+ _mm256_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2,
+ 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2);
+ __m256i rot8 =
+ _mm256_set_epi8(14, 13, 12, 15, 10, 9, 8, 11, 6, 5, 4, 7, 2, 1, 0, 3,
+ 14, 13, 12, 15, 10, 9, 8, 11, 6, 5, 4, 7, 2, 1, 0, 3);
+ uint32_t in12, in13;
+
+ /* the naive way seems as fast (if not a bit faster) than the vector way */
+ __m256i x_0 = _mm256_set1_epi32(x[0]);
+ __m256i x_1 = _mm256_set1_epi32(x[1]);
+ __m256i x_2 = _mm256_set1_epi32(x[2]);
+ __m256i x_3 = _mm256_set1_epi32(x[3]);
+ __m256i x_4 = _mm256_set1_epi32(x[4]);
+ __m256i x_5 = _mm256_set1_epi32(x[5]);
+ __m256i x_6 = _mm256_set1_epi32(x[6]);
+ __m256i x_7 = _mm256_set1_epi32(x[7]);
+ __m256i x_8 = _mm256_set1_epi32(x[8]);
+ __m256i x_9 = _mm256_set1_epi32(x[9]);
+ __m256i x_10 = _mm256_set1_epi32(x[10]);
+ __m256i x_11 = _mm256_set1_epi32(x[11]);
+ __m256i x_12;
+ __m256i x_13;
+ __m256i x_14 = _mm256_set1_epi32(x[14]);
+ __m256i x_15 = _mm256_set1_epi32(x[15]);
+
+ __m256i orig0 = x_0;
+ __m256i orig1 = x_1;
+ __m256i orig2 = x_2;
+ __m256i orig3 = x_3;
+ __m256i orig4 = x_4;
+ __m256i orig5 = x_5;
+ __m256i orig6 = x_6;
+ __m256i orig7 = x_7;
+ __m256i orig8 = x_8;
+ __m256i orig9 = x_9;
+ __m256i orig10 = x_10;
+ __m256i orig11 = x_11;
+ __m256i orig12;
+ __m256i orig13;
+ __m256i orig14 = x_14;
+ __m256i orig15 = x_15;
+ __m256i t_0, t_1, t_2, t_3, t_4, t_5, t_6, t_7, t_8, t_9, t_10, t_11, t_12,
+ t_13, t_14, t_15;
+
+ while (bytes >= 512) {
+ const __m256i addv12 = _mm256_set_epi64x(3, 2, 1, 0);
+ const __m256i addv13 = _mm256_set_epi64x(7, 6, 5, 4);
+ const __m256i permute = _mm256_set_epi32(7, 6, 3, 2, 5, 4, 1, 0);
+ __m256i t12, t13;
+
+ uint64_t in1213;
+ int i;
+
+ x_0 = orig0;
+ x_1 = orig1;
+ x_2 = orig2;
+ x_3 = orig3;
+ x_4 = orig4;
+ x_5 = orig5;
+ x_6 = orig6;
+ x_7 = orig7;
+ x_8 = orig8;
+ x_9 = orig9;
+ x_10 = orig10;
+ x_11 = orig11;
+ x_14 = orig14;
+ x_15 = orig15;
+
+ in12 = x[12];
+ in13 = x[13];
+ in1213 = ((uint64_t) in12) | (((uint64_t) in13) << 32);
+ x_12 = x_13 = _mm256_broadcastq_epi64(_mm_cvtsi64_si128(in1213));
+
+ t12 = _mm256_add_epi64(addv12, x_12);
+ t13 = _mm256_add_epi64(addv13, x_13);
+
+ x_12 = _mm256_unpacklo_epi32(t12, t13);
+ x_13 = _mm256_unpackhi_epi32(t12, t13);
+
+ t12 = _mm256_unpacklo_epi32(x_12, x_13);
+ t13 = _mm256_unpackhi_epi32(x_12, x_13);
+
+ /* required because unpack* are intra-lane */
+ x_12 = _mm256_permutevar8x32_epi32(t12, permute);
+ x_13 = _mm256_permutevar8x32_epi32(t13, permute);
+
+ orig12 = x_12;
+ orig13 = x_13;
+
+ in1213 += 8;
+
+ x[12] = in1213 & 0xFFFFFFFF;
+ x[13] = (in1213 >> 32) & 0xFFFFFFFF;
+
+ for (i = 0; i < ROUNDS; i += 2) {
+ VEC8_ROUND(0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15);
+ VEC8_ROUND(0, 5, 10, 15, 1, 6, 11, 12, 2, 7, 8, 13, 3, 4, 9, 14);
+ }
+
+#define ONEQUAD_TRANSPOSE(A, B, C, D) \
+ { \
+ __m128i t0, t1, t2, t3; \
+ x_##A = _mm256_add_epi32(x_##A, orig##A); \
+ x_##B = _mm256_add_epi32(x_##B, orig##B); \
+ x_##C = _mm256_add_epi32(x_##C, orig##C); \
+ x_##D = _mm256_add_epi32(x_##D, orig##D); \
+ t_##A = _mm256_unpacklo_epi32(x_##A, x_##B); \
+ t_##B = _mm256_unpacklo_epi32(x_##C, x_##D); \
+ t_##C = _mm256_unpackhi_epi32(x_##A, x_##B); \
+ t_##D = _mm256_unpackhi_epi32(x_##C, x_##D); \
+ x_##A = _mm256_unpacklo_epi64(t_##A, t_##B); \
+ x_##B = _mm256_unpackhi_epi64(t_##A, t_##B); \
+ x_##C = _mm256_unpacklo_epi64(t_##C, t_##D); \
+ x_##D = _mm256_unpackhi_epi64(t_##C, t_##D); \
+ t0 = _mm_xor_si128(_mm256_extracti128_si256(x_##A, 0), \
+ _mm_loadu_si128((__m128i*) (m + 0))); \
+ _mm_storeu_si128((__m128i*) (c + 0), t0); \
+ t1 = _mm_xor_si128(_mm256_extracti128_si256(x_##B, 0), \
+ _mm_loadu_si128((__m128i*) (m + 64))); \
+ _mm_storeu_si128((__m128i*) (c + 64), t1); \
+ t2 = _mm_xor_si128(_mm256_extracti128_si256(x_##C, 0), \
+ _mm_loadu_si128((__m128i*) (m + 128))); \
+ _mm_storeu_si128((__m128i*) (c + 128), t2); \
+ t3 = _mm_xor_si128(_mm256_extracti128_si256(x_##D, 0), \
+ _mm_loadu_si128((__m128i*) (m + 192))); \
+ _mm_storeu_si128((__m128i*) (c + 192), t3); \
+ t0 = _mm_xor_si128(_mm256_extracti128_si256(x_##A, 1), \
+ _mm_loadu_si128((__m128i*) (m + 256))); \
+ _mm_storeu_si128((__m128i*) (c + 256), t0); \
+ t1 = _mm_xor_si128(_mm256_extracti128_si256(x_##B, 1), \
+ _mm_loadu_si128((__m128i*) (m + 320))); \
+ _mm_storeu_si128((__m128i*) (c + 320), t1); \
+ t2 = _mm_xor_si128(_mm256_extracti128_si256(x_##C, 1), \
+ _mm_loadu_si128((__m128i*) (m + 384))); \
+ _mm_storeu_si128((__m128i*) (c + 384), t2); \
+ t3 = _mm_xor_si128(_mm256_extracti128_si256(x_##D, 1), \
+ _mm_loadu_si128((__m128i*) (m + 448))); \
+ _mm_storeu_si128((__m128i*) (c + 448), t3); \
+ }
+
+#define ONEQUAD(A, B, C, D) ONEQUAD_TRANSPOSE(A, B, C, D)
+
+#define ONEQUAD_UNPCK(A, B, C, D) \
+ { \
+ x_##A = _mm256_add_epi32(x_##A, orig##A); \
+ x_##B = _mm256_add_epi32(x_##B, orig##B); \
+ x_##C = _mm256_add_epi32(x_##C, orig##C); \
+ x_##D = _mm256_add_epi32(x_##D, orig##D); \
+ t_##A = _mm256_unpacklo_epi32(x_##A, x_##B); \
+ t_##B = _mm256_unpacklo_epi32(x_##C, x_##D); \
+ t_##C = _mm256_unpackhi_epi32(x_##A, x_##B); \
+ t_##D = _mm256_unpackhi_epi32(x_##C, x_##D); \
+ x_##A = _mm256_unpacklo_epi64(t_##A, t_##B); \
+ x_##B = _mm256_unpackhi_epi64(t_##A, t_##B); \
+ x_##C = _mm256_unpacklo_epi64(t_##C, t_##D); \
+ x_##D = _mm256_unpackhi_epi64(t_##C, t_##D); \
+ }
+
+#define ONEOCTO(A, B, C, D, A2, B2, C2, D2) \
+ { \
+ ONEQUAD_UNPCK(A, B, C, D); \
+ ONEQUAD_UNPCK(A2, B2, C2, D2); \
+ t_##A = _mm256_permute2x128_si256(x_##A, x_##A2, 0x20); \
+ t_##A2 = _mm256_permute2x128_si256(x_##A, x_##A2, 0x31); \
+ t_##B = _mm256_permute2x128_si256(x_##B, x_##B2, 0x20); \
+ t_##B2 = _mm256_permute2x128_si256(x_##B, x_##B2, 0x31); \
+ t_##C = _mm256_permute2x128_si256(x_##C, x_##C2, 0x20); \
+ t_##C2 = _mm256_permute2x128_si256(x_##C, x_##C2, 0x31); \
+ t_##D = _mm256_permute2x128_si256(x_##D, x_##D2, 0x20); \
+ t_##D2 = _mm256_permute2x128_si256(x_##D, x_##D2, 0x31); \
+ t_##A = \
+ _mm256_xor_si256(t_##A, _mm256_loadu_si256((__m256i*) (m + 0))); \
+ t_##B = \
+ _mm256_xor_si256(t_##B, _mm256_loadu_si256((__m256i*) (m + 64))); \
+ t_##C = \
+ _mm256_xor_si256(t_##C, _mm256_loadu_si256((__m256i*) (m + 128))); \
+ t_##D = \
+ _mm256_xor_si256(t_##D, _mm256_loadu_si256((__m256i*) (m + 192))); \
+ t_##A2 = _mm256_xor_si256(t_##A2, \
+ _mm256_loadu_si256((__m256i*) (m + 256))); \
+ t_##B2 = _mm256_xor_si256(t_##B2, \
+ _mm256_loadu_si256((__m256i*) (m + 320))); \
+ t_##C2 = _mm256_xor_si256(t_##C2, \
+ _mm256_loadu_si256((__m256i*) (m + 384))); \
+ t_##D2 = _mm256_xor_si256(t_##D2, \
+ _mm256_loadu_si256((__m256i*) (m + 448))); \
+ _mm256_storeu_si256((__m256i*) (c + 0), t_##A); \
+ _mm256_storeu_si256((__m256i*) (c + 64), t_##B); \
+ _mm256_storeu_si256((__m256i*) (c + 128), t_##C); \
+ _mm256_storeu_si256((__m256i*) (c + 192), t_##D); \
+ _mm256_storeu_si256((__m256i*) (c + 256), t_##A2); \
+ _mm256_storeu_si256((__m256i*) (c + 320), t_##B2); \
+ _mm256_storeu_si256((__m256i*) (c + 384), t_##C2); \
+ _mm256_storeu_si256((__m256i*) (c + 448), t_##D2); \
+ }
+
+ ONEOCTO(0, 1, 2, 3, 4, 5, 6, 7);
+ m += 32;
+ c += 32;
+ ONEOCTO(8, 9, 10, 11, 12, 13, 14, 15);
+ m -= 32;
+ c -= 32;
+
+#undef ONEQUAD
+#undef ONEQUAD_TRANSPOSE
+#undef ONEQUAD_UNPCK
+#undef ONEOCTO
+
+ bytes -= 512;
+ c += 512;
+ m += 512;
+ }
+}
+#undef VEC8_ROT
+#undef VEC8_QUARTERROUND
+#undef VEC8_QUARTERROUND_NAIVE
+#undef VEC8_QUARTERROUND_SHUFFLE
+#undef VEC8_QUARTERROUND_SHUFFLE2
+#undef VEC8_LINE1
+#undef VEC8_LINE2
+#undef VEC8_LINE3
+#undef VEC8_LINE4
+#undef VEC8_ROUND
+#undef VEC8_ROUND_SEQ
+#undef VEC8_ROUND_HALF
+#undef VEC8_ROUND_HALFANDHALF
diff --git a/libs/libsodium/src/crypto_stream/chacha20/ref/chacha20_ref.c b/libs/libsodium/src/crypto_stream/chacha20/ref/chacha20_ref.c
new file mode 100644
index 0000000000..f88a99dbdf
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/chacha20/ref/chacha20_ref.c
@@ -0,0 +1,315 @@
+
+/*
+ chacha-merged.c version 20080118
+ D. J. Bernstein
+ Public domain.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "core.h"
+#include "crypto_stream_chacha20.h"
+#include "private/common.h"
+#include "utils.h"
+
+#include "../stream_chacha20.h"
+#include "chacha20_ref.h"
+
+struct chacha_ctx {
+ uint32_t input[16];
+};
+
+typedef struct chacha_ctx chacha_ctx;
+
+#define U32C(v) (v##U)
+
+#define U32V(v) ((uint32_t)(v) &U32C(0xFFFFFFFF))
+
+#define ROTATE(v, c) (ROTL32(v, c))
+#define XOR(v, w) ((v) ^ (w))
+#define PLUS(v, w) (U32V((v) + (w)))
+#define PLUSONE(v) (PLUS((v), 1))
+
+#define QUARTERROUND(a, b, c, d) \
+ a = PLUS(a, b); \
+ d = ROTATE(XOR(d, a), 16); \
+ c = PLUS(c, d); \
+ b = ROTATE(XOR(b, c), 12); \
+ a = PLUS(a, b); \
+ d = ROTATE(XOR(d, a), 8); \
+ c = PLUS(c, d); \
+ b = ROTATE(XOR(b, c), 7);
+
+static void
+chacha_keysetup(chacha_ctx *ctx, const uint8_t *k)
+{
+ ctx->input[0] = U32C(0x61707865);
+ ctx->input[1] = U32C(0x3320646e);
+ ctx->input[2] = U32C(0x79622d32);
+ ctx->input[3] = U32C(0x6b206574);
+ ctx->input[4] = LOAD32_LE(k + 0);
+ ctx->input[5] = LOAD32_LE(k + 4);
+ ctx->input[6] = LOAD32_LE(k + 8);
+ ctx->input[7] = LOAD32_LE(k + 12);
+ ctx->input[8] = LOAD32_LE(k + 16);
+ ctx->input[9] = LOAD32_LE(k + 20);
+ ctx->input[10] = LOAD32_LE(k + 24);
+ ctx->input[11] = LOAD32_LE(k + 28);
+}
+
+static void
+chacha_ivsetup(chacha_ctx *ctx, const uint8_t *iv, const uint8_t *counter)
+{
+ ctx->input[12] = counter == NULL ? 0 : LOAD32_LE(counter + 0);
+ ctx->input[13] = counter == NULL ? 0 : LOAD32_LE(counter + 4);
+ ctx->input[14] = LOAD32_LE(iv + 0);
+ ctx->input[15] = LOAD32_LE(iv + 4);
+}
+
+static void
+chacha_ietf_ivsetup(chacha_ctx *ctx, const uint8_t *iv, const uint8_t *counter)
+{
+ ctx->input[12] = counter == NULL ? 0 : LOAD32_LE(counter);
+ ctx->input[13] = LOAD32_LE(iv + 0);
+ ctx->input[14] = LOAD32_LE(iv + 4);
+ ctx->input[15] = LOAD32_LE(iv + 8);
+}
+
+static void
+chacha20_encrypt_bytes(chacha_ctx *ctx, const uint8_t *m, uint8_t *c,
+ unsigned long long bytes)
+{
+ uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14,
+ x15;
+ uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14,
+ j15;
+ uint8_t *ctarget = NULL;
+ uint8_t tmp[64];
+ unsigned int i;
+
+ if (!bytes) {
+ return; /* LCOV_EXCL_LINE */
+ }
+ if (bytes > crypto_stream_chacha20_MESSAGEBYTES_MAX) {
+ sodium_misuse();
+ }
+ j0 = ctx->input[0];
+ j1 = ctx->input[1];
+ j2 = ctx->input[2];
+ j3 = ctx->input[3];
+ j4 = ctx->input[4];
+ j5 = ctx->input[5];
+ j6 = ctx->input[6];
+ j7 = ctx->input[7];
+ j8 = ctx->input[8];
+ j9 = ctx->input[9];
+ j10 = ctx->input[10];
+ j11 = ctx->input[11];
+ j12 = ctx->input[12];
+ j13 = ctx->input[13];
+ j14 = ctx->input[14];
+ j15 = ctx->input[15];
+
+ for (;;) {
+ if (bytes < 64) {
+ memset(tmp, 0, 64);
+ for (i = 0; i < bytes; ++i) {
+ tmp[i] = m[i];
+ }
+ m = tmp;
+ ctarget = c;
+ c = tmp;
+ }
+ x0 = j0;
+ x1 = j1;
+ x2 = j2;
+ x3 = j3;
+ x4 = j4;
+ x5 = j5;
+ x6 = j6;
+ x7 = j7;
+ x8 = j8;
+ x9 = j9;
+ x10 = j10;
+ x11 = j11;
+ x12 = j12;
+ x13 = j13;
+ x14 = j14;
+ x15 = j15;
+ for (i = 20; i > 0; i -= 2) {
+ QUARTERROUND(x0, x4, x8, x12)
+ QUARTERROUND(x1, x5, x9, x13)
+ QUARTERROUND(x2, x6, x10, x14)
+ QUARTERROUND(x3, x7, x11, x15)
+ QUARTERROUND(x0, x5, x10, x15)
+ QUARTERROUND(x1, x6, x11, x12)
+ QUARTERROUND(x2, x7, x8, x13)
+ QUARTERROUND(x3, x4, x9, x14)
+ }
+ x0 = PLUS(x0, j0);
+ x1 = PLUS(x1, j1);
+ x2 = PLUS(x2, j2);
+ x3 = PLUS(x3, j3);
+ x4 = PLUS(x4, j4);
+ x5 = PLUS(x5, j5);
+ x6 = PLUS(x6, j6);
+ x7 = PLUS(x7, j7);
+ x8 = PLUS(x8, j8);
+ x9 = PLUS(x9, j9);
+ x10 = PLUS(x10, j10);
+ x11 = PLUS(x11, j11);
+ x12 = PLUS(x12, j12);
+ x13 = PLUS(x13, j13);
+ x14 = PLUS(x14, j14);
+ x15 = PLUS(x15, j15);
+
+ x0 = XOR(x0, LOAD32_LE(m + 0));
+ x1 = XOR(x1, LOAD32_LE(m + 4));
+ x2 = XOR(x2, LOAD32_LE(m + 8));
+ x3 = XOR(x3, LOAD32_LE(m + 12));
+ x4 = XOR(x4, LOAD32_LE(m + 16));
+ x5 = XOR(x5, LOAD32_LE(m + 20));
+ x6 = XOR(x6, LOAD32_LE(m + 24));
+ x7 = XOR(x7, LOAD32_LE(m + 28));
+ x8 = XOR(x8, LOAD32_LE(m + 32));
+ x9 = XOR(x9, LOAD32_LE(m + 36));
+ x10 = XOR(x10, LOAD32_LE(m + 40));
+ x11 = XOR(x11, LOAD32_LE(m + 44));
+ x12 = XOR(x12, LOAD32_LE(m + 48));
+ x13 = XOR(x13, LOAD32_LE(m + 52));
+ x14 = XOR(x14, LOAD32_LE(m + 56));
+ x15 = XOR(x15, LOAD32_LE(m + 60));
+
+ j12 = PLUSONE(j12);
+ /* LCOV_EXCL_START */
+ if (!j12) {
+ j13 = PLUSONE(j13);
+ }
+ /* LCOV_EXCL_STOP */
+
+ STORE32_LE(c + 0, x0);
+ STORE32_LE(c + 4, x1);
+ STORE32_LE(c + 8, x2);
+ STORE32_LE(c + 12, x3);
+ STORE32_LE(c + 16, x4);
+ STORE32_LE(c + 20, x5);
+ STORE32_LE(c + 24, x6);
+ STORE32_LE(c + 28, x7);
+ STORE32_LE(c + 32, x8);
+ STORE32_LE(c + 36, x9);
+ STORE32_LE(c + 40, x10);
+ STORE32_LE(c + 44, x11);
+ STORE32_LE(c + 48, x12);
+ STORE32_LE(c + 52, x13);
+ STORE32_LE(c + 56, x14);
+ STORE32_LE(c + 60, x15);
+
+ if (bytes <= 64) {
+ if (bytes < 64) {
+ for (i = 0; i < (unsigned int) bytes; ++i) {
+ ctarget[i] = c[i]; /* ctarget cannot be NULL */
+ }
+ }
+ ctx->input[12] = j12;
+ ctx->input[13] = j13;
+
+ return;
+ }
+ bytes -= 64;
+ c += 64;
+ m += 64;
+ }
+}
+
+static int
+stream_ref(unsigned char *c, unsigned long long clen, const unsigned char *n,
+ const unsigned char *k)
+{
+ struct chacha_ctx ctx;
+
+ if (!clen) {
+ return 0;
+ }
+ COMPILER_ASSERT(crypto_stream_chacha20_KEYBYTES == 256 / 8);
+ chacha_keysetup(&ctx, k);
+ chacha_ivsetup(&ctx, n, NULL);
+ memset(c, 0, clen);
+ chacha20_encrypt_bytes(&ctx, c, c, clen);
+ sodium_memzero(&ctx, sizeof ctx);
+
+ return 0;
+}
+
+static int
+stream_ietf_ref(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k)
+{
+ struct chacha_ctx ctx;
+
+ if (!clen) {
+ return 0;
+ }
+ COMPILER_ASSERT(crypto_stream_chacha20_KEYBYTES == 256 / 8);
+ chacha_keysetup(&ctx, k);
+ chacha_ietf_ivsetup(&ctx, n, NULL);
+ memset(c, 0, clen);
+ chacha20_encrypt_bytes(&ctx, c, c, clen);
+ sodium_memzero(&ctx, sizeof ctx);
+
+ return 0;
+}
+
+static int
+stream_ref_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n, uint64_t ic,
+ const unsigned char *k)
+{
+ struct chacha_ctx ctx;
+ uint8_t ic_bytes[8];
+ uint32_t ic_high;
+ uint32_t ic_low;
+
+ if (!mlen) {
+ return 0;
+ }
+ ic_high = U32V(ic >> 32);
+ ic_low = U32V(ic);
+ STORE32_LE(&ic_bytes[0], ic_low);
+ STORE32_LE(&ic_bytes[4], ic_high);
+ chacha_keysetup(&ctx, k);
+ chacha_ivsetup(&ctx, n, ic_bytes);
+ chacha20_encrypt_bytes(&ctx, m, c, mlen);
+ sodium_memzero(&ctx, sizeof ctx);
+
+ return 0;
+}
+
+static int
+stream_ietf_ref_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ uint32_t ic, const unsigned char *k)
+{
+ struct chacha_ctx ctx;
+ uint8_t ic_bytes[4];
+
+ if (!mlen) {
+ return 0;
+ }
+ STORE32_LE(ic_bytes, ic);
+ chacha_keysetup(&ctx, k);
+ chacha_ietf_ivsetup(&ctx, n, ic_bytes);
+ chacha20_encrypt_bytes(&ctx, m, c, mlen);
+ sodium_memzero(&ctx, sizeof ctx);
+
+ return 0;
+}
+
+struct crypto_stream_chacha20_implementation
+ crypto_stream_chacha20_ref_implementation = {
+ SODIUM_C99(.stream =) stream_ref,
+ SODIUM_C99(.stream_ietf =) stream_ietf_ref,
+ SODIUM_C99(.stream_xor_ic =) stream_ref_xor_ic,
+ SODIUM_C99(.stream_ietf_xor_ic =) stream_ietf_ref_xor_ic
+ };
diff --git a/libs/libsodium/src/crypto_stream/chacha20/ref/chacha20_ref.h b/libs/libsodium/src/crypto_stream/chacha20/ref/chacha20_ref.h
new file mode 100644
index 0000000000..6ac4807554
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/chacha20/ref/chacha20_ref.h
@@ -0,0 +1,8 @@
+
+#include <stdint.h>
+
+#include "../stream_chacha20.h"
+#include "crypto_stream_chacha20.h"
+
+extern struct crypto_stream_chacha20_implementation
+ crypto_stream_chacha20_ref_implementation;
diff --git a/libs/libsodium/src/crypto_stream/chacha20/stream_chacha20.c b/libs/libsodium/src/crypto_stream/chacha20/stream_chacha20.c
new file mode 100644
index 0000000000..3b0895112c
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/chacha20/stream_chacha20.c
@@ -0,0 +1,130 @@
+#include "crypto_stream_chacha20.h"
+#include "private/common.h"
+#include "private/implementations.h"
+#include "randombytes.h"
+#include "runtime.h"
+#include "stream_chacha20.h"
+
+#include "ref/chacha20_ref.h"
+#if defined(HAVE_AVX2INTRIN_H) && defined(HAVE_EMMINTRIN_H) && \
+ defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)
+# include "dolbeau/chacha20_dolbeau-avx2.h"
+#endif
+#if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)
+# include "dolbeau/chacha20_dolbeau-ssse3.h"
+#endif
+
+static const crypto_stream_chacha20_implementation *implementation =
+ &crypto_stream_chacha20_ref_implementation;
+
+size_t
+crypto_stream_chacha20_keybytes(void) {
+ return crypto_stream_chacha20_KEYBYTES;
+}
+
+size_t
+crypto_stream_chacha20_noncebytes(void) {
+ return crypto_stream_chacha20_NONCEBYTES;
+}
+
+size_t
+crypto_stream_chacha20_messagebytes_max(void)
+{
+ return crypto_stream_chacha20_MESSAGEBYTES_MAX;
+}
+
+size_t
+crypto_stream_chacha20_ietf_keybytes(void) {
+ return crypto_stream_chacha20_ietf_KEYBYTES;
+}
+
+size_t
+crypto_stream_chacha20_ietf_noncebytes(void) {
+ return crypto_stream_chacha20_ietf_NONCEBYTES;
+}
+
+size_t
+crypto_stream_chacha20_ietf_messagebytes_max(void)
+{
+ return crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX;
+}
+
+int
+crypto_stream_chacha20(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k)
+{
+ return implementation->stream(c, clen, n, k);
+}
+
+int
+crypto_stream_chacha20_ietf(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k)
+{
+ return implementation->stream_ietf(c, clen, n, k);
+}
+
+int
+crypto_stream_chacha20_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n, uint64_t ic,
+ const unsigned char *k)
+{
+ return implementation->stream_xor_ic(c, m, mlen, n, ic, k);
+}
+
+int
+crypto_stream_chacha20_ietf_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n, uint32_t ic,
+ const unsigned char *k)
+{
+ return implementation->stream_ietf_xor_ic(c, m, mlen, n, ic, k);
+}
+
+int
+crypto_stream_chacha20_xor(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k)
+{
+ return implementation->stream_xor_ic(c, m, mlen, n, 0U, k);
+}
+
+int
+crypto_stream_chacha20_ietf_xor(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k)
+{
+ return implementation->stream_ietf_xor_ic(c, m, mlen, n, 0U, k);
+}
+
+void
+crypto_stream_chacha20_ietf_keygen(unsigned char k[crypto_stream_chacha20_ietf_KEYBYTES])
+{
+ randombytes_buf(k, crypto_stream_chacha20_ietf_KEYBYTES);
+}
+
+void
+crypto_stream_chacha20_keygen(unsigned char k[crypto_stream_chacha20_KEYBYTES])
+{
+ randombytes_buf(k, crypto_stream_chacha20_KEYBYTES);
+}
+
+int
+_crypto_stream_chacha20_pick_best_implementation(void)
+{
+ implementation = &crypto_stream_chacha20_ref_implementation;
+#if defined(HAVE_AVX2INTRIN_H) && defined(HAVE_EMMINTRIN_H) && \
+ defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)
+ if (sodium_runtime_has_avx2()) {
+ implementation = &crypto_stream_chacha20_dolbeau_avx2_implementation;
+ return 0;
+ }
+#endif
+#if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)
+ if (sodium_runtime_has_ssse3()) {
+ implementation = &crypto_stream_chacha20_dolbeau_ssse3_implementation;
+ return 0;
+ }
+#endif
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_stream/chacha20/stream_chacha20.h b/libs/libsodium/src/crypto_stream/chacha20/stream_chacha20.h
new file mode 100644
index 0000000000..d6b71c5e0d
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/chacha20/stream_chacha20.h
@@ -0,0 +1,22 @@
+
+#ifndef stream_chacha20_H
+#define stream_chacha20_H
+
+#include <stdint.h>
+
+typedef struct crypto_stream_chacha20_implementation {
+ int (*stream)(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k);
+ int (*stream_ietf)(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k);
+ int (*stream_xor_ic)(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n, uint64_t ic,
+ const unsigned char *k);
+ int (*stream_ietf_xor_ic)(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n, uint32_t ic,
+ const unsigned char *k);
+} crypto_stream_chacha20_implementation;
+
+#endif
diff --git a/libs/libsodium/src/crypto_stream/crypto_stream.c b/libs/libsodium/src/crypto_stream/crypto_stream.c
new file mode 100644
index 0000000000..58d25381ab
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/crypto_stream.c
@@ -0,0 +1,49 @@
+
+#include "crypto_stream.h"
+#include "randombytes.h"
+
+size_t
+crypto_stream_keybytes(void)
+{
+ return crypto_stream_KEYBYTES;
+}
+
+size_t
+crypto_stream_noncebytes(void)
+{
+ return crypto_stream_NONCEBYTES;
+}
+
+size_t
+crypto_stream_messagebytes_max(void)
+{
+ return crypto_stream_MESSAGEBYTES_MAX;
+}
+
+const char *
+crypto_stream_primitive(void)
+{
+ return crypto_stream_PRIMITIVE;
+}
+
+int
+crypto_stream(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k)
+{
+ return crypto_stream_xsalsa20(c, clen, n, k);
+}
+
+
+int
+crypto_stream_xor(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k)
+{
+ return crypto_stream_xsalsa20_xor(c, m, mlen, n, k);
+}
+
+void
+crypto_stream_keygen(unsigned char k[crypto_stream_KEYBYTES])
+{
+ randombytes_buf(k, crypto_stream_KEYBYTES);
+}
diff --git a/libs/libsodium/src/crypto_stream/salsa20/ref/salsa20_ref.c b/libs/libsodium/src/crypto_stream/salsa20/ref/salsa20_ref.c
new file mode 100644
index 0000000000..f0854ebf7e
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa20/ref/salsa20_ref.c
@@ -0,0 +1,120 @@
+/*
+version 20140420
+D. J. Bernstein
+Public domain.
+*/
+
+#include <stdint.h>
+
+#include "crypto_core_salsa20.h"
+#include "crypto_stream_salsa20.h"
+#include "utils.h"
+
+#include "../stream_salsa20.h"
+#include "salsa20_ref.h"
+
+#ifndef HAVE_AMD64_ASM
+
+static int
+stream_ref(unsigned char *c, unsigned long long clen, const unsigned char *n,
+ const unsigned char *k)
+{
+ unsigned char in[16];
+ unsigned char block[64];
+ unsigned char kcopy[32];
+ unsigned int i;
+ unsigned int u;
+
+ if (!clen) {
+ return 0;
+ }
+ for (i = 0; i < 32; i++) {
+ kcopy[i] = k[i];
+ }
+ for (i = 0; i < 8; i++) {
+ in[i] = n[i];
+ }
+ for (i = 8; i < 16; i++) {
+ in[i] = 0;
+ }
+ while (clen >= 64) {
+ crypto_core_salsa20(c, in, kcopy, NULL);
+ u = 1;
+ for (i = 8; i < 16; i++) {
+ u += (unsigned int) in[i];
+ in[i] = u;
+ u >>= 8;
+ }
+ clen -= 64;
+ c += 64;
+ }
+ if (clen) {
+ crypto_core_salsa20(block, in, kcopy, NULL);
+ for (i = 0; i < (unsigned int) clen; i++) {
+ c[i] = block[i];
+ }
+ }
+ sodium_memzero(block, sizeof block);
+ sodium_memzero(kcopy, sizeof kcopy);
+
+ return 0;
+}
+
+static int
+stream_ref_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n, uint64_t ic,
+ const unsigned char *k)
+{
+ unsigned char in[16];
+ unsigned char block[64];
+ unsigned char kcopy[32];
+ unsigned int i;
+ unsigned int u;
+
+ if (!mlen) {
+ return 0;
+ }
+ for (i = 0; i < 32; i++) {
+ kcopy[i] = k[i];
+ }
+ for (i = 0; i < 8; i++) {
+ in[i] = n[i];
+ }
+ for (i = 8; i < 16; i++) {
+ in[i] = (unsigned char) (ic & 0xff);
+ ic >>= 8;
+ }
+ while (mlen >= 64) {
+ crypto_core_salsa20(block, in, kcopy, NULL);
+ for (i = 0; i < 64; i++) {
+ c[i] = m[i] ^ block[i];
+ }
+ u = 1;
+ for (i = 8; i < 16; i++) {
+ u += (unsigned int) in[i];
+ in[i] = u;
+ u >>= 8;
+ }
+ mlen -= 64;
+ c += 64;
+ m += 64;
+ }
+ if (mlen) {
+ crypto_core_salsa20(block, in, kcopy, NULL);
+ for (i = 0; i < (unsigned int) mlen; i++) {
+ c[i] = m[i] ^ block[i];
+ }
+ }
+ sodium_memzero(block, sizeof block);
+ sodium_memzero(kcopy, sizeof kcopy);
+
+ return 0;
+}
+
+struct crypto_stream_salsa20_implementation
+ crypto_stream_salsa20_ref_implementation = {
+ SODIUM_C99(.stream =) stream_ref,
+ SODIUM_C99(.stream_xor_ic =) stream_ref_xor_ic,
+ };
+
+#endif
diff --git a/libs/libsodium/src/crypto_stream/salsa20/ref/salsa20_ref.h b/libs/libsodium/src/crypto_stream/salsa20/ref/salsa20_ref.h
new file mode 100644
index 0000000000..8716cb4048
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa20/ref/salsa20_ref.h
@@ -0,0 +1,8 @@
+
+#include <stdint.h>
+
+#include "../stream_salsa20.h"
+#include "crypto_stream_salsa20.h"
+
+extern struct crypto_stream_salsa20_implementation
+ crypto_stream_salsa20_ref_implementation;
diff --git a/libs/libsodium/src/crypto_stream/salsa20/stream_salsa20.c b/libs/libsodium/src/crypto_stream/salsa20/stream_salsa20.c
new file mode 100644
index 0000000000..4529850136
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa20/stream_salsa20.c
@@ -0,0 +1,100 @@
+#include "crypto_stream_salsa20.h"
+#include "private/common.h"
+#include "private/implementations.h"
+#include "randombytes.h"
+#include "runtime.h"
+#include "stream_salsa20.h"
+
+#ifdef HAVE_AMD64_ASM
+# include "xmm6/salsa20_xmm6.h"
+#else
+# include "ref/salsa20_ref.h"
+#endif
+#if !defined(HAVE_AMD64_ASM) && defined(HAVE_EMMINTRIN_H)
+# include "xmm6int/salsa20_xmm6int-sse2.h"
+#endif
+#if defined(HAVE_AVX2INTRIN_H) && defined(HAVE_EMMINTRIN_H) && \
+ defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)
+# include "xmm6int/salsa20_xmm6int-avx2.h"
+#endif
+
+#if HAVE_AMD64_ASM
+static const crypto_stream_salsa20_implementation *implementation =
+ &crypto_stream_salsa20_xmm6_implementation;
+#else
+static const crypto_stream_salsa20_implementation *implementation =
+ &crypto_stream_salsa20_ref_implementation;
+#endif
+
+size_t
+crypto_stream_salsa20_keybytes(void)
+{
+ return crypto_stream_salsa20_KEYBYTES;
+}
+
+size_t
+crypto_stream_salsa20_noncebytes(void)
+{
+ return crypto_stream_salsa20_NONCEBYTES;
+}
+
+size_t
+crypto_stream_salsa20_messagebytes_max(void)
+{
+ return crypto_stream_salsa20_MESSAGEBYTES_MAX;
+}
+
+int
+crypto_stream_salsa20(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k)
+{
+ return implementation->stream(c, clen, n, k);
+}
+
+int
+crypto_stream_salsa20_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n, uint64_t ic,
+ const unsigned char *k)
+{
+ return implementation->stream_xor_ic(c, m, mlen, n, ic, k);
+}
+
+int
+crypto_stream_salsa20_xor(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k)
+{
+ return implementation->stream_xor_ic(c, m, mlen, n, 0U, k);
+}
+
+void
+crypto_stream_salsa20_keygen(unsigned char k[crypto_stream_salsa20_KEYBYTES])
+{
+ randombytes_buf(k, crypto_stream_salsa20_KEYBYTES);
+}
+
+int
+_crypto_stream_salsa20_pick_best_implementation(void)
+{
+#ifdef HAVE_AMD64_ASM
+ implementation = &crypto_stream_salsa20_xmm6_implementation;
+#else
+ implementation = &crypto_stream_salsa20_ref_implementation;
+#endif
+
+#if defined(HAVE_AVX2INTRIN_H) && defined(HAVE_EMMINTRIN_H) && \
+ defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)
+ if (sodium_runtime_has_avx2()) {
+ implementation = &crypto_stream_salsa20_xmm6int_avx2_implementation;
+ return 0;
+ }
+#endif
+#if !defined(HAVE_AMD64_ASM) && defined(HAVE_EMMINTRIN_H)
+ if (sodium_runtime_has_sse2()) {
+ implementation = &crypto_stream_salsa20_xmm6int_sse2_implementation;
+ return 0;
+ }
+#endif
+ return 0; /* LCOV_EXCL_LINE */
+}
diff --git a/libs/libsodium/src/crypto_stream/salsa20/stream_salsa20.h b/libs/libsodium/src/crypto_stream/salsa20/stream_salsa20.h
new file mode 100644
index 0000000000..1949d38113
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa20/stream_salsa20.h
@@ -0,0 +1,16 @@
+
+#ifndef stream_salsa20_H
+#define stream_salsa20_H
+
+#include <stdint.h>
+
+typedef struct crypto_stream_salsa20_implementation {
+ int (*stream)(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k);
+ int (*stream_xor_ic)(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n, uint64_t ic,
+ const unsigned char *k);
+} crypto_stream_salsa20_implementation;
+
+#endif
diff --git a/libs/libsodium/src/crypto_stream/salsa20/xmm6/salsa20_xmm6-asm.S b/libs/libsodium/src/crypto_stream/salsa20/xmm6/salsa20_xmm6-asm.S
new file mode 100644
index 0000000000..6d9f354e10
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa20/xmm6/salsa20_xmm6-asm.S
@@ -0,0 +1,960 @@
+#ifdef HAVE_AMD64_ASM
+
+.text
+.p2align 5
+
+#ifdef ASM_HIDE_SYMBOL
+ASM_HIDE_SYMBOL stream_salsa20_xmm6
+ASM_HIDE_SYMBOL _stream_salsa20_xmm6
+#endif
+.globl stream_salsa20_xmm6
+.globl _stream_salsa20_xmm6
+#ifdef __ELF__
+.type stream_salsa20_xmm6, @function
+.type _stream_salsa20_xmm6, @function
+#endif
+stream_salsa20_xmm6:
+_stream_salsa20_xmm6:
+mov %rsp,%r11
+and $31,%r11
+add $512,%r11
+sub %r11,%rsp
+movq %r11,416(%rsp)
+movq %r12,424(%rsp)
+movq %r13,432(%rsp)
+movq %r14,440(%rsp)
+movq %r15,448(%rsp)
+movq %rbx,456(%rsp)
+movq %rbp,464(%rsp)
+mov %rsi,%r9
+mov %rdi,%rdi
+mov %rdi,%rsi
+mov %rdx,%rdx
+mov %rcx,%r10
+cmp $0,%r9
+jbe ._done
+mov $0,%rax
+mov %r9,%rcx
+rep stosb
+sub %r9,%rdi
+movq $0,472(%rsp)
+jmp ._start
+
+.text
+.p2align 5
+
+#ifdef ASM_HIDE_SYMBOL
+ASM_HIDE_SYMBOL stream_salsa20_xmm6_xor_ic
+ASM_HIDE_SYMBOL _stream_salsa20_xmm6_xor_ic
+#endif
+.globl stream_salsa20_xmm6_xor_ic
+.globl _stream_salsa20_xmm6_xor_ic
+#ifdef __ELF__
+.type stream_salsa20_xmm6_xor_ic, @function
+.type _stream_salsa20_xmm6_xor_ic, @function
+#endif
+stream_salsa20_xmm6_xor_ic:
+_stream_salsa20_xmm6_xor_ic:
+
+mov %rsp,%r11
+and $31,%r11
+add $512,%r11
+sub %r11,%rsp
+movq %r11,416(%rsp)
+movq %r12,424(%rsp)
+movq %r13,432(%rsp)
+movq %r14,440(%rsp)
+movq %r15,448(%rsp)
+movq %rbx,456(%rsp)
+movq %rbp,464(%rsp)
+mov %rdi,%rdi
+mov %rsi,%rsi
+mov %r9,%r10
+movq %r8,472(%rsp)
+mov %rdx,%r9
+mov %rcx,%rdx
+cmp $0,%r9
+jbe ._done
+
+._start:
+movl 20(%r10),%ecx
+movl 0(%r10),%r8d
+movl 0(%rdx),%eax
+movl 16(%r10),%r11d
+movl %ecx,64(%rsp)
+movl %r8d,4+64(%rsp)
+movl %eax,8+64(%rsp)
+movl %r11d,12+64(%rsp)
+movl 24(%r10),%r8d
+movl 4(%r10),%eax
+movl 4(%rdx),%edx
+movq 472(%rsp),%rcx
+movl %ecx,80(%rsp)
+movl %r8d,4+80(%rsp)
+movl %eax,8+80(%rsp)
+movl %edx,12+80(%rsp)
+movl 12(%r10),%edx
+shr $32,%rcx
+movl 28(%r10),%r8d
+movl 8(%r10),%eax
+movl %edx,96(%rsp)
+movl %ecx,4+96(%rsp)
+movl %r8d,8+96(%rsp)
+movl %eax,12+96(%rsp)
+mov $1634760805,%rdx
+mov $857760878,%rcx
+mov $2036477234,%r8
+mov $1797285236,%rax
+movl %edx,112(%rsp)
+movl %ecx,4+112(%rsp)
+movl %r8d,8+112(%rsp)
+movl %eax,12+112(%rsp)
+cmp $256,%r9
+jb ._bytesbetween1and255
+movdqa 112(%rsp),%xmm0
+pshufd $0x55,%xmm0,%xmm1
+pshufd $0xaa,%xmm0,%xmm2
+pshufd $0xff,%xmm0,%xmm3
+pshufd $0x00,%xmm0,%xmm0
+movdqa %xmm1,128(%rsp)
+movdqa %xmm2,144(%rsp)
+movdqa %xmm3,160(%rsp)
+movdqa %xmm0,176(%rsp)
+movdqa 64(%rsp),%xmm0
+pshufd $0xaa,%xmm0,%xmm1
+pshufd $0xff,%xmm0,%xmm2
+pshufd $0x00,%xmm0,%xmm3
+pshufd $0x55,%xmm0,%xmm0
+movdqa %xmm1,192(%rsp)
+movdqa %xmm2,208(%rsp)
+movdqa %xmm3,224(%rsp)
+movdqa %xmm0,240(%rsp)
+movdqa 80(%rsp),%xmm0
+pshufd $0xff,%xmm0,%xmm1
+pshufd $0x55,%xmm0,%xmm2
+pshufd $0xaa,%xmm0,%xmm0
+movdqa %xmm1,256(%rsp)
+movdqa %xmm2,272(%rsp)
+movdqa %xmm0,288(%rsp)
+movdqa 96(%rsp),%xmm0
+pshufd $0x00,%xmm0,%xmm1
+pshufd $0xaa,%xmm0,%xmm2
+pshufd $0xff,%xmm0,%xmm0
+movdqa %xmm1,304(%rsp)
+movdqa %xmm2,320(%rsp)
+movdqa %xmm0,336(%rsp)
+
+.p2align 4
+._bytesatleast256:
+movq 472(%rsp),%rdx
+mov %rdx,%rcx
+shr $32,%rcx
+movl %edx,352(%rsp)
+movl %ecx,368(%rsp)
+add $1,%rdx
+mov %rdx,%rcx
+shr $32,%rcx
+movl %edx,4+352(%rsp)
+movl %ecx,4+368(%rsp)
+add $1,%rdx
+mov %rdx,%rcx
+shr $32,%rcx
+movl %edx,8+352(%rsp)
+movl %ecx,8+368(%rsp)
+add $1,%rdx
+mov %rdx,%rcx
+shr $32,%rcx
+movl %edx,12+352(%rsp)
+movl %ecx,12+368(%rsp)
+add $1,%rdx
+mov %rdx,%rcx
+shr $32,%rcx
+movl %edx,80(%rsp)
+movl %ecx,4+96(%rsp)
+movq %rdx,472(%rsp)
+movq %r9,480(%rsp)
+mov $20,%rdx
+movdqa 128(%rsp),%xmm0
+movdqa 144(%rsp),%xmm1
+movdqa 160(%rsp),%xmm2
+movdqa 320(%rsp),%xmm3
+movdqa 336(%rsp),%xmm4
+movdqa 192(%rsp),%xmm5
+movdqa 208(%rsp),%xmm6
+movdqa 240(%rsp),%xmm7
+movdqa 256(%rsp),%xmm8
+movdqa 272(%rsp),%xmm9
+movdqa 288(%rsp),%xmm10
+movdqa 368(%rsp),%xmm11
+movdqa 176(%rsp),%xmm12
+movdqa 224(%rsp),%xmm13
+movdqa 304(%rsp),%xmm14
+movdqa 352(%rsp),%xmm15
+
+.p2align 4
+._mainloop1:
+movdqa %xmm1,384(%rsp)
+movdqa %xmm2,400(%rsp)
+movdqa %xmm13,%xmm1
+paddd %xmm12,%xmm1
+movdqa %xmm1,%xmm2
+pslld $7,%xmm1
+pxor %xmm1,%xmm14
+psrld $25,%xmm2
+pxor %xmm2,%xmm14
+movdqa %xmm7,%xmm1
+paddd %xmm0,%xmm1
+movdqa %xmm1,%xmm2
+pslld $7,%xmm1
+pxor %xmm1,%xmm11
+psrld $25,%xmm2
+pxor %xmm2,%xmm11
+movdqa %xmm12,%xmm1
+paddd %xmm14,%xmm1
+movdqa %xmm1,%xmm2
+pslld $9,%xmm1
+pxor %xmm1,%xmm15
+psrld $23,%xmm2
+pxor %xmm2,%xmm15
+movdqa %xmm0,%xmm1
+paddd %xmm11,%xmm1
+movdqa %xmm1,%xmm2
+pslld $9,%xmm1
+pxor %xmm1,%xmm9
+psrld $23,%xmm2
+pxor %xmm2,%xmm9
+movdqa %xmm14,%xmm1
+paddd %xmm15,%xmm1
+movdqa %xmm1,%xmm2
+pslld $13,%xmm1
+pxor %xmm1,%xmm13
+psrld $19,%xmm2
+pxor %xmm2,%xmm13
+movdqa %xmm11,%xmm1
+paddd %xmm9,%xmm1
+movdqa %xmm1,%xmm2
+pslld $13,%xmm1
+pxor %xmm1,%xmm7
+psrld $19,%xmm2
+pxor %xmm2,%xmm7
+movdqa %xmm15,%xmm1
+paddd %xmm13,%xmm1
+movdqa %xmm1,%xmm2
+pslld $18,%xmm1
+pxor %xmm1,%xmm12
+psrld $14,%xmm2
+pxor %xmm2,%xmm12
+movdqa 384(%rsp),%xmm1
+movdqa %xmm12,384(%rsp)
+movdqa %xmm9,%xmm2
+paddd %xmm7,%xmm2
+movdqa %xmm2,%xmm12
+pslld $18,%xmm2
+pxor %xmm2,%xmm0
+psrld $14,%xmm12
+pxor %xmm12,%xmm0
+movdqa %xmm5,%xmm2
+paddd %xmm1,%xmm2
+movdqa %xmm2,%xmm12
+pslld $7,%xmm2
+pxor %xmm2,%xmm3
+psrld $25,%xmm12
+pxor %xmm12,%xmm3
+movdqa 400(%rsp),%xmm2
+movdqa %xmm0,400(%rsp)
+movdqa %xmm6,%xmm0
+paddd %xmm2,%xmm0
+movdqa %xmm0,%xmm12
+pslld $7,%xmm0
+pxor %xmm0,%xmm4
+psrld $25,%xmm12
+pxor %xmm12,%xmm4
+movdqa %xmm1,%xmm0
+paddd %xmm3,%xmm0
+movdqa %xmm0,%xmm12
+pslld $9,%xmm0
+pxor %xmm0,%xmm10
+psrld $23,%xmm12
+pxor %xmm12,%xmm10
+movdqa %xmm2,%xmm0
+paddd %xmm4,%xmm0
+movdqa %xmm0,%xmm12
+pslld $9,%xmm0
+pxor %xmm0,%xmm8
+psrld $23,%xmm12
+pxor %xmm12,%xmm8
+movdqa %xmm3,%xmm0
+paddd %xmm10,%xmm0
+movdqa %xmm0,%xmm12
+pslld $13,%xmm0
+pxor %xmm0,%xmm5
+psrld $19,%xmm12
+pxor %xmm12,%xmm5
+movdqa %xmm4,%xmm0
+paddd %xmm8,%xmm0
+movdqa %xmm0,%xmm12
+pslld $13,%xmm0
+pxor %xmm0,%xmm6
+psrld $19,%xmm12
+pxor %xmm12,%xmm6
+movdqa %xmm10,%xmm0
+paddd %xmm5,%xmm0
+movdqa %xmm0,%xmm12
+pslld $18,%xmm0
+pxor %xmm0,%xmm1
+psrld $14,%xmm12
+pxor %xmm12,%xmm1
+movdqa 384(%rsp),%xmm0
+movdqa %xmm1,384(%rsp)
+movdqa %xmm4,%xmm1
+paddd %xmm0,%xmm1
+movdqa %xmm1,%xmm12
+pslld $7,%xmm1
+pxor %xmm1,%xmm7
+psrld $25,%xmm12
+pxor %xmm12,%xmm7
+movdqa %xmm8,%xmm1
+paddd %xmm6,%xmm1
+movdqa %xmm1,%xmm12
+pslld $18,%xmm1
+pxor %xmm1,%xmm2
+psrld $14,%xmm12
+pxor %xmm12,%xmm2
+movdqa 400(%rsp),%xmm12
+movdqa %xmm2,400(%rsp)
+movdqa %xmm14,%xmm1
+paddd %xmm12,%xmm1
+movdqa %xmm1,%xmm2
+pslld $7,%xmm1
+pxor %xmm1,%xmm5
+psrld $25,%xmm2
+pxor %xmm2,%xmm5
+movdqa %xmm0,%xmm1
+paddd %xmm7,%xmm1
+movdqa %xmm1,%xmm2
+pslld $9,%xmm1
+pxor %xmm1,%xmm10
+psrld $23,%xmm2
+pxor %xmm2,%xmm10
+movdqa %xmm12,%xmm1
+paddd %xmm5,%xmm1
+movdqa %xmm1,%xmm2
+pslld $9,%xmm1
+pxor %xmm1,%xmm8
+psrld $23,%xmm2
+pxor %xmm2,%xmm8
+movdqa %xmm7,%xmm1
+paddd %xmm10,%xmm1
+movdqa %xmm1,%xmm2
+pslld $13,%xmm1
+pxor %xmm1,%xmm4
+psrld $19,%xmm2
+pxor %xmm2,%xmm4
+movdqa %xmm5,%xmm1
+paddd %xmm8,%xmm1
+movdqa %xmm1,%xmm2
+pslld $13,%xmm1
+pxor %xmm1,%xmm14
+psrld $19,%xmm2
+pxor %xmm2,%xmm14
+movdqa %xmm10,%xmm1
+paddd %xmm4,%xmm1
+movdqa %xmm1,%xmm2
+pslld $18,%xmm1
+pxor %xmm1,%xmm0
+psrld $14,%xmm2
+pxor %xmm2,%xmm0
+movdqa 384(%rsp),%xmm1
+movdqa %xmm0,384(%rsp)
+movdqa %xmm8,%xmm0
+paddd %xmm14,%xmm0
+movdqa %xmm0,%xmm2
+pslld $18,%xmm0
+pxor %xmm0,%xmm12
+psrld $14,%xmm2
+pxor %xmm2,%xmm12
+movdqa %xmm11,%xmm0
+paddd %xmm1,%xmm0
+movdqa %xmm0,%xmm2
+pslld $7,%xmm0
+pxor %xmm0,%xmm6
+psrld $25,%xmm2
+pxor %xmm2,%xmm6
+movdqa 400(%rsp),%xmm2
+movdqa %xmm12,400(%rsp)
+movdqa %xmm3,%xmm0
+paddd %xmm2,%xmm0
+movdqa %xmm0,%xmm12
+pslld $7,%xmm0
+pxor %xmm0,%xmm13
+psrld $25,%xmm12
+pxor %xmm12,%xmm13
+movdqa %xmm1,%xmm0
+paddd %xmm6,%xmm0
+movdqa %xmm0,%xmm12
+pslld $9,%xmm0
+pxor %xmm0,%xmm15
+psrld $23,%xmm12
+pxor %xmm12,%xmm15
+movdqa %xmm2,%xmm0
+paddd %xmm13,%xmm0
+movdqa %xmm0,%xmm12
+pslld $9,%xmm0
+pxor %xmm0,%xmm9
+psrld $23,%xmm12
+pxor %xmm12,%xmm9
+movdqa %xmm6,%xmm0
+paddd %xmm15,%xmm0
+movdqa %xmm0,%xmm12
+pslld $13,%xmm0
+pxor %xmm0,%xmm11
+psrld $19,%xmm12
+pxor %xmm12,%xmm11
+movdqa %xmm13,%xmm0
+paddd %xmm9,%xmm0
+movdqa %xmm0,%xmm12
+pslld $13,%xmm0
+pxor %xmm0,%xmm3
+psrld $19,%xmm12
+pxor %xmm12,%xmm3
+movdqa %xmm15,%xmm0
+paddd %xmm11,%xmm0
+movdqa %xmm0,%xmm12
+pslld $18,%xmm0
+pxor %xmm0,%xmm1
+psrld $14,%xmm12
+pxor %xmm12,%xmm1
+movdqa %xmm9,%xmm0
+paddd %xmm3,%xmm0
+movdqa %xmm0,%xmm12
+pslld $18,%xmm0
+pxor %xmm0,%xmm2
+psrld $14,%xmm12
+pxor %xmm12,%xmm2
+movdqa 384(%rsp),%xmm12
+movdqa 400(%rsp),%xmm0
+sub $2,%rdx
+ja ._mainloop1
+
+paddd 176(%rsp),%xmm12
+paddd 240(%rsp),%xmm7
+paddd 288(%rsp),%xmm10
+paddd 336(%rsp),%xmm4
+movd %xmm12,%rdx
+movd %xmm7,%rcx
+movd %xmm10,%r8
+movd %xmm4,%r9
+pshufd $0x39,%xmm12,%xmm12
+pshufd $0x39,%xmm7,%xmm7
+pshufd $0x39,%xmm10,%xmm10
+pshufd $0x39,%xmm4,%xmm4
+xorl 0(%rsi),%edx
+xorl 4(%rsi),%ecx
+xorl 8(%rsi),%r8d
+xorl 12(%rsi),%r9d
+movl %edx,0(%rdi)
+movl %ecx,4(%rdi)
+movl %r8d,8(%rdi)
+movl %r9d,12(%rdi)
+movd %xmm12,%rdx
+movd %xmm7,%rcx
+movd %xmm10,%r8
+movd %xmm4,%r9
+pshufd $0x39,%xmm12,%xmm12
+pshufd $0x39,%xmm7,%xmm7
+pshufd $0x39,%xmm10,%xmm10
+pshufd $0x39,%xmm4,%xmm4
+xorl 64(%rsi),%edx
+xorl 68(%rsi),%ecx
+xorl 72(%rsi),%r8d
+xorl 76(%rsi),%r9d
+movl %edx,64(%rdi)
+movl %ecx,68(%rdi)
+movl %r8d,72(%rdi)
+movl %r9d,76(%rdi)
+movd %xmm12,%rdx
+movd %xmm7,%rcx
+movd %xmm10,%r8
+movd %xmm4,%r9
+pshufd $0x39,%xmm12,%xmm12
+pshufd $0x39,%xmm7,%xmm7
+pshufd $0x39,%xmm10,%xmm10
+pshufd $0x39,%xmm4,%xmm4
+xorl 128(%rsi),%edx
+xorl 132(%rsi),%ecx
+xorl 136(%rsi),%r8d
+xorl 140(%rsi),%r9d
+movl %edx,128(%rdi)
+movl %ecx,132(%rdi)
+movl %r8d,136(%rdi)
+movl %r9d,140(%rdi)
+movd %xmm12,%rdx
+movd %xmm7,%rcx
+movd %xmm10,%r8
+movd %xmm4,%r9
+xorl 192(%rsi),%edx
+xorl 196(%rsi),%ecx
+xorl 200(%rsi),%r8d
+xorl 204(%rsi),%r9d
+movl %edx,192(%rdi)
+movl %ecx,196(%rdi)
+movl %r8d,200(%rdi)
+movl %r9d,204(%rdi)
+paddd 304(%rsp),%xmm14
+paddd 128(%rsp),%xmm0
+paddd 192(%rsp),%xmm5
+paddd 256(%rsp),%xmm8
+movd %xmm14,%rdx
+movd %xmm0,%rcx
+movd %xmm5,%r8
+movd %xmm8,%r9
+pshufd $0x39,%xmm14,%xmm14
+pshufd $0x39,%xmm0,%xmm0
+pshufd $0x39,%xmm5,%xmm5
+pshufd $0x39,%xmm8,%xmm8
+xorl 16(%rsi),%edx
+xorl 20(%rsi),%ecx
+xorl 24(%rsi),%r8d
+xorl 28(%rsi),%r9d
+movl %edx,16(%rdi)
+movl %ecx,20(%rdi)
+movl %r8d,24(%rdi)
+movl %r9d,28(%rdi)
+movd %xmm14,%rdx
+movd %xmm0,%rcx
+movd %xmm5,%r8
+movd %xmm8,%r9
+pshufd $0x39,%xmm14,%xmm14
+pshufd $0x39,%xmm0,%xmm0
+pshufd $0x39,%xmm5,%xmm5
+pshufd $0x39,%xmm8,%xmm8
+xorl 80(%rsi),%edx
+xorl 84(%rsi),%ecx
+xorl 88(%rsi),%r8d
+xorl 92(%rsi),%r9d
+movl %edx,80(%rdi)
+movl %ecx,84(%rdi)
+movl %r8d,88(%rdi)
+movl %r9d,92(%rdi)
+movd %xmm14,%rdx
+movd %xmm0,%rcx
+movd %xmm5,%r8
+movd %xmm8,%r9
+pshufd $0x39,%xmm14,%xmm14
+pshufd $0x39,%xmm0,%xmm0
+pshufd $0x39,%xmm5,%xmm5
+pshufd $0x39,%xmm8,%xmm8
+xorl 144(%rsi),%edx
+xorl 148(%rsi),%ecx
+xorl 152(%rsi),%r8d
+xorl 156(%rsi),%r9d
+movl %edx,144(%rdi)
+movl %ecx,148(%rdi)
+movl %r8d,152(%rdi)
+movl %r9d,156(%rdi)
+movd %xmm14,%rdx
+movd %xmm0,%rcx
+movd %xmm5,%r8
+movd %xmm8,%r9
+xorl 208(%rsi),%edx
+xorl 212(%rsi),%ecx
+xorl 216(%rsi),%r8d
+xorl 220(%rsi),%r9d
+movl %edx,208(%rdi)
+movl %ecx,212(%rdi)
+movl %r8d,216(%rdi)
+movl %r9d,220(%rdi)
+paddd 352(%rsp),%xmm15
+paddd 368(%rsp),%xmm11
+paddd 144(%rsp),%xmm1
+paddd 208(%rsp),%xmm6
+movd %xmm15,%rdx
+movd %xmm11,%rcx
+movd %xmm1,%r8
+movd %xmm6,%r9
+pshufd $0x39,%xmm15,%xmm15
+pshufd $0x39,%xmm11,%xmm11
+pshufd $0x39,%xmm1,%xmm1
+pshufd $0x39,%xmm6,%xmm6
+xorl 32(%rsi),%edx
+xorl 36(%rsi),%ecx
+xorl 40(%rsi),%r8d
+xorl 44(%rsi),%r9d
+movl %edx,32(%rdi)
+movl %ecx,36(%rdi)
+movl %r8d,40(%rdi)
+movl %r9d,44(%rdi)
+movd %xmm15,%rdx
+movd %xmm11,%rcx
+movd %xmm1,%r8
+movd %xmm6,%r9
+pshufd $0x39,%xmm15,%xmm15
+pshufd $0x39,%xmm11,%xmm11
+pshufd $0x39,%xmm1,%xmm1
+pshufd $0x39,%xmm6,%xmm6
+xorl 96(%rsi),%edx
+xorl 100(%rsi),%ecx
+xorl 104(%rsi),%r8d
+xorl 108(%rsi),%r9d
+movl %edx,96(%rdi)
+movl %ecx,100(%rdi)
+movl %r8d,104(%rdi)
+movl %r9d,108(%rdi)
+movd %xmm15,%rdx
+movd %xmm11,%rcx
+movd %xmm1,%r8
+movd %xmm6,%r9
+pshufd $0x39,%xmm15,%xmm15
+pshufd $0x39,%xmm11,%xmm11
+pshufd $0x39,%xmm1,%xmm1
+pshufd $0x39,%xmm6,%xmm6
+xorl 160(%rsi),%edx
+xorl 164(%rsi),%ecx
+xorl 168(%rsi),%r8d
+xorl 172(%rsi),%r9d
+movl %edx,160(%rdi)
+movl %ecx,164(%rdi)
+movl %r8d,168(%rdi)
+movl %r9d,172(%rdi)
+movd %xmm15,%rdx
+movd %xmm11,%rcx
+movd %xmm1,%r8
+movd %xmm6,%r9
+xorl 224(%rsi),%edx
+xorl 228(%rsi),%ecx
+xorl 232(%rsi),%r8d
+xorl 236(%rsi),%r9d
+movl %edx,224(%rdi)
+movl %ecx,228(%rdi)
+movl %r8d,232(%rdi)
+movl %r9d,236(%rdi)
+paddd 224(%rsp),%xmm13
+paddd 272(%rsp),%xmm9
+paddd 320(%rsp),%xmm3
+paddd 160(%rsp),%xmm2
+movd %xmm13,%rdx
+movd %xmm9,%rcx
+movd %xmm3,%r8
+movd %xmm2,%r9
+pshufd $0x39,%xmm13,%xmm13
+pshufd $0x39,%xmm9,%xmm9
+pshufd $0x39,%xmm3,%xmm3
+pshufd $0x39,%xmm2,%xmm2
+xorl 48(%rsi),%edx
+xorl 52(%rsi),%ecx
+xorl 56(%rsi),%r8d
+xorl 60(%rsi),%r9d
+movl %edx,48(%rdi)
+movl %ecx,52(%rdi)
+movl %r8d,56(%rdi)
+movl %r9d,60(%rdi)
+movd %xmm13,%rdx
+movd %xmm9,%rcx
+movd %xmm3,%r8
+movd %xmm2,%r9
+pshufd $0x39,%xmm13,%xmm13
+pshufd $0x39,%xmm9,%xmm9
+pshufd $0x39,%xmm3,%xmm3
+pshufd $0x39,%xmm2,%xmm2
+xorl 112(%rsi),%edx
+xorl 116(%rsi),%ecx
+xorl 120(%rsi),%r8d
+xorl 124(%rsi),%r9d
+movl %edx,112(%rdi)
+movl %ecx,116(%rdi)
+movl %r8d,120(%rdi)
+movl %r9d,124(%rdi)
+movd %xmm13,%rdx
+movd %xmm9,%rcx
+movd %xmm3,%r8
+movd %xmm2,%r9
+pshufd $0x39,%xmm13,%xmm13
+pshufd $0x39,%xmm9,%xmm9
+pshufd $0x39,%xmm3,%xmm3
+pshufd $0x39,%xmm2,%xmm2
+xorl 176(%rsi),%edx
+xorl 180(%rsi),%ecx
+xorl 184(%rsi),%r8d
+xorl 188(%rsi),%r9d
+movl %edx,176(%rdi)
+movl %ecx,180(%rdi)
+movl %r8d,184(%rdi)
+movl %r9d,188(%rdi)
+movd %xmm13,%rdx
+movd %xmm9,%rcx
+movd %xmm3,%r8
+movd %xmm2,%r9
+xorl 240(%rsi),%edx
+xorl 244(%rsi),%ecx
+xorl 248(%rsi),%r8d
+xorl 252(%rsi),%r9d
+movl %edx,240(%rdi)
+movl %ecx,244(%rdi)
+movl %r8d,248(%rdi)
+movl %r9d,252(%rdi)
+movq 480(%rsp),%r9
+sub $256,%r9
+add $256,%rsi
+add $256,%rdi
+cmp $256,%r9
+jae ._bytesatleast256
+
+cmp $0,%r9
+jbe ._done
+
+._bytesbetween1and255:
+cmp $64,%r9
+jae ._nocopy
+
+mov %rdi,%rdx
+leaq 0(%rsp),%rdi
+mov %r9,%rcx
+rep movsb
+leaq 0(%rsp),%rdi
+leaq 0(%rsp),%rsi
+
+._nocopy:
+movq %r9,480(%rsp)
+movdqa 112(%rsp),%xmm0
+movdqa 64(%rsp),%xmm1
+movdqa 80(%rsp),%xmm2
+movdqa 96(%rsp),%xmm3
+movdqa %xmm1,%xmm4
+mov $20,%rcx
+
+.p2align 4
+._mainloop2:
+paddd %xmm0,%xmm4
+movdqa %xmm0,%xmm5
+movdqa %xmm4,%xmm6
+pslld $7,%xmm4
+psrld $25,%xmm6
+pxor %xmm4,%xmm3
+pxor %xmm6,%xmm3
+paddd %xmm3,%xmm5
+movdqa %xmm3,%xmm4
+movdqa %xmm5,%xmm6
+pslld $9,%xmm5
+psrld $23,%xmm6
+pxor %xmm5,%xmm2
+pshufd $0x93,%xmm3,%xmm3
+pxor %xmm6,%xmm2
+paddd %xmm2,%xmm4
+movdqa %xmm2,%xmm5
+movdqa %xmm4,%xmm6
+pslld $13,%xmm4
+psrld $19,%xmm6
+pxor %xmm4,%xmm1
+pshufd $0x4e,%xmm2,%xmm2
+pxor %xmm6,%xmm1
+paddd %xmm1,%xmm5
+movdqa %xmm3,%xmm4
+movdqa %xmm5,%xmm6
+pslld $18,%xmm5
+psrld $14,%xmm6
+pxor %xmm5,%xmm0
+pshufd $0x39,%xmm1,%xmm1
+pxor %xmm6,%xmm0
+paddd %xmm0,%xmm4
+movdqa %xmm0,%xmm5
+movdqa %xmm4,%xmm6
+pslld $7,%xmm4
+psrld $25,%xmm6
+pxor %xmm4,%xmm1
+pxor %xmm6,%xmm1
+paddd %xmm1,%xmm5
+movdqa %xmm1,%xmm4
+movdqa %xmm5,%xmm6
+pslld $9,%xmm5
+psrld $23,%xmm6
+pxor %xmm5,%xmm2
+pshufd $0x93,%xmm1,%xmm1
+pxor %xmm6,%xmm2
+paddd %xmm2,%xmm4
+movdqa %xmm2,%xmm5
+movdqa %xmm4,%xmm6
+pslld $13,%xmm4
+psrld $19,%xmm6
+pxor %xmm4,%xmm3
+pshufd $0x4e,%xmm2,%xmm2
+pxor %xmm6,%xmm3
+paddd %xmm3,%xmm5
+movdqa %xmm1,%xmm4
+movdqa %xmm5,%xmm6
+pslld $18,%xmm5
+psrld $14,%xmm6
+pxor %xmm5,%xmm0
+pshufd $0x39,%xmm3,%xmm3
+pxor %xmm6,%xmm0
+paddd %xmm0,%xmm4
+movdqa %xmm0,%xmm5
+movdqa %xmm4,%xmm6
+pslld $7,%xmm4
+psrld $25,%xmm6
+pxor %xmm4,%xmm3
+pxor %xmm6,%xmm3
+paddd %xmm3,%xmm5
+movdqa %xmm3,%xmm4
+movdqa %xmm5,%xmm6
+pslld $9,%xmm5
+psrld $23,%xmm6
+pxor %xmm5,%xmm2
+pshufd $0x93,%xmm3,%xmm3
+pxor %xmm6,%xmm2
+paddd %xmm2,%xmm4
+movdqa %xmm2,%xmm5
+movdqa %xmm4,%xmm6
+pslld $13,%xmm4
+psrld $19,%xmm6
+pxor %xmm4,%xmm1
+pshufd $0x4e,%xmm2,%xmm2
+pxor %xmm6,%xmm1
+paddd %xmm1,%xmm5
+movdqa %xmm3,%xmm4
+movdqa %xmm5,%xmm6
+pslld $18,%xmm5
+psrld $14,%xmm6
+pxor %xmm5,%xmm0
+pshufd $0x39,%xmm1,%xmm1
+pxor %xmm6,%xmm0
+paddd %xmm0,%xmm4
+movdqa %xmm0,%xmm5
+movdqa %xmm4,%xmm6
+pslld $7,%xmm4
+psrld $25,%xmm6
+pxor %xmm4,%xmm1
+pxor %xmm6,%xmm1
+paddd %xmm1,%xmm5
+movdqa %xmm1,%xmm4
+movdqa %xmm5,%xmm6
+pslld $9,%xmm5
+psrld $23,%xmm6
+pxor %xmm5,%xmm2
+pshufd $0x93,%xmm1,%xmm1
+pxor %xmm6,%xmm2
+paddd %xmm2,%xmm4
+movdqa %xmm2,%xmm5
+movdqa %xmm4,%xmm6
+pslld $13,%xmm4
+psrld $19,%xmm6
+pxor %xmm4,%xmm3
+pshufd $0x4e,%xmm2,%xmm2
+pxor %xmm6,%xmm3
+sub $4,%rcx
+paddd %xmm3,%xmm5
+movdqa %xmm1,%xmm4
+movdqa %xmm5,%xmm6
+pslld $18,%xmm5
+pxor %xmm7,%xmm7
+psrld $14,%xmm6
+pxor %xmm5,%xmm0
+pshufd $0x39,%xmm3,%xmm3
+pxor %xmm6,%xmm0
+ja ._mainloop2
+
+paddd 112(%rsp),%xmm0
+paddd 64(%rsp),%xmm1
+paddd 80(%rsp),%xmm2
+paddd 96(%rsp),%xmm3
+movd %xmm0,%rcx
+movd %xmm1,%r8
+movd %xmm2,%r9
+movd %xmm3,%rax
+pshufd $0x39,%xmm0,%xmm0
+pshufd $0x39,%xmm1,%xmm1
+pshufd $0x39,%xmm2,%xmm2
+pshufd $0x39,%xmm3,%xmm3
+xorl 0(%rsi),%ecx
+xorl 48(%rsi),%r8d
+xorl 32(%rsi),%r9d
+xorl 16(%rsi),%eax
+movl %ecx,0(%rdi)
+movl %r8d,48(%rdi)
+movl %r9d,32(%rdi)
+movl %eax,16(%rdi)
+movd %xmm0,%rcx
+movd %xmm1,%r8
+movd %xmm2,%r9
+movd %xmm3,%rax
+pshufd $0x39,%xmm0,%xmm0
+pshufd $0x39,%xmm1,%xmm1
+pshufd $0x39,%xmm2,%xmm2
+pshufd $0x39,%xmm3,%xmm3
+xorl 20(%rsi),%ecx
+xorl 4(%rsi),%r8d
+xorl 52(%rsi),%r9d
+xorl 36(%rsi),%eax
+movl %ecx,20(%rdi)
+movl %r8d,4(%rdi)
+movl %r9d,52(%rdi)
+movl %eax,36(%rdi)
+movd %xmm0,%rcx
+movd %xmm1,%r8
+movd %xmm2,%r9
+movd %xmm3,%rax
+pshufd $0x39,%xmm0,%xmm0
+pshufd $0x39,%xmm1,%xmm1
+pshufd $0x39,%xmm2,%xmm2
+pshufd $0x39,%xmm3,%xmm3
+xorl 40(%rsi),%ecx
+xorl 24(%rsi),%r8d
+xorl 8(%rsi),%r9d
+xorl 56(%rsi),%eax
+movl %ecx,40(%rdi)
+movl %r8d,24(%rdi)
+movl %r9d,8(%rdi)
+movl %eax,56(%rdi)
+movd %xmm0,%rcx
+movd %xmm1,%r8
+movd %xmm2,%r9
+movd %xmm3,%rax
+xorl 60(%rsi),%ecx
+xorl 44(%rsi),%r8d
+xorl 28(%rsi),%r9d
+xorl 12(%rsi),%eax
+movl %ecx,60(%rdi)
+movl %r8d,44(%rdi)
+movl %r9d,28(%rdi)
+movl %eax,12(%rdi)
+movq 480(%rsp),%r9
+movq 472(%rsp),%rcx
+add $1,%rcx
+mov %rcx,%r8
+shr $32,%r8
+movl %ecx,80(%rsp)
+movl %r8d,4+96(%rsp)
+movq %rcx,472(%rsp)
+cmp $64,%r9
+ja ._bytesatleast65
+jae ._bytesatleast64
+
+mov %rdi,%rsi
+mov %rdx,%rdi
+mov %r9,%rcx
+rep movsb
+
+._bytesatleast64:
+._done:
+movq 416(%rsp),%r11
+movq 424(%rsp),%r12
+movq 432(%rsp),%r13
+movq 440(%rsp),%r14
+movq 448(%rsp),%r15
+movq 456(%rsp),%rbx
+movq 464(%rsp),%rbp
+add %r11,%rsp
+xor %rax,%rax
+mov %rsi,%rdx
+ret
+
+._bytesatleast65:
+sub $64,%r9
+add $64,%rdi
+add $64,%rsi
+jmp ._bytesbetween1and255
+
+#endif
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/libs/libsodium/src/crypto_stream/salsa20/xmm6/salsa20_xmm6.c b/libs/libsodium/src/crypto_stream/salsa20/xmm6/salsa20_xmm6.c
new file mode 100644
index 0000000000..0a6fee0f3e
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa20/xmm6/salsa20_xmm6.c
@@ -0,0 +1,31 @@
+
+#include <stdint.h>
+
+#include "utils.h"
+
+#include "../stream_salsa20.h"
+#include "salsa20_xmm6.h"
+
+#ifdef HAVE_AMD64_ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int stream_salsa20_xmm6(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k);
+
+extern int stream_salsa20_xmm6_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n,
+ uint64_t ic, const unsigned char *k);
+#ifdef __cplusplus
+}
+#endif
+
+struct crypto_stream_salsa20_implementation
+ crypto_stream_salsa20_xmm6_implementation = {
+ SODIUM_C99(.stream =) stream_salsa20_xmm6,
+ SODIUM_C99(.stream_xor_ic =) stream_salsa20_xmm6_xor_ic,
+ };
+
+#endif
diff --git a/libs/libsodium/src/crypto_stream/salsa20/xmm6/salsa20_xmm6.h b/libs/libsodium/src/crypto_stream/salsa20/xmm6/salsa20_xmm6.h
new file mode 100644
index 0000000000..d38473a9ff
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa20/xmm6/salsa20_xmm6.h
@@ -0,0 +1,8 @@
+
+#include <stdint.h>
+
+#include "../stream_salsa20.h"
+#include "crypto_stream_salsa20.h"
+
+extern struct crypto_stream_salsa20_implementation
+ crypto_stream_salsa20_xmm6_implementation;
diff --git a/libs/libsodium/src/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-avx2.c b/libs/libsodium/src/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-avx2.c
new file mode 100644
index 0000000000..18d4773ec9
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-avx2.c
@@ -0,0 +1,131 @@
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "crypto_stream_salsa20.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+#include "utils.h"
+
+#if defined(HAVE_AVX2INTRIN_H) && defined(HAVE_EMMINTRIN_H) && \
+ defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# pragma GCC target("ssse3")
+# pragma GCC target("sse4.1")
+# pragma GCC target("avx2")
+# endif
+
+#include <emmintrin.h>
+#include <immintrin.h>
+#include <smmintrin.h>
+#include <tmmintrin.h>
+
+# include "../stream_salsa20.h"
+# include "salsa20_xmm6int-avx2.h"
+
+# define ROUNDS 20
+
+typedef struct salsa_ctx {
+ uint32_t input[16];
+} salsa_ctx;
+
+static const int TR[16] = {
+ 0, 5, 10, 15, 12, 1, 6, 11, 8, 13, 2, 7, 4, 9, 14, 3
+};
+
+static void
+salsa_keysetup(salsa_ctx *ctx, const uint8_t *k)
+{
+ ctx->input[TR[1]] = LOAD32_LE(k + 0);
+ ctx->input[TR[2]] = LOAD32_LE(k + 4);
+ ctx->input[TR[3]] = LOAD32_LE(k + 8);
+ ctx->input[TR[4]] = LOAD32_LE(k + 12);
+ ctx->input[TR[11]] = LOAD32_LE(k + 16);
+ ctx->input[TR[12]] = LOAD32_LE(k + 20);
+ ctx->input[TR[13]] = LOAD32_LE(k + 24);
+ ctx->input[TR[14]] = LOAD32_LE(k + 28);
+ ctx->input[TR[0]] = 0x61707865;
+ ctx->input[TR[5]] = 0x3320646e;
+ ctx->input[TR[10]] = 0x79622d32;
+ ctx->input[TR[15]] = 0x6b206574;
+}
+
+static void
+salsa_ivsetup(salsa_ctx *ctx, const uint8_t *iv, const uint8_t *counter)
+{
+ ctx->input[TR[6]] = LOAD32_LE(iv + 0);
+ ctx->input[TR[7]] = LOAD32_LE(iv + 4);
+ ctx->input[TR[8]] = counter == NULL ? 0 : LOAD32_LE(counter + 0);
+ ctx->input[TR[9]] = counter == NULL ? 0 : LOAD32_LE(counter + 4);
+}
+
+static void
+salsa20_encrypt_bytes(salsa_ctx *ctx, const uint8_t *m, uint8_t *c,
+ unsigned long long bytes)
+{
+ uint32_t * const x = &ctx->input[0];
+
+ if (!bytes) {
+ return; /* LCOV_EXCL_LINE */
+ }
+
+#include "u8.h"
+#include "u4.h"
+#include "u1.h"
+#include "u0.h"
+}
+
+static int
+stream_avx2(unsigned char *c, unsigned long long clen, const unsigned char *n,
+ const unsigned char *k)
+{
+ struct salsa_ctx ctx;
+
+ if (!clen) {
+ return 0;
+ }
+ COMPILER_ASSERT(crypto_stream_salsa20_KEYBYTES == 256 / 8);
+ salsa_keysetup(&ctx, k);
+ salsa_ivsetup(&ctx, n, NULL);
+ memset(c, 0, clen);
+ salsa20_encrypt_bytes(&ctx, c, c, clen);
+ sodium_memzero(&ctx, sizeof ctx);
+
+ return 0;
+}
+
+static int
+stream_avx2_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n, uint64_t ic,
+ const unsigned char *k)
+{
+ struct salsa_ctx ctx;
+ uint8_t ic_bytes[8];
+ uint32_t ic_high;
+ uint32_t ic_low;
+
+ if (!mlen) {
+ return 0;
+ }
+ ic_high = (uint32_t) (ic >> 32);
+ ic_low = (uint32_t) ic;
+ STORE32_LE(&ic_bytes[0], ic_low);
+ STORE32_LE(&ic_bytes[4], ic_high);
+ salsa_keysetup(&ctx, k);
+ salsa_ivsetup(&ctx, n, ic_bytes);
+ salsa20_encrypt_bytes(&ctx, m, c, mlen);
+ sodium_memzero(&ctx, sizeof ctx);
+
+ return 0;
+}
+
+struct crypto_stream_salsa20_implementation
+ crypto_stream_salsa20_xmm6int_avx2_implementation = {
+ SODIUM_C99(.stream =) stream_avx2,
+ SODIUM_C99(.stream_xor_ic =) stream_avx2_xor_ic
+ };
+
+#endif
diff --git a/libs/libsodium/src/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-avx2.h b/libs/libsodium/src/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-avx2.h
new file mode 100644
index 0000000000..0924e9baff
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-avx2.h
@@ -0,0 +1,8 @@
+
+#include <stdint.h>
+
+#include "../stream_salsa20.h"
+#include "crypto_stream_salsa20.h"
+
+extern struct crypto_stream_salsa20_implementation
+ crypto_stream_salsa20_xmm6int_avx2_implementation;
diff --git a/libs/libsodium/src/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-sse2.c b/libs/libsodium/src/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-sse2.c
new file mode 100644
index 0000000000..d8e53a6554
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-sse2.c
@@ -0,0 +1,122 @@
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "crypto_stream_salsa20.h"
+#include "private/common.h"
+#include "private/sse2_64_32.h"
+#include "utils.h"
+
+#ifdef HAVE_EMMINTRIN_H
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# endif
+# include <emmintrin.h>
+
+# include "../stream_salsa20.h"
+# include "salsa20_xmm6int-sse2.h"
+
+# define ROUNDS 20
+
+typedef struct salsa_ctx {
+ uint32_t input[16];
+} salsa_ctx;
+
+static const int TR[16] = {
+ 0, 5, 10, 15, 12, 1, 6, 11, 8, 13, 2, 7, 4, 9, 14, 3
+};
+
+static void
+salsa_keysetup(salsa_ctx *ctx, const uint8_t *k)
+{
+ ctx->input[TR[1]] = LOAD32_LE(k + 0);
+ ctx->input[TR[2]] = LOAD32_LE(k + 4);
+ ctx->input[TR[3]] = LOAD32_LE(k + 8);
+ ctx->input[TR[4]] = LOAD32_LE(k + 12);
+ ctx->input[TR[11]] = LOAD32_LE(k + 16);
+ ctx->input[TR[12]] = LOAD32_LE(k + 20);
+ ctx->input[TR[13]] = LOAD32_LE(k + 24);
+ ctx->input[TR[14]] = LOAD32_LE(k + 28);
+ ctx->input[TR[0]] = 0x61707865;
+ ctx->input[TR[5]] = 0x3320646e;
+ ctx->input[TR[10]] = 0x79622d32;
+ ctx->input[TR[15]] = 0x6b206574;
+}
+
+static void
+salsa_ivsetup(salsa_ctx *ctx, const uint8_t *iv, const uint8_t *counter)
+{
+ ctx->input[TR[6]] = LOAD32_LE(iv + 0);
+ ctx->input[TR[7]] = LOAD32_LE(iv + 4);
+ ctx->input[TR[8]] = counter == NULL ? 0 : LOAD32_LE(counter + 0);
+ ctx->input[TR[9]] = counter == NULL ? 0 : LOAD32_LE(counter + 4);
+}
+
+static void
+salsa20_encrypt_bytes(salsa_ctx *ctx, const uint8_t *m, uint8_t *c,
+ unsigned long long bytes)
+{
+ uint32_t * const x = &ctx->input[0];
+
+ if (!bytes) {
+ return; /* LCOV_EXCL_LINE */
+ }
+
+#include "u4.h"
+#include "u1.h"
+#include "u0.h"
+}
+
+static int
+stream_sse2(unsigned char *c, unsigned long long clen, const unsigned char *n,
+ const unsigned char *k)
+{
+ struct salsa_ctx ctx;
+
+ if (!clen) {
+ return 0;
+ }
+ COMPILER_ASSERT(crypto_stream_salsa20_KEYBYTES == 256 / 8);
+ salsa_keysetup(&ctx, k);
+ salsa_ivsetup(&ctx, n, NULL);
+ memset(c, 0, clen);
+ salsa20_encrypt_bytes(&ctx, c, c, clen);
+ sodium_memzero(&ctx, sizeof ctx);
+
+ return 0;
+}
+
+static int
+stream_sse2_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n, uint64_t ic,
+ const unsigned char *k)
+{
+ struct salsa_ctx ctx;
+ uint8_t ic_bytes[8];
+ uint32_t ic_high;
+ uint32_t ic_low;
+
+ if (!mlen) {
+ return 0;
+ }
+ ic_high = (uint32_t) (ic >> 32);
+ ic_low = (uint32_t) (ic);
+ STORE32_LE(&ic_bytes[0], ic_low);
+ STORE32_LE(&ic_bytes[4], ic_high);
+ salsa_keysetup(&ctx, k);
+ salsa_ivsetup(&ctx, n, ic_bytes);
+ salsa20_encrypt_bytes(&ctx, m, c, mlen);
+ sodium_memzero(&ctx, sizeof ctx);
+
+ return 0;
+}
+
+struct crypto_stream_salsa20_implementation
+ crypto_stream_salsa20_xmm6int_sse2_implementation = {
+ SODIUM_C99(.stream =) stream_sse2,
+ SODIUM_C99(.stream_xor_ic =) stream_sse2_xor_ic
+ };
+
+#endif
diff --git a/libs/libsodium/src/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-sse2.h b/libs/libsodium/src/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-sse2.h
new file mode 100644
index 0000000000..ed52a8bcbe
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-sse2.h
@@ -0,0 +1,8 @@
+
+#include <stdint.h>
+
+#include "../stream_salsa20.h"
+#include "crypto_stream_salsa20.h"
+
+extern struct crypto_stream_salsa20_implementation
+ crypto_stream_salsa20_xmm6int_sse2_implementation;
diff --git a/libs/libsodium/src/crypto_stream/salsa20/xmm6int/u0.h b/libs/libsodium/src/crypto_stream/salsa20/xmm6int/u0.h
new file mode 100644
index 0000000000..b2d4168058
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa20/xmm6int/u0.h
@@ -0,0 +1,195 @@
+if (bytes > 0) {
+ __m128i diag0 = _mm_loadu_si128((__m128i *) (x + 0));
+ __m128i diag1 = _mm_loadu_si128((__m128i *) (x + 4));
+ __m128i diag2 = _mm_loadu_si128((__m128i *) (x + 8));
+ __m128i diag3 = _mm_loadu_si128((__m128i *) (x + 12));
+ __m128i a0, a1, a2, a3, a4, a5, a6, a7;
+ __m128i b0, b1, b2, b3, b4, b5, b6, b7;
+ uint8_t partialblock[64];
+
+ unsigned int i;
+
+ a0 = diag1;
+ for (i = 0; i < ROUNDS; i += 4) {
+ a0 = _mm_add_epi32(a0, diag0);
+ a1 = diag0;
+ b0 = a0;
+ a0 = _mm_slli_epi32(a0, 7);
+ b0 = _mm_srli_epi32(b0, 25);
+ diag3 = _mm_xor_si128(diag3, a0);
+
+ diag3 = _mm_xor_si128(diag3, b0);
+
+ a1 = _mm_add_epi32(a1, diag3);
+ a2 = diag3;
+ b1 = a1;
+ a1 = _mm_slli_epi32(a1, 9);
+ b1 = _mm_srli_epi32(b1, 23);
+ diag2 = _mm_xor_si128(diag2, a1);
+ diag3 = _mm_shuffle_epi32(diag3, 0x93);
+ diag2 = _mm_xor_si128(diag2, b1);
+
+ a2 = _mm_add_epi32(a2, diag2);
+ a3 = diag2;
+ b2 = a2;
+ a2 = _mm_slli_epi32(a2, 13);
+ b2 = _mm_srli_epi32(b2, 19);
+ diag1 = _mm_xor_si128(diag1, a2);
+ diag2 = _mm_shuffle_epi32(diag2, 0x4e);
+ diag1 = _mm_xor_si128(diag1, b2);
+
+ a3 = _mm_add_epi32(a3, diag1);
+ a4 = diag3;
+ b3 = a3;
+ a3 = _mm_slli_epi32(a3, 18);
+ b3 = _mm_srli_epi32(b3, 14);
+ diag0 = _mm_xor_si128(diag0, a3);
+ diag1 = _mm_shuffle_epi32(diag1, 0x39);
+ diag0 = _mm_xor_si128(diag0, b3);
+
+ a4 = _mm_add_epi32(a4, diag0);
+ a5 = diag0;
+ b4 = a4;
+ a4 = _mm_slli_epi32(a4, 7);
+ b4 = _mm_srli_epi32(b4, 25);
+ diag1 = _mm_xor_si128(diag1, a4);
+
+ diag1 = _mm_xor_si128(diag1, b4);
+
+ a5 = _mm_add_epi32(a5, diag1);
+ a6 = diag1;
+ b5 = a5;
+ a5 = _mm_slli_epi32(a5, 9);
+ b5 = _mm_srli_epi32(b5, 23);
+ diag2 = _mm_xor_si128(diag2, a5);
+ diag1 = _mm_shuffle_epi32(diag1, 0x93);
+ diag2 = _mm_xor_si128(diag2, b5);
+
+ a6 = _mm_add_epi32(a6, diag2);
+ a7 = diag2;
+ b6 = a6;
+ a6 = _mm_slli_epi32(a6, 13);
+ b6 = _mm_srli_epi32(b6, 19);
+ diag3 = _mm_xor_si128(diag3, a6);
+ diag2 = _mm_shuffle_epi32(diag2, 0x4e);
+ diag3 = _mm_xor_si128(diag3, b6);
+
+ a7 = _mm_add_epi32(a7, diag3);
+ a0 = diag1;
+ b7 = a7;
+ a7 = _mm_slli_epi32(a7, 18);
+ b7 = _mm_srli_epi32(b7, 14);
+ diag0 = _mm_xor_si128(diag0, a7);
+ diag3 = _mm_shuffle_epi32(diag3, 0x39);
+ diag0 = _mm_xor_si128(diag0, b7);
+
+ a0 = _mm_add_epi32(a0, diag0);
+ a1 = diag0;
+ b0 = a0;
+ a0 = _mm_slli_epi32(a0, 7);
+ b0 = _mm_srli_epi32(b0, 25);
+ diag3 = _mm_xor_si128(diag3, a0);
+
+ diag3 = _mm_xor_si128(diag3, b0);
+
+ a1 = _mm_add_epi32(a1, diag3);
+ a2 = diag3;
+ b1 = a1;
+ a1 = _mm_slli_epi32(a1, 9);
+ b1 = _mm_srli_epi32(b1, 23);
+ diag2 = _mm_xor_si128(diag2, a1);
+ diag3 = _mm_shuffle_epi32(diag3, 0x93);
+ diag2 = _mm_xor_si128(diag2, b1);
+
+ a2 = _mm_add_epi32(a2, diag2);
+ a3 = diag2;
+ b2 = a2;
+ a2 = _mm_slli_epi32(a2, 13);
+ b2 = _mm_srli_epi32(b2, 19);
+ diag1 = _mm_xor_si128(diag1, a2);
+ diag2 = _mm_shuffle_epi32(diag2, 0x4e);
+ diag1 = _mm_xor_si128(diag1, b2);
+
+ a3 = _mm_add_epi32(a3, diag1);
+ a4 = diag3;
+ b3 = a3;
+ a3 = _mm_slli_epi32(a3, 18);
+ b3 = _mm_srli_epi32(b3, 14);
+ diag0 = _mm_xor_si128(diag0, a3);
+ diag1 = _mm_shuffle_epi32(diag1, 0x39);
+ diag0 = _mm_xor_si128(diag0, b3);
+
+ a4 = _mm_add_epi32(a4, diag0);
+ a5 = diag0;
+ b4 = a4;
+ a4 = _mm_slli_epi32(a4, 7);
+ b4 = _mm_srli_epi32(b4, 25);
+ diag1 = _mm_xor_si128(diag1, a4);
+
+ diag1 = _mm_xor_si128(diag1, b4);
+
+ a5 = _mm_add_epi32(a5, diag1);
+ a6 = diag1;
+ b5 = a5;
+ a5 = _mm_slli_epi32(a5, 9);
+ b5 = _mm_srli_epi32(b5, 23);
+ diag2 = _mm_xor_si128(diag2, a5);
+ diag1 = _mm_shuffle_epi32(diag1, 0x93);
+ diag2 = _mm_xor_si128(diag2, b5);
+
+ a6 = _mm_add_epi32(a6, diag2);
+ a7 = diag2;
+ b6 = a6;
+ a6 = _mm_slli_epi32(a6, 13);
+ b6 = _mm_srli_epi32(b6, 19);
+ diag3 = _mm_xor_si128(diag3, a6);
+ diag2 = _mm_shuffle_epi32(diag2, 0x4e);
+ diag3 = _mm_xor_si128(diag3, b6);
+
+ a7 = _mm_add_epi32(a7, diag3);
+ a0 = diag1;
+ b7 = a7;
+ a7 = _mm_slli_epi32(a7, 18);
+ b7 = _mm_srli_epi32(b7, 14);
+ diag0 = _mm_xor_si128(diag0, a7);
+ diag3 = _mm_shuffle_epi32(diag3, 0x39);
+ diag0 = _mm_xor_si128(diag0, b7);
+ }
+
+ diag0 = _mm_add_epi32(diag0, _mm_loadu_si128((__m128i *) (x + 0)));
+ diag1 = _mm_add_epi32(diag1, _mm_loadu_si128((__m128i *) (x + 4)));
+ diag2 = _mm_add_epi32(diag2, _mm_loadu_si128((__m128i *) (x + 8)));
+ diag3 = _mm_add_epi32(diag3, _mm_loadu_si128((__m128i *) (x + 12)));
+
+#define ONEQUAD_SHUFFLE(A, B, C, D) \
+ do { \
+ uint32_t in##A = _mm_cvtsi128_si32(diag0); \
+ uint32_t in##B = _mm_cvtsi128_si32(diag1); \
+ uint32_t in##C = _mm_cvtsi128_si32(diag2); \
+ uint32_t in##D = _mm_cvtsi128_si32(diag3); \
+ diag0 = _mm_shuffle_epi32(diag0, 0x39); \
+ diag1 = _mm_shuffle_epi32(diag1, 0x39); \
+ diag2 = _mm_shuffle_epi32(diag2, 0x39); \
+ diag3 = _mm_shuffle_epi32(diag3, 0x39); \
+ *(uint32_t *) (partialblock + (A * 4)) = in##A; \
+ *(uint32_t *) (partialblock + (B * 4)) = in##B; \
+ *(uint32_t *) (partialblock + (C * 4)) = in##C; \
+ *(uint32_t *) (partialblock + (D * 4)) = in##D; \
+ } while (0)
+
+#define ONEQUAD(A, B, C, D) ONEQUAD_SHUFFLE(A, B, C, D)
+
+ ONEQUAD(0, 12, 8, 4);
+ ONEQUAD(5, 1, 13, 9);
+ ONEQUAD(10, 6, 2, 14);
+ ONEQUAD(15, 11, 7, 3);
+
+#undef ONEQUAD
+#undef ONEQUAD_SHUFFLE
+
+ for (i = 0; i < bytes; i++) {
+ c[i] = m[i] ^ partialblock[i];
+ }
+
+ sodium_memzero(partialblock, sizeof partialblock);
+}
diff --git a/libs/libsodium/src/crypto_stream/salsa20/xmm6int/u1.h b/libs/libsodium/src/crypto_stream/salsa20/xmm6int/u1.h
new file mode 100644
index 0000000000..c245d9565f
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa20/xmm6int/u1.h
@@ -0,0 +1,207 @@
+while (bytes >= 64) {
+ __m128i diag0 = _mm_loadu_si128((__m128i *) (x + 0));
+ __m128i diag1 = _mm_loadu_si128((__m128i *) (x + 4));
+ __m128i diag2 = _mm_loadu_si128((__m128i *) (x + 8));
+ __m128i diag3 = _mm_loadu_si128((__m128i *) (x + 12));
+ __m128i a0, a1, a2, a3, a4, a5, a6, a7;
+ __m128i b0, b1, b2, b3, b4, b5, b6, b7;
+
+ uint32_t in8;
+ uint32_t in9;
+ int i;
+
+ a0 = diag1;
+ for (i = 0; i < ROUNDS; i += 4) {
+ a0 = _mm_add_epi32(a0, diag0);
+ a1 = diag0;
+ b0 = a0;
+ a0 = _mm_slli_epi32(a0, 7);
+ b0 = _mm_srli_epi32(b0, 25);
+ diag3 = _mm_xor_si128(diag3, a0);
+
+ diag3 = _mm_xor_si128(diag3, b0);
+
+ a1 = _mm_add_epi32(a1, diag3);
+ a2 = diag3;
+ b1 = a1;
+ a1 = _mm_slli_epi32(a1, 9);
+ b1 = _mm_srli_epi32(b1, 23);
+ diag2 = _mm_xor_si128(diag2, a1);
+ diag3 = _mm_shuffle_epi32(diag3, 0x93);
+ diag2 = _mm_xor_si128(diag2, b1);
+
+ a2 = _mm_add_epi32(a2, diag2);
+ a3 = diag2;
+ b2 = a2;
+ a2 = _mm_slli_epi32(a2, 13);
+ b2 = _mm_srli_epi32(b2, 19);
+ diag1 = _mm_xor_si128(diag1, a2);
+ diag2 = _mm_shuffle_epi32(diag2, 0x4e);
+ diag1 = _mm_xor_si128(diag1, b2);
+
+ a3 = _mm_add_epi32(a3, diag1);
+ a4 = diag3;
+ b3 = a3;
+ a3 = _mm_slli_epi32(a3, 18);
+ b3 = _mm_srli_epi32(b3, 14);
+ diag0 = _mm_xor_si128(diag0, a3);
+ diag1 = _mm_shuffle_epi32(diag1, 0x39);
+ diag0 = _mm_xor_si128(diag0, b3);
+
+ a4 = _mm_add_epi32(a4, diag0);
+ a5 = diag0;
+ b4 = a4;
+ a4 = _mm_slli_epi32(a4, 7);
+ b4 = _mm_srli_epi32(b4, 25);
+ diag1 = _mm_xor_si128(diag1, a4);
+
+ diag1 = _mm_xor_si128(diag1, b4);
+
+ a5 = _mm_add_epi32(a5, diag1);
+ a6 = diag1;
+ b5 = a5;
+ a5 = _mm_slli_epi32(a5, 9);
+ b5 = _mm_srli_epi32(b5, 23);
+ diag2 = _mm_xor_si128(diag2, a5);
+ diag1 = _mm_shuffle_epi32(diag1, 0x93);
+ diag2 = _mm_xor_si128(diag2, b5);
+
+ a6 = _mm_add_epi32(a6, diag2);
+ a7 = diag2;
+ b6 = a6;
+ a6 = _mm_slli_epi32(a6, 13);
+ b6 = _mm_srli_epi32(b6, 19);
+ diag3 = _mm_xor_si128(diag3, a6);
+ diag2 = _mm_shuffle_epi32(diag2, 0x4e);
+ diag3 = _mm_xor_si128(diag3, b6);
+
+ a7 = _mm_add_epi32(a7, diag3);
+ a0 = diag1;
+ b7 = a7;
+ a7 = _mm_slli_epi32(a7, 18);
+ b7 = _mm_srli_epi32(b7, 14);
+ diag0 = _mm_xor_si128(diag0, a7);
+ diag3 = _mm_shuffle_epi32(diag3, 0x39);
+ diag0 = _mm_xor_si128(diag0, b7);
+
+ a0 = _mm_add_epi32(a0, diag0);
+ a1 = diag0;
+ b0 = a0;
+ a0 = _mm_slli_epi32(a0, 7);
+ b0 = _mm_srli_epi32(b0, 25);
+ diag3 = _mm_xor_si128(diag3, a0);
+
+ diag3 = _mm_xor_si128(diag3, b0);
+
+ a1 = _mm_add_epi32(a1, diag3);
+ a2 = diag3;
+ b1 = a1;
+ a1 = _mm_slli_epi32(a1, 9);
+ b1 = _mm_srli_epi32(b1, 23);
+ diag2 = _mm_xor_si128(diag2, a1);
+ diag3 = _mm_shuffle_epi32(diag3, 0x93);
+ diag2 = _mm_xor_si128(diag2, b1);
+
+ a2 = _mm_add_epi32(a2, diag2);
+ a3 = diag2;
+ b2 = a2;
+ a2 = _mm_slli_epi32(a2, 13);
+ b2 = _mm_srli_epi32(b2, 19);
+ diag1 = _mm_xor_si128(diag1, a2);
+ diag2 = _mm_shuffle_epi32(diag2, 0x4e);
+ diag1 = _mm_xor_si128(diag1, b2);
+
+ a3 = _mm_add_epi32(a3, diag1);
+ a4 = diag3;
+ b3 = a3;
+ a3 = _mm_slli_epi32(a3, 18);
+ b3 = _mm_srli_epi32(b3, 14);
+ diag0 = _mm_xor_si128(diag0, a3);
+ diag1 = _mm_shuffle_epi32(diag1, 0x39);
+ diag0 = _mm_xor_si128(diag0, b3);
+
+ a4 = _mm_add_epi32(a4, diag0);
+ a5 = diag0;
+ b4 = a4;
+ a4 = _mm_slli_epi32(a4, 7);
+ b4 = _mm_srli_epi32(b4, 25);
+ diag1 = _mm_xor_si128(diag1, a4);
+
+ diag1 = _mm_xor_si128(diag1, b4);
+
+ a5 = _mm_add_epi32(a5, diag1);
+ a6 = diag1;
+ b5 = a5;
+ a5 = _mm_slli_epi32(a5, 9);
+ b5 = _mm_srli_epi32(b5, 23);
+ diag2 = _mm_xor_si128(diag2, a5);
+ diag1 = _mm_shuffle_epi32(diag1, 0x93);
+ diag2 = _mm_xor_si128(diag2, b5);
+
+ a6 = _mm_add_epi32(a6, diag2);
+ a7 = diag2;
+ b6 = a6;
+ a6 = _mm_slli_epi32(a6, 13);
+ b6 = _mm_srli_epi32(b6, 19);
+ diag3 = _mm_xor_si128(diag3, a6);
+ diag2 = _mm_shuffle_epi32(diag2, 0x4e);
+ diag3 = _mm_xor_si128(diag3, b6);
+
+ a7 = _mm_add_epi32(a7, diag3);
+ a0 = diag1;
+ b7 = a7;
+ a7 = _mm_slli_epi32(a7, 18);
+ b7 = _mm_srli_epi32(b7, 14);
+ diag0 = _mm_xor_si128(diag0, a7);
+ diag3 = _mm_shuffle_epi32(diag3, 0x39);
+ diag0 = _mm_xor_si128(diag0, b7);
+ }
+
+ diag0 = _mm_add_epi32(diag0, _mm_loadu_si128((__m128i *) (x + 0)));
+ diag1 = _mm_add_epi32(diag1, _mm_loadu_si128((__m128i *) (x + 4)));
+ diag2 = _mm_add_epi32(diag2, _mm_loadu_si128((__m128i *) (x + 8)));
+ diag3 = _mm_add_epi32(diag3, _mm_loadu_si128((__m128i *) (x + 12)));
+
+#define ONEQUAD_SHUFFLE(A, B, C, D) \
+ do { \
+ uint32_t in##A = _mm_cvtsi128_si32(diag0); \
+ uint32_t in##B = _mm_cvtsi128_si32(diag1); \
+ uint32_t in##C = _mm_cvtsi128_si32(diag2); \
+ uint32_t in##D = _mm_cvtsi128_si32(diag3); \
+ diag0 = _mm_shuffle_epi32(diag0, 0x39); \
+ diag1 = _mm_shuffle_epi32(diag1, 0x39); \
+ diag2 = _mm_shuffle_epi32(diag2, 0x39); \
+ diag3 = _mm_shuffle_epi32(diag3, 0x39); \
+ in##A ^= *(uint32_t *) (m + (A * 4)); \
+ in##B ^= *(uint32_t *) (m + (B * 4)); \
+ in##C ^= *(uint32_t *) (m + (C * 4)); \
+ in##D ^= *(uint32_t *) (m + (D * 4)); \
+ *(uint32_t *) (c + (A * 4)) = in##A; \
+ *(uint32_t *) (c + (B * 4)) = in##B; \
+ *(uint32_t *) (c + (C * 4)) = in##C; \
+ *(uint32_t *) (c + (D * 4)) = in##D; \
+ } while (0)
+
+#define ONEQUAD(A, B, C, D) ONEQUAD_SHUFFLE(A, B, C, D)
+
+ ONEQUAD(0, 12, 8, 4);
+ ONEQUAD(5, 1, 13, 9);
+ ONEQUAD(10, 6, 2, 14);
+ ONEQUAD(15, 11, 7, 3);
+
+#undef ONEQUAD
+#undef ONEQUAD_SHUFFLE
+
+ in8 = x[8];
+ in9 = x[13];
+ in8++;
+ if (in8 == 0) {
+ in9++;
+ }
+ x[8] = in8;
+ x[13] = in9;
+
+ c += 64;
+ m += 64;
+ bytes -= 64;
+}
diff --git a/libs/libsodium/src/crypto_stream/salsa20/xmm6int/u4.h b/libs/libsodium/src/crypto_stream/salsa20/xmm6int/u4.h
new file mode 100644
index 0000000000..61d935fc90
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa20/xmm6int/u4.h
@@ -0,0 +1,547 @@
+if (bytes >= 256) {
+ __m128i y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14,
+ y15;
+ __m128i z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13, z14,
+ z15;
+ __m128i orig0, orig1, orig2, orig3, orig4, orig5, orig6, orig7, orig8,
+ orig9, orig10, orig11, orig12, orig13, orig14, orig15;
+
+ uint32_t in8;
+ uint32_t in9;
+ int i;
+
+ /* element broadcast immediate for _mm_shuffle_epi32 are in order:
+ 0x00, 0x55, 0xaa, 0xff */
+ z0 = _mm_loadu_si128((__m128i *) (x + 0));
+ z5 = _mm_shuffle_epi32(z0, 0x55);
+ z10 = _mm_shuffle_epi32(z0, 0xaa);
+ z15 = _mm_shuffle_epi32(z0, 0xff);
+ z0 = _mm_shuffle_epi32(z0, 0x00);
+ z1 = _mm_loadu_si128((__m128i *) (x + 4));
+ z6 = _mm_shuffle_epi32(z1, 0xaa);
+ z11 = _mm_shuffle_epi32(z1, 0xff);
+ z12 = _mm_shuffle_epi32(z1, 0x00);
+ z1 = _mm_shuffle_epi32(z1, 0x55);
+ z2 = _mm_loadu_si128((__m128i *) (x + 8));
+ z7 = _mm_shuffle_epi32(z2, 0xff);
+ z13 = _mm_shuffle_epi32(z2, 0x55);
+ z2 = _mm_shuffle_epi32(z2, 0xaa);
+ /* no z8 -> first half of the nonce, will fill later */
+ z3 = _mm_loadu_si128((__m128i *) (x + 12));
+ z4 = _mm_shuffle_epi32(z3, 0x00);
+ z14 = _mm_shuffle_epi32(z3, 0xaa);
+ z3 = _mm_shuffle_epi32(z3, 0xff);
+ /* no z9 -> second half of the nonce, will fill later */
+ orig0 = z0;
+ orig1 = z1;
+ orig2 = z2;
+ orig3 = z3;
+ orig4 = z4;
+ orig5 = z5;
+ orig6 = z6;
+ orig7 = z7;
+ orig10 = z10;
+ orig11 = z11;
+ orig12 = z12;
+ orig13 = z13;
+ orig14 = z14;
+ orig15 = z15;
+
+ while (bytes >= 256) {
+ /* vector implementation for z8 and z9 */
+ /* not sure if it helps for only 4 blocks */
+ const __m128i addv8 = _mm_set_epi64x(1, 0);
+ const __m128i addv9 = _mm_set_epi64x(3, 2);
+ __m128i t8, t9;
+ uint64_t in89;
+
+ in8 = x[8];
+ in9 = x[13];
+ in89 = ((uint64_t) in8) | (((uint64_t) in9) << 32);
+ t8 = _mm_set1_epi64x(in89);
+ t9 = _mm_set1_epi64x(in89);
+
+ z8 = _mm_add_epi64(addv8, t8);
+ z9 = _mm_add_epi64(addv9, t9);
+
+ t8 = _mm_unpacklo_epi32(z8, z9);
+ t9 = _mm_unpackhi_epi32(z8, z9);
+
+ z8 = _mm_unpacklo_epi32(t8, t9);
+ z9 = _mm_unpackhi_epi32(t8, t9);
+
+ orig8 = z8;
+ orig9 = z9;
+
+ in89 += 4;
+
+ x[8] = in89 & 0xFFFFFFFF;
+ x[13] = (in89 >> 32) & 0xFFFFFFFF;
+
+ z5 = orig5;
+ z10 = orig10;
+ z15 = orig15;
+ z14 = orig14;
+ z3 = orig3;
+ z6 = orig6;
+ z11 = orig11;
+ z1 = orig1;
+
+ z7 = orig7;
+ z13 = orig13;
+ z2 = orig2;
+ z9 = orig9;
+ z0 = orig0;
+ z12 = orig12;
+ z4 = orig4;
+ z8 = orig8;
+
+ for (i = 0; i < ROUNDS; i += 2) {
+ /* the inner loop is a direct translation (regexp search/replace)
+ * from the amd64-xmm6 ASM */
+ __m128i r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13,
+ r14, r15;
+
+ y4 = z12;
+ y4 = _mm_add_epi32(y4, z0);
+ r4 = y4;
+ y4 = _mm_slli_epi32(y4, 7);
+ z4 = _mm_xor_si128(z4, y4);
+ r4 = _mm_srli_epi32(r4, 25);
+ z4 = _mm_xor_si128(z4, r4);
+
+ y9 = z1;
+ y9 = _mm_add_epi32(y9, z5);
+ r9 = y9;
+ y9 = _mm_slli_epi32(y9, 7);
+ z9 = _mm_xor_si128(z9, y9);
+ r9 = _mm_srli_epi32(r9, 25);
+ z9 = _mm_xor_si128(z9, r9);
+
+ y8 = z0;
+ y8 = _mm_add_epi32(y8, z4);
+ r8 = y8;
+ y8 = _mm_slli_epi32(y8, 9);
+ z8 = _mm_xor_si128(z8, y8);
+ r8 = _mm_srli_epi32(r8, 23);
+ z8 = _mm_xor_si128(z8, r8);
+
+ y13 = z5;
+ y13 = _mm_add_epi32(y13, z9);
+ r13 = y13;
+ y13 = _mm_slli_epi32(y13, 9);
+ z13 = _mm_xor_si128(z13, y13);
+ r13 = _mm_srli_epi32(r13, 23);
+ z13 = _mm_xor_si128(z13, r13);
+
+ y12 = z4;
+ y12 = _mm_add_epi32(y12, z8);
+ r12 = y12;
+ y12 = _mm_slli_epi32(y12, 13);
+ z12 = _mm_xor_si128(z12, y12);
+ r12 = _mm_srli_epi32(r12, 19);
+ z12 = _mm_xor_si128(z12, r12);
+
+ y1 = z9;
+ y1 = _mm_add_epi32(y1, z13);
+ r1 = y1;
+ y1 = _mm_slli_epi32(y1, 13);
+ z1 = _mm_xor_si128(z1, y1);
+ r1 = _mm_srli_epi32(r1, 19);
+ z1 = _mm_xor_si128(z1, r1);
+
+ y0 = z8;
+ y0 = _mm_add_epi32(y0, z12);
+ r0 = y0;
+ y0 = _mm_slli_epi32(y0, 18);
+ z0 = _mm_xor_si128(z0, y0);
+ r0 = _mm_srli_epi32(r0, 14);
+ z0 = _mm_xor_si128(z0, r0);
+
+ y5 = z13;
+ y5 = _mm_add_epi32(y5, z1);
+ r5 = y5;
+ y5 = _mm_slli_epi32(y5, 18);
+ z5 = _mm_xor_si128(z5, y5);
+ r5 = _mm_srli_epi32(r5, 14);
+ z5 = _mm_xor_si128(z5, r5);
+
+ y14 = z6;
+ y14 = _mm_add_epi32(y14, z10);
+ r14 = y14;
+ y14 = _mm_slli_epi32(y14, 7);
+ z14 = _mm_xor_si128(z14, y14);
+ r14 = _mm_srli_epi32(r14, 25);
+ z14 = _mm_xor_si128(z14, r14);
+
+ y3 = z11;
+ y3 = _mm_add_epi32(y3, z15);
+ r3 = y3;
+ y3 = _mm_slli_epi32(y3, 7);
+ z3 = _mm_xor_si128(z3, y3);
+ r3 = _mm_srli_epi32(r3, 25);
+ z3 = _mm_xor_si128(z3, r3);
+
+ y2 = z10;
+ y2 = _mm_add_epi32(y2, z14);
+ r2 = y2;
+ y2 = _mm_slli_epi32(y2, 9);
+ z2 = _mm_xor_si128(z2, y2);
+ r2 = _mm_srli_epi32(r2, 23);
+ z2 = _mm_xor_si128(z2, r2);
+
+ y7 = z15;
+ y7 = _mm_add_epi32(y7, z3);
+ r7 = y7;
+ y7 = _mm_slli_epi32(y7, 9);
+ z7 = _mm_xor_si128(z7, y7);
+ r7 = _mm_srli_epi32(r7, 23);
+ z7 = _mm_xor_si128(z7, r7);
+
+ y6 = z14;
+ y6 = _mm_add_epi32(y6, z2);
+ r6 = y6;
+ y6 = _mm_slli_epi32(y6, 13);
+ z6 = _mm_xor_si128(z6, y6);
+ r6 = _mm_srli_epi32(r6, 19);
+ z6 = _mm_xor_si128(z6, r6);
+
+ y11 = z3;
+ y11 = _mm_add_epi32(y11, z7);
+ r11 = y11;
+ y11 = _mm_slli_epi32(y11, 13);
+ z11 = _mm_xor_si128(z11, y11);
+ r11 = _mm_srli_epi32(r11, 19);
+ z11 = _mm_xor_si128(z11, r11);
+
+ y10 = z2;
+ y10 = _mm_add_epi32(y10, z6);
+ r10 = y10;
+ y10 = _mm_slli_epi32(y10, 18);
+ z10 = _mm_xor_si128(z10, y10);
+ r10 = _mm_srli_epi32(r10, 14);
+ z10 = _mm_xor_si128(z10, r10);
+
+ y1 = z3;
+ y1 = _mm_add_epi32(y1, z0);
+ r1 = y1;
+ y1 = _mm_slli_epi32(y1, 7);
+ z1 = _mm_xor_si128(z1, y1);
+ r1 = _mm_srli_epi32(r1, 25);
+ z1 = _mm_xor_si128(z1, r1);
+
+ y15 = z7;
+ y15 = _mm_add_epi32(y15, z11);
+ r15 = y15;
+ y15 = _mm_slli_epi32(y15, 18);
+ z15 = _mm_xor_si128(z15, y15);
+ r15 = _mm_srli_epi32(r15, 14);
+ z15 = _mm_xor_si128(z15, r15);
+
+ y6 = z4;
+ y6 = _mm_add_epi32(y6, z5);
+ r6 = y6;
+ y6 = _mm_slli_epi32(y6, 7);
+ z6 = _mm_xor_si128(z6, y6);
+ r6 = _mm_srli_epi32(r6, 25);
+ z6 = _mm_xor_si128(z6, r6);
+
+ y2 = z0;
+ y2 = _mm_add_epi32(y2, z1);
+ r2 = y2;
+ y2 = _mm_slli_epi32(y2, 9);
+ z2 = _mm_xor_si128(z2, y2);
+ r2 = _mm_srli_epi32(r2, 23);
+ z2 = _mm_xor_si128(z2, r2);
+
+ y7 = z5;
+ y7 = _mm_add_epi32(y7, z6);
+ r7 = y7;
+ y7 = _mm_slli_epi32(y7, 9);
+ z7 = _mm_xor_si128(z7, y7);
+ r7 = _mm_srli_epi32(r7, 23);
+ z7 = _mm_xor_si128(z7, r7);
+
+ y3 = z1;
+ y3 = _mm_add_epi32(y3, z2);
+ r3 = y3;
+ y3 = _mm_slli_epi32(y3, 13);
+ z3 = _mm_xor_si128(z3, y3);
+ r3 = _mm_srli_epi32(r3, 19);
+ z3 = _mm_xor_si128(z3, r3);
+
+ y4 = z6;
+ y4 = _mm_add_epi32(y4, z7);
+ r4 = y4;
+ y4 = _mm_slli_epi32(y4, 13);
+ z4 = _mm_xor_si128(z4, y4);
+ r4 = _mm_srli_epi32(r4, 19);
+ z4 = _mm_xor_si128(z4, r4);
+
+ y0 = z2;
+ y0 = _mm_add_epi32(y0, z3);
+ r0 = y0;
+ y0 = _mm_slli_epi32(y0, 18);
+ z0 = _mm_xor_si128(z0, y0);
+ r0 = _mm_srli_epi32(r0, 14);
+ z0 = _mm_xor_si128(z0, r0);
+
+ y5 = z7;
+ y5 = _mm_add_epi32(y5, z4);
+ r5 = y5;
+ y5 = _mm_slli_epi32(y5, 18);
+ z5 = _mm_xor_si128(z5, y5);
+ r5 = _mm_srli_epi32(r5, 14);
+ z5 = _mm_xor_si128(z5, r5);
+
+ y11 = z9;
+ y11 = _mm_add_epi32(y11, z10);
+ r11 = y11;
+ y11 = _mm_slli_epi32(y11, 7);
+ z11 = _mm_xor_si128(z11, y11);
+ r11 = _mm_srli_epi32(r11, 25);
+ z11 = _mm_xor_si128(z11, r11);
+
+ y12 = z14;
+ y12 = _mm_add_epi32(y12, z15);
+ r12 = y12;
+ y12 = _mm_slli_epi32(y12, 7);
+ z12 = _mm_xor_si128(z12, y12);
+ r12 = _mm_srli_epi32(r12, 25);
+ z12 = _mm_xor_si128(z12, r12);
+
+ y8 = z10;
+ y8 = _mm_add_epi32(y8, z11);
+ r8 = y8;
+ y8 = _mm_slli_epi32(y8, 9);
+ z8 = _mm_xor_si128(z8, y8);
+ r8 = _mm_srli_epi32(r8, 23);
+ z8 = _mm_xor_si128(z8, r8);
+
+ y13 = z15;
+ y13 = _mm_add_epi32(y13, z12);
+ r13 = y13;
+ y13 = _mm_slli_epi32(y13, 9);
+ z13 = _mm_xor_si128(z13, y13);
+ r13 = _mm_srli_epi32(r13, 23);
+ z13 = _mm_xor_si128(z13, r13);
+
+ y9 = z11;
+ y9 = _mm_add_epi32(y9, z8);
+ r9 = y9;
+ y9 = _mm_slli_epi32(y9, 13);
+ z9 = _mm_xor_si128(z9, y9);
+ r9 = _mm_srli_epi32(r9, 19);
+ z9 = _mm_xor_si128(z9, r9);
+
+ y14 = z12;
+ y14 = _mm_add_epi32(y14, z13);
+ r14 = y14;
+ y14 = _mm_slli_epi32(y14, 13);
+ z14 = _mm_xor_si128(z14, y14);
+ r14 = _mm_srli_epi32(r14, 19);
+ z14 = _mm_xor_si128(z14, r14);
+
+ y10 = z8;
+ y10 = _mm_add_epi32(y10, z9);
+ r10 = y10;
+ y10 = _mm_slli_epi32(y10, 18);
+ z10 = _mm_xor_si128(z10, y10);
+ r10 = _mm_srli_epi32(r10, 14);
+ z10 = _mm_xor_si128(z10, r10);
+
+ y15 = z13;
+ y15 = _mm_add_epi32(y15, z14);
+ r15 = y15;
+ y15 = _mm_slli_epi32(y15, 18);
+ z15 = _mm_xor_si128(z15, y15);
+ r15 = _mm_srli_epi32(r15, 14);
+ z15 = _mm_xor_si128(z15, r15);
+ }
+
+/* store data ; this macro replicates the original amd64-xmm6 code */
+#define ONEQUAD_SHUFFLE(A, B, C, D) \
+ z##A = _mm_add_epi32(z##A, orig##A); \
+ z##B = _mm_add_epi32(z##B, orig##B); \
+ z##C = _mm_add_epi32(z##C, orig##C); \
+ z##D = _mm_add_epi32(z##D, orig##D); \
+ in##A = _mm_cvtsi128_si32(z##A); \
+ in##B = _mm_cvtsi128_si32(z##B); \
+ in##C = _mm_cvtsi128_si32(z##C); \
+ in##D = _mm_cvtsi128_si32(z##D); \
+ z##A = _mm_shuffle_epi32(z##A, 0x39); \
+ z##B = _mm_shuffle_epi32(z##B, 0x39); \
+ z##C = _mm_shuffle_epi32(z##C, 0x39); \
+ z##D = _mm_shuffle_epi32(z##D, 0x39); \
+ \
+ in##A ^= *(uint32_t *) (m + 0); \
+ in##B ^= *(uint32_t *) (m + 4); \
+ in##C ^= *(uint32_t *) (m + 8); \
+ in##D ^= *(uint32_t *) (m + 12); \
+ \
+ *(uint32_t *) (c + 0) = in##A; \
+ *(uint32_t *) (c + 4) = in##B; \
+ *(uint32_t *) (c + 8) = in##C; \
+ *(uint32_t *) (c + 12) = in##D; \
+ \
+ in##A = _mm_cvtsi128_si32(z##A); \
+ in##B = _mm_cvtsi128_si32(z##B); \
+ in##C = _mm_cvtsi128_si32(z##C); \
+ in##D = _mm_cvtsi128_si32(z##D); \
+ z##A = _mm_shuffle_epi32(z##A, 0x39); \
+ z##B = _mm_shuffle_epi32(z##B, 0x39); \
+ z##C = _mm_shuffle_epi32(z##C, 0x39); \
+ z##D = _mm_shuffle_epi32(z##D, 0x39); \
+ \
+ in##A ^= *(uint32_t *) (m + 64); \
+ in##B ^= *(uint32_t *) (m + 68); \
+ in##C ^= *(uint32_t *) (m + 72); \
+ in##D ^= *(uint32_t *) (m + 76); \
+ *(uint32_t *) (c + 64) = in##A; \
+ *(uint32_t *) (c + 68) = in##B; \
+ *(uint32_t *) (c + 72) = in##C; \
+ *(uint32_t *) (c + 76) = in##D; \
+ \
+ in##A = _mm_cvtsi128_si32(z##A); \
+ in##B = _mm_cvtsi128_si32(z##B); \
+ in##C = _mm_cvtsi128_si32(z##C); \
+ in##D = _mm_cvtsi128_si32(z##D); \
+ z##A = _mm_shuffle_epi32(z##A, 0x39); \
+ z##B = _mm_shuffle_epi32(z##B, 0x39); \
+ z##C = _mm_shuffle_epi32(z##C, 0x39); \
+ z##D = _mm_shuffle_epi32(z##D, 0x39); \
+ \
+ in##A ^= *(uint32_t *) (m + 128); \
+ in##B ^= *(uint32_t *) (m + 132); \
+ in##C ^= *(uint32_t *) (m + 136); \
+ in##D ^= *(uint32_t *) (m + 140); \
+ *(uint32_t *) (c + 128) = in##A; \
+ *(uint32_t *) (c + 132) = in##B; \
+ *(uint32_t *) (c + 136) = in##C; \
+ *(uint32_t *) (c + 140) = in##D; \
+ \
+ in##A = _mm_cvtsi128_si32(z##A); \
+ in##B = _mm_cvtsi128_si32(z##B); \
+ in##C = _mm_cvtsi128_si32(z##C); \
+ in##D = _mm_cvtsi128_si32(z##D); \
+ \
+ in##A ^= *(uint32_t *) (m + 192); \
+ in##B ^= *(uint32_t *) (m + 196); \
+ in##C ^= *(uint32_t *) (m + 200); \
+ in##D ^= *(uint32_t *) (m + 204); \
+ *(uint32_t *) (c + 192) = in##A; \
+ *(uint32_t *) (c + 196) = in##B; \
+ *(uint32_t *) (c + 200) = in##C; \
+ *(uint32_t *) (c + 204) = in##D
+
+/* store data ; this macro replaces shuffle+mov by a direct extract; not much
+ * difference */
+#define ONEQUAD_EXTRACT(A, B, C, D) \
+ z##A = _mm_add_epi32(z##A, orig##A); \
+ z##B = _mm_add_epi32(z##B, orig##B); \
+ z##C = _mm_add_epi32(z##C, orig##C); \
+ z##D = _mm_add_epi32(z##D, orig##D); \
+ in##A = _mm_cvtsi128_si32(z##A); \
+ in##B = _mm_cvtsi128_si32(z##B); \
+ in##C = _mm_cvtsi128_si32(z##C); \
+ in##D = _mm_cvtsi128_si32(z##D); \
+ in##A ^= *(uint32_t *) (m + 0); \
+ in##B ^= *(uint32_t *) (m + 4); \
+ in##C ^= *(uint32_t *) (m + 8); \
+ in##D ^= *(uint32_t *) (m + 12); \
+ *(uint32_t *) (c + 0) = in##A; \
+ *(uint32_t *) (c + 4) = in##B; \
+ *(uint32_t *) (c + 8) = in##C; \
+ *(uint32_t *) (c + 12) = in##D; \
+ \
+ in##A = _mm_extract_epi32(z##A, 1); \
+ in##B = _mm_extract_epi32(z##B, 1); \
+ in##C = _mm_extract_epi32(z##C, 1); \
+ in##D = _mm_extract_epi32(z##D, 1); \
+ \
+ in##A ^= *(uint32_t *) (m + 64); \
+ in##B ^= *(uint32_t *) (m + 68); \
+ in##C ^= *(uint32_t *) (m + 72); \
+ in##D ^= *(uint32_t *) (m + 76); \
+ *(uint32_t *) (c + 64) = in##A; \
+ *(uint32_t *) (c + 68) = in##B; \
+ *(uint32_t *) (c + 72) = in##C; \
+ *(uint32_t *) (c + 76) = in##D; \
+ \
+ in##A = _mm_extract_epi32(z##A, 2); \
+ in##B = _mm_extract_epi32(z##B, 2); \
+ in##C = _mm_extract_epi32(z##C, 2); \
+ in##D = _mm_extract_epi32(z##D, 2); \
+ \
+ in##A ^= *(uint32_t *) (m + 128); \
+ in##B ^= *(uint32_t *) (m + 132); \
+ in##C ^= *(uint32_t *) (m + 136); \
+ in##D ^= *(uint32_t *) (m + 140); \
+ *(uint32_t *) (c + 128) = in##A; \
+ *(uint32_t *) (c + 132) = in##B; \
+ *(uint32_t *) (c + 136) = in##C; \
+ *(uint32_t *) (c + 140) = in##D; \
+ \
+ in##A = _mm_extract_epi32(z##A, 3); \
+ in##B = _mm_extract_epi32(z##B, 3); \
+ in##C = _mm_extract_epi32(z##C, 3); \
+ in##D = _mm_extract_epi32(z##D, 3); \
+ \
+ in##A ^= *(uint32_t *) (m + 192); \
+ in##B ^= *(uint32_t *) (m + 196); \
+ in##C ^= *(uint32_t *) (m + 200); \
+ in##D ^= *(uint32_t *) (m + 204); \
+ *(uint32_t *) (c + 192) = in##A; \
+ *(uint32_t *) (c + 196) = in##B; \
+ *(uint32_t *) (c + 200) = in##C; \
+ *(uint32_t *) (c + 204) = in##D
+
+/* store data ; this macro first transpose data in-registers, and then store
+ * them in memory. much faster with icc. */
+#define ONEQUAD_TRANSPOSE(A, B, C, D) \
+ z##A = _mm_add_epi32(z##A, orig##A); \
+ z##B = _mm_add_epi32(z##B, orig##B); \
+ z##C = _mm_add_epi32(z##C, orig##C); \
+ z##D = _mm_add_epi32(z##D, orig##D); \
+ y##A = _mm_unpacklo_epi32(z##A, z##B); \
+ y##B = _mm_unpacklo_epi32(z##C, z##D); \
+ y##C = _mm_unpackhi_epi32(z##A, z##B); \
+ y##D = _mm_unpackhi_epi32(z##C, z##D); \
+ z##A = _mm_unpacklo_epi64(y##A, y##B); \
+ z##B = _mm_unpackhi_epi64(y##A, y##B); \
+ z##C = _mm_unpacklo_epi64(y##C, y##D); \
+ z##D = _mm_unpackhi_epi64(y##C, y##D); \
+ y##A = _mm_xor_si128(z##A, _mm_loadu_si128((__m128i *) (m + 0))); \
+ _mm_storeu_si128((__m128i *) (c + 0), y##A); \
+ y##B = _mm_xor_si128(z##B, _mm_loadu_si128((__m128i *) (m + 64))); \
+ _mm_storeu_si128((__m128i *) (c + 64), y##B); \
+ y##C = _mm_xor_si128(z##C, _mm_loadu_si128((__m128i *) (m + 128))); \
+ _mm_storeu_si128((__m128i *) (c + 128), y##C); \
+ y##D = _mm_xor_si128(z##D, _mm_loadu_si128((__m128i *) (m + 192))); \
+ _mm_storeu_si128((__m128i *) (c + 192), y##D)
+
+#define ONEQUAD(A, B, C, D) ONEQUAD_TRANSPOSE(A, B, C, D)
+
+ ONEQUAD(0, 1, 2, 3);
+ m += 16;
+ c += 16;
+ ONEQUAD(4, 5, 6, 7);
+ m += 16;
+ c += 16;
+ ONEQUAD(8, 9, 10, 11);
+ m += 16;
+ c += 16;
+ ONEQUAD(12, 13, 14, 15);
+ m -= 48;
+ c -= 48;
+
+#undef ONEQUAD
+#undef ONEQUAD_TRANSPOSE
+#undef ONEQUAD_EXTRACT
+#undef ONEQUAD_SHUFFLE
+
+ bytes -= 256;
+ c += 256;
+ m += 256;
+ }
+}
diff --git a/libs/libsodium/src/crypto_stream/salsa20/xmm6int/u8.h b/libs/libsodium/src/crypto_stream/salsa20/xmm6int/u8.h
new file mode 100644
index 0000000000..467a961299
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa20/xmm6int/u8.h
@@ -0,0 +1,476 @@
+if (bytes >= 512) {
+ __m256i y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14,
+ y15;
+
+ /* the naive way seems as fast (if not a bit faster) than the vector way */
+ __m256i z0 = _mm256_set1_epi32(x[0]);
+ __m256i z5 = _mm256_set1_epi32(x[1]);
+ __m256i z10 = _mm256_set1_epi32(x[2]);
+ __m256i z15 = _mm256_set1_epi32(x[3]);
+ __m256i z12 = _mm256_set1_epi32(x[4]);
+ __m256i z1 = _mm256_set1_epi32(x[5]);
+ __m256i z6 = _mm256_set1_epi32(x[6]);
+ __m256i z11 = _mm256_set1_epi32(x[7]);
+ __m256i z8; /* useless */
+ __m256i z13 = _mm256_set1_epi32(x[9]);
+ __m256i z2 = _mm256_set1_epi32(x[10]);
+ __m256i z7 = _mm256_set1_epi32(x[11]);
+ __m256i z4 = _mm256_set1_epi32(x[12]);
+ __m256i z9; /* useless */
+ __m256i z14 = _mm256_set1_epi32(x[14]);
+ __m256i z3 = _mm256_set1_epi32(x[15]);
+
+ __m256i orig0 = z0;
+ __m256i orig1 = z1;
+ __m256i orig2 = z2;
+ __m256i orig3 = z3;
+ __m256i orig4 = z4;
+ __m256i orig5 = z5;
+ __m256i orig6 = z6;
+ __m256i orig7 = z7;
+ __m256i orig8;
+ __m256i orig9;
+ __m256i orig10 = z10;
+ __m256i orig11 = z11;
+ __m256i orig12 = z12;
+ __m256i orig13 = z13;
+ __m256i orig14 = z14;
+ __m256i orig15 = z15;
+
+ uint32_t in8;
+ uint32_t in9;
+ int i;
+
+ while (bytes >= 512) {
+ /* vector implementation for z8 and z9 */
+ /* faster than the naive version for 8 blocks */
+ const __m256i addv8 = _mm256_set_epi64x(3, 2, 1, 0);
+ const __m256i addv9 = _mm256_set_epi64x(7, 6, 5, 4);
+ const __m256i permute = _mm256_set_epi32(7, 6, 3, 2, 5, 4, 1, 0);
+
+ __m256i t8, t9;
+ uint64_t in89;
+
+ in8 = x[8];
+ in9 = x[13]; /* see arrays above for the address translation */
+ in89 = ((uint64_t) in8) | (((uint64_t) in9) << 32);
+
+ z8 = z9 = _mm256_broadcastq_epi64(_mm_cvtsi64_si128(in89));
+
+ t8 = _mm256_add_epi64(addv8, z8);
+ t9 = _mm256_add_epi64(addv9, z9);
+
+ z8 = _mm256_unpacklo_epi32(t8, t9);
+ z9 = _mm256_unpackhi_epi32(t8, t9);
+
+ t8 = _mm256_unpacklo_epi32(z8, z9);
+ t9 = _mm256_unpackhi_epi32(z8, z9);
+
+ /* required because unpack* are intra-lane */
+ z8 = _mm256_permutevar8x32_epi32(t8, permute);
+ z9 = _mm256_permutevar8x32_epi32(t9, permute);
+
+ orig8 = z8;
+ orig9 = z9;
+
+ in89 += 8;
+
+ x[8] = in89 & 0xFFFFFFFF;
+ x[13] = (in89 >> 32) & 0xFFFFFFFF;
+
+ z5 = orig5;
+ z10 = orig10;
+ z15 = orig15;
+ z14 = orig14;
+ z3 = orig3;
+ z6 = orig6;
+ z11 = orig11;
+ z1 = orig1;
+
+ z7 = orig7;
+ z13 = orig13;
+ z2 = orig2;
+ z9 = orig9;
+ z0 = orig0;
+ z12 = orig12;
+ z4 = orig4;
+ z8 = orig8;
+
+ for (i = 0; i < ROUNDS; i += 2) {
+ /* the inner loop is a direct translation (regexp search/replace)
+ * from the amd64-xmm6 ASM */
+ __m256i r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13,
+ r14, r15;
+
+ y4 = z12;
+ y4 = _mm256_add_epi32(y4, z0);
+ r4 = y4;
+ y4 = _mm256_slli_epi32(y4, 7);
+ z4 = _mm256_xor_si256(z4, y4);
+ r4 = _mm256_srli_epi32(r4, 25);
+ z4 = _mm256_xor_si256(z4, r4);
+
+ y9 = z1;
+ y9 = _mm256_add_epi32(y9, z5);
+ r9 = y9;
+ y9 = _mm256_slli_epi32(y9, 7);
+ z9 = _mm256_xor_si256(z9, y9);
+ r9 = _mm256_srli_epi32(r9, 25);
+ z9 = _mm256_xor_si256(z9, r9);
+
+ y8 = z0;
+ y8 = _mm256_add_epi32(y8, z4);
+ r8 = y8;
+ y8 = _mm256_slli_epi32(y8, 9);
+ z8 = _mm256_xor_si256(z8, y8);
+ r8 = _mm256_srli_epi32(r8, 23);
+ z8 = _mm256_xor_si256(z8, r8);
+
+ y13 = z5;
+ y13 = _mm256_add_epi32(y13, z9);
+ r13 = y13;
+ y13 = _mm256_slli_epi32(y13, 9);
+ z13 = _mm256_xor_si256(z13, y13);
+ r13 = _mm256_srli_epi32(r13, 23);
+ z13 = _mm256_xor_si256(z13, r13);
+
+ y12 = z4;
+ y12 = _mm256_add_epi32(y12, z8);
+ r12 = y12;
+ y12 = _mm256_slli_epi32(y12, 13);
+ z12 = _mm256_xor_si256(z12, y12);
+ r12 = _mm256_srli_epi32(r12, 19);
+ z12 = _mm256_xor_si256(z12, r12);
+
+ y1 = z9;
+ y1 = _mm256_add_epi32(y1, z13);
+ r1 = y1;
+ y1 = _mm256_slli_epi32(y1, 13);
+ z1 = _mm256_xor_si256(z1, y1);
+ r1 = _mm256_srli_epi32(r1, 19);
+ z1 = _mm256_xor_si256(z1, r1);
+
+ y0 = z8;
+ y0 = _mm256_add_epi32(y0, z12);
+ r0 = y0;
+ y0 = _mm256_slli_epi32(y0, 18);
+ z0 = _mm256_xor_si256(z0, y0);
+ r0 = _mm256_srli_epi32(r0, 14);
+ z0 = _mm256_xor_si256(z0, r0);
+
+ y5 = z13;
+ y5 = _mm256_add_epi32(y5, z1);
+ r5 = y5;
+ y5 = _mm256_slli_epi32(y5, 18);
+ z5 = _mm256_xor_si256(z5, y5);
+ r5 = _mm256_srli_epi32(r5, 14);
+ z5 = _mm256_xor_si256(z5, r5);
+
+ y14 = z6;
+ y14 = _mm256_add_epi32(y14, z10);
+ r14 = y14;
+ y14 = _mm256_slli_epi32(y14, 7);
+ z14 = _mm256_xor_si256(z14, y14);
+ r14 = _mm256_srli_epi32(r14, 25);
+ z14 = _mm256_xor_si256(z14, r14);
+
+ y3 = z11;
+ y3 = _mm256_add_epi32(y3, z15);
+ r3 = y3;
+ y3 = _mm256_slli_epi32(y3, 7);
+ z3 = _mm256_xor_si256(z3, y3);
+ r3 = _mm256_srli_epi32(r3, 25);
+ z3 = _mm256_xor_si256(z3, r3);
+
+ y2 = z10;
+ y2 = _mm256_add_epi32(y2, z14);
+ r2 = y2;
+ y2 = _mm256_slli_epi32(y2, 9);
+ z2 = _mm256_xor_si256(z2, y2);
+ r2 = _mm256_srli_epi32(r2, 23);
+ z2 = _mm256_xor_si256(z2, r2);
+
+ y7 = z15;
+ y7 = _mm256_add_epi32(y7, z3);
+ r7 = y7;
+ y7 = _mm256_slli_epi32(y7, 9);
+ z7 = _mm256_xor_si256(z7, y7);
+ r7 = _mm256_srli_epi32(r7, 23);
+ z7 = _mm256_xor_si256(z7, r7);
+
+ y6 = z14;
+ y6 = _mm256_add_epi32(y6, z2);
+ r6 = y6;
+ y6 = _mm256_slli_epi32(y6, 13);
+ z6 = _mm256_xor_si256(z6, y6);
+ r6 = _mm256_srli_epi32(r6, 19);
+ z6 = _mm256_xor_si256(z6, r6);
+
+ y11 = z3;
+ y11 = _mm256_add_epi32(y11, z7);
+ r11 = y11;
+ y11 = _mm256_slli_epi32(y11, 13);
+ z11 = _mm256_xor_si256(z11, y11);
+ r11 = _mm256_srli_epi32(r11, 19);
+ z11 = _mm256_xor_si256(z11, r11);
+
+ y10 = z2;
+ y10 = _mm256_add_epi32(y10, z6);
+ r10 = y10;
+ y10 = _mm256_slli_epi32(y10, 18);
+ z10 = _mm256_xor_si256(z10, y10);
+ r10 = _mm256_srli_epi32(r10, 14);
+ z10 = _mm256_xor_si256(z10, r10);
+
+ y1 = z3;
+ y1 = _mm256_add_epi32(y1, z0);
+ r1 = y1;
+ y1 = _mm256_slli_epi32(y1, 7);
+ z1 = _mm256_xor_si256(z1, y1);
+ r1 = _mm256_srli_epi32(r1, 25);
+ z1 = _mm256_xor_si256(z1, r1);
+
+ y15 = z7;
+ y15 = _mm256_add_epi32(y15, z11);
+ r15 = y15;
+ y15 = _mm256_slli_epi32(y15, 18);
+ z15 = _mm256_xor_si256(z15, y15);
+ r15 = _mm256_srli_epi32(r15, 14);
+ z15 = _mm256_xor_si256(z15, r15);
+
+ y6 = z4;
+ y6 = _mm256_add_epi32(y6, z5);
+ r6 = y6;
+ y6 = _mm256_slli_epi32(y6, 7);
+ z6 = _mm256_xor_si256(z6, y6);
+ r6 = _mm256_srli_epi32(r6, 25);
+ z6 = _mm256_xor_si256(z6, r6);
+
+ y2 = z0;
+ y2 = _mm256_add_epi32(y2, z1);
+ r2 = y2;
+ y2 = _mm256_slli_epi32(y2, 9);
+ z2 = _mm256_xor_si256(z2, y2);
+ r2 = _mm256_srli_epi32(r2, 23);
+ z2 = _mm256_xor_si256(z2, r2);
+
+ y7 = z5;
+ y7 = _mm256_add_epi32(y7, z6);
+ r7 = y7;
+ y7 = _mm256_slli_epi32(y7, 9);
+ z7 = _mm256_xor_si256(z7, y7);
+ r7 = _mm256_srli_epi32(r7, 23);
+ z7 = _mm256_xor_si256(z7, r7);
+
+ y3 = z1;
+ y3 = _mm256_add_epi32(y3, z2);
+ r3 = y3;
+ y3 = _mm256_slli_epi32(y3, 13);
+ z3 = _mm256_xor_si256(z3, y3);
+ r3 = _mm256_srli_epi32(r3, 19);
+ z3 = _mm256_xor_si256(z3, r3);
+
+ y4 = z6;
+ y4 = _mm256_add_epi32(y4, z7);
+ r4 = y4;
+ y4 = _mm256_slli_epi32(y4, 13);
+ z4 = _mm256_xor_si256(z4, y4);
+ r4 = _mm256_srli_epi32(r4, 19);
+ z4 = _mm256_xor_si256(z4, r4);
+
+ y0 = z2;
+ y0 = _mm256_add_epi32(y0, z3);
+ r0 = y0;
+ y0 = _mm256_slli_epi32(y0, 18);
+ z0 = _mm256_xor_si256(z0, y0);
+ r0 = _mm256_srli_epi32(r0, 14);
+ z0 = _mm256_xor_si256(z0, r0);
+
+ y5 = z7;
+ y5 = _mm256_add_epi32(y5, z4);
+ r5 = y5;
+ y5 = _mm256_slli_epi32(y5, 18);
+ z5 = _mm256_xor_si256(z5, y5);
+ r5 = _mm256_srli_epi32(r5, 14);
+ z5 = _mm256_xor_si256(z5, r5);
+
+ y11 = z9;
+ y11 = _mm256_add_epi32(y11, z10);
+ r11 = y11;
+ y11 = _mm256_slli_epi32(y11, 7);
+ z11 = _mm256_xor_si256(z11, y11);
+ r11 = _mm256_srli_epi32(r11, 25);
+ z11 = _mm256_xor_si256(z11, r11);
+
+ y12 = z14;
+ y12 = _mm256_add_epi32(y12, z15);
+ r12 = y12;
+ y12 = _mm256_slli_epi32(y12, 7);
+ z12 = _mm256_xor_si256(z12, y12);
+ r12 = _mm256_srli_epi32(r12, 25);
+ z12 = _mm256_xor_si256(z12, r12);
+
+ y8 = z10;
+ y8 = _mm256_add_epi32(y8, z11);
+ r8 = y8;
+ y8 = _mm256_slli_epi32(y8, 9);
+ z8 = _mm256_xor_si256(z8, y8);
+ r8 = _mm256_srli_epi32(r8, 23);
+ z8 = _mm256_xor_si256(z8, r8);
+
+ y13 = z15;
+ y13 = _mm256_add_epi32(y13, z12);
+ r13 = y13;
+ y13 = _mm256_slli_epi32(y13, 9);
+ z13 = _mm256_xor_si256(z13, y13);
+ r13 = _mm256_srli_epi32(r13, 23);
+ z13 = _mm256_xor_si256(z13, r13);
+
+ y9 = z11;
+ y9 = _mm256_add_epi32(y9, z8);
+ r9 = y9;
+ y9 = _mm256_slli_epi32(y9, 13);
+ z9 = _mm256_xor_si256(z9, y9);
+ r9 = _mm256_srli_epi32(r9, 19);
+ z9 = _mm256_xor_si256(z9, r9);
+
+ y14 = z12;
+ y14 = _mm256_add_epi32(y14, z13);
+ r14 = y14;
+ y14 = _mm256_slli_epi32(y14, 13);
+ z14 = _mm256_xor_si256(z14, y14);
+ r14 = _mm256_srli_epi32(r14, 19);
+ z14 = _mm256_xor_si256(z14, r14);
+
+ y10 = z8;
+ y10 = _mm256_add_epi32(y10, z9);
+ r10 = y10;
+ y10 = _mm256_slli_epi32(y10, 18);
+ z10 = _mm256_xor_si256(z10, y10);
+ r10 = _mm256_srli_epi32(r10, 14);
+ z10 = _mm256_xor_si256(z10, r10);
+
+ y15 = z13;
+ y15 = _mm256_add_epi32(y15, z14);
+ r15 = y15;
+ y15 = _mm256_slli_epi32(y15, 18);
+ z15 = _mm256_xor_si256(z15, y15);
+ r15 = _mm256_srli_epi32(r15, 14);
+ z15 = _mm256_xor_si256(z15, r15);
+ }
+
+/* store data ; this macro first transpose data in-registers, and then store
+ * them in memory. much faster with icc. */
+#define ONEQUAD_TRANSPOSE(A, B, C, D) \
+ { \
+ __m128i t0, t1, t2, t3; \
+ z##A = _mm256_add_epi32(z##A, orig##A); \
+ z##B = _mm256_add_epi32(z##B, orig##B); \
+ z##C = _mm256_add_epi32(z##C, orig##C); \
+ z##D = _mm256_add_epi32(z##D, orig##D); \
+ y##A = _mm256_unpacklo_epi32(z##A, z##B); \
+ y##B = _mm256_unpacklo_epi32(z##C, z##D); \
+ y##C = _mm256_unpackhi_epi32(z##A, z##B); \
+ y##D = _mm256_unpackhi_epi32(z##C, z##D); \
+ z##A = _mm256_unpacklo_epi64(y##A, y##B); \
+ z##B = _mm256_unpackhi_epi64(y##A, y##B); \
+ z##C = _mm256_unpacklo_epi64(y##C, y##D); \
+ z##D = _mm256_unpackhi_epi64(y##C, y##D); \
+ t0 = _mm_xor_si128(_mm256_extracti128_si256(z##A, 0), \
+ _mm_loadu_si128((__m128i*) (m + 0))); \
+ _mm_storeu_si128((__m128i*) (c + 0), t0); \
+ t1 = _mm_xor_si128(_mm256_extracti128_si256(z##B, 0), \
+ _mm_loadu_si128((__m128i*) (m + 64))); \
+ _mm_storeu_si128((__m128i*) (c + 64), t1); \
+ t2 = _mm_xor_si128(_mm256_extracti128_si256(z##C, 0), \
+ _mm_loadu_si128((__m128i*) (m + 128))); \
+ _mm_storeu_si128((__m128i*) (c + 128), t2); \
+ t3 = _mm_xor_si128(_mm256_extracti128_si256(z##D, 0), \
+ _mm_loadu_si128((__m128i*) (m + 192))); \
+ _mm_storeu_si128((__m128i*) (c + 192), t3); \
+ t0 = _mm_xor_si128(_mm256_extracti128_si256(z##A, 1), \
+ _mm_loadu_si128((__m128i*) (m + 256))); \
+ _mm_storeu_si128((__m128i*) (c + 256), t0); \
+ t1 = _mm_xor_si128(_mm256_extracti128_si256(z##B, 1), \
+ _mm_loadu_si128((__m128i*) (m + 320))); \
+ _mm_storeu_si128((__m128i*) (c + 320), t1); \
+ t2 = _mm_xor_si128(_mm256_extracti128_si256(z##C, 1), \
+ _mm_loadu_si128((__m128i*) (m + 384))); \
+ _mm_storeu_si128((__m128i*) (c + 384), t2); \
+ t3 = _mm_xor_si128(_mm256_extracti128_si256(z##D, 1), \
+ _mm_loadu_si128((__m128i*) (m + 448))); \
+ _mm_storeu_si128((__m128i*) (c + 448), t3); \
+ }
+
+#define ONEQUAD(A, B, C, D) ONEQUAD_TRANSPOSE(A, B, C, D)
+
+#define ONEQUAD_UNPCK(A, B, C, D) \
+ { \
+ z##A = _mm256_add_epi32(z##A, orig##A); \
+ z##B = _mm256_add_epi32(z##B, orig##B); \
+ z##C = _mm256_add_epi32(z##C, orig##C); \
+ z##D = _mm256_add_epi32(z##D, orig##D); \
+ y##A = _mm256_unpacklo_epi32(z##A, z##B); \
+ y##B = _mm256_unpacklo_epi32(z##C, z##D); \
+ y##C = _mm256_unpackhi_epi32(z##A, z##B); \
+ y##D = _mm256_unpackhi_epi32(z##C, z##D); \
+ z##A = _mm256_unpacklo_epi64(y##A, y##B); \
+ z##B = _mm256_unpackhi_epi64(y##A, y##B); \
+ z##C = _mm256_unpacklo_epi64(y##C, y##D); \
+ z##D = _mm256_unpackhi_epi64(y##C, y##D); \
+ }
+
+#define ONEOCTO(A, B, C, D, A2, B2, C2, D2) \
+ { \
+ ONEQUAD_UNPCK(A, B, C, D); \
+ ONEQUAD_UNPCK(A2, B2, C2, D2); \
+ y##A = _mm256_permute2x128_si256(z##A, z##A2, 0x20); \
+ y##A2 = _mm256_permute2x128_si256(z##A, z##A2, 0x31); \
+ y##B = _mm256_permute2x128_si256(z##B, z##B2, 0x20); \
+ y##B2 = _mm256_permute2x128_si256(z##B, z##B2, 0x31); \
+ y##C = _mm256_permute2x128_si256(z##C, z##C2, 0x20); \
+ y##C2 = _mm256_permute2x128_si256(z##C, z##C2, 0x31); \
+ y##D = _mm256_permute2x128_si256(z##D, z##D2, 0x20); \
+ y##D2 = _mm256_permute2x128_si256(z##D, z##D2, 0x31); \
+ y##A = _mm256_xor_si256(y##A, _mm256_loadu_si256((__m256i*) (m + 0))); \
+ y##B = \
+ _mm256_xor_si256(y##B, _mm256_loadu_si256((__m256i*) (m + 64))); \
+ y##C = \
+ _mm256_xor_si256(y##C, _mm256_loadu_si256((__m256i*) (m + 128))); \
+ y##D = \
+ _mm256_xor_si256(y##D, _mm256_loadu_si256((__m256i*) (m + 192))); \
+ y##A2 = \
+ _mm256_xor_si256(y##A2, _mm256_loadu_si256((__m256i*) (m + 256))); \
+ y##B2 = \
+ _mm256_xor_si256(y##B2, _mm256_loadu_si256((__m256i*) (m + 320))); \
+ y##C2 = \
+ _mm256_xor_si256(y##C2, _mm256_loadu_si256((__m256i*) (m + 384))); \
+ y##D2 = \
+ _mm256_xor_si256(y##D2, _mm256_loadu_si256((__m256i*) (m + 448))); \
+ _mm256_storeu_si256((__m256i*) (c + 0), y##A); \
+ _mm256_storeu_si256((__m256i*) (c + 64), y##B); \
+ _mm256_storeu_si256((__m256i*) (c + 128), y##C); \
+ _mm256_storeu_si256((__m256i*) (c + 192), y##D); \
+ _mm256_storeu_si256((__m256i*) (c + 256), y##A2); \
+ _mm256_storeu_si256((__m256i*) (c + 320), y##B2); \
+ _mm256_storeu_si256((__m256i*) (c + 384), y##C2); \
+ _mm256_storeu_si256((__m256i*) (c + 448), y##D2); \
+ }
+
+ ONEOCTO(0, 1, 2, 3, 4, 5, 6, 7);
+ m += 32;
+ c += 32;
+ ONEOCTO(8, 9, 10, 11, 12, 13, 14, 15);
+ m -= 32;
+ c -= 32;
+
+#undef ONEQUAD
+#undef ONEQUAD_TRANSPOSE
+#undef ONEQUAD_UNPCK
+#undef ONEOCTO
+
+ bytes -= 512;
+ c += 512;
+ m += 512;
+ }
+}
diff --git a/libs/libsodium/src/crypto_stream/salsa2012/ref/stream_salsa2012_ref.c b/libs/libsodium/src/crypto_stream/salsa2012/ref/stream_salsa2012_ref.c
new file mode 100644
index 0000000000..bfdfeedba3
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa2012/ref/stream_salsa2012_ref.c
@@ -0,0 +1,106 @@
+/*
+version 20140420
+D. J. Bernstein
+Public domain.
+*/
+
+#include <stdint.h>
+
+#include "crypto_core_salsa2012.h"
+#include "crypto_stream_salsa2012.h"
+#include "utils.h"
+
+int
+crypto_stream_salsa2012(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k)
+{
+ unsigned char in[16];
+ unsigned char block[64];
+ unsigned char kcopy[32];
+ unsigned int i;
+ unsigned int u;
+
+ if (!clen) {
+ return 0;
+ }
+ for (i = 0; i < 32; ++i) {
+ kcopy[i] = k[i];
+ }
+ for (i = 0; i < 8; ++i) {
+ in[i] = n[i];
+ }
+ for (i = 8; i < 16; ++i) {
+ in[i] = 0;
+ }
+ while (clen >= 64) {
+ crypto_core_salsa2012(c, in, kcopy, NULL);
+ u = 1;
+ for (i = 8; i < 16; ++i) {
+ u += (unsigned int)in[i];
+ in[i] = u;
+ u >>= 8;
+ }
+ clen -= 64;
+ c += 64;
+ }
+ if (clen) {
+ crypto_core_salsa2012(block, in, kcopy, NULL);
+ for (i = 0; i < (unsigned int)clen; ++i) {
+ c[i] = block[i];
+ }
+ }
+ sodium_memzero(block, sizeof block);
+ sodium_memzero(kcopy, sizeof kcopy);
+
+ return 0;
+}
+
+int
+crypto_stream_salsa2012_xor(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k)
+{
+ unsigned char in[16];
+ unsigned char block[64];
+ unsigned char kcopy[32];
+ unsigned int i;
+ unsigned int u;
+
+ if (!mlen) {
+ return 0;
+ }
+ for (i = 0; i < 32; ++i) {
+ kcopy[i] = k[i];
+ }
+ for (i = 0; i < 8; ++i) {
+ in[i] = n[i];
+ }
+ for (i = 8; i < 16; ++i) {
+ in[i] = 0;
+ }
+ while (mlen >= 64) {
+ crypto_core_salsa2012(block, in, kcopy, NULL);
+ for (i = 0; i < 64; ++i) {
+ c[i] = m[i] ^ block[i];
+ }
+ u = 1;
+ for (i = 8; i < 16; ++i) {
+ u += (unsigned int)in[i];
+ in[i] = u;
+ u >>= 8;
+ }
+ mlen -= 64;
+ c += 64;
+ m += 64;
+ }
+ if (mlen) {
+ crypto_core_salsa2012(block, in, kcopy, NULL);
+ for (i = 0; i < (unsigned int)mlen; ++i) {
+ c[i] = m[i] ^ block[i];
+ }
+ }
+ sodium_memzero(block, sizeof block);
+ sodium_memzero(kcopy, sizeof kcopy);
+
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_stream/salsa2012/stream_salsa2012.c b/libs/libsodium/src/crypto_stream/salsa2012/stream_salsa2012.c
new file mode 100644
index 0000000000..d0cc0f68ee
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa2012/stream_salsa2012.c
@@ -0,0 +1,26 @@
+#include "crypto_stream_salsa2012.h"
+#include "randombytes.h"
+
+size_t
+crypto_stream_salsa2012_keybytes(void)
+{
+ return crypto_stream_salsa2012_KEYBYTES;
+}
+
+size_t
+crypto_stream_salsa2012_noncebytes(void)
+{
+ return crypto_stream_salsa2012_NONCEBYTES;
+}
+
+size_t
+crypto_stream_salsa2012_messagebytes_max(void)
+{
+ return crypto_stream_salsa2012_MESSAGEBYTES_MAX;
+}
+
+void
+crypto_stream_salsa2012_keygen(unsigned char k[crypto_stream_salsa2012_KEYBYTES])
+{
+ randombytes_buf(k, crypto_stream_salsa2012_KEYBYTES);
+}
diff --git a/libs/libsodium/src/crypto_stream/salsa208/ref/stream_salsa208_ref.c b/libs/libsodium/src/crypto_stream/salsa208/ref/stream_salsa208_ref.c
new file mode 100644
index 0000000000..7ec0c4e78e
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa208/ref/stream_salsa208_ref.c
@@ -0,0 +1,106 @@
+/*
+version 20140420
+D. J. Bernstein
+Public domain.
+*/
+
+#include <stdint.h>
+
+#include "crypto_core_salsa208.h"
+#include "crypto_stream_salsa208.h"
+#include "utils.h"
+
+int
+crypto_stream_salsa208(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k)
+{
+ unsigned char in[16];
+ unsigned char block[64];
+ unsigned char kcopy[32];
+ unsigned int i;
+ unsigned int u;
+
+ if (!clen) {
+ return 0;
+ }
+ for (i = 0; i < 32; ++i) {
+ kcopy[i] = k[i];
+ }
+ for (i = 0; i < 8; ++i) {
+ in[i] = n[i];
+ }
+ for (i = 8; i < 16; ++i) {
+ in[i] = 0;
+ }
+ while (clen >= 64) {
+ crypto_core_salsa208(c, in, kcopy, NULL);
+ u = 1;
+ for (i = 8; i < 16; ++i) {
+ u += (unsigned int)in[i];
+ in[i] = u;
+ u >>= 8;
+ }
+ clen -= 64;
+ c += 64;
+ }
+ if (clen) {
+ crypto_core_salsa208(block, in, kcopy, NULL);
+ for (i = 0; i < (unsigned int)clen; ++i) {
+ c[i] = block[i];
+ }
+ }
+ sodium_memzero(block, sizeof block);
+ sodium_memzero(kcopy, sizeof kcopy);
+
+ return 0;
+}
+
+int
+crypto_stream_salsa208_xor(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k)
+{
+ unsigned char in[16];
+ unsigned char block[64];
+ unsigned char kcopy[32];
+ unsigned int i;
+ unsigned int u;
+
+ if (!mlen) {
+ return 0;
+ }
+ for (i = 0; i < 32; ++i) {
+ kcopy[i] = k[i];
+ }
+ for (i = 0; i < 8; ++i) {
+ in[i] = n[i];
+ }
+ for (i = 8; i < 16; ++i) {
+ in[i] = 0;
+ }
+ while (mlen >= 64) {
+ crypto_core_salsa208(block, in, kcopy, NULL);
+ for (i = 0; i < 64; ++i) {
+ c[i] = m[i] ^ block[i];
+ }
+ u = 1;
+ for (i = 8; i < 16; ++i) {
+ u += (unsigned int)in[i];
+ in[i] = u;
+ u >>= 8;
+ }
+ mlen -= 64;
+ c += 64;
+ m += 64;
+ }
+ if (mlen) {
+ crypto_core_salsa208(block, in, kcopy, NULL);
+ for (i = 0; i < (unsigned int)mlen; ++i) {
+ c[i] = m[i] ^ block[i];
+ }
+ }
+ sodium_memzero(block, sizeof block);
+ sodium_memzero(kcopy, sizeof kcopy);
+
+ return 0;
+}
diff --git a/libs/libsodium/src/crypto_stream/salsa208/stream_salsa208.c b/libs/libsodium/src/crypto_stream/salsa208/stream_salsa208.c
new file mode 100644
index 0000000000..b79bda5ec2
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/salsa208/stream_salsa208.c
@@ -0,0 +1,26 @@
+#include "crypto_stream_salsa208.h"
+#include "randombytes.h"
+
+size_t
+crypto_stream_salsa208_keybytes(void)
+{
+ return crypto_stream_salsa208_KEYBYTES;
+}
+
+size_t
+crypto_stream_salsa208_noncebytes(void)
+{
+ return crypto_stream_salsa208_NONCEBYTES;
+}
+
+size_t
+crypto_stream_salsa208_messagebytes_max(void)
+{
+ return crypto_stream_salsa208_MESSAGEBYTES_MAX;
+}
+
+void
+crypto_stream_salsa208_keygen(unsigned char k[crypto_stream_salsa208_KEYBYTES])
+{
+ randombytes_buf(k, crypto_stream_salsa208_KEYBYTES);
+}
diff --git a/libs/libsodium/src/crypto_stream/xchacha20/stream_xchacha20.c b/libs/libsodium/src/crypto_stream/xchacha20/stream_xchacha20.c
new file mode 100644
index 0000000000..8b1bc09abd
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/xchacha20/stream_xchacha20.c
@@ -0,0 +1,69 @@
+
+#include <stdlib.h>
+
+#include "crypto_core_hchacha20.h"
+#include "crypto_stream_chacha20.h"
+#include "crypto_stream_xchacha20.h"
+#include "private/common.h"
+#include "randombytes.h"
+
+size_t
+crypto_stream_xchacha20_keybytes(void)
+{
+ return crypto_stream_xchacha20_KEYBYTES;
+}
+
+size_t
+crypto_stream_xchacha20_noncebytes(void)
+{
+ return crypto_stream_xchacha20_NONCEBYTES;
+}
+
+size_t
+crypto_stream_xchacha20_messagebytes_max(void)
+{
+ return crypto_stream_xchacha20_MESSAGEBYTES_MAX;
+}
+
+int
+crypto_stream_xchacha20(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k)
+{
+ unsigned char k2[crypto_core_hchacha20_OUTPUTBYTES];
+
+ crypto_core_hchacha20(k2, n, k, NULL);
+ COMPILER_ASSERT(crypto_stream_chacha20_KEYBYTES <= sizeof k2);
+ COMPILER_ASSERT(crypto_stream_chacha20_NONCEBYTES ==
+ crypto_stream_xchacha20_NONCEBYTES -
+ crypto_core_hchacha20_INPUTBYTES);
+
+ return crypto_stream_chacha20(c, clen, n + crypto_core_hchacha20_INPUTBYTES,
+ k2);
+}
+
+int
+crypto_stream_xchacha20_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ uint64_t ic, const unsigned char *k)
+{
+ unsigned char k2[crypto_core_hchacha20_OUTPUTBYTES];
+
+ crypto_core_hchacha20(k2, n, k, NULL);
+ return crypto_stream_chacha20_xor_ic(
+ c, m, mlen, n + crypto_core_hchacha20_INPUTBYTES, ic, k2);
+}
+
+int
+crypto_stream_xchacha20_xor(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k)
+{
+ return crypto_stream_xchacha20_xor_ic(c, m, mlen, n, 0U, k);
+}
+
+void
+crypto_stream_xchacha20_keygen(
+ unsigned char k[crypto_stream_xchacha20_KEYBYTES])
+{
+ randombytes_buf(k, crypto_stream_xchacha20_KEYBYTES);
+}
diff --git a/libs/libsodium/src/crypto_stream/xsalsa20/stream_xsalsa20.c b/libs/libsodium/src/crypto_stream/xsalsa20/stream_xsalsa20.c
new file mode 100644
index 0000000000..dc831a94d8
--- /dev/null
+++ b/libs/libsodium/src/crypto_stream/xsalsa20/stream_xsalsa20.c
@@ -0,0 +1,66 @@
+#include "crypto_core_hsalsa20.h"
+#include "crypto_stream_salsa20.h"
+#include "crypto_stream_xsalsa20.h"
+#include "randombytes.h"
+#include "utils.h"
+
+int
+crypto_stream_xsalsa20(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k)
+{
+ unsigned char subkey[32];
+ int ret;
+
+ crypto_core_hsalsa20(subkey, n, k, NULL);
+ ret = crypto_stream_salsa20(c, clen, n + 16, subkey);
+ sodium_memzero(subkey, sizeof subkey);
+
+ return ret;
+}
+
+int
+crypto_stream_xsalsa20_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ uint64_t ic, const unsigned char *k)
+{
+ unsigned char subkey[32];
+ int ret;
+
+ crypto_core_hsalsa20(subkey, n, k, NULL);
+ ret = crypto_stream_salsa20_xor_ic(c, m, mlen, n + 16, ic, subkey);
+ sodium_memzero(subkey, sizeof subkey);
+
+ return ret;
+}
+
+int
+crypto_stream_xsalsa20_xor(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k)
+{
+ return crypto_stream_xsalsa20_xor_ic(c, m, mlen, n, 0ULL, k);
+}
+
+size_t
+crypto_stream_xsalsa20_keybytes(void)
+{
+ return crypto_stream_xsalsa20_KEYBYTES;
+}
+
+size_t
+crypto_stream_xsalsa20_noncebytes(void)
+{
+ return crypto_stream_xsalsa20_NONCEBYTES;
+}
+
+size_t
+crypto_stream_xsalsa20_messagebytes_max(void)
+{
+ return crypto_stream_xsalsa20_MESSAGEBYTES_MAX;
+}
+
+void
+crypto_stream_xsalsa20_keygen(unsigned char k[crypto_stream_xsalsa20_KEYBYTES])
+{
+ randombytes_buf(k, crypto_stream_xsalsa20_KEYBYTES);
+}
diff --git a/libs/libsodium/src/crypto_verify/sodium/verify.c b/libs/libsodium/src/crypto_verify/sodium/verify.c
new file mode 100644
index 0000000000..ffebf220a0
--- /dev/null
+++ b/libs/libsodium/src/crypto_verify/sodium/verify.c
@@ -0,0 +1,98 @@
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "crypto_verify_16.h"
+#include "crypto_verify_32.h"
+#include "crypto_verify_64.h"
+
+size_t
+crypto_verify_16_bytes(void)
+{
+ return crypto_verify_16_BYTES;
+}
+
+size_t
+crypto_verify_32_bytes(void)
+{
+ return crypto_verify_32_BYTES;
+}
+
+size_t
+crypto_verify_64_bytes(void)
+{
+ return crypto_verify_64_BYTES;
+}
+
+#if defined(HAVE_EMMINTRIN_H) && defined(__SSE2__)
+
+# ifdef __GNUC__
+# pragma GCC target("sse2")
+# endif
+# include <emmintrin.h>
+
+static inline int
+crypto_verify_n(const unsigned char *x_, const unsigned char *y_,
+ const int n)
+{
+ const __m128i zero = _mm_setzero_si128();
+ volatile __m128i v1, v2, z;
+ volatile int m;
+ int i;
+
+ const volatile __m128i *volatile x =
+ (const volatile __m128i *volatile) (const void *) x_;
+ const volatile __m128i *volatile y =
+ (const volatile __m128i *volatile) (const void *) y_;
+ v1 = _mm_loadu_si128((const __m128i *) &x[0]);
+ v2 = _mm_loadu_si128((const __m128i *) &y[0]);
+ z = _mm_xor_si128(v1, v2);
+ for (i = 1; i < n / 16; i++) {
+ v1 = _mm_loadu_si128((const __m128i *) &x[i]);
+ v2 = _mm_loadu_si128((const __m128i *) &y[i]);
+ z = _mm_or_si128(z, _mm_xor_si128(v1, v2));
+ }
+ m = _mm_movemask_epi8(_mm_cmpeq_epi32(z, zero));
+ v1 = zero; v2 = zero; z = zero;
+
+ return (int) (((uint32_t) m + 1U) >> 16) - 1;
+}
+
+#else
+
+static inline int
+crypto_verify_n(const unsigned char *x_, const unsigned char *y_,
+ const int n)
+{
+ const volatile unsigned char *volatile x =
+ (const volatile unsigned char *volatile) x_;
+ const volatile unsigned char *volatile y =
+ (const volatile unsigned char *volatile) y_;
+ volatile uint_fast16_t d = 0U;
+ int i;
+
+ for (i = 0; i < n; i++) {
+ d |= x[i] ^ y[i];
+ }
+ return (1 & ((d - 1) >> 8)) - 1;
+}
+
+#endif
+
+int
+crypto_verify_16(const unsigned char *x, const unsigned char *y)
+{
+ return crypto_verify_n(x, y, crypto_verify_16_BYTES);
+}
+
+int
+crypto_verify_32(const unsigned char *x, const unsigned char *y)
+{
+ return crypto_verify_n(x, y, crypto_verify_32_BYTES);
+}
+
+int
+crypto_verify_64(const unsigned char *x, const unsigned char *y)
+{
+ return crypto_verify_n(x, y, crypto_verify_64_BYTES);
+}
diff --git a/libs/libsodium/src/include/Makefile.am b/libs/libsodium/src/include/Makefile.am
new file mode 100644
index 0000000000..b70c22b39b
--- /dev/null
+++ b/libs/libsodium/src/include/Makefile.am
@@ -0,0 +1,75 @@
+
+SODIUM_EXPORT = \
+ sodium.h \
+ sodium/core.h \
+ sodium/crypto_aead_aes256gcm.h \
+ sodium/crypto_aead_chacha20poly1305.h \
+ sodium/crypto_aead_xchacha20poly1305.h \
+ sodium/crypto_auth.h \
+ sodium/crypto_auth_hmacsha256.h \
+ sodium/crypto_auth_hmacsha512.h \
+ sodium/crypto_auth_hmacsha512256.h \
+ sodium/crypto_box.h \
+ sodium/crypto_box_curve25519xchacha20poly1305.h \
+ sodium/crypto_box_curve25519xsalsa20poly1305.h \
+ sodium/crypto_core_ed25519.h \
+ sodium/crypto_core_hchacha20.h \
+ sodium/crypto_core_hsalsa20.h \
+ sodium/crypto_core_salsa20.h \
+ sodium/crypto_core_salsa2012.h \
+ sodium/crypto_core_salsa208.h \
+ sodium/crypto_generichash.h \
+ sodium/crypto_generichash_blake2b.h \
+ sodium/crypto_hash.h \
+ sodium/crypto_hash_sha256.h \
+ sodium/crypto_hash_sha512.h \
+ sodium/crypto_kdf.h \
+ sodium/crypto_kdf_blake2b.h \
+ sodium/crypto_kx.h \
+ sodium/crypto_onetimeauth.h \
+ sodium/crypto_onetimeauth_poly1305.h \
+ sodium/crypto_pwhash.h \
+ sodium/crypto_pwhash_argon2i.h \
+ sodium/crypto_pwhash_argon2id.h \
+ sodium/crypto_pwhash_scryptsalsa208sha256.h \
+ sodium/crypto_scalarmult.h \
+ sodium/crypto_scalarmult_curve25519.h \
+ sodium/crypto_scalarmult_ed25519.h \
+ sodium/crypto_secretbox.h \
+ sodium/crypto_secretbox_xchacha20poly1305.h \
+ sodium/crypto_secretbox_xsalsa20poly1305.h \
+ sodium/crypto_secretstream_xchacha20poly1305.h \
+ sodium/crypto_shorthash.h \
+ sodium/crypto_shorthash_siphash24.h \
+ sodium/crypto_sign.h \
+ sodium/crypto_sign_ed25519.h \
+ sodium/crypto_sign_edwards25519sha512batch.h \
+ sodium/crypto_stream.h \
+ sodium/crypto_stream_chacha20.h \
+ sodium/crypto_stream_salsa20.h \
+ sodium/crypto_stream_salsa2012.h \
+ sodium/crypto_stream_salsa208.h \
+ sodium/crypto_stream_xchacha20.h \
+ sodium/crypto_stream_xsalsa20.h \
+ sodium/crypto_verify_16.h \
+ sodium/crypto_verify_32.h \
+ sodium/crypto_verify_64.h \
+ sodium/export.h \
+ sodium/randombytes.h \
+ sodium/randombytes_salsa20_random.h \
+ sodium/randombytes_sysrandom.h \
+ sodium/runtime.h \
+ sodium/utils.h
+
+if NATIVECLIENT
+SODIUM_EXPORT += \
+ sodium/randombytes_nativeclient.h
+endif
+
+EXTRA_SRC = $(SODIUM_EXPORT) \
+ sodium/version.h.in
+
+nobase_include_HEADERS = $(SODIUM_EXPORT)
+
+nobase_nodist_include_HEADERS = \
+ sodium/version.h
diff --git a/libs/libsodium/src/include/sodium.h b/libs/libsodium/src/include/sodium.h
new file mode 100644
index 0000000000..e7b1af46f0
--- /dev/null
+++ b/libs/libsodium/src/include/sodium.h
@@ -0,0 +1,70 @@
+
+#ifndef sodium_H
+#define sodium_H
+
+#include "sodium/version.h"
+
+#include "sodium/core.h"
+#include "sodium/crypto_aead_aes256gcm.h"
+#include "sodium/crypto_aead_chacha20poly1305.h"
+#include "sodium/crypto_aead_xchacha20poly1305.h"
+#include "sodium/crypto_auth.h"
+#include "sodium/crypto_auth_hmacsha256.h"
+#include "sodium/crypto_auth_hmacsha512.h"
+#include "sodium/crypto_auth_hmacsha512256.h"
+#include "sodium/crypto_box.h"
+#include "sodium/crypto_box_curve25519xsalsa20poly1305.h"
+#include "sodium/crypto_core_hsalsa20.h"
+#include "sodium/crypto_core_hchacha20.h"
+#include "sodium/crypto_core_salsa20.h"
+#include "sodium/crypto_core_salsa2012.h"
+#include "sodium/crypto_core_salsa208.h"
+#include "sodium/crypto_generichash.h"
+#include "sodium/crypto_generichash_blake2b.h"
+#include "sodium/crypto_hash.h"
+#include "sodium/crypto_hash_sha256.h"
+#include "sodium/crypto_hash_sha512.h"
+#include "sodium/crypto_kdf.h"
+#include "sodium/crypto_kdf_blake2b.h"
+#include "sodium/crypto_kx.h"
+#include "sodium/crypto_onetimeauth.h"
+#include "sodium/crypto_onetimeauth_poly1305.h"
+#include "sodium/crypto_pwhash.h"
+#include "sodium/crypto_pwhash_argon2i.h"
+#include "sodium/crypto_scalarmult.h"
+#include "sodium/crypto_scalarmult_curve25519.h"
+#include "sodium/crypto_secretbox.h"
+#include "sodium/crypto_secretbox_xsalsa20poly1305.h"
+#include "sodium/crypto_secretstream_xchacha20poly1305.h"
+#include "sodium/crypto_shorthash.h"
+#include "sodium/crypto_shorthash_siphash24.h"
+#include "sodium/crypto_sign.h"
+#include "sodium/crypto_sign_ed25519.h"
+#include "sodium/crypto_stream.h"
+#include "sodium/crypto_stream_chacha20.h"
+#include "sodium/crypto_stream_salsa20.h"
+#include "sodium/crypto_stream_xsalsa20.h"
+#include "sodium/crypto_verify_16.h"
+#include "sodium/crypto_verify_32.h"
+#include "sodium/crypto_verify_64.h"
+#include "sodium/randombytes.h"
+#ifdef __native_client__
+# include "sodium/randombytes_nativeclient.h"
+#endif
+#include "sodium/randombytes_salsa20_random.h"
+#include "sodium/randombytes_sysrandom.h"
+#include "sodium/runtime.h"
+#include "sodium/utils.h"
+
+#ifndef SODIUM_LIBRARY_MINIMAL
+# include "sodium/crypto_box_curve25519xchacha20poly1305.h"
+# include "sodium/crypto_core_ed25519.h"
+# include "sodium/crypto_scalarmult_ed25519.h"
+# include "sodium/crypto_secretbox_xchacha20poly1305.h"
+# include "sodium/crypto_pwhash_scryptsalsa208sha256.h"
+# include "sodium/crypto_stream_salsa2012.h"
+# include "sodium/crypto_stream_salsa208.h"
+# include "sodium/crypto_stream_xchacha20.h"
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/core.h b/libs/libsodium/src/include/sodium/core.h
new file mode 100644
index 0000000000..dd088d2cae
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/core.h
@@ -0,0 +1,28 @@
+
+#ifndef sodium_core_H
+#define sodium_core_H
+
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SODIUM_EXPORT
+int sodium_init(void)
+ __attribute__ ((warn_unused_result));
+
+/* ---- */
+
+SODIUM_EXPORT
+int sodium_set_misuse_handler(void (*handler)(void));
+
+SODIUM_EXPORT
+void sodium_misuse(void)
+ __attribute__ ((noreturn));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_aead_aes256gcm.h b/libs/libsodium/src/include/sodium/crypto_aead_aes256gcm.h
new file mode 100644
index 0000000000..46a3800f37
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_aead_aes256gcm.h
@@ -0,0 +1,171 @@
+#ifndef crypto_aead_aes256gcm_H
+#define crypto_aead_aes256gcm_H
+
+/*
+ * WARNING: Despite being the most popular AEAD construction due to its
+ * use in TLS, safely using AES-GCM in a different context is tricky.
+ *
+ * No more than ~ 350 GB of input data should be encrypted with a given key.
+ * This is for ~ 16 KB messages -- Actual figures vary according to
+ * message sizes.
+ *
+ * In addition, nonces are short and repeated nonces would totally destroy
+ * the security of this scheme.
+ *
+ * Nonces should thus come from atomic counters, which can be difficult to
+ * set up in a distributed environment.
+ *
+ * Unless you absolutely need AES-GCM, use crypto_aead_xchacha20poly1305_ietf_*()
+ * instead. It doesn't have any of these limitations.
+ * Or, if you don't need to authenticate additional data, just stick to
+ * crypto_secretbox().
+ */
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+SODIUM_EXPORT
+int crypto_aead_aes256gcm_is_available(void);
+
+#define crypto_aead_aes256gcm_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_aead_aes256gcm_keybytes(void);
+
+#define crypto_aead_aes256gcm_NSECBYTES 0U
+SODIUM_EXPORT
+size_t crypto_aead_aes256gcm_nsecbytes(void);
+
+#define crypto_aead_aes256gcm_NPUBBYTES 12U
+SODIUM_EXPORT
+size_t crypto_aead_aes256gcm_npubbytes(void);
+
+#define crypto_aead_aes256gcm_ABYTES 16U
+SODIUM_EXPORT
+size_t crypto_aead_aes256gcm_abytes(void);
+
+#define crypto_aead_aes256gcm_MESSAGEBYTES_MAX \
+ SODIUM_MIN(SODIUM_SIZE_MAX - crypto_aead_aes256gcm_ABYTES, \
+ (16ULL * ((1ULL << 32) - 2ULL)) - crypto_aead_aes256gcm_ABYTES)
+SODIUM_EXPORT
+size_t crypto_aead_aes256gcm_messagebytes_max(void);
+
+typedef CRYPTO_ALIGN(16) unsigned char crypto_aead_aes256gcm_state[512];
+
+SODIUM_EXPORT
+size_t crypto_aead_aes256gcm_statebytes(void);
+
+SODIUM_EXPORT
+int crypto_aead_aes256gcm_encrypt(unsigned char *c,
+ unsigned long long *clen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_aead_aes256gcm_decrypt(unsigned char *m,
+ unsigned long long *mlen_p,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_aead_aes256gcm_encrypt_detached(unsigned char *c,
+ unsigned char *mac,
+ unsigned long long *maclen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_aead_aes256gcm_decrypt_detached(unsigned char *m,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *mac,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+/* -- Precomputation interface -- */
+
+SODIUM_EXPORT
+int crypto_aead_aes256gcm_beforenm(crypto_aead_aes256gcm_state *ctx_,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_aead_aes256gcm_encrypt_afternm(unsigned char *c,
+ unsigned long long *clen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const crypto_aead_aes256gcm_state *ctx_);
+
+SODIUM_EXPORT
+int crypto_aead_aes256gcm_decrypt_afternm(unsigned char *m,
+ unsigned long long *mlen_p,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const crypto_aead_aes256gcm_state *ctx_)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_aead_aes256gcm_encrypt_detached_afternm(unsigned char *c,
+ unsigned char *mac,
+ unsigned long long *maclen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const crypto_aead_aes256gcm_state *ctx_);
+
+SODIUM_EXPORT
+int crypto_aead_aes256gcm_decrypt_detached_afternm(unsigned char *m,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *mac,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const crypto_aead_aes256gcm_state *ctx_)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+void crypto_aead_aes256gcm_keygen(unsigned char k[crypto_aead_aes256gcm_KEYBYTES]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_aead_chacha20poly1305.h b/libs/libsodium/src/include/sodium/crypto_aead_chacha20poly1305.h
new file mode 100644
index 0000000000..a575ec7173
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_aead_chacha20poly1305.h
@@ -0,0 +1,174 @@
+#ifndef crypto_aead_chacha20poly1305_H
+#define crypto_aead_chacha20poly1305_H
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+/* -- IETF ChaCha20-Poly1305 construction with a 96-bit nonce and a 32-bit internal counter -- */
+
+#define crypto_aead_chacha20poly1305_ietf_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_aead_chacha20poly1305_ietf_keybytes(void);
+
+#define crypto_aead_chacha20poly1305_ietf_NSECBYTES 0U
+SODIUM_EXPORT
+size_t crypto_aead_chacha20poly1305_ietf_nsecbytes(void);
+
+#define crypto_aead_chacha20poly1305_ietf_NPUBBYTES 12U
+
+SODIUM_EXPORT
+size_t crypto_aead_chacha20poly1305_ietf_npubbytes(void);
+
+#define crypto_aead_chacha20poly1305_ietf_ABYTES 16U
+SODIUM_EXPORT
+size_t crypto_aead_chacha20poly1305_ietf_abytes(void);
+
+#define crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX \
+ SODIUM_MIN(SODIUM_SIZE_MAX - crypto_aead_chacha20poly1305_ietf_ABYTES, \
+ (64ULL * (1ULL << 32) - 64ULL) - crypto_aead_chacha20poly1305_ietf_ABYTES)
+SODIUM_EXPORT
+size_t crypto_aead_chacha20poly1305_ietf_messagebytes_max(void);
+
+SODIUM_EXPORT
+int crypto_aead_chacha20poly1305_ietf_encrypt(unsigned char *c,
+ unsigned long long *clen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_aead_chacha20poly1305_ietf_decrypt(unsigned char *m,
+ unsigned long long *mlen_p,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_aead_chacha20poly1305_ietf_encrypt_detached(unsigned char *c,
+ unsigned char *mac,
+ unsigned long long *maclen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_aead_chacha20poly1305_ietf_decrypt_detached(unsigned char *m,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *mac,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+void crypto_aead_chacha20poly1305_ietf_keygen(unsigned char k[crypto_aead_chacha20poly1305_ietf_KEYBYTES]);
+
+/* -- Original ChaCha20-Poly1305 construction with a 64-bit nonce and a 64-bit internal counter -- */
+
+#define crypto_aead_chacha20poly1305_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_aead_chacha20poly1305_keybytes(void);
+
+#define crypto_aead_chacha20poly1305_NSECBYTES 0U
+SODIUM_EXPORT
+size_t crypto_aead_chacha20poly1305_nsecbytes(void);
+
+#define crypto_aead_chacha20poly1305_NPUBBYTES 8U
+SODIUM_EXPORT
+size_t crypto_aead_chacha20poly1305_npubbytes(void);
+
+#define crypto_aead_chacha20poly1305_ABYTES 16U
+SODIUM_EXPORT
+size_t crypto_aead_chacha20poly1305_abytes(void);
+
+#define crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX \
+ (SODIUM_SIZE_MAX - crypto_aead_chacha20poly1305_ABYTES)
+SODIUM_EXPORT
+size_t crypto_aead_chacha20poly1305_messagebytes_max(void);
+
+SODIUM_EXPORT
+int crypto_aead_chacha20poly1305_encrypt(unsigned char *c,
+ unsigned long long *clen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_aead_chacha20poly1305_decrypt(unsigned char *m,
+ unsigned long long *mlen_p,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_aead_chacha20poly1305_encrypt_detached(unsigned char *c,
+ unsigned char *mac,
+ unsigned long long *maclen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_aead_chacha20poly1305_decrypt_detached(unsigned char *m,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *mac,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+void crypto_aead_chacha20poly1305_keygen(unsigned char k[crypto_aead_chacha20poly1305_KEYBYTES]);
+
+/* Aliases */
+
+#define crypto_aead_chacha20poly1305_IETF_KEYBYTES crypto_aead_chacha20poly1305_ietf_KEYBYTES
+#define crypto_aead_chacha20poly1305_IETF_NSECBYTES crypto_aead_chacha20poly1305_ietf_NSECBYTES
+#define crypto_aead_chacha20poly1305_IETF_NPUBBYTES crypto_aead_chacha20poly1305_ietf_NPUBBYTES
+#define crypto_aead_chacha20poly1305_IETF_ABYTES crypto_aead_chacha20poly1305_ietf_ABYTES
+#define crypto_aead_chacha20poly1305_IETF_MESSAGEBYTES_MAX crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_aead_xchacha20poly1305.h b/libs/libsodium/src/include/sodium/crypto_aead_xchacha20poly1305.h
new file mode 100644
index 0000000000..99692aae9a
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_aead_xchacha20poly1305.h
@@ -0,0 +1,97 @@
+#ifndef crypto_aead_xchacha20poly1305_H
+#define crypto_aead_xchacha20poly1305_H
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_aead_xchacha20poly1305_ietf_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_aead_xchacha20poly1305_ietf_keybytes(void);
+
+#define crypto_aead_xchacha20poly1305_ietf_NSECBYTES 0U
+SODIUM_EXPORT
+size_t crypto_aead_xchacha20poly1305_ietf_nsecbytes(void);
+
+#define crypto_aead_xchacha20poly1305_ietf_NPUBBYTES 24U
+SODIUM_EXPORT
+size_t crypto_aead_xchacha20poly1305_ietf_npubbytes(void);
+
+#define crypto_aead_xchacha20poly1305_ietf_ABYTES 16U
+SODIUM_EXPORT
+size_t crypto_aead_xchacha20poly1305_ietf_abytes(void);
+
+#define crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX \
+ (SODIUM_SIZE_MAX - crypto_aead_xchacha20poly1305_ietf_ABYTES)
+SODIUM_EXPORT
+size_t crypto_aead_xchacha20poly1305_ietf_messagebytes_max(void);
+
+SODIUM_EXPORT
+int crypto_aead_xchacha20poly1305_ietf_encrypt(unsigned char *c,
+ unsigned long long *clen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_aead_xchacha20poly1305_ietf_decrypt(unsigned char *m,
+ unsigned long long *mlen_p,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_aead_xchacha20poly1305_ietf_encrypt_detached(unsigned char *c,
+ unsigned char *mac,
+ unsigned long long *maclen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *nsec,
+ const unsigned char *npub,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_aead_xchacha20poly1305_ietf_decrypt_detached(unsigned char *m,
+ unsigned char *nsec,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *mac,
+ const unsigned char *ad,
+ unsigned long long adlen,
+ const unsigned char *npub,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+void crypto_aead_xchacha20poly1305_ietf_keygen(unsigned char k[crypto_aead_xchacha20poly1305_ietf_KEYBYTES]);
+
+/* Aliases */
+
+#define crypto_aead_xchacha20poly1305_IETF_KEYBYTES crypto_aead_xchacha20poly1305_ietf_KEYBYTES
+#define crypto_aead_xchacha20poly1305_IETF_NSECBYTES crypto_aead_xchacha20poly1305_ietf_NSECBYTES
+#define crypto_aead_xchacha20poly1305_IETF_NPUBBYTES crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
+#define crypto_aead_xchacha20poly1305_IETF_ABYTES crypto_aead_xchacha20poly1305_ietf_ABYTES
+#define crypto_aead_xchacha20poly1305_IETF_MESSAGEBYTES_MAX crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_auth.h b/libs/libsodium/src/include/sodium/crypto_auth.h
new file mode 100644
index 0000000000..7174e7bced
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_auth.h
@@ -0,0 +1,44 @@
+#ifndef crypto_auth_H
+#define crypto_auth_H
+
+#include <stddef.h>
+
+#include "crypto_auth_hmacsha512256.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_auth_BYTES crypto_auth_hmacsha512256_BYTES
+SODIUM_EXPORT
+size_t crypto_auth_bytes(void);
+
+#define crypto_auth_KEYBYTES crypto_auth_hmacsha512256_KEYBYTES
+SODIUM_EXPORT
+size_t crypto_auth_keybytes(void);
+
+#define crypto_auth_PRIMITIVE "hmacsha512256"
+SODIUM_EXPORT
+const char *crypto_auth_primitive(void);
+
+SODIUM_EXPORT
+int crypto_auth(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_auth_verify(const unsigned char *h, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+void crypto_auth_keygen(unsigned char k[crypto_auth_KEYBYTES]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_auth_hmacsha256.h b/libs/libsodium/src/include/sodium/crypto_auth_hmacsha256.h
new file mode 100644
index 0000000000..deec5266e6
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_auth_hmacsha256.h
@@ -0,0 +1,68 @@
+#ifndef crypto_auth_hmacsha256_H
+#define crypto_auth_hmacsha256_H
+
+#include <stddef.h>
+#include "crypto_hash_sha256.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_auth_hmacsha256_BYTES 32U
+SODIUM_EXPORT
+size_t crypto_auth_hmacsha256_bytes(void);
+
+#define crypto_auth_hmacsha256_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_auth_hmacsha256_keybytes(void);
+
+SODIUM_EXPORT
+int crypto_auth_hmacsha256(unsigned char *out,
+ const unsigned char *in,
+ unsigned long long inlen,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_auth_hmacsha256_verify(const unsigned char *h,
+ const unsigned char *in,
+ unsigned long long inlen,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+/* ------------------------------------------------------------------------- */
+
+typedef struct crypto_auth_hmacsha256_state {
+ crypto_hash_sha256_state ictx;
+ crypto_hash_sha256_state octx;
+} crypto_auth_hmacsha256_state;
+
+SODIUM_EXPORT
+size_t crypto_auth_hmacsha256_statebytes(void);
+
+SODIUM_EXPORT
+int crypto_auth_hmacsha256_init(crypto_auth_hmacsha256_state *state,
+ const unsigned char *key,
+ size_t keylen);
+
+SODIUM_EXPORT
+int crypto_auth_hmacsha256_update(crypto_auth_hmacsha256_state *state,
+ const unsigned char *in,
+ unsigned long long inlen);
+
+SODIUM_EXPORT
+int crypto_auth_hmacsha256_final(crypto_auth_hmacsha256_state *state,
+ unsigned char *out);
+
+
+SODIUM_EXPORT
+void crypto_auth_hmacsha256_keygen(unsigned char k[crypto_auth_hmacsha256_KEYBYTES]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_auth_hmacsha512.h b/libs/libsodium/src/include/sodium/crypto_auth_hmacsha512.h
new file mode 100644
index 0000000000..77a55fbc00
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_auth_hmacsha512.h
@@ -0,0 +1,67 @@
+#ifndef crypto_auth_hmacsha512_H
+#define crypto_auth_hmacsha512_H
+
+#include <stddef.h>
+#include "crypto_hash_sha512.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_auth_hmacsha512_BYTES 64U
+SODIUM_EXPORT
+size_t crypto_auth_hmacsha512_bytes(void);
+
+#define crypto_auth_hmacsha512_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_auth_hmacsha512_keybytes(void);
+
+SODIUM_EXPORT
+int crypto_auth_hmacsha512(unsigned char *out,
+ const unsigned char *in,
+ unsigned long long inlen,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_auth_hmacsha512_verify(const unsigned char *h,
+ const unsigned char *in,
+ unsigned long long inlen,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+/* ------------------------------------------------------------------------- */
+
+typedef struct crypto_auth_hmacsha512_state {
+ crypto_hash_sha512_state ictx;
+ crypto_hash_sha512_state octx;
+} crypto_auth_hmacsha512_state;
+
+SODIUM_EXPORT
+size_t crypto_auth_hmacsha512_statebytes(void);
+
+SODIUM_EXPORT
+int crypto_auth_hmacsha512_init(crypto_auth_hmacsha512_state *state,
+ const unsigned char *key,
+ size_t keylen);
+
+SODIUM_EXPORT
+int crypto_auth_hmacsha512_update(crypto_auth_hmacsha512_state *state,
+ const unsigned char *in,
+ unsigned long long inlen);
+
+SODIUM_EXPORT
+int crypto_auth_hmacsha512_final(crypto_auth_hmacsha512_state *state,
+ unsigned char *out);
+
+SODIUM_EXPORT
+void crypto_auth_hmacsha512_keygen(unsigned char k[crypto_auth_hmacsha512_KEYBYTES]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_auth_hmacsha512256.h b/libs/libsodium/src/include/sodium/crypto_auth_hmacsha512256.h
new file mode 100644
index 0000000000..4842f3debc
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_auth_hmacsha512256.h
@@ -0,0 +1,62 @@
+#ifndef crypto_auth_hmacsha512256_H
+#define crypto_auth_hmacsha512256_H
+
+#include <stddef.h>
+#include "crypto_auth_hmacsha512.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_auth_hmacsha512256_BYTES 32U
+SODIUM_EXPORT
+size_t crypto_auth_hmacsha512256_bytes(void);
+
+#define crypto_auth_hmacsha512256_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_auth_hmacsha512256_keybytes(void);
+
+SODIUM_EXPORT
+int crypto_auth_hmacsha512256(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen,const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_auth_hmacsha512256_verify(const unsigned char *h,
+ const unsigned char *in,
+ unsigned long long inlen,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+/* ------------------------------------------------------------------------- */
+
+typedef crypto_auth_hmacsha512_state crypto_auth_hmacsha512256_state;
+
+SODIUM_EXPORT
+size_t crypto_auth_hmacsha512256_statebytes(void);
+
+SODIUM_EXPORT
+int crypto_auth_hmacsha512256_init(crypto_auth_hmacsha512256_state *state,
+ const unsigned char *key,
+ size_t keylen);
+
+SODIUM_EXPORT
+int crypto_auth_hmacsha512256_update(crypto_auth_hmacsha512256_state *state,
+ const unsigned char *in,
+ unsigned long long inlen);
+
+SODIUM_EXPORT
+int crypto_auth_hmacsha512256_final(crypto_auth_hmacsha512256_state *state,
+ unsigned char *out);
+
+SODIUM_EXPORT
+void crypto_auth_hmacsha512256_keygen(unsigned char k[crypto_auth_hmacsha512256_KEYBYTES]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_box.h b/libs/libsodium/src/include/sodium/crypto_box.h
new file mode 100644
index 0000000000..99ee19a8f6
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_box.h
@@ -0,0 +1,173 @@
+#ifndef crypto_box_H
+#define crypto_box_H
+
+/*
+ * THREAD SAFETY: crypto_box_keypair() is thread-safe,
+ * provided that sodium_init() was called before.
+ *
+ * Other functions are always thread-safe.
+ */
+
+#include <stddef.h>
+
+#include "crypto_box_curve25519xsalsa20poly1305.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_box_SEEDBYTES crypto_box_curve25519xsalsa20poly1305_SEEDBYTES
+SODIUM_EXPORT
+size_t crypto_box_seedbytes(void);
+
+#define crypto_box_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
+SODIUM_EXPORT
+size_t crypto_box_publickeybytes(void);
+
+#define crypto_box_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES
+SODIUM_EXPORT
+size_t crypto_box_secretkeybytes(void);
+
+#define crypto_box_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_NONCEBYTES
+SODIUM_EXPORT
+size_t crypto_box_noncebytes(void);
+
+#define crypto_box_MACBYTES crypto_box_curve25519xsalsa20poly1305_MACBYTES
+SODIUM_EXPORT
+size_t crypto_box_macbytes(void);
+
+#define crypto_box_MESSAGEBYTES_MAX crypto_box_curve25519xsalsa20poly1305_MESSAGEBYTES_MAX
+SODIUM_EXPORT
+size_t crypto_box_messagebytes_max(void);
+
+#define crypto_box_PRIMITIVE "curve25519xsalsa20poly1305"
+SODIUM_EXPORT
+const char *crypto_box_primitive(void);
+
+SODIUM_EXPORT
+int crypto_box_seed_keypair(unsigned char *pk, unsigned char *sk,
+ const unsigned char *seed);
+
+SODIUM_EXPORT
+int crypto_box_keypair(unsigned char *pk, unsigned char *sk);
+
+SODIUM_EXPORT
+int crypto_box_easy(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *pk, const unsigned char *sk)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_box_open_easy(unsigned char *m, const unsigned char *c,
+ unsigned long long clen, const unsigned char *n,
+ const unsigned char *pk, const unsigned char *sk)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_box_detached(unsigned char *c, unsigned char *mac,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *n, const unsigned char *pk,
+ const unsigned char *sk)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_box_open_detached(unsigned char *m, const unsigned char *c,
+ const unsigned char *mac,
+ unsigned long long clen,
+ const unsigned char *n,
+ const unsigned char *pk,
+ const unsigned char *sk)
+ __attribute__ ((warn_unused_result));
+
+/* -- Precomputation interface -- */
+
+#define crypto_box_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES
+SODIUM_EXPORT
+size_t crypto_box_beforenmbytes(void);
+
+SODIUM_EXPORT
+int crypto_box_beforenm(unsigned char *k, const unsigned char *pk,
+ const unsigned char *sk)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_box_easy_afternm(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_box_open_easy_afternm(unsigned char *m, const unsigned char *c,
+ unsigned long long clen, const unsigned char *n,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_box_detached_afternm(unsigned char *c, unsigned char *mac,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *n, const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_box_open_detached_afternm(unsigned char *m, const unsigned char *c,
+ const unsigned char *mac,
+ unsigned long long clen, const unsigned char *n,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+/* -- Ephemeral SK interface -- */
+
+#define crypto_box_SEALBYTES (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)
+SODIUM_EXPORT
+size_t crypto_box_sealbytes(void);
+
+SODIUM_EXPORT
+int crypto_box_seal(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *pk);
+
+SODIUM_EXPORT
+int crypto_box_seal_open(unsigned char *m, const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *pk, const unsigned char *sk)
+ __attribute__ ((warn_unused_result));
+
+/* -- NaCl compatibility interface ; Requires padding -- */
+
+#define crypto_box_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_ZEROBYTES
+SODIUM_EXPORT
+size_t crypto_box_zerobytes(void);
+
+#define crypto_box_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES
+SODIUM_EXPORT
+size_t crypto_box_boxzerobytes(void);
+
+SODIUM_EXPORT
+int crypto_box(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *pk, const unsigned char *sk)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_box_open(unsigned char *m, const unsigned char *c,
+ unsigned long long clen, const unsigned char *n,
+ const unsigned char *pk, const unsigned char *sk)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_box_afternm(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_box_open_afternm(unsigned char *m, const unsigned char *c,
+ unsigned long long clen, const unsigned char *n,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_box_curve25519xchacha20poly1305.h b/libs/libsodium/src/include/sodium/crypto_box_curve25519xchacha20poly1305.h
new file mode 100644
index 0000000000..c1cf756687
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_box_curve25519xchacha20poly1305.h
@@ -0,0 +1,159 @@
+
+#ifndef crypto_box_curve25519xchacha20poly1305_H
+#define crypto_box_curve25519xchacha20poly1305_H
+
+#include <stddef.h>
+#include "crypto_stream_xchacha20.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_box_curve25519xchacha20poly1305_SEEDBYTES 32U
+SODIUM_EXPORT
+size_t crypto_box_curve25519xchacha20poly1305_seedbytes(void);
+
+#define crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_box_curve25519xchacha20poly1305_publickeybytes(void);
+
+#define crypto_box_curve25519xchacha20poly1305_SECRETKEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_box_curve25519xchacha20poly1305_secretkeybytes(void);
+
+#define crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES 32U
+SODIUM_EXPORT
+size_t crypto_box_curve25519xchacha20poly1305_beforenmbytes(void);
+
+#define crypto_box_curve25519xchacha20poly1305_NONCEBYTES 24U
+SODIUM_EXPORT
+size_t crypto_box_curve25519xchacha20poly1305_noncebytes(void);
+
+#define crypto_box_curve25519xchacha20poly1305_MACBYTES 16U
+SODIUM_EXPORT
+size_t crypto_box_curve25519xchacha20poly1305_macbytes(void);
+
+#define crypto_box_curve25519xchacha20poly1305_MESSAGEBYTES_MAX \
+ (crypto_stream_xchacha20_MESSAGEBYTES_MAX - crypto_box_curve25519xchacha20poly1305_MACBYTES)
+SODIUM_EXPORT
+size_t crypto_box_curve25519xchacha20poly1305_messagebytes_max(void);
+
+SODIUM_EXPORT
+int crypto_box_curve25519xchacha20poly1305_seed_keypair(unsigned char *pk,
+ unsigned char *sk,
+ const unsigned char *seed);
+
+SODIUM_EXPORT
+int crypto_box_curve25519xchacha20poly1305_keypair(unsigned char *pk,
+ unsigned char *sk);
+
+SODIUM_EXPORT
+int crypto_box_curve25519xchacha20poly1305_easy(unsigned char *c,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n,
+ const unsigned char *pk,
+ const unsigned char *sk)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_box_curve25519xchacha20poly1305_open_easy(unsigned char *m,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *n,
+ const unsigned char *pk,
+ const unsigned char *sk)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_box_curve25519xchacha20poly1305_detached(unsigned char *c,
+ unsigned char *mac,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n,
+ const unsigned char *pk,
+ const unsigned char *sk)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_box_curve25519xchacha20poly1305_open_detached(unsigned char *m,
+ const unsigned char *c,
+ const unsigned char *mac,
+ unsigned long long clen,
+ const unsigned char *n,
+ const unsigned char *pk,
+ const unsigned char *sk)
+ __attribute__ ((warn_unused_result));
+
+/* -- Precomputation interface -- */
+
+SODIUM_EXPORT
+int crypto_box_curve25519xchacha20poly1305_beforenm(unsigned char *k,
+ const unsigned char *pk,
+ const unsigned char *sk)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_box_curve25519xchacha20poly1305_easy_afternm(unsigned char *c,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_box_curve25519xchacha20poly1305_open_easy_afternm(unsigned char *m,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *n,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_box_curve25519xchacha20poly1305_detached_afternm(unsigned char *c,
+ unsigned char *mac,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_box_curve25519xchacha20poly1305_open_detached_afternm(unsigned char *m,
+ const unsigned char *c,
+ const unsigned char *mac,
+ unsigned long long clen,
+ const unsigned char *n,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+/* -- Ephemeral SK interface -- */
+
+#define crypto_box_curve25519xchacha20poly1305_SEALBYTES \
+ (crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES + \
+ crypto_box_curve25519xchacha20poly1305_MACBYTES)
+
+SODIUM_EXPORT
+size_t crypto_box_curve25519xchacha20poly1305_sealbytes(void);
+
+SODIUM_EXPORT
+int crypto_box_curve25519xchacha20poly1305_seal(unsigned char *c,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *pk);
+
+SODIUM_EXPORT
+int crypto_box_curve25519xchacha20poly1305_seal_open(unsigned char *m,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *pk,
+ const unsigned char *sk)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_box_curve25519xsalsa20poly1305.h b/libs/libsodium/src/include/sodium/crypto_box_curve25519xsalsa20poly1305.h
new file mode 100644
index 0000000000..c5b15f42e4
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_box_curve25519xsalsa20poly1305.h
@@ -0,0 +1,109 @@
+#ifndef crypto_box_curve25519xsalsa20poly1305_H
+#define crypto_box_curve25519xsalsa20poly1305_H
+
+#include <stddef.h>
+#include "crypto_stream_xsalsa20.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_box_curve25519xsalsa20poly1305_SEEDBYTES 32U
+SODIUM_EXPORT
+size_t crypto_box_curve25519xsalsa20poly1305_seedbytes(void);
+
+#define crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_box_curve25519xsalsa20poly1305_publickeybytes(void);
+
+#define crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_box_curve25519xsalsa20poly1305_secretkeybytes(void);
+
+#define crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES 32U
+SODIUM_EXPORT
+size_t crypto_box_curve25519xsalsa20poly1305_beforenmbytes(void);
+
+#define crypto_box_curve25519xsalsa20poly1305_NONCEBYTES 24U
+SODIUM_EXPORT
+size_t crypto_box_curve25519xsalsa20poly1305_noncebytes(void);
+
+#define crypto_box_curve25519xsalsa20poly1305_MACBYTES 16U
+SODIUM_EXPORT
+size_t crypto_box_curve25519xsalsa20poly1305_macbytes(void);
+
+/* Only for the libsodium API - The NaCl compatibility API would require BOXZEROBYTES extra bytes */
+#define crypto_box_curve25519xsalsa20poly1305_MESSAGEBYTES_MAX \
+ (crypto_stream_xsalsa20_MESSAGEBYTES_MAX - crypto_box_curve25519xsalsa20poly1305_MACBYTES)
+SODIUM_EXPORT
+size_t crypto_box_curve25519xsalsa20poly1305_messagebytes_max(void);
+
+SODIUM_EXPORT
+int crypto_box_curve25519xsalsa20poly1305_seed_keypair(unsigned char *pk,
+ unsigned char *sk,
+ const unsigned char *seed);
+
+SODIUM_EXPORT
+int crypto_box_curve25519xsalsa20poly1305_keypair(unsigned char *pk,
+ unsigned char *sk);
+
+SODIUM_EXPORT
+int crypto_box_curve25519xsalsa20poly1305_beforenm(unsigned char *k,
+ const unsigned char *pk,
+ const unsigned char *sk)
+ __attribute__ ((warn_unused_result));
+
+/* -- NaCl compatibility interface ; Requires padding -- */
+
+#define crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES 16U
+SODIUM_EXPORT
+size_t crypto_box_curve25519xsalsa20poly1305_boxzerobytes(void);
+
+#define crypto_box_curve25519xsalsa20poly1305_ZEROBYTES \
+ (crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES + \
+ crypto_box_curve25519xsalsa20poly1305_MACBYTES)
+SODIUM_EXPORT
+size_t crypto_box_curve25519xsalsa20poly1305_zerobytes(void);
+
+SODIUM_EXPORT
+int crypto_box_curve25519xsalsa20poly1305(unsigned char *c,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n,
+ const unsigned char *pk,
+ const unsigned char *sk)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_box_curve25519xsalsa20poly1305_open(unsigned char *m,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *n,
+ const unsigned char *pk,
+ const unsigned char *sk)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_box_curve25519xsalsa20poly1305_afternm(unsigned char *c,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_box_curve25519xsalsa20poly1305_open_afternm(unsigned char *m,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *n,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_core_ed25519.h b/libs/libsodium/src/include/sodium/crypto_core_ed25519.h
new file mode 100644
index 0000000000..1536294b21
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_core_ed25519.h
@@ -0,0 +1,37 @@
+#ifndef crypto_core_ed25519_H
+#define crypto_core_ed25519_H
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define crypto_core_ed25519_BYTES 32
+SODIUM_EXPORT
+size_t crypto_core_ed25519_bytes(void);
+
+#define crypto_core_ed25519_UNIFORMBYTES 32
+SODIUM_EXPORT
+size_t crypto_core_ed25519_uniformbytes(void);
+
+SODIUM_EXPORT
+int crypto_core_ed25519_is_valid_point(const unsigned char *p);
+
+SODIUM_EXPORT
+int crypto_core_ed25519_add(unsigned char *r,
+ const unsigned char *p, const unsigned char *q);
+
+SODIUM_EXPORT
+int crypto_core_ed25519_sub(unsigned char *r,
+ const unsigned char *p, const unsigned char *q);
+
+SODIUM_EXPORT
+int crypto_core_ed25519_from_uniform(unsigned char *p, const unsigned char *r);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_core_hchacha20.h b/libs/libsodium/src/include/sodium/crypto_core_hchacha20.h
new file mode 100644
index 0000000000..05e5670c10
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_core_hchacha20.h
@@ -0,0 +1,35 @@
+#ifndef crypto_core_hchacha20_H
+#define crypto_core_hchacha20_H
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define crypto_core_hchacha20_OUTPUTBYTES 32U
+SODIUM_EXPORT
+size_t crypto_core_hchacha20_outputbytes(void);
+
+#define crypto_core_hchacha20_INPUTBYTES 16U
+SODIUM_EXPORT
+size_t crypto_core_hchacha20_inputbytes(void);
+
+#define crypto_core_hchacha20_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_core_hchacha20_keybytes(void);
+
+#define crypto_core_hchacha20_CONSTBYTES 16U
+SODIUM_EXPORT
+size_t crypto_core_hchacha20_constbytes(void);
+
+SODIUM_EXPORT
+int crypto_core_hchacha20(unsigned char *out, const unsigned char *in,
+ const unsigned char *k, const unsigned char *c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_core_hsalsa20.h b/libs/libsodium/src/include/sodium/crypto_core_hsalsa20.h
new file mode 100644
index 0000000000..82e475b8f6
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_core_hsalsa20.h
@@ -0,0 +1,35 @@
+#ifndef crypto_core_hsalsa20_H
+#define crypto_core_hsalsa20_H
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define crypto_core_hsalsa20_OUTPUTBYTES 32U
+SODIUM_EXPORT
+size_t crypto_core_hsalsa20_outputbytes(void);
+
+#define crypto_core_hsalsa20_INPUTBYTES 16U
+SODIUM_EXPORT
+size_t crypto_core_hsalsa20_inputbytes(void);
+
+#define crypto_core_hsalsa20_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_core_hsalsa20_keybytes(void);
+
+#define crypto_core_hsalsa20_CONSTBYTES 16U
+SODIUM_EXPORT
+size_t crypto_core_hsalsa20_constbytes(void);
+
+SODIUM_EXPORT
+int crypto_core_hsalsa20(unsigned char *out, const unsigned char *in,
+ const unsigned char *k, const unsigned char *c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_core_salsa20.h b/libs/libsodium/src/include/sodium/crypto_core_salsa20.h
new file mode 100644
index 0000000000..160cc56d2c
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_core_salsa20.h
@@ -0,0 +1,35 @@
+#ifndef crypto_core_salsa20_H
+#define crypto_core_salsa20_H
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define crypto_core_salsa20_OUTPUTBYTES 64U
+SODIUM_EXPORT
+size_t crypto_core_salsa20_outputbytes(void);
+
+#define crypto_core_salsa20_INPUTBYTES 16U
+SODIUM_EXPORT
+size_t crypto_core_salsa20_inputbytes(void);
+
+#define crypto_core_salsa20_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_core_salsa20_keybytes(void);
+
+#define crypto_core_salsa20_CONSTBYTES 16U
+SODIUM_EXPORT
+size_t crypto_core_salsa20_constbytes(void);
+
+SODIUM_EXPORT
+int crypto_core_salsa20(unsigned char *out, const unsigned char *in,
+ const unsigned char *k, const unsigned char *c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_core_salsa2012.h b/libs/libsodium/src/include/sodium/crypto_core_salsa2012.h
new file mode 100644
index 0000000000..bdd5f9fdbb
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_core_salsa2012.h
@@ -0,0 +1,35 @@
+#ifndef crypto_core_salsa2012_H
+#define crypto_core_salsa2012_H
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define crypto_core_salsa2012_OUTPUTBYTES 64U
+SODIUM_EXPORT
+size_t crypto_core_salsa2012_outputbytes(void);
+
+#define crypto_core_salsa2012_INPUTBYTES 16U
+SODIUM_EXPORT
+size_t crypto_core_salsa2012_inputbytes(void);
+
+#define crypto_core_salsa2012_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_core_salsa2012_keybytes(void);
+
+#define crypto_core_salsa2012_CONSTBYTES 16U
+SODIUM_EXPORT
+size_t crypto_core_salsa2012_constbytes(void);
+
+SODIUM_EXPORT
+int crypto_core_salsa2012(unsigned char *out, const unsigned char *in,
+ const unsigned char *k, const unsigned char *c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_core_salsa208.h b/libs/libsodium/src/include/sodium/crypto_core_salsa208.h
new file mode 100644
index 0000000000..876bda8936
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_core_salsa208.h
@@ -0,0 +1,39 @@
+#ifndef crypto_core_salsa208_H
+#define crypto_core_salsa208_H
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define crypto_core_salsa208_OUTPUTBYTES 64U
+SODIUM_EXPORT
+size_t crypto_core_salsa208_outputbytes(void)
+ __attribute__ ((deprecated));
+
+#define crypto_core_salsa208_INPUTBYTES 16U
+SODIUM_EXPORT
+size_t crypto_core_salsa208_inputbytes(void)
+ __attribute__ ((deprecated));
+
+#define crypto_core_salsa208_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_core_salsa208_keybytes(void)
+ __attribute__ ((deprecated));
+
+#define crypto_core_salsa208_CONSTBYTES 16U
+SODIUM_EXPORT
+size_t crypto_core_salsa208_constbytes(void)
+ __attribute__ ((deprecated));
+
+SODIUM_EXPORT
+int crypto_core_salsa208(unsigned char *out, const unsigned char *in,
+ const unsigned char *k, const unsigned char *c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_generichash.h b/libs/libsodium/src/include/sodium/crypto_generichash.h
new file mode 100644
index 0000000000..2398fb9dbb
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_generichash.h
@@ -0,0 +1,75 @@
+#ifndef crypto_generichash_H
+#define crypto_generichash_H
+
+#include <stddef.h>
+
+#include "crypto_generichash_blake2b.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_generichash_BYTES_MIN crypto_generichash_blake2b_BYTES_MIN
+SODIUM_EXPORT
+size_t crypto_generichash_bytes_min(void);
+
+#define crypto_generichash_BYTES_MAX crypto_generichash_blake2b_BYTES_MAX
+SODIUM_EXPORT
+size_t crypto_generichash_bytes_max(void);
+
+#define crypto_generichash_BYTES crypto_generichash_blake2b_BYTES
+SODIUM_EXPORT
+size_t crypto_generichash_bytes(void);
+
+#define crypto_generichash_KEYBYTES_MIN crypto_generichash_blake2b_KEYBYTES_MIN
+SODIUM_EXPORT
+size_t crypto_generichash_keybytes_min(void);
+
+#define crypto_generichash_KEYBYTES_MAX crypto_generichash_blake2b_KEYBYTES_MAX
+SODIUM_EXPORT
+size_t crypto_generichash_keybytes_max(void);
+
+#define crypto_generichash_KEYBYTES crypto_generichash_blake2b_KEYBYTES
+SODIUM_EXPORT
+size_t crypto_generichash_keybytes(void);
+
+#define crypto_generichash_PRIMITIVE "blake2b"
+SODIUM_EXPORT
+const char *crypto_generichash_primitive(void);
+
+typedef crypto_generichash_blake2b_state crypto_generichash_state;
+
+SODIUM_EXPORT
+size_t crypto_generichash_statebytes(void);
+
+SODIUM_EXPORT
+int crypto_generichash(unsigned char *out, size_t outlen,
+ const unsigned char *in, unsigned long long inlen,
+ const unsigned char *key, size_t keylen);
+
+SODIUM_EXPORT
+int crypto_generichash_init(crypto_generichash_state *state,
+ const unsigned char *key,
+ const size_t keylen, const size_t outlen);
+
+SODIUM_EXPORT
+int crypto_generichash_update(crypto_generichash_state *state,
+ const unsigned char *in,
+ unsigned long long inlen);
+
+SODIUM_EXPORT
+int crypto_generichash_final(crypto_generichash_state *state,
+ unsigned char *out, const size_t outlen);
+
+SODIUM_EXPORT
+void crypto_generichash_keygen(unsigned char k[crypto_generichash_KEYBYTES]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_generichash_blake2b.h b/libs/libsodium/src/include/sodium/crypto_generichash_blake2b.h
new file mode 100644
index 0000000000..9326a04ad1
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_generichash_blake2b.h
@@ -0,0 +1,117 @@
+#ifndef crypto_generichash_blake2b_H
+#define crypto_generichash_blake2b_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#if defined(__IBMC__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+# pragma pack(1)
+#else
+# pragma pack(push, 1)
+#endif
+
+typedef struct CRYPTO_ALIGN(64) crypto_generichash_blake2b_state {
+ uint64_t h[8];
+ uint64_t t[2];
+ uint64_t f[2];
+ uint8_t buf[2 * 128];
+ size_t buflen;
+ uint8_t last_node;
+} crypto_generichash_blake2b_state;
+
+#if defined(__IBMC__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+# pragma pack()
+#else
+# pragma pack(pop)
+#endif
+
+#define crypto_generichash_blake2b_BYTES_MIN 16U
+SODIUM_EXPORT
+size_t crypto_generichash_blake2b_bytes_min(void);
+
+#define crypto_generichash_blake2b_BYTES_MAX 64U
+SODIUM_EXPORT
+size_t crypto_generichash_blake2b_bytes_max(void);
+
+#define crypto_generichash_blake2b_BYTES 32U
+SODIUM_EXPORT
+size_t crypto_generichash_blake2b_bytes(void);
+
+#define crypto_generichash_blake2b_KEYBYTES_MIN 16U
+SODIUM_EXPORT
+size_t crypto_generichash_blake2b_keybytes_min(void);
+
+#define crypto_generichash_blake2b_KEYBYTES_MAX 64U
+SODIUM_EXPORT
+size_t crypto_generichash_blake2b_keybytes_max(void);
+
+#define crypto_generichash_blake2b_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_generichash_blake2b_keybytes(void);
+
+#define crypto_generichash_blake2b_SALTBYTES 16U
+SODIUM_EXPORT
+size_t crypto_generichash_blake2b_saltbytes(void);
+
+#define crypto_generichash_blake2b_PERSONALBYTES 16U
+SODIUM_EXPORT
+size_t crypto_generichash_blake2b_personalbytes(void);
+
+SODIUM_EXPORT
+size_t crypto_generichash_blake2b_statebytes(void);
+
+SODIUM_EXPORT
+int crypto_generichash_blake2b(unsigned char *out, size_t outlen,
+ const unsigned char *in,
+ unsigned long long inlen,
+ const unsigned char *key, size_t keylen);
+
+SODIUM_EXPORT
+int crypto_generichash_blake2b_salt_personal(unsigned char *out, size_t outlen,
+ const unsigned char *in,
+ unsigned long long inlen,
+ const unsigned char *key,
+ size_t keylen,
+ const unsigned char *salt,
+ const unsigned char *personal);
+
+SODIUM_EXPORT
+int crypto_generichash_blake2b_init(crypto_generichash_blake2b_state *state,
+ const unsigned char *key,
+ const size_t keylen, const size_t outlen);
+
+SODIUM_EXPORT
+int crypto_generichash_blake2b_init_salt_personal(crypto_generichash_blake2b_state *state,
+ const unsigned char *key,
+ const size_t keylen, const size_t outlen,
+ const unsigned char *salt,
+ const unsigned char *personal);
+
+SODIUM_EXPORT
+int crypto_generichash_blake2b_update(crypto_generichash_blake2b_state *state,
+ const unsigned char *in,
+ unsigned long long inlen);
+
+SODIUM_EXPORT
+int crypto_generichash_blake2b_final(crypto_generichash_blake2b_state *state,
+ unsigned char *out,
+ const size_t outlen);
+
+SODIUM_EXPORT
+void crypto_generichash_blake2b_keygen(unsigned char k[crypto_generichash_blake2b_KEYBYTES]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_hash.h b/libs/libsodium/src/include/sodium/crypto_hash.h
new file mode 100644
index 0000000000..302ed5c5ea
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_hash.h
@@ -0,0 +1,40 @@
+#ifndef crypto_hash_H
+#define crypto_hash_H
+
+/*
+ * WARNING: Unless you absolutely need to use SHA512 for interoperatibility,
+ * purposes, you might want to consider crypto_generichash() instead.
+ * Unlike SHA512, crypto_generichash() is not vulnerable to length
+ * extension attacks.
+ */
+
+#include <stddef.h>
+
+#include "crypto_hash_sha512.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_hash_BYTES crypto_hash_sha512_BYTES
+SODIUM_EXPORT
+size_t crypto_hash_bytes(void);
+
+SODIUM_EXPORT
+int crypto_hash(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen);
+
+#define crypto_hash_PRIMITIVE "sha512"
+SODIUM_EXPORT
+const char *crypto_hash_primitive(void)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_hash_sha256.h b/libs/libsodium/src/include/sodium/crypto_hash_sha256.h
new file mode 100644
index 0000000000..f64d16e0e5
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_hash_sha256.h
@@ -0,0 +1,57 @@
+#ifndef crypto_hash_sha256_H
+#define crypto_hash_sha256_H
+
+/*
+ * WARNING: Unless you absolutely need to use SHA256 for interoperatibility,
+ * purposes, you might want to consider crypto_generichash() instead.
+ * Unlike SHA256, crypto_generichash() is not vulnerable to length
+ * extension attacks.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+typedef struct crypto_hash_sha256_state {
+ uint32_t state[8];
+ uint64_t count;
+ uint8_t buf[64];
+} crypto_hash_sha256_state;
+
+SODIUM_EXPORT
+size_t crypto_hash_sha256_statebytes(void);
+
+#define crypto_hash_sha256_BYTES 32U
+SODIUM_EXPORT
+size_t crypto_hash_sha256_bytes(void);
+
+SODIUM_EXPORT
+int crypto_hash_sha256(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen);
+
+SODIUM_EXPORT
+int crypto_hash_sha256_init(crypto_hash_sha256_state *state);
+
+SODIUM_EXPORT
+int crypto_hash_sha256_update(crypto_hash_sha256_state *state,
+ const unsigned char *in,
+ unsigned long long inlen);
+
+SODIUM_EXPORT
+int crypto_hash_sha256_final(crypto_hash_sha256_state *state,
+ unsigned char *out);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_hash_sha512.h b/libs/libsodium/src/include/sodium/crypto_hash_sha512.h
new file mode 100644
index 0000000000..6b0330f14f
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_hash_sha512.h
@@ -0,0 +1,57 @@
+#ifndef crypto_hash_sha512_H
+#define crypto_hash_sha512_H
+
+/*
+ * WARNING: Unless you absolutely need to use SHA512 for interoperatibility,
+ * purposes, you might want to consider crypto_generichash() instead.
+ * Unlike SHA512, crypto_generichash() is not vulnerable to length
+ * extension attacks.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+typedef struct crypto_hash_sha512_state {
+ uint64_t state[8];
+ uint64_t count[2];
+ uint8_t buf[128];
+} crypto_hash_sha512_state;
+
+SODIUM_EXPORT
+size_t crypto_hash_sha512_statebytes(void);
+
+#define crypto_hash_sha512_BYTES 64U
+SODIUM_EXPORT
+size_t crypto_hash_sha512_bytes(void);
+
+SODIUM_EXPORT
+int crypto_hash_sha512(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen);
+
+SODIUM_EXPORT
+int crypto_hash_sha512_init(crypto_hash_sha512_state *state);
+
+SODIUM_EXPORT
+int crypto_hash_sha512_update(crypto_hash_sha512_state *state,
+ const unsigned char *in,
+ unsigned long long inlen);
+
+SODIUM_EXPORT
+int crypto_hash_sha512_final(crypto_hash_sha512_state *state,
+ unsigned char *out);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_kdf.h b/libs/libsodium/src/include/sodium/crypto_kdf.h
new file mode 100644
index 0000000000..52e496a744
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_kdf.h
@@ -0,0 +1,51 @@
+#ifndef crypto_kdf_H
+#define crypto_kdf_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "crypto_kdf_blake2b.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_kdf_BYTES_MIN crypto_kdf_blake2b_BYTES_MIN
+SODIUM_EXPORT
+size_t crypto_kdf_bytes_min(void);
+
+#define crypto_kdf_BYTES_MAX crypto_kdf_blake2b_BYTES_MAX
+SODIUM_EXPORT
+size_t crypto_kdf_bytes_max(void);
+
+#define crypto_kdf_CONTEXTBYTES crypto_kdf_blake2b_CONTEXTBYTES
+SODIUM_EXPORT
+size_t crypto_kdf_contextbytes(void);
+
+#define crypto_kdf_KEYBYTES crypto_kdf_blake2b_KEYBYTES
+SODIUM_EXPORT
+size_t crypto_kdf_keybytes(void);
+
+#define crypto_kdf_PRIMITIVE "blake2b"
+SODIUM_EXPORT
+const char *crypto_kdf_primitive(void)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_kdf_derive_from_key(unsigned char *subkey, size_t subkey_len,
+ uint64_t subkey_id,
+ const char ctx[crypto_kdf_CONTEXTBYTES],
+ const unsigned char key[crypto_kdf_KEYBYTES]);
+
+SODIUM_EXPORT
+void crypto_kdf_keygen(unsigned char k[crypto_kdf_KEYBYTES]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_kdf_blake2b.h b/libs/libsodium/src/include/sodium/crypto_kdf_blake2b.h
new file mode 100644
index 0000000000..5480ebe82f
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_kdf_blake2b.h
@@ -0,0 +1,42 @@
+#ifndef crypto_kdf_blake2b_H
+#define crypto_kdf_blake2b_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "crypto_kdf_blake2b.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_kdf_blake2b_BYTES_MIN 16
+SODIUM_EXPORT
+size_t crypto_kdf_blake2b_bytes_min(void);
+
+#define crypto_kdf_blake2b_BYTES_MAX 64
+SODIUM_EXPORT
+size_t crypto_kdf_blake2b_bytes_max(void);
+
+#define crypto_kdf_blake2b_CONTEXTBYTES 8
+SODIUM_EXPORT
+size_t crypto_kdf_blake2b_contextbytes(void);
+
+#define crypto_kdf_blake2b_KEYBYTES 32
+SODIUM_EXPORT
+size_t crypto_kdf_blake2b_keybytes(void);
+
+SODIUM_EXPORT
+int crypto_kdf_blake2b_derive_from_key(unsigned char *subkey, size_t subkey_len,
+ uint64_t subkey_id,
+ const char ctx[crypto_kdf_blake2b_CONTEXTBYTES],
+ const unsigned char key[crypto_kdf_blake2b_KEYBYTES]);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_kx.h b/libs/libsodium/src/include/sodium/crypto_kx.h
new file mode 100644
index 0000000000..d1fce90da5
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_kx.h
@@ -0,0 +1,64 @@
+#ifndef crypto_kx_H
+#define crypto_kx_H
+
+#include <stddef.h>
+
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_kx_PUBLICKEYBYTES 32
+SODIUM_EXPORT
+size_t crypto_kx_publickeybytes(void);
+
+#define crypto_kx_SECRETKEYBYTES 32
+SODIUM_EXPORT
+size_t crypto_kx_secretkeybytes(void);
+
+#define crypto_kx_SEEDBYTES 32
+SODIUM_EXPORT
+size_t crypto_kx_seedbytes(void);
+
+#define crypto_kx_SESSIONKEYBYTES 32
+SODIUM_EXPORT
+size_t crypto_kx_sessionkeybytes(void);
+
+#define crypto_kx_PRIMITIVE "x25519blake2b"
+SODIUM_EXPORT
+const char *crypto_kx_primitive(void);
+
+SODIUM_EXPORT
+int crypto_kx_seed_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES],
+ unsigned char sk[crypto_kx_SECRETKEYBYTES],
+ const unsigned char seed[crypto_kx_SEEDBYTES]);
+
+SODIUM_EXPORT
+int crypto_kx_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES],
+ unsigned char sk[crypto_kx_SECRETKEYBYTES]);
+
+SODIUM_EXPORT
+int crypto_kx_client_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES],
+ unsigned char tx[crypto_kx_SESSIONKEYBYTES],
+ const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES],
+ const unsigned char client_sk[crypto_kx_SECRETKEYBYTES],
+ const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES])
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_kx_server_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES],
+ unsigned char tx[crypto_kx_SESSIONKEYBYTES],
+ const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES],
+ const unsigned char server_sk[crypto_kx_SECRETKEYBYTES],
+ const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES])
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_onetimeauth.h b/libs/libsodium/src/include/sodium/crypto_onetimeauth.h
new file mode 100644
index 0000000000..5951c5b82d
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_onetimeauth.h
@@ -0,0 +1,62 @@
+#ifndef crypto_onetimeauth_H
+#define crypto_onetimeauth_H
+
+#include <stddef.h>
+
+#include "crypto_onetimeauth_poly1305.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+typedef crypto_onetimeauth_poly1305_state crypto_onetimeauth_state;
+
+SODIUM_EXPORT
+size_t crypto_onetimeauth_statebytes(void);
+
+#define crypto_onetimeauth_BYTES crypto_onetimeauth_poly1305_BYTES
+SODIUM_EXPORT
+size_t crypto_onetimeauth_bytes(void);
+
+#define crypto_onetimeauth_KEYBYTES crypto_onetimeauth_poly1305_KEYBYTES
+SODIUM_EXPORT
+size_t crypto_onetimeauth_keybytes(void);
+
+#define crypto_onetimeauth_PRIMITIVE "poly1305"
+SODIUM_EXPORT
+const char *crypto_onetimeauth_primitive(void);
+
+SODIUM_EXPORT
+int crypto_onetimeauth(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_onetimeauth_verify(const unsigned char *h, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_onetimeauth_init(crypto_onetimeauth_state *state,
+ const unsigned char *key);
+
+SODIUM_EXPORT
+int crypto_onetimeauth_update(crypto_onetimeauth_state *state,
+ const unsigned char *in,
+ unsigned long long inlen);
+
+SODIUM_EXPORT
+int crypto_onetimeauth_final(crypto_onetimeauth_state *state,
+ unsigned char *out);
+
+SODIUM_EXPORT
+void crypto_onetimeauth_keygen(unsigned char k[crypto_onetimeauth_KEYBYTES]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_onetimeauth_poly1305.h b/libs/libsodium/src/include/sodium/crypto_onetimeauth_poly1305.h
new file mode 100644
index 0000000000..4b89c4f019
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_onetimeauth_poly1305.h
@@ -0,0 +1,67 @@
+#ifndef crypto_onetimeauth_poly1305_H
+#define crypto_onetimeauth_poly1305_H
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+
+#include "export.h"
+
+typedef struct CRYPTO_ALIGN(16) crypto_onetimeauth_poly1305_state {
+ unsigned char opaque[256];
+} crypto_onetimeauth_poly1305_state;
+
+SODIUM_EXPORT
+size_t crypto_onetimeauth_poly1305_statebytes(void);
+
+#define crypto_onetimeauth_poly1305_BYTES 16U
+SODIUM_EXPORT
+size_t crypto_onetimeauth_poly1305_bytes(void);
+
+#define crypto_onetimeauth_poly1305_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_onetimeauth_poly1305_keybytes(void);
+
+SODIUM_EXPORT
+int crypto_onetimeauth_poly1305(unsigned char *out,
+ const unsigned char *in,
+ unsigned long long inlen,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_onetimeauth_poly1305_verify(const unsigned char *h,
+ const unsigned char *in,
+ unsigned long long inlen,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_onetimeauth_poly1305_init(crypto_onetimeauth_poly1305_state *state,
+ const unsigned char *key);
+
+SODIUM_EXPORT
+int crypto_onetimeauth_poly1305_update(crypto_onetimeauth_poly1305_state *state,
+ const unsigned char *in,
+ unsigned long long inlen);
+
+SODIUM_EXPORT
+int crypto_onetimeauth_poly1305_final(crypto_onetimeauth_poly1305_state *state,
+ unsigned char *out);
+
+SODIUM_EXPORT
+void crypto_onetimeauth_poly1305_keygen(unsigned char k[crypto_onetimeauth_poly1305_KEYBYTES]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_pwhash.h b/libs/libsodium/src/include/sodium/crypto_pwhash.h
new file mode 100644
index 0000000000..2c76461f44
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_pwhash.h
@@ -0,0 +1,147 @@
+#ifndef crypto_pwhash_H
+#define crypto_pwhash_H
+
+#include <stddef.h>
+
+#include "crypto_pwhash_argon2i.h"
+#include "crypto_pwhash_argon2id.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_pwhash_ALG_ARGON2I13 crypto_pwhash_argon2i_ALG_ARGON2I13
+SODIUM_EXPORT
+int crypto_pwhash_alg_argon2i13(void);
+
+#define crypto_pwhash_ALG_ARGON2ID13 crypto_pwhash_argon2id_ALG_ARGON2ID13
+SODIUM_EXPORT
+int crypto_pwhash_alg_argon2id13(void);
+
+#define crypto_pwhash_ALG_DEFAULT crypto_pwhash_ALG_ARGON2ID13
+SODIUM_EXPORT
+int crypto_pwhash_alg_default(void);
+
+#define crypto_pwhash_BYTES_MIN crypto_pwhash_argon2id_BYTES_MIN
+SODIUM_EXPORT
+size_t crypto_pwhash_bytes_min(void);
+
+#define crypto_pwhash_BYTES_MAX crypto_pwhash_argon2id_BYTES_MAX
+SODIUM_EXPORT
+size_t crypto_pwhash_bytes_max(void);
+
+#define crypto_pwhash_PASSWD_MIN crypto_pwhash_argon2id_PASSWD_MIN
+SODIUM_EXPORT
+size_t crypto_pwhash_passwd_min(void);
+
+#define crypto_pwhash_PASSWD_MAX crypto_pwhash_argon2id_PASSWD_MAX
+SODIUM_EXPORT
+size_t crypto_pwhash_passwd_max(void);
+
+#define crypto_pwhash_SALTBYTES crypto_pwhash_argon2id_SALTBYTES
+SODIUM_EXPORT
+size_t crypto_pwhash_saltbytes(void);
+
+#define crypto_pwhash_STRBYTES crypto_pwhash_argon2id_STRBYTES
+SODIUM_EXPORT
+size_t crypto_pwhash_strbytes(void);
+
+#define crypto_pwhash_STRPREFIX crypto_pwhash_argon2id_STRPREFIX
+SODIUM_EXPORT
+const char *crypto_pwhash_strprefix(void);
+
+#define crypto_pwhash_OPSLIMIT_MIN crypto_pwhash_argon2id_OPSLIMIT_MIN
+SODIUM_EXPORT
+size_t crypto_pwhash_opslimit_min(void);
+
+#define crypto_pwhash_OPSLIMIT_MAX crypto_pwhash_argon2id_OPSLIMIT_MAX
+SODIUM_EXPORT
+size_t crypto_pwhash_opslimit_max(void);
+
+#define crypto_pwhash_MEMLIMIT_MIN crypto_pwhash_argon2id_MEMLIMIT_MIN
+SODIUM_EXPORT
+size_t crypto_pwhash_memlimit_min(void);
+
+#define crypto_pwhash_MEMLIMIT_MAX crypto_pwhash_argon2id_MEMLIMIT_MAX
+SODIUM_EXPORT
+size_t crypto_pwhash_memlimit_max(void);
+
+#define crypto_pwhash_OPSLIMIT_INTERACTIVE crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE
+SODIUM_EXPORT
+size_t crypto_pwhash_opslimit_interactive(void);
+
+#define crypto_pwhash_MEMLIMIT_INTERACTIVE crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE
+SODIUM_EXPORT
+size_t crypto_pwhash_memlimit_interactive(void);
+
+#define crypto_pwhash_OPSLIMIT_MODERATE crypto_pwhash_argon2id_OPSLIMIT_MODERATE
+SODIUM_EXPORT
+size_t crypto_pwhash_opslimit_moderate(void);
+
+#define crypto_pwhash_MEMLIMIT_MODERATE crypto_pwhash_argon2id_MEMLIMIT_MODERATE
+SODIUM_EXPORT
+size_t crypto_pwhash_memlimit_moderate(void);
+
+#define crypto_pwhash_OPSLIMIT_SENSITIVE crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE
+SODIUM_EXPORT
+size_t crypto_pwhash_opslimit_sensitive(void);
+
+#define crypto_pwhash_MEMLIMIT_SENSITIVE crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE
+SODIUM_EXPORT
+size_t crypto_pwhash_memlimit_sensitive(void);
+
+/*
+ * With this function, do not forget to store all parameters, including the
+ * algorithm identifier in order to produce deterministic output.
+ * The crypto_pwhash_* definitions, including crypto_pwhash_ALG_DEFAULT,
+ * may change.
+ */
+SODIUM_EXPORT
+int crypto_pwhash(unsigned char * const out, unsigned long long outlen,
+ const char * const passwd, unsigned long long passwdlen,
+ const unsigned char * const salt,
+ unsigned long long opslimit, size_t memlimit, int alg)
+ __attribute__ ((warn_unused_result));
+
+/*
+ * The output string already includes all the required parameters, including
+ * the algorithm identifier. The string is all that has to be stored in
+ * order to verify a password.
+ */
+SODIUM_EXPORT
+int crypto_pwhash_str(char out[crypto_pwhash_STRBYTES],
+ const char * const passwd, unsigned long long passwdlen,
+ unsigned long long opslimit, size_t memlimit)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_pwhash_str_alg(char out[crypto_pwhash_STRBYTES],
+ const char * const passwd, unsigned long long passwdlen,
+ unsigned long long opslimit, size_t memlimit, int alg)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_pwhash_str_verify(const char str[crypto_pwhash_STRBYTES],
+ const char * const passwd,
+ unsigned long long passwdlen)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_pwhash_str_needs_rehash(const char str[crypto_pwhash_STRBYTES],
+ unsigned long long opslimit, size_t memlimit)
+ __attribute__ ((warn_unused_result));
+
+#define crypto_pwhash_PRIMITIVE "argon2i"
+SODIUM_EXPORT
+const char *crypto_pwhash_primitive(void)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_pwhash_argon2i.h b/libs/libsodium/src/include/sodium/crypto_pwhash_argon2i.h
new file mode 100644
index 0000000000..8e4c1c3531
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_pwhash_argon2i.h
@@ -0,0 +1,122 @@
+#ifndef crypto_pwhash_argon2i_H
+#define crypto_pwhash_argon2i_H
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_pwhash_argon2i_ALG_ARGON2I13 1
+SODIUM_EXPORT
+int crypto_pwhash_argon2i_alg_argon2i13(void);
+
+#define crypto_pwhash_argon2i_BYTES_MIN 16U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2i_bytes_min(void);
+
+#define crypto_pwhash_argon2i_BYTES_MAX SODIUM_MIN(SODIUM_SIZE_MAX, 4294967295U)
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2i_bytes_max(void);
+
+#define crypto_pwhash_argon2i_PASSWD_MIN 0U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2i_passwd_min(void);
+
+#define crypto_pwhash_argon2i_PASSWD_MAX 4294967295U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2i_passwd_max(void);
+
+#define crypto_pwhash_argon2i_SALTBYTES 16U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2i_saltbytes(void);
+
+#define crypto_pwhash_argon2i_STRBYTES 128U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2i_strbytes(void);
+
+#define crypto_pwhash_argon2i_STRPREFIX "$argon2i$"
+SODIUM_EXPORT
+const char *crypto_pwhash_argon2i_strprefix(void);
+
+#define crypto_pwhash_argon2i_OPSLIMIT_MIN 3U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2i_opslimit_min(void);
+
+#define crypto_pwhash_argon2i_OPSLIMIT_MAX 4294967295U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2i_opslimit_max(void);
+
+#define crypto_pwhash_argon2i_MEMLIMIT_MIN 8192U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2i_memlimit_min(void);
+
+#define crypto_pwhash_argon2i_MEMLIMIT_MAX \
+ ((SIZE_MAX >= 4398046510080U) ? 4398046510080U : (SIZE_MAX >= 2147483648U) ? 2147483648U : 32768U)
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2i_memlimit_max(void);
+
+#define crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE 4U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2i_opslimit_interactive(void);
+
+#define crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE 33554432U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2i_memlimit_interactive(void);
+
+#define crypto_pwhash_argon2i_OPSLIMIT_MODERATE 6U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2i_opslimit_moderate(void);
+
+#define crypto_pwhash_argon2i_MEMLIMIT_MODERATE 134217728U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2i_memlimit_moderate(void);
+
+#define crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE 8U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2i_opslimit_sensitive(void);
+
+#define crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE 536870912U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2i_memlimit_sensitive(void);
+
+SODIUM_EXPORT
+int crypto_pwhash_argon2i(unsigned char * const out,
+ unsigned long long outlen,
+ const char * const passwd,
+ unsigned long long passwdlen,
+ const unsigned char * const salt,
+ unsigned long long opslimit, size_t memlimit,
+ int alg)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_pwhash_argon2i_str(char out[crypto_pwhash_argon2i_STRBYTES],
+ const char * const passwd,
+ unsigned long long passwdlen,
+ unsigned long long opslimit, size_t memlimit)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_pwhash_argon2i_str_verify(const char str[crypto_pwhash_argon2i_STRBYTES],
+ const char * const passwd,
+ unsigned long long passwdlen)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_pwhash_argon2i_str_needs_rehash(const char str[crypto_pwhash_argon2i_STRBYTES],
+ unsigned long long opslimit, size_t memlimit)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_pwhash_argon2id.h b/libs/libsodium/src/include/sodium/crypto_pwhash_argon2id.h
new file mode 100644
index 0000000000..51b17aa8e3
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_pwhash_argon2id.h
@@ -0,0 +1,122 @@
+#ifndef crypto_pwhash_argon2id_H
+#define crypto_pwhash_argon2id_H
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_pwhash_argon2id_ALG_ARGON2ID13 2
+SODIUM_EXPORT
+int crypto_pwhash_argon2id_alg_argon2id13(void);
+
+#define crypto_pwhash_argon2id_BYTES_MIN 16U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2id_bytes_min(void);
+
+#define crypto_pwhash_argon2id_BYTES_MAX SODIUM_MIN(SODIUM_SIZE_MAX, 4294967295U)
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2id_bytes_max(void);
+
+#define crypto_pwhash_argon2id_PASSWD_MIN 0U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2id_passwd_min(void);
+
+#define crypto_pwhash_argon2id_PASSWD_MAX 4294967295U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2id_passwd_max(void);
+
+#define crypto_pwhash_argon2id_SALTBYTES 16U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2id_saltbytes(void);
+
+#define crypto_pwhash_argon2id_STRBYTES 128U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2id_strbytes(void);
+
+#define crypto_pwhash_argon2id_STRPREFIX "$argon2id$"
+SODIUM_EXPORT
+const char *crypto_pwhash_argon2id_strprefix(void);
+
+#define crypto_pwhash_argon2id_OPSLIMIT_MIN 1U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2id_opslimit_min(void);
+
+#define crypto_pwhash_argon2id_OPSLIMIT_MAX 4294967295U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2id_opslimit_max(void);
+
+#define crypto_pwhash_argon2id_MEMLIMIT_MIN 8192U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2id_memlimit_min(void);
+
+#define crypto_pwhash_argon2id_MEMLIMIT_MAX \
+ ((SIZE_MAX >= 4398046510080U) ? 4398046510080U : (SIZE_MAX >= 2147483648U) ? 2147483648U : 32768U)
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2id_memlimit_max(void);
+
+#define crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE 2U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2id_opslimit_interactive(void);
+
+#define crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE 67108864U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2id_memlimit_interactive(void);
+
+#define crypto_pwhash_argon2id_OPSLIMIT_MODERATE 3U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2id_opslimit_moderate(void);
+
+#define crypto_pwhash_argon2id_MEMLIMIT_MODERATE 268435456U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2id_memlimit_moderate(void);
+
+#define crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE 4U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2id_opslimit_sensitive(void);
+
+#define crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE 1073741824U
+SODIUM_EXPORT
+size_t crypto_pwhash_argon2id_memlimit_sensitive(void);
+
+SODIUM_EXPORT
+int crypto_pwhash_argon2id(unsigned char * const out,
+ unsigned long long outlen,
+ const char * const passwd,
+ unsigned long long passwdlen,
+ const unsigned char * const salt,
+ unsigned long long opslimit, size_t memlimit,
+ int alg)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_pwhash_argon2id_str(char out[crypto_pwhash_argon2id_STRBYTES],
+ const char * const passwd,
+ unsigned long long passwdlen,
+ unsigned long long opslimit, size_t memlimit)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_pwhash_argon2id_str_verify(const char str[crypto_pwhash_argon2id_STRBYTES],
+ const char * const passwd,
+ unsigned long long passwdlen)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_pwhash_argon2id_str_needs_rehash(const char str[crypto_pwhash_argon2id_STRBYTES],
+ unsigned long long opslimit, size_t memlimit)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_pwhash_scryptsalsa208sha256.h b/libs/libsodium/src/include/sodium/crypto_pwhash_scryptsalsa208sha256.h
new file mode 100644
index 0000000000..951b87b962
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_pwhash_scryptsalsa208sha256.h
@@ -0,0 +1,120 @@
+#ifndef crypto_pwhash_scryptsalsa208sha256_H
+#define crypto_pwhash_scryptsalsa208sha256_H
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_pwhash_scryptsalsa208sha256_BYTES_MIN 16U
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_bytes_min(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_BYTES_MAX \
+ SODIUM_MIN(SODIUM_SIZE_MAX, 0x1fffffffe0ULL)
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_bytes_max(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN 0U
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_passwd_min(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX SODIUM_SIZE_MAX
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_passwd_max(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_SALTBYTES 32U
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_saltbytes(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_STRBYTES 102U
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_strbytes(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_STRPREFIX "$7$"
+SODIUM_EXPORT
+const char *crypto_pwhash_scryptsalsa208sha256_strprefix(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN 32768U
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_opslimit_min(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX 4294967295U
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_opslimit_max(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN 16777216U
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_memlimit_min(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX \
+ SODIUM_MIN(SIZE_MAX, 68719476736ULL)
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_memlimit_max(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE 524288U
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE 16777216U
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE 33554432U
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE 1073741824U
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void);
+
+SODIUM_EXPORT
+int crypto_pwhash_scryptsalsa208sha256(unsigned char * const out,
+ unsigned long long outlen,
+ const char * const passwd,
+ unsigned long long passwdlen,
+ const unsigned char * const salt,
+ unsigned long long opslimit,
+ size_t memlimit)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_pwhash_scryptsalsa208sha256_str(char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
+ const char * const passwd,
+ unsigned long long passwdlen,
+ unsigned long long opslimit,
+ size_t memlimit)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
+ const char * const passwd,
+ unsigned long long passwdlen)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t * passwd, size_t passwdlen,
+ const uint8_t * salt, size_t saltlen,
+ uint64_t N, uint32_t r, uint32_t p,
+ uint8_t * buf, size_t buflen)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
+ unsigned long long opslimit,
+ size_t memlimit)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_scalarmult.h b/libs/libsodium/src/include/sodium/crypto_scalarmult.h
new file mode 100644
index 0000000000..f7fa6f8f39
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_scalarmult.h
@@ -0,0 +1,45 @@
+#ifndef crypto_scalarmult_H
+#define crypto_scalarmult_H
+
+#include <stddef.h>
+
+#include "crypto_scalarmult_curve25519.h"
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define crypto_scalarmult_BYTES crypto_scalarmult_curve25519_BYTES
+SODIUM_EXPORT
+size_t crypto_scalarmult_bytes(void);
+
+#define crypto_scalarmult_SCALARBYTES crypto_scalarmult_curve25519_SCALARBYTES
+SODIUM_EXPORT
+size_t crypto_scalarmult_scalarbytes(void);
+
+#define crypto_scalarmult_PRIMITIVE "curve25519"
+SODIUM_EXPORT
+const char *crypto_scalarmult_primitive(void);
+
+SODIUM_EXPORT
+int crypto_scalarmult_base(unsigned char *q, const unsigned char *n);
+
+/*
+ * NOTE: Do not use the result of this function directly.
+ *
+ * Hash the result with the public keys in order to compute a shared
+ * secret key: H(q || client_pk || server_pk)
+ *
+ * Or unless this is not an option, use the crypto_kx() API instead.
+ */
+SODIUM_EXPORT
+int crypto_scalarmult(unsigned char *q, const unsigned char *n,
+ const unsigned char *p)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_scalarmult_curve25519.h b/libs/libsodium/src/include/sodium/crypto_scalarmult_curve25519.h
new file mode 100644
index 0000000000..ae85eadc22
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_scalarmult_curve25519.h
@@ -0,0 +1,40 @@
+#ifndef crypto_scalarmult_curve25519_H
+#define crypto_scalarmult_curve25519_H
+
+#include <stddef.h>
+
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define crypto_scalarmult_curve25519_BYTES 32U
+SODIUM_EXPORT
+size_t crypto_scalarmult_curve25519_bytes(void);
+
+#define crypto_scalarmult_curve25519_SCALARBYTES 32U
+SODIUM_EXPORT
+size_t crypto_scalarmult_curve25519_scalarbytes(void);
+
+/*
+ * NOTE: Do not use the result of this function directly.
+ *
+ * Hash the result with the public keys in order to compute a shared
+ * secret key: H(q || client_pk || server_pk)
+ *
+ * Or unless this is not an option, use the crypto_kx() API instead.
+ */
+SODIUM_EXPORT
+int crypto_scalarmult_curve25519(unsigned char *q, const unsigned char *n,
+ const unsigned char *p)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_scalarmult_curve25519_base(unsigned char *q, const unsigned char *n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_scalarmult_ed25519.h b/libs/libsodium/src/include/sodium/crypto_scalarmult_ed25519.h
new file mode 100644
index 0000000000..3d51235112
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_scalarmult_ed25519.h
@@ -0,0 +1,41 @@
+
+#ifndef crypto_scalarmult_ed25519_H
+#define crypto_scalarmult_ed25519_H
+
+#include <stddef.h>
+
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define crypto_scalarmult_ed25519_BYTES 32U
+SODIUM_EXPORT
+size_t crypto_scalarmult_ed25519_bytes(void);
+
+#define crypto_scalarmult_ed25519_SCALARBYTES 32U
+SODIUM_EXPORT
+size_t crypto_scalarmult_ed25519_scalarbytes(void);
+
+/*
+ * NOTE: Do not use the result of this function directly.
+ *
+ * Hash the result with the public keys in order to compute a shared
+ * secret key: H(q || client_pk || server_pk)
+ *
+ * Or unless this is not an option, use the crypto_kx() API instead.
+ */
+SODIUM_EXPORT
+int crypto_scalarmult_ed25519(unsigned char *q, const unsigned char *n,
+ const unsigned char *p)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_scalarmult_ed25519_base(unsigned char *q, const unsigned char *n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_secretbox.h b/libs/libsodium/src/include/sodium/crypto_secretbox.h
new file mode 100644
index 0000000000..55e94a0292
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_secretbox.h
@@ -0,0 +1,91 @@
+#ifndef crypto_secretbox_H
+#define crypto_secretbox_H
+
+#include <stddef.h>
+
+#include "crypto_secretbox_xsalsa20poly1305.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_secretbox_KEYBYTES crypto_secretbox_xsalsa20poly1305_KEYBYTES
+SODIUM_EXPORT
+size_t crypto_secretbox_keybytes(void);
+
+#define crypto_secretbox_NONCEBYTES crypto_secretbox_xsalsa20poly1305_NONCEBYTES
+SODIUM_EXPORT
+size_t crypto_secretbox_noncebytes(void);
+
+#define crypto_secretbox_MACBYTES crypto_secretbox_xsalsa20poly1305_MACBYTES
+SODIUM_EXPORT
+size_t crypto_secretbox_macbytes(void);
+
+#define crypto_secretbox_PRIMITIVE "xsalsa20poly1305"
+SODIUM_EXPORT
+const char *crypto_secretbox_primitive(void);
+
+#define crypto_secretbox_MESSAGEBYTES_MAX crypto_secretbox_xsalsa20poly1305_MESSAGEBYTES_MAX
+SODIUM_EXPORT
+size_t crypto_secretbox_messagebytes_max(void);
+
+SODIUM_EXPORT
+int crypto_secretbox_easy(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_secretbox_open_easy(unsigned char *m, const unsigned char *c,
+ unsigned long long clen, const unsigned char *n,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_secretbox_detached(unsigned char *c, unsigned char *mac,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_secretbox_open_detached(unsigned char *m,
+ const unsigned char *c,
+ const unsigned char *mac,
+ unsigned long long clen,
+ const unsigned char *n,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+void crypto_secretbox_keygen(unsigned char k[crypto_secretbox_KEYBYTES]);
+
+/* -- NaCl compatibility interface ; Requires padding -- */
+
+#define crypto_secretbox_ZEROBYTES crypto_secretbox_xsalsa20poly1305_ZEROBYTES
+SODIUM_EXPORT
+size_t crypto_secretbox_zerobytes(void);
+
+#define crypto_secretbox_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES
+SODIUM_EXPORT
+size_t crypto_secretbox_boxzerobytes(void);
+
+SODIUM_EXPORT
+int crypto_secretbox(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_secretbox_open(unsigned char *m, const unsigned char *c,
+ unsigned long long clen, const unsigned char *n,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_secretbox_xchacha20poly1305.h b/libs/libsodium/src/include/sodium/crypto_secretbox_xchacha20poly1305.h
new file mode 100644
index 0000000000..2919da161c
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_secretbox_xchacha20poly1305.h
@@ -0,0 +1,68 @@
+#ifndef crypto_secretbox_xchacha20poly1305_H
+#define crypto_secretbox_xchacha20poly1305_H
+
+#include <stddef.h>
+#include "crypto_stream_xchacha20.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_secretbox_xchacha20poly1305_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_secretbox_xchacha20poly1305_keybytes(void);
+
+#define crypto_secretbox_xchacha20poly1305_NONCEBYTES 24U
+SODIUM_EXPORT
+size_t crypto_secretbox_xchacha20poly1305_noncebytes(void);
+
+#define crypto_secretbox_xchacha20poly1305_MACBYTES 16U
+SODIUM_EXPORT
+size_t crypto_secretbox_xchacha20poly1305_macbytes(void);
+
+#define crypto_secretbox_xchacha20poly1305_MESSAGEBYTES_MAX \
+ (crypto_stream_xchacha20_MESSAGEBYTES_MAX - crypto_secretbox_xchacha20poly1305_MACBYTES)
+SODIUM_EXPORT
+size_t crypto_secretbox_xchacha20poly1305_messagebytes_max(void);
+
+SODIUM_EXPORT
+int crypto_secretbox_xchacha20poly1305_easy(unsigned char *c,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_secretbox_xchacha20poly1305_open_easy(unsigned char *m,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *n,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_secretbox_xchacha20poly1305_detached(unsigned char *c,
+ unsigned char *mac,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_secretbox_xchacha20poly1305_open_detached(unsigned char *m,
+ const unsigned char *c,
+ const unsigned char *mac,
+ unsigned long long clen,
+ const unsigned char *n,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_secretbox_xsalsa20poly1305.h b/libs/libsodium/src/include/sodium/crypto_secretbox_xsalsa20poly1305.h
new file mode 100644
index 0000000000..4b8c7c8ea2
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_secretbox_xsalsa20poly1305.h
@@ -0,0 +1,67 @@
+#ifndef crypto_secretbox_xsalsa20poly1305_H
+#define crypto_secretbox_xsalsa20poly1305_H
+
+#include <stddef.h>
+#include "crypto_stream_xsalsa20.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_secretbox_xsalsa20poly1305_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_secretbox_xsalsa20poly1305_keybytes(void);
+
+#define crypto_secretbox_xsalsa20poly1305_NONCEBYTES 24U
+SODIUM_EXPORT
+size_t crypto_secretbox_xsalsa20poly1305_noncebytes(void);
+
+#define crypto_secretbox_xsalsa20poly1305_MACBYTES 16U
+SODIUM_EXPORT
+size_t crypto_secretbox_xsalsa20poly1305_macbytes(void);
+
+/* Only for the libsodium API - The NaCl compatibility API would require BOXZEROBYTES extra bytes */
+#define crypto_secretbox_xsalsa20poly1305_MESSAGEBYTES_MAX \
+ (crypto_stream_xsalsa20_MESSAGEBYTES_MAX - crypto_secretbox_xsalsa20poly1305_MACBYTES)
+SODIUM_EXPORT
+size_t crypto_secretbox_xsalsa20poly1305_messagebytes_max(void);
+
+SODIUM_EXPORT
+int crypto_secretbox_xsalsa20poly1305(unsigned char *c,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_secretbox_xsalsa20poly1305_open(unsigned char *m,
+ const unsigned char *c,
+ unsigned long long clen,
+ const unsigned char *n,
+ const unsigned char *k)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+void crypto_secretbox_xsalsa20poly1305_keygen(unsigned char k[crypto_secretbox_xsalsa20poly1305_KEYBYTES]);
+
+/* -- NaCl compatibility interface ; Requires padding -- */
+
+#define crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES 16U
+SODIUM_EXPORT
+size_t crypto_secretbox_xsalsa20poly1305_boxzerobytes(void);
+
+#define crypto_secretbox_xsalsa20poly1305_ZEROBYTES \
+ (crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES + \
+ crypto_secretbox_xsalsa20poly1305_MACBYTES)
+SODIUM_EXPORT
+size_t crypto_secretbox_xsalsa20poly1305_zerobytes(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_secretstream_xchacha20poly1305.h b/libs/libsodium/src/include/sodium/crypto_secretstream_xchacha20poly1305.h
new file mode 100644
index 0000000000..7d3fa2a9e3
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_secretstream_xchacha20poly1305.h
@@ -0,0 +1,102 @@
+#ifndef crypto_secretstream_xchacha20poly1305_H
+#define crypto_secretstream_xchacha20poly1305_H
+
+#include <stddef.h>
+
+#include "crypto_aead_xchacha20poly1305.h"
+#include "crypto_stream_chacha20.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_secretstream_xchacha20poly1305_ABYTES \
+ (1U + crypto_aead_xchacha20poly1305_ietf_ABYTES)
+SODIUM_EXPORT
+size_t crypto_secretstream_xchacha20poly1305_abytes(void);
+
+#define crypto_secretstream_xchacha20poly1305_HEADERBYTES \
+ crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
+SODIUM_EXPORT
+size_t crypto_secretstream_xchacha20poly1305_headerbytes(void);
+
+#define crypto_secretstream_xchacha20poly1305_KEYBYTES \
+ crypto_aead_xchacha20poly1305_ietf_KEYBYTES
+SODIUM_EXPORT
+size_t crypto_secretstream_xchacha20poly1305_keybytes(void);
+
+#define crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX \
+ SODIUM_MIN(SODIUM_SIZE_MAX, ((1ULL << 32) - 2ULL) * 64ULL)
+SODIUM_EXPORT
+size_t crypto_secretstream_xchacha20poly1305_messagebytes_max(void);
+
+#define crypto_secretstream_xchacha20poly1305_TAG_MESSAGE 0x00
+SODIUM_EXPORT
+unsigned char crypto_secretstream_xchacha20poly1305_tag_message(void);
+
+#define crypto_secretstream_xchacha20poly1305_TAG_PUSH 0x01
+SODIUM_EXPORT
+unsigned char crypto_secretstream_xchacha20poly1305_tag_push(void);
+
+#define crypto_secretstream_xchacha20poly1305_TAG_REKEY 0x02
+SODIUM_EXPORT
+unsigned char crypto_secretstream_xchacha20poly1305_tag_rekey(void);
+
+#define crypto_secretstream_xchacha20poly1305_TAG_FINAL \
+ (crypto_secretstream_xchacha20poly1305_TAG_PUSH | \
+ crypto_secretstream_xchacha20poly1305_TAG_REKEY)
+SODIUM_EXPORT
+unsigned char crypto_secretstream_xchacha20poly1305_tag_final(void);
+
+typedef struct crypto_secretstream_xchacha20poly1305_state {
+ unsigned char k[crypto_stream_chacha20_ietf_KEYBYTES];
+ unsigned char nonce[crypto_stream_chacha20_ietf_NONCEBYTES];
+ unsigned char _pad[8];
+} crypto_secretstream_xchacha20poly1305_state;
+
+SODIUM_EXPORT
+size_t crypto_secretstream_xchacha20poly1305_statebytes(void);
+
+SODIUM_EXPORT
+void crypto_secretstream_xchacha20poly1305_keygen
+ (unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]);
+
+SODIUM_EXPORT
+int crypto_secretstream_xchacha20poly1305_init_push
+ (crypto_secretstream_xchacha20poly1305_state *state,
+ unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES],
+ const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]);
+
+SODIUM_EXPORT
+int crypto_secretstream_xchacha20poly1305_push
+ (crypto_secretstream_xchacha20poly1305_state *state,
+ unsigned char *c, unsigned long long *clen_p,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *ad, unsigned long long adlen, unsigned char tag);
+
+SODIUM_EXPORT
+int crypto_secretstream_xchacha20poly1305_init_pull
+ (crypto_secretstream_xchacha20poly1305_state *state,
+ const unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES],
+ const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]);
+
+SODIUM_EXPORT
+int crypto_secretstream_xchacha20poly1305_pull
+ (crypto_secretstream_xchacha20poly1305_state *state,
+ unsigned char *m, unsigned long long *mlen_p, unsigned char *tag_p,
+ const unsigned char *c, unsigned long long clen,
+ const unsigned char *ad, unsigned long long adlen);
+
+SODIUM_EXPORT
+void crypto_secretstream_xchacha20poly1305_rekey
+ (crypto_secretstream_xchacha20poly1305_state *state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_shorthash.h b/libs/libsodium/src/include/sodium/crypto_shorthash.h
new file mode 100644
index 0000000000..a498808247
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_shorthash.h
@@ -0,0 +1,39 @@
+#ifndef crypto_shorthash_H
+#define crypto_shorthash_H
+
+#include <stddef.h>
+
+#include "crypto_shorthash_siphash24.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_shorthash_BYTES crypto_shorthash_siphash24_BYTES
+SODIUM_EXPORT
+size_t crypto_shorthash_bytes(void);
+
+#define crypto_shorthash_KEYBYTES crypto_shorthash_siphash24_KEYBYTES
+SODIUM_EXPORT
+size_t crypto_shorthash_keybytes(void);
+
+#define crypto_shorthash_PRIMITIVE "siphash24"
+SODIUM_EXPORT
+const char *crypto_shorthash_primitive(void);
+
+SODIUM_EXPORT
+int crypto_shorthash(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k);
+
+SODIUM_EXPORT
+void crypto_shorthash_keygen(unsigned char k[crypto_shorthash_KEYBYTES]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_shorthash_siphash24.h b/libs/libsodium/src/include/sodium/crypto_shorthash_siphash24.h
new file mode 100644
index 0000000000..745ed48fae
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_shorthash_siphash24.h
@@ -0,0 +1,48 @@
+#ifndef crypto_shorthash_siphash24_H
+#define crypto_shorthash_siphash24_H
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+/* -- 64-bit output -- */
+
+#define crypto_shorthash_siphash24_BYTES 8U
+SODIUM_EXPORT
+size_t crypto_shorthash_siphash24_bytes(void);
+
+#define crypto_shorthash_siphash24_KEYBYTES 16U
+SODIUM_EXPORT
+size_t crypto_shorthash_siphash24_keybytes(void);
+
+SODIUM_EXPORT
+int crypto_shorthash_siphash24(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k);
+
+#ifndef SODIUM_LIBRARY_MINIMAL
+/* -- 128-bit output -- */
+
+#define crypto_shorthash_siphashx24_BYTES 16U
+SODIUM_EXPORT
+size_t crypto_shorthash_siphashx24_bytes(void);
+
+#define crypto_shorthash_siphashx24_KEYBYTES 16U
+SODIUM_EXPORT
+size_t crypto_shorthash_siphashx24_keybytes(void);
+
+SODIUM_EXPORT
+int crypto_shorthash_siphashx24(unsigned char *out, const unsigned char *in,
+ unsigned long long inlen, const unsigned char *k);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_sign.h b/libs/libsodium/src/include/sodium/crypto_sign.h
new file mode 100644
index 0000000000..85aff0c9db
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_sign.h
@@ -0,0 +1,103 @@
+#ifndef crypto_sign_H
+#define crypto_sign_H
+
+/*
+ * THREAD SAFETY: crypto_sign_keypair() is thread-safe,
+ * provided that sodium_init() was called before.
+ *
+ * Other functions, including crypto_sign_seed_keypair() are always thread-safe.
+ */
+
+#include <stddef.h>
+
+#include "crypto_sign_ed25519.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+typedef crypto_sign_ed25519ph_state crypto_sign_state;
+
+SODIUM_EXPORT
+size_t crypto_sign_statebytes(void);
+
+#define crypto_sign_BYTES crypto_sign_ed25519_BYTES
+SODIUM_EXPORT
+size_t crypto_sign_bytes(void);
+
+#define crypto_sign_SEEDBYTES crypto_sign_ed25519_SEEDBYTES
+SODIUM_EXPORT
+size_t crypto_sign_seedbytes(void);
+
+#define crypto_sign_PUBLICKEYBYTES crypto_sign_ed25519_PUBLICKEYBYTES
+SODIUM_EXPORT
+size_t crypto_sign_publickeybytes(void);
+
+#define crypto_sign_SECRETKEYBYTES crypto_sign_ed25519_SECRETKEYBYTES
+SODIUM_EXPORT
+size_t crypto_sign_secretkeybytes(void);
+
+#define crypto_sign_MESSAGEBYTES_MAX crypto_sign_ed25519_MESSAGEBYTES_MAX
+SODIUM_EXPORT
+size_t crypto_sign_messagebytes_max(void);
+
+#define crypto_sign_PRIMITIVE "ed25519"
+SODIUM_EXPORT
+const char *crypto_sign_primitive(void);
+
+SODIUM_EXPORT
+int crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk,
+ const unsigned char *seed);
+
+SODIUM_EXPORT
+int crypto_sign_keypair(unsigned char *pk, unsigned char *sk);
+
+SODIUM_EXPORT
+int crypto_sign(unsigned char *sm, unsigned long long *smlen_p,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *sk);
+
+SODIUM_EXPORT
+int crypto_sign_open(unsigned char *m, unsigned long long *mlen_p,
+ const unsigned char *sm, unsigned long long smlen,
+ const unsigned char *pk)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_sign_detached(unsigned char *sig, unsigned long long *siglen_p,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *sk);
+
+SODIUM_EXPORT
+int crypto_sign_verify_detached(const unsigned char *sig,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *pk)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_sign_init(crypto_sign_state *state);
+
+SODIUM_EXPORT
+int crypto_sign_update(crypto_sign_state *state,
+ const unsigned char *m, unsigned long long mlen);
+
+SODIUM_EXPORT
+int crypto_sign_final_create(crypto_sign_state *state, unsigned char *sig,
+ unsigned long long *siglen_p,
+ const unsigned char *sk);
+
+SODIUM_EXPORT
+int crypto_sign_final_verify(crypto_sign_state *state, unsigned char *sig,
+ const unsigned char *pk)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_sign_ed25519.h b/libs/libsodium/src/include/sodium/crypto_sign_ed25519.h
new file mode 100644
index 0000000000..38d2b9dd63
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_sign_ed25519.h
@@ -0,0 +1,114 @@
+#ifndef crypto_sign_ed25519_H
+#define crypto_sign_ed25519_H
+
+#include <stddef.h>
+#include "crypto_hash_sha512.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+typedef struct crypto_sign_ed25519ph_state {
+ crypto_hash_sha512_state hs;
+} crypto_sign_ed25519ph_state;
+
+SODIUM_EXPORT
+size_t crypto_sign_ed25519ph_statebytes(void);
+
+#define crypto_sign_ed25519_BYTES 64U
+SODIUM_EXPORT
+size_t crypto_sign_ed25519_bytes(void);
+
+#define crypto_sign_ed25519_SEEDBYTES 32U
+SODIUM_EXPORT
+size_t crypto_sign_ed25519_seedbytes(void);
+
+#define crypto_sign_ed25519_PUBLICKEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_sign_ed25519_publickeybytes(void);
+
+#define crypto_sign_ed25519_SECRETKEYBYTES (32U + 32U)
+SODIUM_EXPORT
+size_t crypto_sign_ed25519_secretkeybytes(void);
+
+#define crypto_sign_ed25519_MESSAGEBYTES_MAX (SODIUM_SIZE_MAX - crypto_sign_ed25519_BYTES)
+SODIUM_EXPORT
+size_t crypto_sign_ed25519_messagebytes_max(void);
+
+SODIUM_EXPORT
+int crypto_sign_ed25519(unsigned char *sm, unsigned long long *smlen_p,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *sk);
+
+SODIUM_EXPORT
+int crypto_sign_ed25519_open(unsigned char *m, unsigned long long *mlen_p,
+ const unsigned char *sm, unsigned long long smlen,
+ const unsigned char *pk)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_sign_ed25519_detached(unsigned char *sig,
+ unsigned long long *siglen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *sk);
+
+SODIUM_EXPORT
+int crypto_sign_ed25519_verify_detached(const unsigned char *sig,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *pk)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_sign_ed25519_keypair(unsigned char *pk, unsigned char *sk);
+
+SODIUM_EXPORT
+int crypto_sign_ed25519_seed_keypair(unsigned char *pk, unsigned char *sk,
+ const unsigned char *seed);
+
+SODIUM_EXPORT
+int crypto_sign_ed25519_pk_to_curve25519(unsigned char *curve25519_pk,
+ const unsigned char *ed25519_pk)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int crypto_sign_ed25519_sk_to_curve25519(unsigned char *curve25519_sk,
+ const unsigned char *ed25519_sk);
+
+SODIUM_EXPORT
+int crypto_sign_ed25519_sk_to_seed(unsigned char *seed,
+ const unsigned char *sk);
+
+SODIUM_EXPORT
+int crypto_sign_ed25519_sk_to_pk(unsigned char *pk, const unsigned char *sk);
+
+SODIUM_EXPORT
+int crypto_sign_ed25519ph_init(crypto_sign_ed25519ph_state *state);
+
+SODIUM_EXPORT
+int crypto_sign_ed25519ph_update(crypto_sign_ed25519ph_state *state,
+ const unsigned char *m,
+ unsigned long long mlen);
+
+SODIUM_EXPORT
+int crypto_sign_ed25519ph_final_create(crypto_sign_ed25519ph_state *state,
+ unsigned char *sig,
+ unsigned long long *siglen_p,
+ const unsigned char *sk);
+
+SODIUM_EXPORT
+int crypto_sign_ed25519ph_final_verify(crypto_sign_ed25519ph_state *state,
+ unsigned char *sig,
+ const unsigned char *pk)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_sign_edwards25519sha512batch.h b/libs/libsodium/src/include/sodium/crypto_sign_edwards25519sha512batch.h
new file mode 100644
index 0000000000..4bb9192470
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_sign_edwards25519sha512batch.h
@@ -0,0 +1,55 @@
+#ifndef crypto_sign_edwards25519sha512batch_H
+#define crypto_sign_edwards25519sha512batch_H
+
+/*
+ * WARNING: This construction was a prototype, which should not be used
+ * any more in new projects.
+ *
+ * crypto_sign_edwards25519sha512batch is provided for applications
+ * initially built with NaCl, but as recommended by the author of this
+ * construction, new applications should use ed25519 instead.
+ *
+ * In Sodium, you should use the high-level crypto_sign_*() functions instead.
+ */
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_sign_edwards25519sha512batch_BYTES 64U
+#define crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES 32U
+#define crypto_sign_edwards25519sha512batch_SECRETKEYBYTES (32U + 32U)
+#define crypto_sign_edwards25519sha512batch_MESSAGEBYTES_MAX (SODIUM_SIZE_MAX - crypto_sign_edwards25519sha512batch_BYTES)
+
+SODIUM_EXPORT
+int crypto_sign_edwards25519sha512batch(unsigned char *sm,
+ unsigned long long *smlen_p,
+ const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *sk)
+ __attribute__ ((deprecated));
+
+SODIUM_EXPORT
+int crypto_sign_edwards25519sha512batch_open(unsigned char *m,
+ unsigned long long *mlen_p,
+ const unsigned char *sm,
+ unsigned long long smlen,
+ const unsigned char *pk)
+ __attribute__ ((deprecated));
+
+SODIUM_EXPORT
+int crypto_sign_edwards25519sha512batch_keypair(unsigned char *pk,
+ unsigned char *sk)
+ __attribute__ ((deprecated));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_stream.h b/libs/libsodium/src/include/sodium/crypto_stream.h
new file mode 100644
index 0000000000..d288f0b6dd
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_stream.h
@@ -0,0 +1,56 @@
+#ifndef crypto_stream_H
+#define crypto_stream_H
+
+/*
+ * WARNING: This is just a stream cipher. It is NOT authenticated encryption.
+ * While it provides some protection against eavesdropping, it does NOT
+ * provide any security against active attacks.
+ * Unless you know what you're doing, what you are looking for is probably
+ * the crypto_box functions.
+ */
+
+#include <stddef.h>
+
+#include "crypto_stream_xsalsa20.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_stream_KEYBYTES crypto_stream_xsalsa20_KEYBYTES
+SODIUM_EXPORT
+size_t crypto_stream_keybytes(void);
+
+#define crypto_stream_NONCEBYTES crypto_stream_xsalsa20_NONCEBYTES
+SODIUM_EXPORT
+size_t crypto_stream_noncebytes(void);
+
+#define crypto_stream_MESSAGEBYTES_MAX crypto_stream_xsalsa20_MESSAGEBYTES_MAX
+SODIUM_EXPORT
+size_t crypto_stream_messagebytes_max(void);
+
+#define crypto_stream_PRIMITIVE "xsalsa20"
+SODIUM_EXPORT
+const char *crypto_stream_primitive(void);
+
+SODIUM_EXPORT
+int crypto_stream(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_stream_xor(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+void crypto_stream_keygen(unsigned char k[crypto_stream_KEYBYTES]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_stream_chacha20.h b/libs/libsodium/src/include/sodium/crypto_stream_chacha20.h
new file mode 100644
index 0000000000..d3e2b234ef
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_stream_chacha20.h
@@ -0,0 +1,98 @@
+#ifndef crypto_stream_chacha20_H
+#define crypto_stream_chacha20_H
+
+/*
+ * WARNING: This is just a stream cipher. It is NOT authenticated encryption.
+ * While it provides some protection against eavesdropping, it does NOT
+ * provide any security against active attacks.
+ * Unless you know what you're doing, what you are looking for is probably
+ * the crypto_box functions.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_stream_chacha20_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_stream_chacha20_keybytes(void);
+
+#define crypto_stream_chacha20_NONCEBYTES 8U
+SODIUM_EXPORT
+size_t crypto_stream_chacha20_noncebytes(void);
+
+#define crypto_stream_chacha20_MESSAGEBYTES_MAX SODIUM_SIZE_MAX
+SODIUM_EXPORT
+size_t crypto_stream_chacha20_messagebytes_max(void);
+
+/* ChaCha20 with a 64-bit nonce and a 64-bit counter, as originally designed */
+
+SODIUM_EXPORT
+int crypto_stream_chacha20(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_stream_chacha20_xor(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_stream_chacha20_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n, uint64_t ic,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+void crypto_stream_chacha20_keygen(unsigned char k[crypto_stream_chacha20_KEYBYTES]);
+
+/* ChaCha20 with a 96-bit nonce and a 32-bit counter (IETF) */
+
+#define crypto_stream_chacha20_ietf_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_stream_chacha20_ietf_keybytes(void);
+
+#define crypto_stream_chacha20_ietf_NONCEBYTES 12U
+SODIUM_EXPORT
+size_t crypto_stream_chacha20_ietf_noncebytes(void);
+
+#define crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX \
+ SODIUM_MIN(SODIUM_SIZE_MAX, 64ULL * (1ULL << 32))
+SODIUM_EXPORT
+size_t crypto_stream_chacha20_ietf_messagebytes_max(void);
+
+SODIUM_EXPORT
+int crypto_stream_chacha20_ietf(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_stream_chacha20_ietf_xor(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_stream_chacha20_ietf_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n, uint32_t ic,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+void crypto_stream_chacha20_ietf_keygen(unsigned char k[crypto_stream_chacha20_ietf_KEYBYTES]);
+
+/* Aliases */
+
+#define crypto_stream_chacha20_IETF_KEYBYTES crypto_stream_chacha20_ietf_KEYBYTES
+#define crypto_stream_chacha20_IETF_NONCEBYTES crypto_stream_chacha20_ietf_NONCEBYTES
+#define crypto_stream_chacha20_IETF_MESSAGEBYTES_MAX crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_stream_salsa20.h b/libs/libsodium/src/include/sodium/crypto_stream_salsa20.h
new file mode 100644
index 0000000000..0c7688c736
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_stream_salsa20.h
@@ -0,0 +1,57 @@
+#ifndef crypto_stream_salsa20_H
+#define crypto_stream_salsa20_H
+
+/*
+ * WARNING: This is just a stream cipher. It is NOT authenticated encryption.
+ * While it provides some protection against eavesdropping, it does NOT
+ * provide any security against active attacks.
+ * Unless you know what you're doing, what you are looking for is probably
+ * the crypto_box functions.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_stream_salsa20_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_stream_salsa20_keybytes(void);
+
+#define crypto_stream_salsa20_NONCEBYTES 8U
+SODIUM_EXPORT
+size_t crypto_stream_salsa20_noncebytes(void);
+
+#define crypto_stream_salsa20_MESSAGEBYTES_MAX SODIUM_SIZE_MAX
+SODIUM_EXPORT
+size_t crypto_stream_salsa20_messagebytes_max(void);
+
+SODIUM_EXPORT
+int crypto_stream_salsa20(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_stream_salsa20_xor(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_stream_salsa20_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n, uint64_t ic,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+void crypto_stream_salsa20_keygen(unsigned char k[crypto_stream_salsa20_KEYBYTES]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_stream_salsa2012.h b/libs/libsodium/src/include/sodium/crypto_stream_salsa2012.h
new file mode 100644
index 0000000000..c93d1c81f8
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_stream_salsa2012.h
@@ -0,0 +1,50 @@
+#ifndef crypto_stream_salsa2012_H
+#define crypto_stream_salsa2012_H
+
+/*
+ * WARNING: This is just a stream cipher. It is NOT authenticated encryption.
+ * While it provides some protection against eavesdropping, it does NOT
+ * provide any security against active attacks.
+ * Unless you know what you're doing, what you are looking for is probably
+ * the crypto_box functions.
+ */
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_stream_salsa2012_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_stream_salsa2012_keybytes(void);
+
+#define crypto_stream_salsa2012_NONCEBYTES 8U
+SODIUM_EXPORT
+size_t crypto_stream_salsa2012_noncebytes(void);
+
+#define crypto_stream_salsa2012_MESSAGEBYTES_MAX SODIUM_SIZE_MAX
+SODIUM_EXPORT
+size_t crypto_stream_salsa2012_messagebytes_max(void);
+
+SODIUM_EXPORT
+int crypto_stream_salsa2012(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_stream_salsa2012_xor(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+void crypto_stream_salsa2012_keygen(unsigned char k[crypto_stream_salsa2012_KEYBYTES]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_stream_salsa208.h b/libs/libsodium/src/include/sodium/crypto_stream_salsa208.h
new file mode 100644
index 0000000000..653f6504bd
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_stream_salsa208.h
@@ -0,0 +1,56 @@
+#ifndef crypto_stream_salsa208_H
+#define crypto_stream_salsa208_H
+
+/*
+ * WARNING: This is just a stream cipher. It is NOT authenticated encryption.
+ * While it provides some protection against eavesdropping, it does NOT
+ * provide any security against active attacks.
+ * Unless you know what you're doing, what you are looking for is probably
+ * the crypto_box functions.
+ */
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_stream_salsa208_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_stream_salsa208_keybytes(void)
+ __attribute__ ((deprecated));
+
+#define crypto_stream_salsa208_NONCEBYTES 8U
+SODIUM_EXPORT
+size_t crypto_stream_salsa208_noncebytes(void)
+ __attribute__ ((deprecated));
+
+#define crypto_stream_salsa208_MESSAGEBYTES_MAX SODIUM_SIZE_MAX
+ SODIUM_EXPORT
+size_t crypto_stream_salsa208_messagebytes_max(void)
+ __attribute__ ((deprecated));
+
+SODIUM_EXPORT
+int crypto_stream_salsa208(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k)
+ __attribute__ ((deprecated));
+
+SODIUM_EXPORT
+int crypto_stream_salsa208_xor(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k)
+ __attribute__ ((deprecated));
+
+SODIUM_EXPORT
+void crypto_stream_salsa208_keygen(unsigned char k[crypto_stream_salsa208_KEYBYTES])
+ __attribute__ ((deprecated));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_stream_xchacha20.h b/libs/libsodium/src/include/sodium/crypto_stream_xchacha20.h
new file mode 100644
index 0000000000..cf0407ffa7
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_stream_xchacha20.h
@@ -0,0 +1,57 @@
+#ifndef crypto_stream_xchacha20_H
+#define crypto_stream_xchacha20_H
+
+/*
+ * WARNING: This is just a stream cipher. It is NOT authenticated encryption.
+ * While it provides some protection against eavesdropping, it does NOT
+ * provide any security against active attacks.
+ * Unless you know what you're doing, what you are looking for is probably
+ * the crypto_box functions.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_stream_xchacha20_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_stream_xchacha20_keybytes(void);
+
+#define crypto_stream_xchacha20_NONCEBYTES 24U
+SODIUM_EXPORT
+size_t crypto_stream_xchacha20_noncebytes(void);
+
+#define crypto_stream_xchacha20_MESSAGEBYTES_MAX SODIUM_SIZE_MAX
+SODIUM_EXPORT
+size_t crypto_stream_xchacha20_messagebytes_max(void);
+
+SODIUM_EXPORT
+int crypto_stream_xchacha20(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_stream_xchacha20_xor(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_stream_xchacha20_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n, uint64_t ic,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+void crypto_stream_xchacha20_keygen(unsigned char k[crypto_stream_xchacha20_KEYBYTES]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_stream_xsalsa20.h b/libs/libsodium/src/include/sodium/crypto_stream_xsalsa20.h
new file mode 100644
index 0000000000..cb4c44a8b8
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_stream_xsalsa20.h
@@ -0,0 +1,57 @@
+#ifndef crypto_stream_xsalsa20_H
+#define crypto_stream_xsalsa20_H
+
+/*
+ * WARNING: This is just a stream cipher. It is NOT authenticated encryption.
+ * While it provides some protection against eavesdropping, it does NOT
+ * provide any security against active attacks.
+ * Unless you know what you're doing, what you are looking for is probably
+ * the crypto_box functions.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_stream_xsalsa20_KEYBYTES 32U
+SODIUM_EXPORT
+size_t crypto_stream_xsalsa20_keybytes(void);
+
+#define crypto_stream_xsalsa20_NONCEBYTES 24U
+SODIUM_EXPORT
+size_t crypto_stream_xsalsa20_noncebytes(void);
+
+#define crypto_stream_xsalsa20_MESSAGEBYTES_MAX SODIUM_SIZE_MAX
+SODIUM_EXPORT
+size_t crypto_stream_xsalsa20_messagebytes_max(void);
+
+SODIUM_EXPORT
+int crypto_stream_xsalsa20(unsigned char *c, unsigned long long clen,
+ const unsigned char *n, const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_stream_xsalsa20_xor(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen, const unsigned char *n,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+int crypto_stream_xsalsa20_xor_ic(unsigned char *c, const unsigned char *m,
+ unsigned long long mlen,
+ const unsigned char *n, uint64_t ic,
+ const unsigned char *k);
+
+SODIUM_EXPORT
+void crypto_stream_xsalsa20_keygen(unsigned char k[crypto_stream_xsalsa20_KEYBYTES]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_verify_16.h b/libs/libsodium/src/include/sodium/crypto_verify_16.h
new file mode 100644
index 0000000000..5e9eeabee8
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_verify_16.h
@@ -0,0 +1,23 @@
+#ifndef crypto_verify_16_H
+#define crypto_verify_16_H
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define crypto_verify_16_BYTES 16U
+SODIUM_EXPORT
+size_t crypto_verify_16_bytes(void);
+
+SODIUM_EXPORT
+int crypto_verify_16(const unsigned char *x, const unsigned char *y)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_verify_32.h b/libs/libsodium/src/include/sodium/crypto_verify_32.h
new file mode 100644
index 0000000000..281b5a1bb7
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_verify_32.h
@@ -0,0 +1,23 @@
+#ifndef crypto_verify_32_H
+#define crypto_verify_32_H
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define crypto_verify_32_BYTES 32U
+SODIUM_EXPORT
+size_t crypto_verify_32_bytes(void);
+
+SODIUM_EXPORT
+int crypto_verify_32(const unsigned char *x, const unsigned char *y)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/crypto_verify_64.h b/libs/libsodium/src/include/sodium/crypto_verify_64.h
new file mode 100644
index 0000000000..0dc7c304a9
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/crypto_verify_64.h
@@ -0,0 +1,23 @@
+#ifndef crypto_verify_64_H
+#define crypto_verify_64_H
+
+#include <stddef.h>
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define crypto_verify_64_BYTES 64U
+SODIUM_EXPORT
+size_t crypto_verify_64_bytes(void);
+
+SODIUM_EXPORT
+int crypto_verify_64(const unsigned char *x, const unsigned char *y)
+ __attribute__ ((warn_unused_result));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/export.h b/libs/libsodium/src/include/sodium/export.h
new file mode 100644
index 0000000000..0f624ae3c5
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/export.h
@@ -0,0 +1,53 @@
+
+#ifndef sodium_export_H
+#define sodium_export_H
+
+#ifndef __GNUC__
+# ifdef __attribute__
+# undef __attribute__
+# endif
+# define __attribute__(a)
+#endif
+
+#ifdef SODIUM_STATIC
+# define SODIUM_EXPORT
+# define SODIUM_EXPORT_WEAK
+#else
+# if defined(_MSC_VER)
+# ifdef SODIUM_DLL_EXPORT
+# define SODIUM_EXPORT __declspec(dllexport)
+# else
+# define SODIUM_EXPORT __declspec(dllimport)
+# endif
+# else
+# if defined(__SUNPRO_C)
+# ifndef __GNU_C__
+# define SODIUM_EXPORT __attribute__ (visibility(__global))
+# else
+# define SODIUM_EXPORT __attribute__ __global
+# endif
+# elif defined(_MSG_VER)
+# define SODIUM_EXPORT extern __declspec(dllexport)
+# else
+# define SODIUM_EXPORT __attribute__ ((visibility ("default")))
+# endif
+# endif
+# if defined(__ELF__) && !defined(SODIUM_DISABLE_WEAK_FUNCTIONS)
+# define SODIUM_EXPORT_WEAK SODIUM_EXPORT __attribute__((weak))
+# else
+# define SODIUM_EXPORT_WEAK SODIUM_EXPORT
+# endif
+#endif
+
+#ifndef CRYPTO_ALIGN
+# if defined(__INTEL_COMPILER) || defined(_MSC_VER)
+# define CRYPTO_ALIGN(x) __declspec(align(x))
+# else
+# define CRYPTO_ALIGN(x) __attribute__ ((aligned(x)))
+# endif
+#endif
+
+#define SODIUM_MIN(A, B) ((A) < (B) ? (A) : (B))
+#define SODIUM_SIZE_MAX SODIUM_MIN(UINT64_MAX, SIZE_MAX)
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/private/common.h b/libs/libsodium/src/include/sodium/private/common.h
new file mode 100644
index 0000000000..954d02ccd7
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/private/common.h
@@ -0,0 +1,246 @@
+#ifndef common_H
+#define common_H 1
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define COMPILER_ASSERT(X) (void) sizeof(char[(X) ? 1 : -1])
+
+#ifdef HAVE_TI_MODE
+# if defined(__SIZEOF_INT128__)
+typedef unsigned __int128 uint128_t;
+# else
+typedef unsigned uint128_t __attribute__((mode(TI)));
+# endif
+#endif
+
+#define ROTL32(X, B) rotl32((X), (B))
+static inline uint32_t
+rotl32(const uint32_t x, const int b)
+{
+ return (x << b) | (x >> (32 - b));
+}
+
+#define ROTL64(X, B) rotl64((X), (B))
+static inline uint64_t
+rotl64(const uint64_t x, const int b)
+{
+ return (x << b) | (x >> (64 - b));
+}
+
+#define ROTR32(X, B) rotr32((X), (B))
+static inline uint32_t
+rotr32(const uint32_t x, const int b)
+{
+ return (x >> b) | (x << (32 - b));
+}
+
+#define ROTR64(X, B) rotr64((X), (B))
+static inline uint64_t
+rotr64(const uint64_t x, const int b)
+{
+ return (x >> b) | (x << (64 - b));
+}
+
+#define LOAD64_LE(SRC) load64_le(SRC)
+static inline uint64_t
+load64_le(const uint8_t src[8])
+{
+#ifdef NATIVE_LITTLE_ENDIAN
+ uint64_t w;
+ memcpy(&w, src, sizeof w);
+ return w;
+#else
+ uint64_t w = (uint64_t) src[0];
+ w |= (uint64_t) src[1] << 8;
+ w |= (uint64_t) src[2] << 16;
+ w |= (uint64_t) src[3] << 24;
+ w |= (uint64_t) src[4] << 32;
+ w |= (uint64_t) src[5] << 40;
+ w |= (uint64_t) src[6] << 48;
+ w |= (uint64_t) src[7] << 56;
+ return w;
+#endif
+}
+
+#define STORE64_LE(DST, W) store64_le((DST), (W))
+static inline void
+store64_le(uint8_t dst[8], uint64_t w)
+{
+#ifdef NATIVE_LITTLE_ENDIAN
+ memcpy(dst, &w, sizeof w);
+#else
+ dst[0] = (uint8_t) w; w >>= 8;
+ dst[1] = (uint8_t) w; w >>= 8;
+ dst[2] = (uint8_t) w; w >>= 8;
+ dst[3] = (uint8_t) w; w >>= 8;
+ dst[4] = (uint8_t) w; w >>= 8;
+ dst[5] = (uint8_t) w; w >>= 8;
+ dst[6] = (uint8_t) w; w >>= 8;
+ dst[7] = (uint8_t) w;
+#endif
+}
+
+#define LOAD32_LE(SRC) load32_le(SRC)
+static inline uint32_t
+load32_le(const uint8_t src[4])
+{
+#ifdef NATIVE_LITTLE_ENDIAN
+ uint32_t w;
+ memcpy(&w, src, sizeof w);
+ return w;
+#else
+ uint32_t w = (uint32_t) src[0];
+ w |= (uint32_t) src[1] << 8;
+ w |= (uint32_t) src[2] << 16;
+ w |= (uint32_t) src[3] << 24;
+ return w;
+#endif
+}
+
+#define STORE32_LE(DST, W) store32_le((DST), (W))
+static inline void
+store32_le(uint8_t dst[4], uint32_t w)
+{
+#ifdef NATIVE_LITTLE_ENDIAN
+ memcpy(dst, &w, sizeof w);
+#else
+ dst[0] = (uint8_t) w; w >>= 8;
+ dst[1] = (uint8_t) w; w >>= 8;
+ dst[2] = (uint8_t) w; w >>= 8;
+ dst[3] = (uint8_t) w;
+#endif
+}
+
+/* ----- */
+
+#define LOAD64_BE(SRC) load64_be(SRC)
+static inline uint64_t
+load64_be(const uint8_t src[8])
+{
+#ifdef NATIVE_BIG_ENDIAN
+ uint64_t w;
+ memcpy(&w, src, sizeof w);
+ return w;
+#else
+ uint64_t w = (uint64_t) src[7];
+ w |= (uint64_t) src[6] << 8;
+ w |= (uint64_t) src[5] << 16;
+ w |= (uint64_t) src[4] << 24;
+ w |= (uint64_t) src[3] << 32;
+ w |= (uint64_t) src[2] << 40;
+ w |= (uint64_t) src[1] << 48;
+ w |= (uint64_t) src[0] << 56;
+ return w;
+#endif
+}
+
+#define STORE64_BE(DST, W) store64_be((DST), (W))
+static inline void
+store64_be(uint8_t dst[8], uint64_t w)
+{
+#ifdef NATIVE_BIG_ENDIAN
+ memcpy(dst, &w, sizeof w);
+#else
+ dst[7] = (uint8_t) w; w >>= 8;
+ dst[6] = (uint8_t) w; w >>= 8;
+ dst[5] = (uint8_t) w; w >>= 8;
+ dst[4] = (uint8_t) w; w >>= 8;
+ dst[3] = (uint8_t) w; w >>= 8;
+ dst[2] = (uint8_t) w; w >>= 8;
+ dst[1] = (uint8_t) w; w >>= 8;
+ dst[0] = (uint8_t) w;
+#endif
+}
+
+#define LOAD32_BE(SRC) load32_be(SRC)
+static inline uint32_t
+load32_be(const uint8_t src[4])
+{
+#ifdef NATIVE_BIG_ENDIAN
+ uint32_t w;
+ memcpy(&w, src, sizeof w);
+ return w;
+#else
+ uint32_t w = (uint32_t) src[3];
+ w |= (uint32_t) src[2] << 8;
+ w |= (uint32_t) src[1] << 16;
+ w |= (uint32_t) src[0] << 24;
+ return w;
+#endif
+}
+
+#define STORE32_BE(DST, W) store32_be((DST), (W))
+static inline void
+store32_be(uint8_t dst[4], uint32_t w)
+{
+#ifdef NATIVE_BIG_ENDIAN
+ memcpy(dst, &w, sizeof w);
+#else
+ dst[3] = (uint8_t) w; w >>= 8;
+ dst[2] = (uint8_t) w; w >>= 8;
+ dst[1] = (uint8_t) w; w >>= 8;
+ dst[0] = (uint8_t) w;
+#endif
+}
+
+#define XOR_BUF(OUT, IN, N) xor_buf((OUT), (IN), (N))
+static inline void
+xor_buf(unsigned char *out, const unsigned char *in, size_t n)
+{
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ out[i] ^= in[i];
+ }
+}
+
+#ifndef __GNUC__
+# ifdef __attribute__
+# undef __attribute__
+# endif
+# define __attribute__(a)
+#endif
+
+#ifndef CRYPTO_ALIGN
+# if defined(__INTEL_COMPILER) || defined(_MSC_VER)
+# define CRYPTO_ALIGN(x) __declspec(align(x))
+# else
+# define CRYPTO_ALIGN(x) __attribute__ ((aligned(x)))
+# endif
+#endif
+
+#if defined(_MSC_VER) && \
+ (defined(_M_X64) || defined(_M_AMD64) || defined(_M_IX86))
+
+# include <intrin.h>
+
+# define HAVE_INTRIN_H 1
+# define HAVE_MMINTRIN_H 1
+# define HAVE_EMMINTRIN_H 1
+# define HAVE_PMMINTRIN_H 1
+# define HAVE_TMMINTRIN_H 1
+# define HAVE_SMMINTRIN_H 1
+# define HAVE_AVXINTRIN_H 1
+# if _MSC_VER >= 1600
+# define HAVE_WMMINTRIN_H 1
+# endif
+# if _MSC_VER >= 1700 && defined(_M_X64)
+# define HAVE_AVX2INTRIN_H 1
+# endif
+#elif defined(HAVE_INTRIN_H)
+# include <intrin.h>
+#endif
+
+#ifdef HAVE_LIBCTGRIND
+extern void ct_poison (const void *, size_t);
+extern void ct_unpoison(const void *, size_t);
+# define POISON(X, L) ct_poison((X), (L))
+# define UNPOISON(X, L) ct_unpoison((X), (L))
+#else
+# define POISON(X, L) (void) 0
+# define UNPOISON(X, L) (void) 0
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/private/ed25519_ref10.h b/libs/libsodium/src/include/sodium/private/ed25519_ref10.h
new file mode 100644
index 0000000000..42fcd98139
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/private/ed25519_ref10.h
@@ -0,0 +1,125 @@
+#ifndef ed25519_ref10_H
+#define ed25519_ref10_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+ fe means field element.
+ Here the field is \Z/(2^255-19).
+ */
+
+#ifdef HAVE_TI_MODE
+typedef uint64_t fe25519[5];
+#else
+typedef int32_t fe25519[10];
+#endif
+
+void fe25519_invert(fe25519 out, const fe25519 z);
+void fe25519_frombytes(fe25519 h, const unsigned char *s);
+void fe25519_tobytes(unsigned char *s, const fe25519 h);
+
+#ifdef HAVE_TI_MODE
+# include "ed25519_ref10_fe_51.h"
+#else
+# include "ed25519_ref10_fe_25_5.h"
+#endif
+
+
+/*
+ ge means group element.
+
+ Here the group is the set of pairs (x,y) of field elements
+ satisfying -x^2 + y^2 = 1 + d x^2y^2
+ where d = -121665/121666.
+
+ Representations:
+ ge25519_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
+ ge25519_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
+ ge25519_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
+ ge25519_precomp (Duif): (y+x,y-x,2dxy)
+ */
+
+typedef struct {
+ fe25519 X;
+ fe25519 Y;
+ fe25519 Z;
+} ge25519_p2;
+
+typedef struct {
+ fe25519 X;
+ fe25519 Y;
+ fe25519 Z;
+ fe25519 T;
+} ge25519_p3;
+
+typedef struct {
+ fe25519 X;
+ fe25519 Y;
+ fe25519 Z;
+ fe25519 T;
+} ge25519_p1p1;
+
+typedef struct {
+ fe25519 yplusx;
+ fe25519 yminusx;
+ fe25519 xy2d;
+} ge25519_precomp;
+
+typedef struct {
+ fe25519 YplusX;
+ fe25519 YminusX;
+ fe25519 Z;
+ fe25519 T2d;
+} ge25519_cached;
+
+void ge25519_tobytes(unsigned char *s, const ge25519_p2 *h);
+
+void ge25519_p3_tobytes(unsigned char *s, const ge25519_p3 *h);
+
+int ge25519_frombytes(ge25519_p3 *h, const unsigned char *s);
+
+int ge25519_frombytes_negate_vartime(ge25519_p3 *h, const unsigned char *s);
+
+void ge25519_p3_to_cached(ge25519_cached *r, const ge25519_p3 *p);
+
+void ge25519_p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p);
+
+void ge25519_p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p);
+
+void ge25519_add(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_cached *q);
+
+void ge25519_sub(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_cached *q);
+
+void ge25519_scalarmult_base(ge25519_p3 *h, const unsigned char *a);
+
+void ge25519_double_scalarmult_vartime(ge25519_p2 *r, const unsigned char *a,
+ const ge25519_p3 *A,
+ const unsigned char *b);
+
+void ge25519_scalarmult(ge25519_p3 *h, const unsigned char *a,
+ const ge25519_p3 *p);
+
+int ge25519_is_canonical(const unsigned char *s);
+
+int ge25519_is_on_curve(const ge25519_p3 *p);
+
+int ge25519_is_on_main_subgroup(const ge25519_p3 *p);
+
+int ge25519_has_small_order(const unsigned char s[32]);
+
+void ge25519_from_uniform(unsigned char s[32], const unsigned char r[32]);
+
+/*
+ The set of scalars is \Z/l
+ where l = 2^252 + 27742317777372353535851937790883648493.
+ */
+
+void sc25519_reduce(unsigned char *s);
+
+void sc25519_muladd(unsigned char *s, const unsigned char *a,
+ const unsigned char *b, const unsigned char *c);
+
+int sc25519_is_canonical(const unsigned char *s);
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/private/ed25519_ref10_fe_25_5.h b/libs/libsodium/src/include/sodium/private/ed25519_ref10_fe_25_5.h
new file mode 100644
index 0000000000..5a0b6148b7
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/private/ed25519_ref10_fe_25_5.h
@@ -0,0 +1,1050 @@
+#include <string.h>
+
+#include "private/common.h"
+#include "utils.h"
+
+/*
+ h = 0
+ */
+
+static inline void
+fe25519_0(fe25519 h)
+{
+ memset(&h[0], 0, 10 * sizeof h[0]);
+}
+
+/*
+ h = 1
+ */
+
+static inline void
+fe25519_1(fe25519 h)
+{
+ h[0] = 1;
+ h[1] = 0;
+ memset(&h[2], 0, 8 * sizeof h[0]);
+}
+
+/*
+ h = f + g
+ Can overlap h with f or g.
+ *
+ Preconditions:
+ |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+ |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+ *
+ Postconditions:
+ |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+ */
+
+static inline void
+fe25519_add(fe25519 h, const fe25519 f, const fe25519 g)
+{
+ int32_t h0 = f[0] + g[0];
+ int32_t h1 = f[1] + g[1];
+ int32_t h2 = f[2] + g[2];
+ int32_t h3 = f[3] + g[3];
+ int32_t h4 = f[4] + g[4];
+ int32_t h5 = f[5] + g[5];
+ int32_t h6 = f[6] + g[6];
+ int32_t h7 = f[7] + g[7];
+ int32_t h8 = f[8] + g[8];
+ int32_t h9 = f[9] + g[9];
+
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+ h[5] = h5;
+ h[6] = h6;
+ h[7] = h7;
+ h[8] = h8;
+ h[9] = h9;
+}
+
+/*
+ h = f - g
+ Can overlap h with f or g.
+ *
+ Preconditions:
+ |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+ |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+ *
+ Postconditions:
+ |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+ */
+
+static void
+fe25519_sub(fe25519 h, const fe25519 f, const fe25519 g)
+{
+ int32_t h0 = f[0] - g[0];
+ int32_t h1 = f[1] - g[1];
+ int32_t h2 = f[2] - g[2];
+ int32_t h3 = f[3] - g[3];
+ int32_t h4 = f[4] - g[4];
+ int32_t h5 = f[5] - g[5];
+ int32_t h6 = f[6] - g[6];
+ int32_t h7 = f[7] - g[7];
+ int32_t h8 = f[8] - g[8];
+ int32_t h9 = f[9] - g[9];
+
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+ h[5] = h5;
+ h[6] = h6;
+ h[7] = h7;
+ h[8] = h8;
+ h[9] = h9;
+}
+
+/*
+ h = -f
+ *
+ Preconditions:
+ |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+ *
+ Postconditions:
+ |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+ */
+
+static inline void
+fe25519_neg(fe25519 h, const fe25519 f)
+{
+ int32_t h0 = -f[0];
+ int32_t h1 = -f[1];
+ int32_t h2 = -f[2];
+ int32_t h3 = -f[3];
+ int32_t h4 = -f[4];
+ int32_t h5 = -f[5];
+ int32_t h6 = -f[6];
+ int32_t h7 = -f[7];
+ int32_t h8 = -f[8];
+ int32_t h9 = -f[9];
+
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+ h[5] = h5;
+ h[6] = h6;
+ h[7] = h7;
+ h[8] = h8;
+ h[9] = h9;
+}
+
+/*
+ Replace (f,g) with (g,g) if b == 1;
+ replace (f,g) with (f,g) if b == 0.
+ *
+ Preconditions: b in {0,1}.
+ */
+
+static void
+fe25519_cmov(fe25519 f, const fe25519 g, unsigned int b)
+{
+ const uint32_t mask = (uint32_t) (-(int32_t) b);
+
+ int32_t f0 = f[0];
+ int32_t f1 = f[1];
+ int32_t f2 = f[2];
+ int32_t f3 = f[3];
+ int32_t f4 = f[4];
+ int32_t f5 = f[5];
+ int32_t f6 = f[6];
+ int32_t f7 = f[7];
+ int32_t f8 = f[8];
+ int32_t f9 = f[9];
+
+ int32_t x0 = f0 ^ g[0];
+ int32_t x1 = f1 ^ g[1];
+ int32_t x2 = f2 ^ g[2];
+ int32_t x3 = f3 ^ g[3];
+ int32_t x4 = f4 ^ g[4];
+ int32_t x5 = f5 ^ g[5];
+ int32_t x6 = f6 ^ g[6];
+ int32_t x7 = f7 ^ g[7];
+ int32_t x8 = f8 ^ g[8];
+ int32_t x9 = f9 ^ g[9];
+
+ x0 &= mask;
+ x1 &= mask;
+ x2 &= mask;
+ x3 &= mask;
+ x4 &= mask;
+ x5 &= mask;
+ x6 &= mask;
+ x7 &= mask;
+ x8 &= mask;
+ x9 &= mask;
+
+ f[0] = f0 ^ x0;
+ f[1] = f1 ^ x1;
+ f[2] = f2 ^ x2;
+ f[3] = f3 ^ x3;
+ f[4] = f4 ^ x4;
+ f[5] = f5 ^ x5;
+ f[6] = f6 ^ x6;
+ f[7] = f7 ^ x7;
+ f[8] = f8 ^ x8;
+ f[9] = f9 ^ x9;
+}
+
+static void
+fe25519_cswap(fe25519 f, fe25519 g, unsigned int b)
+{
+ const uint32_t mask = (uint32_t) (-(int64_t) b);
+
+ int32_t f0 = f[0];
+ int32_t f1 = f[1];
+ int32_t f2 = f[2];
+ int32_t f3 = f[3];
+ int32_t f4 = f[4];
+ int32_t f5 = f[5];
+ int32_t f6 = f[6];
+ int32_t f7 = f[7];
+ int32_t f8 = f[8];
+ int32_t f9 = f[9];
+
+ int32_t g0 = g[0];
+ int32_t g1 = g[1];
+ int32_t g2 = g[2];
+ int32_t g3 = g[3];
+ int32_t g4 = g[4];
+ int32_t g5 = g[5];
+ int32_t g6 = g[6];
+ int32_t g7 = g[7];
+ int32_t g8 = g[8];
+ int32_t g9 = g[9];
+
+ int32_t x0 = f0 ^ g0;
+ int32_t x1 = f1 ^ g1;
+ int32_t x2 = f2 ^ g2;
+ int32_t x3 = f3 ^ g3;
+ int32_t x4 = f4 ^ g4;
+ int32_t x5 = f5 ^ g5;
+ int32_t x6 = f6 ^ g6;
+ int32_t x7 = f7 ^ g7;
+ int32_t x8 = f8 ^ g8;
+ int32_t x9 = f9 ^ g9;
+
+ x0 &= mask;
+ x1 &= mask;
+ x2 &= mask;
+ x3 &= mask;
+ x4 &= mask;
+ x5 &= mask;
+ x6 &= mask;
+ x7 &= mask;
+ x8 &= mask;
+ x9 &= mask;
+
+ f[0] = f0 ^ x0;
+ f[1] = f1 ^ x1;
+ f[2] = f2 ^ x2;
+ f[3] = f3 ^ x3;
+ f[4] = f4 ^ x4;
+ f[5] = f5 ^ x5;
+ f[6] = f6 ^ x6;
+ f[7] = f7 ^ x7;
+ f[8] = f8 ^ x8;
+ f[9] = f9 ^ x9;
+
+ g[0] = g0 ^ x0;
+ g[1] = g1 ^ x1;
+ g[2] = g2 ^ x2;
+ g[3] = g3 ^ x3;
+ g[4] = g4 ^ x4;
+ g[5] = g5 ^ x5;
+ g[6] = g6 ^ x6;
+ g[7] = g7 ^ x7;
+ g[8] = g8 ^ x8;
+ g[9] = g9 ^ x9;
+}
+
+/*
+ h = f
+ */
+
+static inline void
+fe25519_copy(fe25519 h, const fe25519 f)
+{
+ int32_t f0 = f[0];
+ int32_t f1 = f[1];
+ int32_t f2 = f[2];
+ int32_t f3 = f[3];
+ int32_t f4 = f[4];
+ int32_t f5 = f[5];
+ int32_t f6 = f[6];
+ int32_t f7 = f[7];
+ int32_t f8 = f[8];
+ int32_t f9 = f[9];
+
+ h[0] = f0;
+ h[1] = f1;
+ h[2] = f2;
+ h[3] = f3;
+ h[4] = f4;
+ h[5] = f5;
+ h[6] = f6;
+ h[7] = f7;
+ h[8] = f8;
+ h[9] = f9;
+}
+
+/*
+ return 1 if f is in {1,3,5,...,q-2}
+ return 0 if f is in {0,2,4,...,q-1}
+
+ Preconditions:
+ |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+ */
+
+static inline int
+fe25519_isnegative(const fe25519 f)
+{
+ unsigned char s[32];
+
+ fe25519_tobytes(s, f);
+
+ return s[0] & 1;
+}
+
+/*
+ return 1 if f == 0
+ return 0 if f != 0
+
+ Preconditions:
+ |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+ */
+
+static inline int
+fe25519_iszero(const fe25519 f)
+{
+ unsigned char s[32];
+
+ fe25519_tobytes(s, f);
+
+ return sodium_is_zero(s, 32);
+}
+
+/*
+ h = f * g
+ Can overlap h with f or g.
+ *
+ Preconditions:
+ |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+ |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+ *
+ Postconditions:
+ |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
+ */
+
+/*
+ Notes on implementation strategy:
+ *
+ Using schoolbook multiplication.
+ Karatsuba would save a little in some cost models.
+ *
+ Most multiplications by 2 and 19 are 32-bit precomputations;
+ cheaper than 64-bit postcomputations.
+ *
+ There is one remaining multiplication by 19 in the carry chain;
+ one *19 precomputation can be merged into this,
+ but the resulting data flow is considerably less clean.
+ *
+ There are 12 carries below.
+ 10 of them are 2-way parallelizable and vectorizable.
+ Can get away with 11 carries, but then data flow is much deeper.
+ *
+ With tighter constraints on inputs can squeeze carries into int32.
+ */
+
+static void
+fe25519_mul(fe25519 h, const fe25519 f, const fe25519 g)
+{
+ int32_t f0 = f[0];
+ int32_t f1 = f[1];
+ int32_t f2 = f[2];
+ int32_t f3 = f[3];
+ int32_t f4 = f[4];
+ int32_t f5 = f[5];
+ int32_t f6 = f[6];
+ int32_t f7 = f[7];
+ int32_t f8 = f[8];
+ int32_t f9 = f[9];
+
+ int32_t g0 = g[0];
+ int32_t g1 = g[1];
+ int32_t g2 = g[2];
+ int32_t g3 = g[3];
+ int32_t g4 = g[4];
+ int32_t g5 = g[5];
+ int32_t g6 = g[6];
+ int32_t g7 = g[7];
+ int32_t g8 = g[8];
+ int32_t g9 = g[9];
+
+ int32_t g1_19 = 19 * g1; /* 1.959375*2^29 */
+ int32_t g2_19 = 19 * g2; /* 1.959375*2^30; still ok */
+ int32_t g3_19 = 19 * g3;
+ int32_t g4_19 = 19 * g4;
+ int32_t g5_19 = 19 * g5;
+ int32_t g6_19 = 19 * g6;
+ int32_t g7_19 = 19 * g7;
+ int32_t g8_19 = 19 * g8;
+ int32_t g9_19 = 19 * g9;
+ int32_t f1_2 = 2 * f1;
+ int32_t f3_2 = 2 * f3;
+ int32_t f5_2 = 2 * f5;
+ int32_t f7_2 = 2 * f7;
+ int32_t f9_2 = 2 * f9;
+
+ int64_t f0g0 = f0 * (int64_t) g0;
+ int64_t f0g1 = f0 * (int64_t) g1;
+ int64_t f0g2 = f0 * (int64_t) g2;
+ int64_t f0g3 = f0 * (int64_t) g3;
+ int64_t f0g4 = f0 * (int64_t) g4;
+ int64_t f0g5 = f0 * (int64_t) g5;
+ int64_t f0g6 = f0 * (int64_t) g6;
+ int64_t f0g7 = f0 * (int64_t) g7;
+ int64_t f0g8 = f0 * (int64_t) g8;
+ int64_t f0g9 = f0 * (int64_t) g9;
+ int64_t f1g0 = f1 * (int64_t) g0;
+ int64_t f1g1_2 = f1_2 * (int64_t) g1;
+ int64_t f1g2 = f1 * (int64_t) g2;
+ int64_t f1g3_2 = f1_2 * (int64_t) g3;
+ int64_t f1g4 = f1 * (int64_t) g4;
+ int64_t f1g5_2 = f1_2 * (int64_t) g5;
+ int64_t f1g6 = f1 * (int64_t) g6;
+ int64_t f1g7_2 = f1_2 * (int64_t) g7;
+ int64_t f1g8 = f1 * (int64_t) g8;
+ int64_t f1g9_38 = f1_2 * (int64_t) g9_19;
+ int64_t f2g0 = f2 * (int64_t) g0;
+ int64_t f2g1 = f2 * (int64_t) g1;
+ int64_t f2g2 = f2 * (int64_t) g2;
+ int64_t f2g3 = f2 * (int64_t) g3;
+ int64_t f2g4 = f2 * (int64_t) g4;
+ int64_t f2g5 = f2 * (int64_t) g5;
+ int64_t f2g6 = f2 * (int64_t) g6;
+ int64_t f2g7 = f2 * (int64_t) g7;
+ int64_t f2g8_19 = f2 * (int64_t) g8_19;
+ int64_t f2g9_19 = f2 * (int64_t) g9_19;
+ int64_t f3g0 = f3 * (int64_t) g0;
+ int64_t f3g1_2 = f3_2 * (int64_t) g1;
+ int64_t f3g2 = f3 * (int64_t) g2;
+ int64_t f3g3_2 = f3_2 * (int64_t) g3;
+ int64_t f3g4 = f3 * (int64_t) g4;
+ int64_t f3g5_2 = f3_2 * (int64_t) g5;
+ int64_t f3g6 = f3 * (int64_t) g6;
+ int64_t f3g7_38 = f3_2 * (int64_t) g7_19;
+ int64_t f3g8_19 = f3 * (int64_t) g8_19;
+ int64_t f3g9_38 = f3_2 * (int64_t) g9_19;
+ int64_t f4g0 = f4 * (int64_t) g0;
+ int64_t f4g1 = f4 * (int64_t) g1;
+ int64_t f4g2 = f4 * (int64_t) g2;
+ int64_t f4g3 = f4 * (int64_t) g3;
+ int64_t f4g4 = f4 * (int64_t) g4;
+ int64_t f4g5 = f4 * (int64_t) g5;
+ int64_t f4g6_19 = f4 * (int64_t) g6_19;
+ int64_t f4g7_19 = f4 * (int64_t) g7_19;
+ int64_t f4g8_19 = f4 * (int64_t) g8_19;
+ int64_t f4g9_19 = f4 * (int64_t) g9_19;
+ int64_t f5g0 = f5 * (int64_t) g0;
+ int64_t f5g1_2 = f5_2 * (int64_t) g1;
+ int64_t f5g2 = f5 * (int64_t) g2;
+ int64_t f5g3_2 = f5_2 * (int64_t) g3;
+ int64_t f5g4 = f5 * (int64_t) g4;
+ int64_t f5g5_38 = f5_2 * (int64_t) g5_19;
+ int64_t f5g6_19 = f5 * (int64_t) g6_19;
+ int64_t f5g7_38 = f5_2 * (int64_t) g7_19;
+ int64_t f5g8_19 = f5 * (int64_t) g8_19;
+ int64_t f5g9_38 = f5_2 * (int64_t) g9_19;
+ int64_t f6g0 = f6 * (int64_t) g0;
+ int64_t f6g1 = f6 * (int64_t) g1;
+ int64_t f6g2 = f6 * (int64_t) g2;
+ int64_t f6g3 = f6 * (int64_t) g3;
+ int64_t f6g4_19 = f6 * (int64_t) g4_19;
+ int64_t f6g5_19 = f6 * (int64_t) g5_19;
+ int64_t f6g6_19 = f6 * (int64_t) g6_19;
+ int64_t f6g7_19 = f6 * (int64_t) g7_19;
+ int64_t f6g8_19 = f6 * (int64_t) g8_19;
+ int64_t f6g9_19 = f6 * (int64_t) g9_19;
+ int64_t f7g0 = f7 * (int64_t) g0;
+ int64_t f7g1_2 = f7_2 * (int64_t) g1;
+ int64_t f7g2 = f7 * (int64_t) g2;
+ int64_t f7g3_38 = f7_2 * (int64_t) g3_19;
+ int64_t f7g4_19 = f7 * (int64_t) g4_19;
+ int64_t f7g5_38 = f7_2 * (int64_t) g5_19;
+ int64_t f7g6_19 = f7 * (int64_t) g6_19;
+ int64_t f7g7_38 = f7_2 * (int64_t) g7_19;
+ int64_t f7g8_19 = f7 * (int64_t) g8_19;
+ int64_t f7g9_38 = f7_2 * (int64_t) g9_19;
+ int64_t f8g0 = f8 * (int64_t) g0;
+ int64_t f8g1 = f8 * (int64_t) g1;
+ int64_t f8g2_19 = f8 * (int64_t) g2_19;
+ int64_t f8g3_19 = f8 * (int64_t) g3_19;
+ int64_t f8g4_19 = f8 * (int64_t) g4_19;
+ int64_t f8g5_19 = f8 * (int64_t) g5_19;
+ int64_t f8g6_19 = f8 * (int64_t) g6_19;
+ int64_t f8g7_19 = f8 * (int64_t) g7_19;
+ int64_t f8g8_19 = f8 * (int64_t) g8_19;
+ int64_t f8g9_19 = f8 * (int64_t) g9_19;
+ int64_t f9g0 = f9 * (int64_t) g0;
+ int64_t f9g1_38 = f9_2 * (int64_t) g1_19;
+ int64_t f9g2_19 = f9 * (int64_t) g2_19;
+ int64_t f9g3_38 = f9_2 * (int64_t) g3_19;
+ int64_t f9g4_19 = f9 * (int64_t) g4_19;
+ int64_t f9g5_38 = f9_2 * (int64_t) g5_19;
+ int64_t f9g6_19 = f9 * (int64_t) g6_19;
+ int64_t f9g7_38 = f9_2 * (int64_t) g7_19;
+ int64_t f9g8_19 = f9 * (int64_t) g8_19;
+ int64_t f9g9_38 = f9_2 * (int64_t) g9_19;
+
+ int64_t h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 +
+ f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38;
+ int64_t h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 +
+ f7g4_19 + f8g3_19 + f9g2_19;
+ int64_t h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 +
+ f7g5_38 + f8g4_19 + f9g3_38;
+ int64_t h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 +
+ f7g6_19 + f8g5_19 + f9g4_19;
+ int64_t h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 +
+ f7g7_38 + f8g6_19 + f9g5_38;
+ int64_t h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 +
+ f8g7_19 + f9g6_19;
+ int64_t h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 +
+ f7g9_38 + f8g8_19 + f9g7_38;
+ int64_t h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 +
+ f8g9_19 + f9g8_19;
+ int64_t h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 +
+ f8g0 + f9g9_38;
+ int64_t h9 =
+ f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0;
+
+ int64_t carry0;
+ int64_t carry1;
+ int64_t carry2;
+ int64_t carry3;
+ int64_t carry4;
+ int64_t carry5;
+ int64_t carry6;
+ int64_t carry7;
+ int64_t carry8;
+ int64_t carry9;
+
+ /*
+ |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38))
+ i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8
+ |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19))
+ i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9
+ */
+
+ carry0 = (h0 + (int64_t)(1L << 25)) >> 26;
+ h1 += carry0;
+ h0 -= carry0 * ((uint64_t) 1L << 26);
+ carry4 = (h4 + (int64_t)(1L << 25)) >> 26;
+ h5 += carry4;
+ h4 -= carry4 * ((uint64_t) 1L << 26);
+ /* |h0| <= 2^25 */
+ /* |h4| <= 2^25 */
+ /* |h1| <= 1.71*2^59 */
+ /* |h5| <= 1.71*2^59 */
+
+ carry1 = (h1 + (int64_t)(1L << 24)) >> 25;
+ h2 += carry1;
+ h1 -= carry1 * ((uint64_t) 1L << 25);
+ carry5 = (h5 + (int64_t)(1L << 24)) >> 25;
+ h6 += carry5;
+ h5 -= carry5 * ((uint64_t) 1L << 25);
+ /* |h1| <= 2^24; from now on fits into int32 */
+ /* |h5| <= 2^24; from now on fits into int32 */
+ /* |h2| <= 1.41*2^60 */
+ /* |h6| <= 1.41*2^60 */
+
+ carry2 = (h2 + (int64_t)(1L << 25)) >> 26;
+ h3 += carry2;
+ h2 -= carry2 * ((uint64_t) 1L << 26);
+ carry6 = (h6 + (int64_t)(1L << 25)) >> 26;
+ h7 += carry6;
+ h6 -= carry6 * ((uint64_t) 1L << 26);
+ /* |h2| <= 2^25; from now on fits into int32 unchanged */
+ /* |h6| <= 2^25; from now on fits into int32 unchanged */
+ /* |h3| <= 1.71*2^59 */
+ /* |h7| <= 1.71*2^59 */
+
+ carry3 = (h3 + (int64_t)(1L << 24)) >> 25;
+ h4 += carry3;
+ h3 -= carry3 * ((uint64_t) 1L << 25);
+ carry7 = (h7 + (int64_t)(1L << 24)) >> 25;
+ h8 += carry7;
+ h7 -= carry7 * ((uint64_t) 1L << 25);
+ /* |h3| <= 2^24; from now on fits into int32 unchanged */
+ /* |h7| <= 2^24; from now on fits into int32 unchanged */
+ /* |h4| <= 1.72*2^34 */
+ /* |h8| <= 1.41*2^60 */
+
+ carry4 = (h4 + (int64_t)(1L << 25)) >> 26;
+ h5 += carry4;
+ h4 -= carry4 * ((uint64_t) 1L << 26);
+ carry8 = (h8 + (int64_t)(1L << 25)) >> 26;
+ h9 += carry8;
+ h8 -= carry8 * ((uint64_t) 1L << 26);
+ /* |h4| <= 2^25; from now on fits into int32 unchanged */
+ /* |h8| <= 2^25; from now on fits into int32 unchanged */
+ /* |h5| <= 1.01*2^24 */
+ /* |h9| <= 1.71*2^59 */
+
+ carry9 = (h9 + (int64_t)(1L << 24)) >> 25;
+ h0 += carry9 * 19;
+ h9 -= carry9 * ((uint64_t) 1L << 25);
+ /* |h9| <= 2^24; from now on fits into int32 unchanged */
+ /* |h0| <= 1.1*2^39 */
+
+ carry0 = (h0 + (int64_t)(1L << 25)) >> 26;
+ h1 += carry0;
+ h0 -= carry0 * ((uint64_t) 1L << 26);
+ /* |h0| <= 2^25; from now on fits into int32 unchanged */
+ /* |h1| <= 1.01*2^24 */
+
+ h[0] = (int32_t) h0;
+ h[1] = (int32_t) h1;
+ h[2] = (int32_t) h2;
+ h[3] = (int32_t) h3;
+ h[4] = (int32_t) h4;
+ h[5] = (int32_t) h5;
+ h[6] = (int32_t) h6;
+ h[7] = (int32_t) h7;
+ h[8] = (int32_t) h8;
+ h[9] = (int32_t) h9;
+}
+
+/*
+ h = f * f
+ Can overlap h with f.
+ *
+ Preconditions:
+ |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+ *
+ Postconditions:
+ |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
+ */
+
+static void
+fe25519_sq(fe25519 h, const fe25519 f)
+{
+ int32_t f0 = f[0];
+ int32_t f1 = f[1];
+ int32_t f2 = f[2];
+ int32_t f3 = f[3];
+ int32_t f4 = f[4];
+ int32_t f5 = f[5];
+ int32_t f6 = f[6];
+ int32_t f7 = f[7];
+ int32_t f8 = f[8];
+ int32_t f9 = f[9];
+
+ int32_t f0_2 = 2 * f0;
+ int32_t f1_2 = 2 * f1;
+ int32_t f2_2 = 2 * f2;
+ int32_t f3_2 = 2 * f3;
+ int32_t f4_2 = 2 * f4;
+ int32_t f5_2 = 2 * f5;
+ int32_t f6_2 = 2 * f6;
+ int32_t f7_2 = 2 * f7;
+ int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */
+ int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */
+ int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */
+ int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */
+ int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */
+
+ int64_t f0f0 = f0 * (int64_t) f0;
+ int64_t f0f1_2 = f0_2 * (int64_t) f1;
+ int64_t f0f2_2 = f0_2 * (int64_t) f2;
+ int64_t f0f3_2 = f0_2 * (int64_t) f3;
+ int64_t f0f4_2 = f0_2 * (int64_t) f4;
+ int64_t f0f5_2 = f0_2 * (int64_t) f5;
+ int64_t f0f6_2 = f0_2 * (int64_t) f6;
+ int64_t f0f7_2 = f0_2 * (int64_t) f7;
+ int64_t f0f8_2 = f0_2 * (int64_t) f8;
+ int64_t f0f9_2 = f0_2 * (int64_t) f9;
+ int64_t f1f1_2 = f1_2 * (int64_t) f1;
+ int64_t f1f2_2 = f1_2 * (int64_t) f2;
+ int64_t f1f3_4 = f1_2 * (int64_t) f3_2;
+ int64_t f1f4_2 = f1_2 * (int64_t) f4;
+ int64_t f1f5_4 = f1_2 * (int64_t) f5_2;
+ int64_t f1f6_2 = f1_2 * (int64_t) f6;
+ int64_t f1f7_4 = f1_2 * (int64_t) f7_2;
+ int64_t f1f8_2 = f1_2 * (int64_t) f8;
+ int64_t f1f9_76 = f1_2 * (int64_t) f9_38;
+ int64_t f2f2 = f2 * (int64_t) f2;
+ int64_t f2f3_2 = f2_2 * (int64_t) f3;
+ int64_t f2f4_2 = f2_2 * (int64_t) f4;
+ int64_t f2f5_2 = f2_2 * (int64_t) f5;
+ int64_t f2f6_2 = f2_2 * (int64_t) f6;
+ int64_t f2f7_2 = f2_2 * (int64_t) f7;
+ int64_t f2f8_38 = f2_2 * (int64_t) f8_19;
+ int64_t f2f9_38 = f2 * (int64_t) f9_38;
+ int64_t f3f3_2 = f3_2 * (int64_t) f3;
+ int64_t f3f4_2 = f3_2 * (int64_t) f4;
+ int64_t f3f5_4 = f3_2 * (int64_t) f5_2;
+ int64_t f3f6_2 = f3_2 * (int64_t) f6;
+ int64_t f3f7_76 = f3_2 * (int64_t) f7_38;
+ int64_t f3f8_38 = f3_2 * (int64_t) f8_19;
+ int64_t f3f9_76 = f3_2 * (int64_t) f9_38;
+ int64_t f4f4 = f4 * (int64_t) f4;
+ int64_t f4f5_2 = f4_2 * (int64_t) f5;
+ int64_t f4f6_38 = f4_2 * (int64_t) f6_19;
+ int64_t f4f7_38 = f4 * (int64_t) f7_38;
+ int64_t f4f8_38 = f4_2 * (int64_t) f8_19;
+ int64_t f4f9_38 = f4 * (int64_t) f9_38;
+ int64_t f5f5_38 = f5 * (int64_t) f5_38;
+ int64_t f5f6_38 = f5_2 * (int64_t) f6_19;
+ int64_t f5f7_76 = f5_2 * (int64_t) f7_38;
+ int64_t f5f8_38 = f5_2 * (int64_t) f8_19;
+ int64_t f5f9_76 = f5_2 * (int64_t) f9_38;
+ int64_t f6f6_19 = f6 * (int64_t) f6_19;
+ int64_t f6f7_38 = f6 * (int64_t) f7_38;
+ int64_t f6f8_38 = f6_2 * (int64_t) f8_19;
+ int64_t f6f9_38 = f6 * (int64_t) f9_38;
+ int64_t f7f7_38 = f7 * (int64_t) f7_38;
+ int64_t f7f8_38 = f7_2 * (int64_t) f8_19;
+ int64_t f7f9_76 = f7_2 * (int64_t) f9_38;
+ int64_t f8f8_19 = f8 * (int64_t) f8_19;
+ int64_t f8f9_38 = f8 * (int64_t) f9_38;
+ int64_t f9f9_38 = f9 * (int64_t) f9_38;
+
+ int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38;
+ int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38;
+ int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19;
+ int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38;
+ int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38;
+ int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38;
+ int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19;
+ int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38;
+ int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38;
+ int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2;
+
+ int64_t carry0;
+ int64_t carry1;
+ int64_t carry2;
+ int64_t carry3;
+ int64_t carry4;
+ int64_t carry5;
+ int64_t carry6;
+ int64_t carry7;
+ int64_t carry8;
+ int64_t carry9;
+
+ carry0 = (h0 + (int64_t)(1L << 25)) >> 26;
+ h1 += carry0;
+ h0 -= carry0 * ((uint64_t) 1L << 26);
+ carry4 = (h4 + (int64_t)(1L << 25)) >> 26;
+ h5 += carry4;
+ h4 -= carry4 * ((uint64_t) 1L << 26);
+
+ carry1 = (h1 + (int64_t)(1L << 24)) >> 25;
+ h2 += carry1;
+ h1 -= carry1 * ((uint64_t) 1L << 25);
+ carry5 = (h5 + (int64_t)(1L << 24)) >> 25;
+ h6 += carry5;
+ h5 -= carry5 * ((uint64_t) 1L << 25);
+
+ carry2 = (h2 + (int64_t)(1L << 25)) >> 26;
+ h3 += carry2;
+ h2 -= carry2 * ((uint64_t) 1L << 26);
+ carry6 = (h6 + (int64_t)(1L << 25)) >> 26;
+ h7 += carry6;
+ h6 -= carry6 * ((uint64_t) 1L << 26);
+
+ carry3 = (h3 + (int64_t)(1L << 24)) >> 25;
+ h4 += carry3;
+ h3 -= carry3 * ((uint64_t) 1L << 25);
+ carry7 = (h7 + (int64_t)(1L << 24)) >> 25;
+ h8 += carry7;
+ h7 -= carry7 * ((uint64_t) 1L << 25);
+
+ carry4 = (h4 + (int64_t)(1L << 25)) >> 26;
+ h5 += carry4;
+ h4 -= carry4 * ((uint64_t) 1L << 26);
+ carry8 = (h8 + (int64_t)(1L << 25)) >> 26;
+ h9 += carry8;
+ h8 -= carry8 * ((uint64_t) 1L << 26);
+
+ carry9 = (h9 + (int64_t)(1L << 24)) >> 25;
+ h0 += carry9 * 19;
+ h9 -= carry9 * ((uint64_t) 1L << 25);
+
+ carry0 = (h0 + (int64_t)(1L << 25)) >> 26;
+ h1 += carry0;
+ h0 -= carry0 * ((uint64_t) 1L << 26);
+
+ h[0] = (int32_t) h0;
+ h[1] = (int32_t) h1;
+ h[2] = (int32_t) h2;
+ h[3] = (int32_t) h3;
+ h[4] = (int32_t) h4;
+ h[5] = (int32_t) h5;
+ h[6] = (int32_t) h6;
+ h[7] = (int32_t) h7;
+ h[8] = (int32_t) h8;
+ h[9] = (int32_t) h9;
+}
+
+/*
+ h = 2 * f * f
+ Can overlap h with f.
+ *
+ Preconditions:
+ |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+ *
+ Postconditions:
+ |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
+ */
+
+static void
+fe25519_sq2(fe25519 h, const fe25519 f)
+{
+ int32_t f0 = f[0];
+ int32_t f1 = f[1];
+ int32_t f2 = f[2];
+ int32_t f3 = f[3];
+ int32_t f4 = f[4];
+ int32_t f5 = f[5];
+ int32_t f6 = f[6];
+ int32_t f7 = f[7];
+ int32_t f8 = f[8];
+ int32_t f9 = f[9];
+
+ int32_t f0_2 = 2 * f0;
+ int32_t f1_2 = 2 * f1;
+ int32_t f2_2 = 2 * f2;
+ int32_t f3_2 = 2 * f3;
+ int32_t f4_2 = 2 * f4;
+ int32_t f5_2 = 2 * f5;
+ int32_t f6_2 = 2 * f6;
+ int32_t f7_2 = 2 * f7;
+ int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */
+ int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */
+ int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */
+ int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */
+ int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */
+
+ int64_t f0f0 = f0 * (int64_t) f0;
+ int64_t f0f1_2 = f0_2 * (int64_t) f1;
+ int64_t f0f2_2 = f0_2 * (int64_t) f2;
+ int64_t f0f3_2 = f0_2 * (int64_t) f3;
+ int64_t f0f4_2 = f0_2 * (int64_t) f4;
+ int64_t f0f5_2 = f0_2 * (int64_t) f5;
+ int64_t f0f6_2 = f0_2 * (int64_t) f6;
+ int64_t f0f7_2 = f0_2 * (int64_t) f7;
+ int64_t f0f8_2 = f0_2 * (int64_t) f8;
+ int64_t f0f9_2 = f0_2 * (int64_t) f9;
+ int64_t f1f1_2 = f1_2 * (int64_t) f1;
+ int64_t f1f2_2 = f1_2 * (int64_t) f2;
+ int64_t f1f3_4 = f1_2 * (int64_t) f3_2;
+ int64_t f1f4_2 = f1_2 * (int64_t) f4;
+ int64_t f1f5_4 = f1_2 * (int64_t) f5_2;
+ int64_t f1f6_2 = f1_2 * (int64_t) f6;
+ int64_t f1f7_4 = f1_2 * (int64_t) f7_2;
+ int64_t f1f8_2 = f1_2 * (int64_t) f8;
+ int64_t f1f9_76 = f1_2 * (int64_t) f9_38;
+ int64_t f2f2 = f2 * (int64_t) f2;
+ int64_t f2f3_2 = f2_2 * (int64_t) f3;
+ int64_t f2f4_2 = f2_2 * (int64_t) f4;
+ int64_t f2f5_2 = f2_2 * (int64_t) f5;
+ int64_t f2f6_2 = f2_2 * (int64_t) f6;
+ int64_t f2f7_2 = f2_2 * (int64_t) f7;
+ int64_t f2f8_38 = f2_2 * (int64_t) f8_19;
+ int64_t f2f9_38 = f2 * (int64_t) f9_38;
+ int64_t f3f3_2 = f3_2 * (int64_t) f3;
+ int64_t f3f4_2 = f3_2 * (int64_t) f4;
+ int64_t f3f5_4 = f3_2 * (int64_t) f5_2;
+ int64_t f3f6_2 = f3_2 * (int64_t) f6;
+ int64_t f3f7_76 = f3_2 * (int64_t) f7_38;
+ int64_t f3f8_38 = f3_2 * (int64_t) f8_19;
+ int64_t f3f9_76 = f3_2 * (int64_t) f9_38;
+ int64_t f4f4 = f4 * (int64_t) f4;
+ int64_t f4f5_2 = f4_2 * (int64_t) f5;
+ int64_t f4f6_38 = f4_2 * (int64_t) f6_19;
+ int64_t f4f7_38 = f4 * (int64_t) f7_38;
+ int64_t f4f8_38 = f4_2 * (int64_t) f8_19;
+ int64_t f4f9_38 = f4 * (int64_t) f9_38;
+ int64_t f5f5_38 = f5 * (int64_t) f5_38;
+ int64_t f5f6_38 = f5_2 * (int64_t) f6_19;
+ int64_t f5f7_76 = f5_2 * (int64_t) f7_38;
+ int64_t f5f8_38 = f5_2 * (int64_t) f8_19;
+ int64_t f5f9_76 = f5_2 * (int64_t) f9_38;
+ int64_t f6f6_19 = f6 * (int64_t) f6_19;
+ int64_t f6f7_38 = f6 * (int64_t) f7_38;
+ int64_t f6f8_38 = f6_2 * (int64_t) f8_19;
+ int64_t f6f9_38 = f6 * (int64_t) f9_38;
+ int64_t f7f7_38 = f7 * (int64_t) f7_38;
+ int64_t f7f8_38 = f7_2 * (int64_t) f8_19;
+ int64_t f7f9_76 = f7_2 * (int64_t) f9_38;
+ int64_t f8f8_19 = f8 * (int64_t) f8_19;
+ int64_t f8f9_38 = f8 * (int64_t) f9_38;
+ int64_t f9f9_38 = f9 * (int64_t) f9_38;
+
+ int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38;
+ int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38;
+ int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19;
+ int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38;
+ int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38;
+ int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38;
+ int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19;
+ int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38;
+ int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38;
+ int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2;
+
+ int64_t carry0;
+ int64_t carry1;
+ int64_t carry2;
+ int64_t carry3;
+ int64_t carry4;
+ int64_t carry5;
+ int64_t carry6;
+ int64_t carry7;
+ int64_t carry8;
+ int64_t carry9;
+
+ h0 += h0;
+ h1 += h1;
+ h2 += h2;
+ h3 += h3;
+ h4 += h4;
+ h5 += h5;
+ h6 += h6;
+ h7 += h7;
+ h8 += h8;
+ h9 += h9;
+
+ carry0 = (h0 + (int64_t)(1L << 25)) >> 26;
+ h1 += carry0;
+ h0 -= carry0 * ((uint64_t) 1L << 26);
+ carry4 = (h4 + (int64_t)(1L << 25)) >> 26;
+ h5 += carry4;
+ h4 -= carry4 * ((uint64_t) 1L << 26);
+
+ carry1 = (h1 + (int64_t)(1L << 24)) >> 25;
+ h2 += carry1;
+ h1 -= carry1 * ((uint64_t) 1L << 25);
+ carry5 = (h5 + (int64_t)(1L << 24)) >> 25;
+ h6 += carry5;
+ h5 -= carry5 * ((uint64_t) 1L << 25);
+
+ carry2 = (h2 + (int64_t)(1L << 25)) >> 26;
+ h3 += carry2;
+ h2 -= carry2 * ((uint64_t) 1L << 26);
+ carry6 = (h6 + (int64_t)(1L << 25)) >> 26;
+ h7 += carry6;
+ h6 -= carry6 * ((uint64_t) 1L << 26);
+
+ carry3 = (h3 + (int64_t)(1L << 24)) >> 25;
+ h4 += carry3;
+ h3 -= carry3 * ((uint64_t) 1L << 25);
+ carry7 = (h7 + (int64_t)(1L << 24)) >> 25;
+ h8 += carry7;
+ h7 -= carry7 * ((uint64_t) 1L << 25);
+
+ carry4 = (h4 + (int64_t)(1L << 25)) >> 26;
+ h5 += carry4;
+ h4 -= carry4 * ((uint64_t) 1L << 26);
+ carry8 = (h8 + (int64_t)(1L << 25)) >> 26;
+ h9 += carry8;
+ h8 -= carry8 * ((uint64_t) 1L << 26);
+
+ carry9 = (h9 + (int64_t)(1L << 24)) >> 25;
+ h0 += carry9 * 19;
+ h9 -= carry9 * ((uint64_t) 1L << 25);
+
+ carry0 = (h0 + (int64_t)(1L << 25)) >> 26;
+ h1 += carry0;
+ h0 -= carry0 * ((uint64_t) 1L << 26);
+
+ h[0] = (int32_t) h0;
+ h[1] = (int32_t) h1;
+ h[2] = (int32_t) h2;
+ h[3] = (int32_t) h3;
+ h[4] = (int32_t) h4;
+ h[5] = (int32_t) h5;
+ h[6] = (int32_t) h6;
+ h[7] = (int32_t) h7;
+ h[8] = (int32_t) h8;
+ h[9] = (int32_t) h9;
+}
+
+static void
+fe25519_scalar_product(fe25519 h, const fe25519 f, uint32_t n)
+{
+ int64_t sn = (int64_t) n;
+ int32_t f0 = f[0];
+ int32_t f1 = f[1];
+ int32_t f2 = f[2];
+ int32_t f3 = f[3];
+ int32_t f4 = f[4];
+ int32_t f5 = f[5];
+ int32_t f6 = f[6];
+ int32_t f7 = f[7];
+ int32_t f8 = f[8];
+ int32_t f9 = f[9];
+ int64_t h0 = f0 * sn;
+ int64_t h1 = f1 * sn;
+ int64_t h2 = f2 * sn;
+ int64_t h3 = f3 * sn;
+ int64_t h4 = f4 * sn;
+ int64_t h5 = f5 * sn;
+ int64_t h6 = f6 * sn;
+ int64_t h7 = f7 * sn;
+ int64_t h8 = f8 * sn;
+ int64_t h9 = f9 * sn;
+ int64_t carry0, carry1, carry2, carry3, carry4, carry5, carry6, carry7,
+ carry8, carry9;
+
+ carry9 = (h9 + ((int64_t) 1 << 24)) >> 25;
+ h0 += carry9 * 19;
+ h9 -= carry9 * ((int64_t) 1 << 25);
+ carry1 = (h1 + ((int64_t) 1 << 24)) >> 25;
+ h2 += carry1;
+ h1 -= carry1 * ((int64_t) 1 << 25);
+ carry3 = (h3 + ((int64_t) 1 << 24)) >> 25;
+ h4 += carry3;
+ h3 -= carry3 * ((int64_t) 1 << 25);
+ carry5 = (h5 + ((int64_t) 1 << 24)) >> 25;
+ h6 += carry5;
+ h5 -= carry5 * ((int64_t) 1 << 25);
+ carry7 = (h7 + ((int64_t) 1 << 24)) >> 25;
+ h8 += carry7;
+ h7 -= carry7 * ((int64_t) 1 << 25);
+
+ carry0 = (h0 + ((int64_t) 1 << 25)) >> 26;
+ h1 += carry0;
+ h0 -= carry0 * ((int64_t) 1 << 26);
+ carry2 = (h2 + ((int64_t) 1 << 25)) >> 26;
+ h3 += carry2;
+ h2 -= carry2 * ((int64_t) 1 << 26);
+ carry4 = (h4 + ((int64_t) 1 << 25)) >> 26;
+ h5 += carry4;
+ h4 -= carry4 * ((int64_t) 1 << 26);
+ carry6 = (h6 + ((int64_t) 1 << 25)) >> 26;
+ h7 += carry6;
+ h6 -= carry6 * ((int64_t) 1 << 26);
+ carry8 = (h8 + ((int64_t) 1 << 25)) >> 26;
+ h9 += carry8;
+ h8 -= carry8 * ((int64_t) 1 << 26);
+
+ h[0] = (int32_t) h0;
+ h[1] = (int32_t) h1;
+ h[2] = (int32_t) h2;
+ h[3] = (int32_t) h3;
+ h[4] = (int32_t) h4;
+ h[5] = (int32_t) h5;
+ h[6] = (int32_t) h6;
+ h[7] = (int32_t) h7;
+ h[8] = (int32_t) h8;
+ h[9] = (int32_t) h9;
+}
diff --git a/libs/libsodium/src/include/sodium/private/ed25519_ref10_fe_51.h b/libs/libsodium/src/include/sodium/private/ed25519_ref10_fe_51.h
new file mode 100644
index 0000000000..3a30f30148
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/private/ed25519_ref10_fe_51.h
@@ -0,0 +1,518 @@
+#include <string.h>
+
+#include "private/common.h"
+#include "utils.h"
+
+/*
+ h = 0
+ */
+
+static inline void
+fe25519_0(fe25519 h)
+{
+ memset(&h[0], 0, 5 * sizeof h[0]);
+}
+
+/*
+ h = 1
+ */
+
+static inline void
+fe25519_1(fe25519 h)
+{
+ h[0] = 1;
+ memset(&h[1], 0, 4 * sizeof h[0]);
+}
+
+/*
+ h = f + g
+ Can overlap h with f or g.
+ */
+
+static inline void
+fe25519_add(fe25519 h, const fe25519 f, const fe25519 g)
+{
+ uint64_t h0 = f[0] + g[0];
+ uint64_t h1 = f[1] + g[1];
+ uint64_t h2 = f[2] + g[2];
+ uint64_t h3 = f[3] + g[3];
+ uint64_t h4 = f[4] + g[4];
+
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+}
+
+/*
+ h = f - g
+ */
+
+static void
+fe25519_sub(fe25519 h, const fe25519 f, const fe25519 g)
+{
+ const uint64_t mask = 0x7ffffffffffffULL;
+ uint64_t h0, h1, h2, h3, h4;
+
+ h0 = g[0];
+ h1 = g[1];
+ h2 = g[2];
+ h3 = g[3];
+ h4 = g[4];
+
+ h1 += h0 >> 51;
+ h0 &= mask;
+ h2 += h1 >> 51;
+ h1 &= mask;
+ h3 += h2 >> 51;
+ h2 &= mask;
+ h4 += h3 >> 51;
+ h3 &= mask;
+ h0 += 19ULL * (h4 >> 51);
+ h4 &= mask;
+
+ h0 = (f[0] + 0xfffffffffffdaULL) - h0;
+ h1 = (f[1] + 0xffffffffffffeULL) - h1;
+ h2 = (f[2] + 0xffffffffffffeULL) - h2;
+ h3 = (f[3] + 0xffffffffffffeULL) - h3;
+ h4 = (f[4] + 0xffffffffffffeULL) - h4;
+
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+}
+
+/*
+ h = -f
+ */
+
+static inline void
+fe25519_neg(fe25519 h, const fe25519 f)
+{
+ fe25519 zero;
+
+ fe25519_0(zero);
+ fe25519_sub(h, zero, f);
+}
+
+/*
+ Replace (f,g) with (g,g) if b == 1;
+ replace (f,g) with (f,g) if b == 0.
+ *
+ Preconditions: b in {0,1}.
+ */
+
+static void
+fe25519_cmov(fe25519 f, const fe25519 g, unsigned int b)
+{
+ const uint64_t mask = (uint64_t) (-(int64_t) b);
+
+ uint64_t f0 = f[0];
+ uint64_t f1 = f[1];
+ uint64_t f2 = f[2];
+ uint64_t f3 = f[3];
+ uint64_t f4 = f[4];
+
+ uint64_t x0 = f0 ^ g[0];
+ uint64_t x1 = f1 ^ g[1];
+ uint64_t x2 = f2 ^ g[2];
+ uint64_t x3 = f3 ^ g[3];
+ uint64_t x4 = f4 ^ g[4];
+
+ x0 &= mask;
+ x1 &= mask;
+ x2 &= mask;
+ x3 &= mask;
+ x4 &= mask;
+
+ f[0] = f0 ^ x0;
+ f[1] = f1 ^ x1;
+ f[2] = f2 ^ x2;
+ f[3] = f3 ^ x3;
+ f[4] = f4 ^ x4;
+}
+
+/*
+Replace (f,g) with (g,f) if b == 1;
+replace (f,g) with (f,g) if b == 0.
+
+Preconditions: b in {0,1}.
+*/
+
+static void
+fe25519_cswap(fe25519 f, fe25519 g, unsigned int b)
+{
+ const uint64_t mask = (uint64_t) (-(int64_t) b);
+
+ uint64_t f0 = f[0];
+ uint64_t f1 = f[1];
+ uint64_t f2 = f[2];
+ uint64_t f3 = f[3];
+ uint64_t f4 = f[4];
+
+ uint64_t g0 = g[0];
+ uint64_t g1 = g[1];
+ uint64_t g2 = g[2];
+ uint64_t g3 = g[3];
+ uint64_t g4 = g[4];
+
+ uint64_t x0 = f0 ^ g0;
+ uint64_t x1 = f1 ^ g1;
+ uint64_t x2 = f2 ^ g2;
+ uint64_t x3 = f3 ^ g3;
+ uint64_t x4 = f4 ^ g4;
+
+ x0 &= mask;
+ x1 &= mask;
+ x2 &= mask;
+ x3 &= mask;
+ x4 &= mask;
+
+ f[0] = f0 ^ x0;
+ f[1] = f1 ^ x1;
+ f[2] = f2 ^ x2;
+ f[3] = f3 ^ x3;
+ f[4] = f4 ^ x4;
+
+ g[0] = g0 ^ x0;
+ g[1] = g1 ^ x1;
+ g[2] = g2 ^ x2;
+ g[3] = g3 ^ x3;
+ g[4] = g4 ^ x4;
+}
+
+/*
+ h = f
+ */
+
+static inline void
+fe25519_copy(fe25519 h, const fe25519 f)
+{
+ uint64_t f0 = f[0];
+ uint64_t f1 = f[1];
+ uint64_t f2 = f[2];
+ uint64_t f3 = f[3];
+ uint64_t f4 = f[4];
+
+ h[0] = f0;
+ h[1] = f1;
+ h[2] = f2;
+ h[3] = f3;
+ h[4] = f4;
+}
+
+/*
+ return 1 if f is in {1,3,5,...,q-2}
+ return 0 if f is in {0,2,4,...,q-1}
+ */
+
+static inline int
+fe25519_isnegative(const fe25519 f)
+{
+ unsigned char s[32];
+
+ fe25519_tobytes(s, f);
+
+ return s[0] & 1;
+}
+
+/*
+ return 1 if f == 0
+ return 0 if f != 0
+ */
+
+static inline int
+fe25519_iszero(const fe25519 f)
+{
+ unsigned char s[32];
+
+ fe25519_tobytes(s, f);
+
+ return sodium_is_zero(s, 32);
+}
+
+/*
+ h = f * g
+ Can overlap h with f or g.
+ */
+
+static void
+fe25519_mul(fe25519 h, const fe25519 f, const fe25519 g)
+{
+ const uint64_t mask = 0x7ffffffffffffULL;
+ uint128_t r0, r1, r2, r3, r4, carry;
+ uint64_t f0, f1, f2, f3, f4;
+ uint64_t f1_19, f2_19, f3_19, f4_19;
+ uint64_t g0, g1, g2, g3, g4;
+ uint64_t r00, r01, r02, r03, r04;
+
+ f0 = f[0];
+ f1 = f[1];
+ f2 = f[2];
+ f3 = f[3];
+ f4 = f[4];
+
+ g0 = g[0];
+ g1 = g[1];
+ g2 = g[2];
+ g3 = g[3];
+ g4 = g[4];
+
+ f1_19 = 19ULL * f1;
+ f2_19 = 19ULL * f2;
+ f3_19 = 19ULL * f3;
+ f4_19 = 19ULL * f4;
+
+ r0 = ((uint128_t) f0 ) * ((uint128_t) g0);
+ r0 += ((uint128_t) f1_19) * ((uint128_t) g4);
+ r0 += ((uint128_t) f2_19) * ((uint128_t) g3);
+ r0 += ((uint128_t) f3_19) * ((uint128_t) g2);
+ r0 += ((uint128_t) f4_19) * ((uint128_t) g1);
+
+ r1 = ((uint128_t) f0 ) * ((uint128_t) g1);
+ r1 += ((uint128_t) f1 ) * ((uint128_t) g0);
+ r1 += ((uint128_t) f2_19) * ((uint128_t) g4);
+ r1 += ((uint128_t) f3_19) * ((uint128_t) g3);
+ r1 += ((uint128_t) f4_19) * ((uint128_t) g2);
+
+ r2 = ((uint128_t) f0 ) * ((uint128_t) g2);
+ r2 += ((uint128_t) f1 ) * ((uint128_t) g1);
+ r2 += ((uint128_t) f2 ) * ((uint128_t) g0);
+ r2 += ((uint128_t) f3_19) * ((uint128_t) g4);
+ r2 += ((uint128_t) f4_19) * ((uint128_t) g3);
+
+ r3 = ((uint128_t) f0 ) * ((uint128_t) g3);
+ r3 += ((uint128_t) f1 ) * ((uint128_t) g2);
+ r3 += ((uint128_t) f2 ) * ((uint128_t) g1);
+ r3 += ((uint128_t) f3 ) * ((uint128_t) g0);
+ r3 += ((uint128_t) f4_19) * ((uint128_t) g4);
+
+ r4 = ((uint128_t) f0 ) * ((uint128_t) g4);
+ r4 += ((uint128_t) f1 ) * ((uint128_t) g3);
+ r4 += ((uint128_t) f2 ) * ((uint128_t) g2);
+ r4 += ((uint128_t) f3 ) * ((uint128_t) g1);
+ r4 += ((uint128_t) f4 ) * ((uint128_t) g0);
+
+ r00 = ((uint64_t) r0) & mask;
+ carry = r0 >> 51;
+ r1 += carry;
+ r01 = ((uint64_t) r1) & mask;
+ carry = r1 >> 51;
+ r2 += carry;
+ r02 = ((uint64_t) r2) & mask;
+ carry = r2 >> 51;
+ r3 += carry;
+ r03 = ((uint64_t) r3) & mask;
+ carry = r3 >> 51;
+ r4 += carry;
+ r04 = ((uint64_t) r4) & mask;
+ carry = r4 >> 51;
+ r00 += 19ULL * (uint64_t) carry;
+ carry = r00 >> 51;
+ r00 &= mask;
+ r01 += (uint64_t) carry;
+ carry = r01 >> 51;
+ r01 &= mask;
+ r02 += (uint64_t) carry;
+
+ h[0] = r00;
+ h[1] = r01;
+ h[2] = r02;
+ h[3] = r03;
+ h[4] = r04;
+}
+
+/*
+ h = f * f
+ Can overlap h with f.
+ */
+
+static void
+fe25519_sq(fe25519 h, const fe25519 f)
+{
+ const uint64_t mask = 0x7ffffffffffffULL;
+ uint128_t r0, r1, r2, r3, r4, carry;
+ uint64_t f0, f1, f2, f3, f4;
+ uint64_t f0_2, f1_2, f1_38, f2_38, f3_38, f3_19, f4_19;
+ uint64_t r00, r01, r02, r03, r04;
+
+ f0 = f[0];
+ f1 = f[1];
+ f2 = f[2];
+ f3 = f[3];
+ f4 = f[4];
+
+ f0_2 = f0 << 1;
+ f1_2 = f1 << 1;
+
+ f1_38 = 38ULL * f1;
+ f2_38 = 38ULL * f2;
+ f3_38 = 38ULL * f3;
+
+ f3_19 = 19ULL * f3;
+ f4_19 = 19ULL * f4;
+
+ r0 = ((uint128_t) f0 ) * ((uint128_t) f0);
+ r0 += ((uint128_t) f1_38) * ((uint128_t) f4);
+ r0 += ((uint128_t) f2_38) * ((uint128_t) f3);
+
+ r1 = ((uint128_t) f0_2 ) * ((uint128_t) f1);
+ r1 += ((uint128_t) f2_38) * ((uint128_t) f4);
+ r1 += ((uint128_t) f3_19) * ((uint128_t) f3);
+
+ r2 = ((uint128_t) f0_2 ) * ((uint128_t) f2);
+ r2 += ((uint128_t) f1 ) * ((uint128_t) f1);
+ r2 += ((uint128_t) f3_38) * ((uint128_t) f4);
+
+ r3 = ((uint128_t) f0_2 ) * ((uint128_t) f3);
+ r3 += ((uint128_t) f1_2 ) * ((uint128_t) f2);
+ r3 += ((uint128_t) f4_19) * ((uint128_t) f4);
+
+ r4 = ((uint128_t) f0_2 ) * ((uint128_t) f4);
+ r4 += ((uint128_t) f1_2 ) * ((uint128_t) f3);
+ r4 += ((uint128_t) f2 ) * ((uint128_t) f2);
+
+ r00 = ((uint64_t) r0) & mask;
+ carry = r0 >> 51;
+ r1 += carry;
+ r01 = ((uint64_t) r1) & mask;
+ carry = r1 >> 51;
+ r2 += carry;
+ r02 = ((uint64_t) r2) & mask;
+ carry = r2 >> 51;
+ r3 += carry;
+ r03 = ((uint64_t) r3) & mask;
+ carry = r3 >> 51;
+ r4 += carry;
+ r04 = ((uint64_t) r4) & mask;
+ carry = r4 >> 51;
+ r00 += 19ULL * (uint64_t) carry;
+ carry = r00 >> 51;
+ r00 &= mask;
+ r01 += (uint64_t) carry;
+ carry = r01 >> 51;
+ r01 &= mask;
+ r02 += (uint64_t) carry;
+
+ h[0] = r00;
+ h[1] = r01;
+ h[2] = r02;
+ h[3] = r03;
+ h[4] = r04;
+}
+
+/*
+ h = 2 * f * f
+ Can overlap h with f.
+*/
+
+static void
+fe25519_sq2(fe25519 h, const fe25519 f)
+{
+ const uint64_t mask = 0x7ffffffffffffULL;
+ uint128_t r0, r1, r2, r3, r4, carry;
+ uint64_t f0, f1, f2, f3, f4;
+ uint64_t f0_2, f1_2, f1_38, f2_38, f3_38, f3_19, f4_19;
+ uint64_t r00, r01, r02, r03, r04;
+
+ f0 = f[0];
+ f1 = f[1];
+ f2 = f[2];
+ f3 = f[3];
+ f4 = f[4];
+
+ f0_2 = f0 << 1;
+ f1_2 = f1 << 1;
+
+ f1_38 = 38ULL * f1;
+ f2_38 = 38ULL * f2;
+ f3_38 = 38ULL * f3;
+
+ f3_19 = 19ULL * f3;
+ f4_19 = 19ULL * f4;
+
+ r0 = ((uint128_t) f0 ) * ((uint128_t) f0);
+ r0 += ((uint128_t) f1_38) * ((uint128_t) f4);
+ r0 += ((uint128_t) f2_38) * ((uint128_t) f3);
+
+ r1 = ((uint128_t) f0_2 ) * ((uint128_t) f1);
+ r1 += ((uint128_t) f2_38) * ((uint128_t) f4);
+ r1 += ((uint128_t) f3_19) * ((uint128_t) f3);
+
+ r2 = ((uint128_t) f0_2 ) * ((uint128_t) f2);
+ r2 += ((uint128_t) f1 ) * ((uint128_t) f1);
+ r2 += ((uint128_t) f3_38) * ((uint128_t) f4);
+
+ r3 = ((uint128_t) f0_2 ) * ((uint128_t) f3);
+ r3 += ((uint128_t) f1_2 ) * ((uint128_t) f2);
+ r3 += ((uint128_t) f4_19) * ((uint128_t) f4);
+
+ r4 = ((uint128_t) f0_2 ) * ((uint128_t) f4);
+ r4 += ((uint128_t) f1_2 ) * ((uint128_t) f3);
+ r4 += ((uint128_t) f2 ) * ((uint128_t) f2);
+
+ r0 <<= 1;
+ r1 <<= 1;
+ r2 <<= 1;
+ r3 <<= 1;
+ r4 <<= 1;
+
+ r00 = ((uint64_t) r0) & mask;
+ carry = r0 >> 51;
+ r1 += carry;
+ r01 = ((uint64_t) r1) & mask;
+ carry = r1 >> 51;
+ r2 += carry;
+ r02 = ((uint64_t) r2) & mask;
+ carry = r2 >> 51;
+ r3 += carry;
+ r03 = ((uint64_t) r3) & mask;
+ carry = r3 >> 51;
+ r4 += carry;
+ r04 = ((uint64_t) r4) & mask;
+ carry = r4 >> 51;
+ r00 += 19ULL * (uint64_t) carry;
+ carry = r00 >> 51;
+ r00 &= mask;
+ r01 += (uint64_t) carry;
+ carry = r01 >> 51;
+ r01 &= mask;
+ r02 += (uint64_t) carry;
+
+ h[0] = r00;
+ h[1] = r01;
+ h[2] = r02;
+ h[3] = r03;
+ h[4] = r04;
+}
+
+static void
+fe25519_scalar_product(fe25519 h, const fe25519 f, uint32_t n)
+{
+ const uint64_t mask = 0x7ffffffffffffULL;
+ uint128_t a;
+ uint128_t sn = (uint128_t) n;
+ uint64_t h0, h1, h2, h3, h4;
+
+ a = f[0] * sn;
+ h0 = ((uint64_t) a) & mask;
+ a = f[1] * sn + ((uint64_t) (a >> 51));
+ h1 = ((uint64_t) a) & mask;
+ a = f[2] * sn + ((uint64_t) (a >> 51));
+ h2 = ((uint64_t) a) & mask;
+ a = f[3] * sn + ((uint64_t) (a >> 51));
+ h3 = ((uint64_t) a) & mask;
+ a = f[4] * sn + ((uint64_t) (a >> 51));
+ h4 = ((uint64_t) a) & mask;
+
+ h0 += (a >> 51) * 19ULL;
+
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+}
diff --git a/libs/libsodium/src/include/sodium/private/implementations.h b/libs/libsodium/src/include/sodium/private/implementations.h
new file mode 100644
index 0000000000..c7237f851d
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/private/implementations.h
@@ -0,0 +1,11 @@
+#ifndef implementations_H
+#define implementations_H
+
+int _crypto_generichash_blake2b_pick_best_implementation(void);
+int _crypto_onetimeauth_poly1305_pick_best_implementation(void);
+int _crypto_pwhash_argon2_pick_best_implementation(void);
+int _crypto_scalarmult_curve25519_pick_best_implementation(void);
+int _crypto_stream_chacha20_pick_best_implementation(void);
+int _crypto_stream_salsa20_pick_best_implementation(void);
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/private/mutex.h b/libs/libsodium/src/include/sodium/private/mutex.h
new file mode 100644
index 0000000000..322b6742b2
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/private/mutex.h
@@ -0,0 +1,7 @@
+#ifndef mutex_H
+#define mutex_H 1
+
+extern int sodium_crit_enter(void);
+extern int sodium_crit_leave(void);
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/private/sse2_64_32.h b/libs/libsodium/src/include/sodium/private/sse2_64_32.h
new file mode 100644
index 0000000000..d0455b41b4
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/private/sse2_64_32.h
@@ -0,0 +1,50 @@
+#ifndef sse2_64_32_H
+#define sse2_64_32_H 1
+
+#include "common.h"
+
+#ifdef HAVE_INTRIN_H
+# include <intrin.h>
+#endif
+
+#if defined(HAVE_EMMINTRIN_H) && \
+ !(defined(__amd64) || defined(__amd64__) || defined(__x86_64__) || \
+ defined(_M_X64) || defined(_M_AMD64))
+
+# include <emmintrin.h>
+# include <stdint.h>
+
+# ifndef _mm_set_epi64x
+# define _mm_set_epi64x(Q0, Q1) sodium__mm_set_epi64x((Q0), (Q1))
+static inline __m128i
+sodium__mm_set_epi64x(int64_t q1, int64_t q0)
+{
+ union { int64_t as64; int32_t as32[2]; } x0, x1;
+ x0.as64 = q0; x1.as64 = q1;
+ return _mm_set_epi32(x1.as32[1], x1.as32[0], x0.as32[1], x0.as32[0]);
+}
+# endif
+
+# ifndef _mm_set1_epi64x
+# define _mm_set1_epi64x(Q) sodium__mm_set1_epi64x(Q)
+static inline __m128i
+sodium__mm_set1_epi64x(int64_t q)
+{
+ return _mm_set_epi64x(q, q);
+}
+# endif
+
+# ifndef _mm_cvtsi64_si128
+# define _mm_cvtsi64_si128(Q) sodium__mm_cvtsi64_si128(Q)
+static inline __m128i
+sodium__mm_cvtsi64_si128(int64_t q)
+{
+ union { int64_t as64; int32_t as32[2]; } x;
+ x.as64 = q;
+ return _mm_setr_epi32(x.as32[0], x.as32[1], 0, 0);
+}
+# endif
+
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/randombytes.h b/libs/libsodium/src/include/sodium/randombytes.h
new file mode 100644
index 0000000000..d19f684ed6
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/randombytes.h
@@ -0,0 +1,68 @@
+
+#ifndef randombytes_H
+#define randombytes_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <sys/types.h>
+
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+typedef struct randombytes_implementation {
+ const char *(*implementation_name)(void); /* required */
+ uint32_t (*random)(void); /* required */
+ void (*stir)(void); /* optional */
+ uint32_t (*uniform)(const uint32_t upper_bound); /* optional, a default implementation will be used if NULL */
+ void (*buf)(void * const buf, const size_t size); /* required */
+ int (*close)(void); /* optional */
+} randombytes_implementation;
+
+#define randombytes_BYTES_MAX SODIUM_MIN(SODIUM_SIZE_MAX, 0xffffffffUL)
+
+#define randombytes_SEEDBYTES 32U
+SODIUM_EXPORT
+size_t randombytes_seedbytes(void);
+
+SODIUM_EXPORT
+void randombytes_buf(void * const buf, const size_t size);
+
+SODIUM_EXPORT
+void randombytes_buf_deterministic(void * const buf, const size_t size,
+ const unsigned char seed[randombytes_SEEDBYTES]);
+
+SODIUM_EXPORT
+uint32_t randombytes_random(void);
+
+SODIUM_EXPORT
+uint32_t randombytes_uniform(const uint32_t upper_bound);
+
+SODIUM_EXPORT
+void randombytes_stir(void);
+
+SODIUM_EXPORT
+int randombytes_close(void);
+
+SODIUM_EXPORT
+int randombytes_set_implementation(randombytes_implementation *impl);
+
+SODIUM_EXPORT
+const char *randombytes_implementation_name(void);
+
+/* -- NaCl compatibility interface -- */
+
+SODIUM_EXPORT
+void randombytes(unsigned char * const buf, const unsigned long long buf_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/randombytes_nativeclient.h b/libs/libsodium/src/include/sodium/randombytes_nativeclient.h
new file mode 100644
index 0000000000..5158d8c3c3
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/randombytes_nativeclient.h
@@ -0,0 +1,23 @@
+
+#ifndef randombytes_nativeclient_H
+#define randombytes_nativeclient_H
+
+#ifdef __native_client__
+
+# include "export.h"
+# include "randombytes.h"
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+SODIUM_EXPORT
+extern struct randombytes_implementation randombytes_nativeclient_implementation;
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/randombytes_salsa20_random.h b/libs/libsodium/src/include/sodium/randombytes_salsa20_random.h
new file mode 100644
index 0000000000..4deae15b6d
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/randombytes_salsa20_random.h
@@ -0,0 +1,19 @@
+
+#ifndef randombytes_salsa20_random_H
+#define randombytes_salsa20_random_H
+
+#include "export.h"
+#include "randombytes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SODIUM_EXPORT
+extern struct randombytes_implementation randombytes_salsa20_implementation;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/randombytes_sysrandom.h b/libs/libsodium/src/include/sodium/randombytes_sysrandom.h
new file mode 100644
index 0000000000..9e27b674c7
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/randombytes_sysrandom.h
@@ -0,0 +1,19 @@
+
+#ifndef randombytes_sysrandom_H
+#define randombytes_sysrandom_H
+
+#include "export.h"
+#include "randombytes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SODIUM_EXPORT
+extern struct randombytes_implementation randombytes_sysrandom_implementation;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/runtime.h b/libs/libsodium/src/include/sodium/runtime.h
new file mode 100644
index 0000000000..7f15d58e7c
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/runtime.h
@@ -0,0 +1,52 @@
+
+#ifndef sodium_runtime_H
+#define sodium_runtime_H
+
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_neon(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_sse2(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_sse3(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_ssse3(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_sse41(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_avx(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_avx2(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_avx512f(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_pclmul(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_aesni(void);
+
+SODIUM_EXPORT_WEAK
+int sodium_runtime_has_rdrand(void);
+
+/* ------------------------------------------------------------------------- */
+
+int _sodium_runtime_get_cpu_features(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/utils.h b/libs/libsodium/src/include/sodium/utils.h
new file mode 100644
index 0000000000..46eb331cfd
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/utils.h
@@ -0,0 +1,170 @@
+
+#ifndef sodium_utils_H
+#define sodium_utils_H
+
+#include <stddef.h>
+
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef SODIUM_C99
+# if defined(__cplusplus) || !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
+# define SODIUM_C99(X)
+# else
+# define SODIUM_C99(X) X
+# endif
+#endif
+
+SODIUM_EXPORT
+void sodium_memzero(void * const pnt, const size_t len);
+
+SODIUM_EXPORT
+void sodium_stackzero(const size_t len);
+
+/*
+ * WARNING: sodium_memcmp() must be used to verify if two secret keys
+ * are equal, in constant time.
+ * It returns 0 if the keys are equal, and -1 if they differ.
+ * This function is not designed for lexicographical comparisons.
+ */
+SODIUM_EXPORT
+int sodium_memcmp(const void * const b1_, const void * const b2_, size_t len)
+ __attribute__ ((warn_unused_result));
+
+/*
+ * sodium_compare() returns -1 if b1_ < b2_, 1 if b1_ > b2_ and 0 if b1_ == b2_
+ * It is suitable for lexicographical comparisons, or to compare nonces
+ * and counters stored in little-endian format.
+ * However, it is slower than sodium_memcmp().
+ */
+SODIUM_EXPORT
+int sodium_compare(const unsigned char *b1_, const unsigned char *b2_,
+ size_t len)
+ __attribute__ ((warn_unused_result));
+
+SODIUM_EXPORT
+int sodium_is_zero(const unsigned char *n, const size_t nlen);
+
+SODIUM_EXPORT
+void sodium_increment(unsigned char *n, const size_t nlen);
+
+SODIUM_EXPORT
+void sodium_add(unsigned char *a, const unsigned char *b, const size_t len);
+
+SODIUM_EXPORT
+char *sodium_bin2hex(char * const hex, const size_t hex_maxlen,
+ const unsigned char * const bin, const size_t bin_len);
+
+SODIUM_EXPORT
+int sodium_hex2bin(unsigned char * const bin, const size_t bin_maxlen,
+ const char * const hex, const size_t hex_len,
+ const char * const ignore, size_t * const bin_len,
+ const char ** const hex_end);
+
+#define sodium_base64_VARIANT_ORIGINAL 1
+#define sodium_base64_VARIANT_ORIGINAL_NO_PADDING 3
+#define sodium_base64_VARIANT_URLSAFE 5
+#define sodium_base64_VARIANT_URLSAFE_NO_PADDING 7
+
+/*
+ * Computes the required length to encode BIN_LEN bytes as a base64 string
+ * using the given variant. The computed length includes a trailing \0.
+ */
+#define sodium_base64_ENCODED_LEN(BIN_LEN, VARIANT) \
+ (((BIN_LEN) / 3U) * 4U + \
+ ((((BIN_LEN) - ((BIN_LEN) / 3U) * 3U) | (((BIN_LEN) - ((BIN_LEN) / 3U) * 3U) >> 1)) & 1U) * \
+ (4U - (~((((VARIANT) & 2U) >> 1) - 1U) & (3U - ((BIN_LEN) - ((BIN_LEN) / 3U) * 3U)))) + 1U)
+
+SODIUM_EXPORT
+size_t sodium_base64_encoded_len(const size_t bin_len, const int variant);
+
+SODIUM_EXPORT
+char *sodium_bin2base64(char * const b64, const size_t b64_maxlen,
+ const unsigned char * const bin, const size_t bin_len,
+ const int variant);
+
+SODIUM_EXPORT
+int sodium_base642bin(unsigned char * const bin, const size_t bin_maxlen,
+ const char * const b64, const size_t b64_len,
+ const char * const ignore, size_t * const bin_len,
+ const char ** const b64_end, const int variant);
+
+SODIUM_EXPORT
+int sodium_mlock(void * const addr, const size_t len);
+
+SODIUM_EXPORT
+int sodium_munlock(void * const addr, const size_t len);
+
+/* WARNING: sodium_malloc() and sodium_allocarray() are not general-purpose
+ * allocation functions.
+ *
+ * They return a pointer to a region filled with 0xd0 bytes, immediately
+ * followed by a guard page.
+ * As a result, accessing a single byte after the requested allocation size
+ * will intentionally trigger a segmentation fault.
+ *
+ * A canary and an additional guard page placed before the beginning of the
+ * region may also kill the process if a buffer underflow is detected.
+ *
+ * The memory layout is:
+ * [unprotected region size (read only)][guard page (no access)][unprotected pages (read/write)][guard page (no access)]
+ * With the layout of the unprotected pages being:
+ * [optional padding][16-bytes canary][user region]
+ *
+ * However:
+ * - These functions are significantly slower than standard functions
+ * - Each allocation requires 3 or 4 additional pages
+ * - The returned address will not be aligned if the allocation size is not
+ * a multiple of the required alignment. For this reason, these functions
+ * are designed to store data, such as secret keys and messages.
+ *
+ * sodium_malloc() can be used to allocate any libsodium data structure.
+ *
+ * The crypto_generichash_state structure is packed and its length is
+ * either 357 or 361 bytes. For this reason, when using sodium_malloc() to
+ * allocate a crypto_generichash_state structure, padding must be added in
+ * order to ensure proper alignment. crypto_generichash_statebytes()
+ * returns the rounded up structure size, and should be prefered to sizeof():
+ * state = sodium_malloc(crypto_generichash_statebytes());
+ */
+
+SODIUM_EXPORT
+void *sodium_malloc(const size_t size)
+ __attribute__ ((malloc));
+
+SODIUM_EXPORT
+void *sodium_allocarray(size_t count, size_t size)
+ __attribute__ ((malloc));
+
+SODIUM_EXPORT
+void sodium_free(void *ptr);
+
+SODIUM_EXPORT
+int sodium_mprotect_noaccess(void *ptr);
+
+SODIUM_EXPORT
+int sodium_mprotect_readonly(void *ptr);
+
+SODIUM_EXPORT
+int sodium_mprotect_readwrite(void *ptr);
+
+SODIUM_EXPORT
+int sodium_pad(size_t *padded_buflen_p, unsigned char *buf,
+ size_t unpadded_buflen, size_t blocksize, size_t max_buflen);
+
+SODIUM_EXPORT
+int sodium_unpad(size_t *unpadded_buflen_p, const unsigned char *buf,
+ size_t padded_buflen, size_t blocksize);
+
+/* -------- */
+
+int _sodium_alloc_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/include/sodium/version.h b/libs/libsodium/src/include/sodium/version.h
new file mode 100644
index 0000000000..56ec2b9550
--- /dev/null
+++ b/libs/libsodium/src/include/sodium/version.h
@@ -0,0 +1,32 @@
+
+#ifndef sodium_version_H
+#define sodium_version_H
+
+#include "export.h"
+
+#define SODIUM_VERSION_STRING "1.0.16"
+
+#define SODIUM_LIBRARY_VERSION_MAJOR 10
+#define SODIUM_LIBRARY_VERSION_MINOR 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SODIUM_EXPORT
+const char *sodium_version_string(void);
+
+SODIUM_EXPORT
+int sodium_library_version_major(void);
+
+SODIUM_EXPORT
+int sodium_library_version_minor(void);
+
+SODIUM_EXPORT
+int sodium_library_minimal(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/libsodium/src/randombytes/nativeclient/randombytes_nativeclient.c b/libs/libsodium/src/randombytes/nativeclient/randombytes_nativeclient.c
new file mode 100644
index 0000000000..85ffa9b29b
--- /dev/null
+++ b/libs/libsodium/src/randombytes/nativeclient/randombytes_nativeclient.c
@@ -0,0 +1,61 @@
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifdef __native_client__
+# include <irt.h>
+
+# include "core.h"
+# include "utils.h"
+# include "randombytes.h"
+# include "randombytes_nativeclient.h"
+
+static void
+randombytes_nativeclient_buf(void * const buf, const size_t size)
+{
+ unsigned char *buf_ = (unsigned char *) buf;
+ struct nacl_irt_random rand_intf;
+ size_t readnb = (size_t) 0U;
+ size_t toread = size;
+
+ if (nacl_interface_query(NACL_IRT_RANDOM_v0_1, &rand_intf,
+ sizeof rand_intf) != sizeof rand_intf) {
+ sodium_misuse();
+ }
+ while (toread > (size_t) 0U) {
+ if (rand_intf.get_random_bytes(buf_, size, &readnb) != 0 ||
+ readnb > size) {
+ sodium_misuse();
+ }
+ toread -= readnb;
+ buf_ += readnb;
+ }
+}
+
+static uint32_t
+randombytes_nativeclient_random(void)
+{
+ uint32_t r;
+
+ randombytes_nativeclient_buf(&r, sizeof r);
+
+ return r;
+}
+
+static const char *
+randombytes_nativeclient_implementation_name(void)
+{
+ return "nativeclient";
+}
+
+struct randombytes_implementation randombytes_nativeclient_implementation = {
+ SODIUM_C99(.implementation_name =) randombytes_nativeclient_implementation_name,
+ SODIUM_C99(.random =) randombytes_nativeclient_random,
+ SODIUM_C99(.stir =) NULL,
+ SODIUM_C99(.uniform =) NULL,
+ SODIUM_C99(.buf =) randombytes_nativeclient_buf,
+ SODIUM_C99(.close =) NULL
+};
+
+#endif
diff --git a/libs/libsodium/src/randombytes/randombytes.c b/libs/libsodium/src/randombytes/randombytes.c
new file mode 100644
index 0000000000..708616b8aa
--- /dev/null
+++ b/libs/libsodium/src/randombytes/randombytes.c
@@ -0,0 +1,206 @@
+
+#include <assert.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+
+#ifdef __EMSCRIPTEN__
+# include <emscripten.h>
+#endif
+
+#include "core.h"
+#include "crypto_stream_chacha20.h"
+#include "randombytes.h"
+#ifdef RANDOMBYTES_DEFAULT_IMPLEMENTATION
+# include "randombytes_default.h"
+#else
+# ifdef __native_client__
+# include "randombytes_nativeclient.h"
+# else
+# include "randombytes_sysrandom.h"
+# endif
+#endif
+#include "private/common.h"
+
+/* C++Builder defines a "random" macro */
+#undef random
+
+static const randombytes_implementation *implementation;
+
+#ifndef RANDOMBYTES_DEFAULT_IMPLEMENTATION
+# ifdef __EMSCRIPTEN__
+# define RANDOMBYTES_DEFAULT_IMPLEMENTATION NULL
+# else
+# ifdef __native_client__
+# define RANDOMBYTES_DEFAULT_IMPLEMENTATION &randombytes_nativeclient_implementation;
+# else
+# define RANDOMBYTES_DEFAULT_IMPLEMENTATION &randombytes_sysrandom_implementation;
+# endif
+# endif
+#endif
+
+static void
+randombytes_init_if_needed(void)
+{
+ if (implementation == NULL) {
+ implementation = RANDOMBYTES_DEFAULT_IMPLEMENTATION;
+ randombytes_stir();
+ }
+}
+
+int
+randombytes_set_implementation(randombytes_implementation *impl)
+{
+ implementation = impl;
+
+ return 0;
+}
+
+const char *
+randombytes_implementation_name(void)
+{
+#ifndef __EMSCRIPTEN__
+ randombytes_init_if_needed();
+ return implementation->implementation_name();
+#else
+ return "js";
+#endif
+}
+
+uint32_t
+randombytes_random(void)
+{
+#ifndef __EMSCRIPTEN__
+ randombytes_init_if_needed();
+ return implementation->random();
+#else
+ return EM_ASM_INT_V({
+ return Module.getRandomValue();
+ });
+#endif
+}
+
+void
+randombytes_stir(void)
+{
+#ifndef __EMSCRIPTEN__
+ randombytes_init_if_needed();
+ if (implementation->stir != NULL) {
+ implementation->stir();
+ }
+#else
+ EM_ASM({
+ if (Module.getRandomValue === undefined) {
+ try {
+ var window_ = 'object' === typeof window ? window : self;
+ var crypto_ = typeof window_.crypto !== 'undefined' ? window_.crypto : window_.msCrypto;
+ var randomValuesStandard = function() {
+ var buf = new Uint32Array(1);
+ crypto_.getRandomValues(buf);
+ return buf[0] >>> 0;
+ };
+ randomValuesStandard();
+ Module.getRandomValue = randomValuesStandard;
+ } catch (e) {
+ try {
+ var crypto = require('crypto');
+ var randomValueNodeJS = function() {
+ var buf = crypto.randomBytes(4);
+ return (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]) >>> 0;
+ };
+ randomValueNodeJS();
+ Module.getRandomValue = randomValueNodeJS;
+ } catch (e) {
+ throw 'No secure random number generator found';
+ }
+ }
+ }
+ });
+#endif
+}
+
+uint32_t
+randombytes_uniform(const uint32_t upper_bound)
+{
+ uint32_t min;
+ uint32_t r;
+
+#ifndef __EMSCRIPTEN__
+ randombytes_init_if_needed();
+ if (implementation->uniform != NULL) {
+ return implementation->uniform(upper_bound);
+ }
+#endif
+ if (upper_bound < 2) {
+ return 0;
+ }
+ min = (1U + ~upper_bound) % upper_bound; /* = 2**32 mod upper_bound */
+ do {
+ r = randombytes_random();
+ } while (r < min);
+ /* r is now clamped to a set whose size mod upper_bound == 0
+ * the worst case (2**31+1) requires ~ 2 attempts */
+
+ return r % upper_bound;
+}
+
+void
+randombytes_buf(void * const buf, const size_t size)
+{
+#ifndef __EMSCRIPTEN__
+ randombytes_init_if_needed();
+ if (size > (size_t) 0U) {
+ implementation->buf(buf, size);
+ }
+#else
+ unsigned char *p = (unsigned char *) buf;
+ size_t i;
+
+ for (i = (size_t) 0U; i < size; i++) {
+ p[i] = (unsigned char) randombytes_random();
+ }
+#endif
+}
+
+void
+randombytes_buf_deterministic(void * const buf, const size_t size,
+ const unsigned char seed[randombytes_SEEDBYTES])
+{
+ static const unsigned char nonce[crypto_stream_chacha20_ietf_NONCEBYTES] = {
+ 'L', 'i', 'b', 's', 'o', 'd', 'i', 'u', 'm', 'D', 'R', 'G'
+ };
+
+ COMPILER_ASSERT(randombytes_SEEDBYTES == crypto_stream_chacha20_ietf_KEYBYTES);
+#if SIZE_MAX > 0x4000000000ULL
+ COMPILER_ASSERT(randombytes_BYTES_MAX <= 0x4000000000ULL);
+ if (size > 0x4000000000ULL) {
+ sodium_misuse();
+ }
+#endif
+ crypto_stream_chacha20_ietf((unsigned char *) buf, (unsigned long long) size,
+ nonce, seed);
+}
+
+size_t
+randombytes_seedbytes(void)
+{
+ return randombytes_SEEDBYTES;
+}
+
+int
+randombytes_close(void)
+{
+ if (implementation != NULL && implementation->close != NULL) {
+ return implementation->close();
+ }
+ return 0;
+}
+
+void
+randombytes(unsigned char * const buf, const unsigned long long buf_len)
+{
+ assert(buf_len <= SIZE_MAX);
+ randombytes_buf(buf, (size_t) buf_len);
+}
diff --git a/libs/libsodium/src/randombytes/salsa20/randombytes_salsa20_random.c b/libs/libsodium/src/randombytes/salsa20/randombytes_salsa20_random.c
new file mode 100644
index 0000000000..79916eabc0
--- /dev/null
+++ b/libs/libsodium/src/randombytes/salsa20/randombytes_salsa20_random.c
@@ -0,0 +1,564 @@
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdlib.h>
+#include <string.h>
+#if !defined(_MSC_VER) && !defined(__BORLANDC__)
+# include <unistd.h>
+#endif
+
+#include <sys/types.h>
+#ifndef _WIN32
+# include <sys/stat.h>
+# include <sys/time.h>
+#endif
+#ifdef __linux__
+# ifdef __dietlibc__
+# define _LINUX_SOURCE
+# else
+# include <sys/syscall.h>
+# endif
+# include <poll.h>
+#endif
+#ifdef HAVE_RDRAND
+# pragma GCC target("rdrnd")
+# include <immintrin.h>
+#endif
+
+#include "core.h"
+#include "crypto_core_salsa20.h"
+#include "crypto_stream_salsa20.h"
+#include "private/common.h"
+#include "randombytes.h"
+#include "randombytes_salsa20_random.h"
+#include "runtime.h"
+#include "utils.h"
+
+#ifdef _WIN32
+# include <windows.h>
+# include <sys/timeb.h>
+# define RtlGenRandom SystemFunction036
+# if defined(__cplusplus)
+extern "C"
+# endif
+BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
+# pragma comment(lib, "advapi32.lib")
+# ifdef __BORLANDC__
+# define _ftime ftime
+# define _timeb timeb
+# endif
+#endif
+
+#define SALSA20_RANDOM_BLOCK_SIZE crypto_core_salsa20_OUTPUTBYTES
+
+#if defined(__OpenBSD__) || defined(__CloudABI__)
+# define HAVE_SAFE_ARC4RANDOM 1
+#endif
+
+#ifndef SSIZE_MAX
+# define SSIZE_MAX (SIZE_MAX / 2 - 1)
+#endif
+#ifndef S_ISNAM
+# ifdef __COMPCERT__
+# define S_ISNAM(X) 1
+# else
+# define S_ISNAM(X) 0
+# endif
+#endif
+
+#ifndef TLS
+# ifdef _WIN32
+# define TLS __declspec(thread)
+# else
+# define TLS
+# endif
+#endif
+
+typedef struct Salsa20RandomGlobal_ {
+ int initialized;
+ int random_data_source_fd;
+ int getrandom_available;
+ int rdrand_available;
+#ifdef HAVE_GETPID
+ pid_t pid;
+#endif
+} Salsa20RandomGlobal;
+
+typedef struct Salsa20Random_ {
+ int initialized;
+ size_t rnd32_outleft;
+ unsigned char key[crypto_stream_salsa20_KEYBYTES];
+ unsigned char rnd32[16U * SALSA20_RANDOM_BLOCK_SIZE];
+ uint64_t nonce;
+} Salsa20Random;
+
+static Salsa20RandomGlobal global = {
+ SODIUM_C99(.initialized =) 0,
+ SODIUM_C99(.random_data_source_fd =) -1
+};
+
+static TLS Salsa20Random stream = {
+ SODIUM_C99(.initialized =) 0,
+ SODIUM_C99(.rnd32_outleft =) (size_t) 0U
+};
+
+
+/*
+ * Get a high-resolution timestamp, as a uint64_t value
+ */
+
+#ifdef _WIN32
+static uint64_t
+sodium_hrtime(void)
+{
+ struct _timeb tb;
+# pragma warning(push)
+# pragma warning(disable: 4996)
+ _ftime(&tb);
+# pragma warning(pop)
+ return ((uint64_t) tb.time) * 1000000U + ((uint64_t) tb.millitm) * 1000U;
+}
+
+#else /* _WIN32 */
+
+static uint64_t
+sodium_hrtime(void)
+{
+ struct timeval tv;
+
+ if (gettimeofday(&tv, NULL) != 0) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+ return ((uint64_t) tv.tv_sec) * 1000000U + (uint64_t) tv.tv_usec;
+}
+#endif
+
+/*
+ * Initialize the entropy source
+ */
+
+#ifdef _WIN32
+
+static void
+randombytes_salsa20_random_init(void)
+{
+ stream.nonce = sodium_hrtime();
+ assert(stream.nonce != (uint64_t) 0U);
+ global.rdrand_available = sodium_runtime_has_rdrand();
+}
+
+#else /* _WIN32 */
+
+static ssize_t
+safe_read(const int fd, void * const buf_, size_t size)
+{
+ unsigned char *buf = (unsigned char *) buf_;
+ ssize_t readnb;
+
+ assert(size > (size_t) 0U);
+ assert(size <= SSIZE_MAX);
+ do {
+ while ((readnb = read(fd, buf, size)) < (ssize_t) 0 &&
+ (errno == EINTR || errno == EAGAIN)); /* LCOV_EXCL_LINE */
+ if (readnb < (ssize_t) 0) {
+ return readnb; /* LCOV_EXCL_LINE */
+ }
+ if (readnb == (ssize_t) 0) {
+ break; /* LCOV_EXCL_LINE */
+ }
+ size -= (size_t) readnb;
+ buf += readnb;
+ } while (size > (ssize_t) 0);
+
+ return (ssize_t) (buf - (unsigned char *) buf_);
+}
+
+# if defined(__linux__) && !defined(USE_BLOCKING_RANDOM) && !defined(NO_BLOCKING_RANDOM_POLL)
+static int
+randombytes_block_on_dev_random(void)
+{
+ struct pollfd pfd;
+ int fd;
+ int pret;
+
+ fd = open("/dev/random", O_RDONLY);
+ if (fd == -1) {
+ return 0;
+ }
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+ do {
+ pret = poll(&pfd, 1, -1);
+ } while (pret < 0 && (errno == EINTR || errno == EAGAIN));
+ if (pret != 1) {
+ (void) close(fd);
+ errno = EIO;
+ return -1;
+ }
+ return close(fd);
+}
+# endif
+
+# ifndef HAVE_SAFE_ARC4RANDOM
+static int
+randombytes_salsa20_random_random_dev_open(void)
+{
+/* LCOV_EXCL_START */
+ struct stat st;
+ static const char *devices[] = {
+# ifndef USE_BLOCKING_RANDOM
+ "/dev/urandom",
+# endif
+ "/dev/random", NULL
+ };
+ const char **device = devices;
+ int fd;
+
+# if defined(__linux__) && !defined(USE_BLOCKING_RANDOM) && !defined(NO_BLOCKING_RANDOM_POLL)
+ if (randombytes_block_on_dev_random() != 0) {
+ return -1;
+ }
+# endif
+ do {
+ fd = open(*device, O_RDONLY);
+ if (fd != -1) {
+ if (fstat(fd, &st) == 0 && (S_ISNAM(st.st_mode) || S_ISCHR(st.st_mode))) {
+# if defined(F_SETFD) && defined(FD_CLOEXEC)
+ (void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+# endif
+ return fd;
+ }
+ (void) close(fd);
+ } else if (errno == EINTR) {
+ continue;
+ }
+ device++;
+ } while (*device != NULL);
+
+ errno = EIO;
+ return -1;
+/* LCOV_EXCL_STOP */
+}
+# endif
+
+# if defined(__dietlibc__) || (defined(SYS_getrandom) && defined(__NR_getrandom))
+static int
+_randombytes_linux_getrandom(void * const buf, const size_t size)
+{
+ int readnb;
+
+ assert(size <= 256U);
+ do {
+# ifdef __dietlibc__
+ readnb = getrandom(buf, size, 0);
+# else
+ readnb = syscall(SYS_getrandom, buf, (int) size, 0);
+# endif
+ } while (readnb < 0 && (errno == EINTR || errno == EAGAIN));
+
+ return (readnb == (int) size) - 1;
+}
+
+static int
+randombytes_linux_getrandom(void * const buf_, size_t size)
+{
+ unsigned char *buf = (unsigned char *) buf_;
+ size_t chunk_size = 256U;
+
+ do {
+ if (size < chunk_size) {
+ chunk_size = size;
+ assert(chunk_size > (size_t) 0U);
+ }
+ if (_randombytes_linux_getrandom(buf, chunk_size) != 0) {
+ return -1;
+ }
+ size -= chunk_size;
+ buf += chunk_size;
+ } while (size > (size_t) 0U);
+
+ return 0;
+}
+# endif
+
+static void
+randombytes_salsa20_random_init(void)
+{
+ const int errno_save = errno;
+
+ stream.nonce = sodium_hrtime();
+ global.rdrand_available = sodium_runtime_has_rdrand();
+ assert(stream.nonce != (uint64_t) 0U);
+
+# ifdef HAVE_SAFE_ARC4RANDOM
+ errno = errno_save;
+# else
+
+# if defined(SYS_getrandom) && defined(__NR_getrandom)
+ {
+ unsigned char fodder[16];
+
+ if (randombytes_linux_getrandom(fodder, sizeof fodder) == 0) {
+ global.getrandom_available = 1;
+ errno = errno_save;
+ return;
+ }
+ global.getrandom_available = 0;
+ }
+# endif /* SYS_getrandom */
+
+ if ((global.random_data_source_fd =
+ randombytes_salsa20_random_random_dev_open()) == -1) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+ errno = errno_save;
+# endif /* HAVE_SAFE_ARC4RANDOM */
+}
+
+#endif /* _WIN32 */
+
+/*
+ * (Re)seed the generator using the entropy source
+ */
+
+static void
+randombytes_salsa20_random_stir(void)
+{
+ unsigned char m0[crypto_stream_salsa20_KEYBYTES +
+ crypto_stream_salsa20_NONCEBYTES];
+
+ memset(stream.rnd32, 0, sizeof stream.rnd32);
+ stream.rnd32_outleft = (size_t) 0U;
+ if (global.initialized == 0) {
+ randombytes_salsa20_random_init();
+ global.initialized = 1;
+ }
+#ifdef HAVE_GETPID
+ global.pid = getpid();
+#endif
+
+#ifndef _WIN32
+
+# ifdef HAVE_SAFE_ARC4RANDOM
+ arc4random_buf(m0, sizeof m0);
+# elif defined(SYS_getrandom) && defined(__NR_getrandom)
+ if (global.getrandom_available != 0) {
+ if (randombytes_linux_getrandom(m0, sizeof m0) != 0) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+ } else if (global.random_data_source_fd == -1 ||
+ safe_read(global.random_data_source_fd, m0,
+ sizeof m0) != (ssize_t) sizeof m0) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+# else
+ if (global.random_data_source_fd == -1 ||
+ safe_read(global.random_data_source_fd, m0,
+ sizeof m0) != (ssize_t) sizeof m0) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+# endif
+
+#else /* _WIN32 */
+ if (! RtlGenRandom((PVOID) m0, (ULONG) sizeof m0)) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+#endif
+
+ crypto_stream_salsa20(stream.key, sizeof stream.key,
+ m0 + crypto_stream_salsa20_KEYBYTES, m0);
+ sodium_memzero(m0, sizeof m0);
+ stream.initialized = 1;
+}
+
+/*
+ * Reseed the generator if it hasn't been initialized yet
+ */
+
+static void
+randombytes_salsa20_random_stir_if_needed(void)
+{
+#ifdef HAVE_GETPID
+ if (stream.initialized == 0) {
+ randombytes_salsa20_random_stir();
+ } else if (global.pid != getpid()) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+#else
+ if (stream.initialized == 0) {
+ randombytes_salsa20_random_stir();
+ }
+#endif
+}
+
+/*
+ * Close the stream, free global resources
+ */
+
+#ifdef _WIN32
+static int
+randombytes_salsa20_random_close(void)
+{
+ int ret = -1;
+
+ if (global.initialized != 0) {
+ global.initialized = 0;
+ ret = 0;
+ }
+ sodium_memzero(&stream, sizeof stream);
+
+ return ret;
+}
+#else
+static int
+randombytes_salsa20_random_close(void)
+{
+ int ret = -1;
+
+ if (global.random_data_source_fd != -1 &&
+ close(global.random_data_source_fd) == 0) {
+ global.random_data_source_fd = -1;
+ global.initialized = 0;
+# ifdef HAVE_GETPID
+ global.pid = (pid_t) 0;
+# endif
+ ret = 0;
+ }
+
+# ifdef HAVE_SAFE_ARC4RANDOM
+ ret = 0;
+# endif
+
+# if defined(SYS_getrandom) && defined(__NR_getrandom)
+ if (global.getrandom_available != 0) {
+ ret = 0;
+ }
+# endif
+
+ sodium_memzero(&stream, sizeof stream);
+
+ return ret;
+}
+#endif
+
+/*
+ * RDRAND is only used to mitigate prediction if a key is compromised
+ */
+
+static void
+randombytes_salsa20_random_xorhwrand(void)
+{
+/* LCOV_EXCL_START */
+#ifdef HAVE_RDRAND
+ unsigned int r;
+
+ if (global.rdrand_available == 0) {
+ return;
+ }
+ (void) _rdrand32_step(&r);
+ * (uint32_t *) (void *)
+ &stream.key[crypto_stream_salsa20_KEYBYTES - 4] ^= (uint32_t) r;
+#endif
+/* LCOV_EXCL_STOP */
+}
+
+/*
+ * XOR the key with another same-length secret
+ */
+
+static inline void
+randombytes_salsa20_random_xorkey(const unsigned char * const mix)
+{
+ unsigned char *key = stream.key;
+ size_t i;
+
+ for (i = (size_t) 0U; i < sizeof stream.key; i++) {
+ key[i] ^= mix[i];
+ }
+}
+
+/*
+ * Put `size` random bytes into `buf` and overwrite the key
+ */
+
+static void
+randombytes_salsa20_random_buf(void * const buf, const size_t size)
+{
+ size_t i;
+ int ret;
+
+ randombytes_salsa20_random_stir_if_needed();
+ COMPILER_ASSERT(sizeof stream.nonce == crypto_stream_salsa20_NONCEBYTES);
+#if defined(ULONG_LONG_MAX) && defined(SIZE_MAX)
+# if SIZE_MAX > ULONG_LONG_MAX
+ /* coverity[result_independent_of_operands] */
+ assert(size <= ULONG_LONG_MAX);
+# endif
+#endif
+ ret = crypto_stream_salsa20((unsigned char *) buf, (unsigned long long) size,
+ (unsigned char *) &stream.nonce, stream.key);
+ assert(ret == 0);
+ for (i = 0U; i < sizeof size; i++) {
+ stream.key[i] ^= ((const unsigned char *) (const void *) &size)[i];
+ }
+ randombytes_salsa20_random_xorhwrand();
+ stream.nonce++;
+ crypto_stream_salsa20_xor(stream.key, stream.key, sizeof stream.key,
+ (unsigned char *) &stream.nonce, stream.key);
+}
+
+/*
+ * Pop a 32-bit value from the random pool
+ *
+ * Overwrite the key after the pool gets refilled.
+ */
+
+static uint32_t
+randombytes_salsa20_random(void)
+{
+ uint32_t val;
+ int ret;
+
+ COMPILER_ASSERT(sizeof stream.rnd32 >= (sizeof stream.key) + (sizeof val));
+ COMPILER_ASSERT(((sizeof stream.rnd32) - (sizeof stream.key))
+ % sizeof val == (size_t) 0U);
+ if (stream.rnd32_outleft <= (size_t) 0U) {
+ randombytes_salsa20_random_stir_if_needed();
+ COMPILER_ASSERT(sizeof stream.nonce == crypto_stream_salsa20_NONCEBYTES);
+ ret = crypto_stream_salsa20((unsigned char *) stream.rnd32,
+ (unsigned long long) sizeof stream.rnd32,
+ (unsigned char *) &stream.nonce,
+ stream.key);
+ assert(ret == 0);
+ stream.rnd32_outleft = (sizeof stream.rnd32) - (sizeof stream.key);
+ randombytes_salsa20_random_xorhwrand();
+ randombytes_salsa20_random_xorkey(&stream.rnd32[stream.rnd32_outleft]);
+ memset(&stream.rnd32[stream.rnd32_outleft], 0, sizeof stream.key);
+ stream.nonce++;
+ }
+ stream.rnd32_outleft -= sizeof val;
+ memcpy(&val, &stream.rnd32[stream.rnd32_outleft], sizeof val);
+ memset(&stream.rnd32[stream.rnd32_outleft], 0, sizeof val);
+
+ return val;
+}
+
+static const char *
+randombytes_salsa20_implementation_name(void)
+{
+ return "salsa20";
+}
+
+struct randombytes_implementation randombytes_salsa20_implementation = {
+ SODIUM_C99(.implementation_name =) randombytes_salsa20_implementation_name,
+ SODIUM_C99(.random =) randombytes_salsa20_random,
+ SODIUM_C99(.stir =) randombytes_salsa20_random_stir,
+ SODIUM_C99(.uniform =) NULL,
+ SODIUM_C99(.buf =) randombytes_salsa20_random_buf,
+ SODIUM_C99(.close =) randombytes_salsa20_random_close
+};
diff --git a/libs/libsodium/src/randombytes/sysrandom/randombytes_sysrandom.c b/libs/libsodium/src/randombytes/sysrandom/randombytes_sysrandom.c
new file mode 100644
index 0000000000..f4dec08f5b
--- /dev/null
+++ b/libs/libsodium/src/randombytes/sysrandom/randombytes_sysrandom.c
@@ -0,0 +1,382 @@
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdint.h>
+#include <string.h>
+#ifndef _WIN32
+# include <unistd.h>
+#endif
+
+#include <stdlib.h>
+#include <sys/types.h>
+#ifndef _WIN32
+# include <sys/stat.h>
+# include <sys/time.h>
+#endif
+#ifdef __linux__
+# ifdef __dietlibc__
+# define _LINUX_SOURCE
+# else
+# include <sys/syscall.h>
+# endif
+# include <poll.h>
+#endif
+
+#include "core.h"
+#include "private/common.h"
+#include "randombytes.h"
+#include "randombytes_sysrandom.h"
+#include "utils.h"
+
+#ifdef _WIN32
+/* `RtlGenRandom` is used over `CryptGenRandom` on Microsoft Windows based systems:
+ * - `CryptGenRandom` requires pulling in `CryptoAPI` which causes unnecessary
+ * memory overhead if this API is not being used for other purposes
+ * - `RtlGenRandom` is thus called directly instead. A detailed explanation
+ * can be found here: https://blogs.msdn.microsoft.com/michael_howard/2005/01/14/cryptographically-secure-random-number-on-windows-without-using-cryptoapi/
+ *
+ * In spite of the disclaimer on the `RtlGenRandom` documentation page that was
+ * written back in the Windows XP days, this function is here to stay. The CRT
+ * function `rand_s()` directly depends on it, so touching it would break many
+ * applications released since Windows XP.
+ *
+ * Also note that Rust, Firefox and BoringSSL (thus, Google Chrome and everything
+ * based on Chromium) also depend on it, and that libsodium allows the RNG to be
+ * replaced without patching nor recompiling the library.
+ */
+# include <windows.h>
+# define RtlGenRandom SystemFunction036
+# if defined(__cplusplus)
+extern "C"
+# endif
+BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
+# pragma comment(lib, "advapi32.lib")
+#endif
+
+#if defined(__OpenBSD__) || defined(__CloudABI__)
+# define HAVE_SAFE_ARC4RANDOM 1
+#endif
+
+#ifndef SSIZE_MAX
+# define SSIZE_MAX (SIZE_MAX / 2 - 1)
+#endif
+
+#ifdef HAVE_SAFE_ARC4RANDOM
+
+static uint32_t
+randombytes_sysrandom(void)
+{
+ return arc4random();
+}
+
+static void
+randombytes_sysrandom_stir(void)
+{
+}
+
+static void
+randombytes_sysrandom_buf(void * const buf, const size_t size)
+{
+ arc4random_buf(buf, size);
+}
+
+static int
+randombytes_sysrandom_close(void)
+{
+ return 0;
+}
+
+#else /* __OpenBSD__ */
+
+typedef struct SysRandom_ {
+ int random_data_source_fd;
+ int initialized;
+ int getrandom_available;
+} SysRandom;
+
+static SysRandom stream = {
+ SODIUM_C99(.random_data_source_fd =) -1,
+ SODIUM_C99(.initialized =) 0,
+ SODIUM_C99(.getrandom_available =) 0
+};
+
+#ifndef _WIN32
+static ssize_t
+safe_read(const int fd, void * const buf_, size_t size)
+{
+ unsigned char *buf = (unsigned char *) buf_;
+ ssize_t readnb;
+
+ assert(size > (size_t) 0U);
+ assert(size <= SSIZE_MAX);
+ do {
+ while ((readnb = read(fd, buf, size)) < (ssize_t) 0 &&
+ (errno == EINTR || errno == EAGAIN)); /* LCOV_EXCL_LINE */
+ if (readnb < (ssize_t) 0) {
+ return readnb; /* LCOV_EXCL_LINE */
+ }
+ if (readnb == (ssize_t) 0) {
+ break; /* LCOV_EXCL_LINE */
+ }
+ size -= (size_t) readnb;
+ buf += readnb;
+ } while (size > (ssize_t) 0);
+
+ return (ssize_t) (buf - (unsigned char *) buf_);
+}
+#endif
+
+#ifndef _WIN32
+# if defined(__linux__) && !defined(USE_BLOCKING_RANDOM) && !defined(NO_BLOCKING_RANDOM_POLL)
+static int
+randombytes_block_on_dev_random(void)
+{
+ struct pollfd pfd;
+ int fd;
+ int pret;
+
+ fd = open("/dev/random", O_RDONLY);
+ if (fd == -1) {
+ return 0;
+ }
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+ do {
+ pret = poll(&pfd, 1, -1);
+ } while (pret < 0 && (errno == EINTR || errno == EAGAIN));
+ if (pret != 1) {
+ (void) close(fd);
+ errno = EIO;
+ return -1;
+ }
+ return close(fd);
+}
+# endif
+
+static int
+randombytes_sysrandom_random_dev_open(void)
+{
+/* LCOV_EXCL_START */
+ struct stat st;
+ static const char *devices[] = {
+# ifndef USE_BLOCKING_RANDOM
+ "/dev/urandom",
+# endif
+ "/dev/random", NULL
+ };
+ const char **device = devices;
+ int fd;
+
+# if defined(__linux__) && !defined(USE_BLOCKING_RANDOM) && !defined(NO_BLOCKING_RANDOM_POLL)
+ if (randombytes_block_on_dev_random() != 0) {
+ return -1;
+ }
+# endif
+ do {
+ fd = open(*device, O_RDONLY);
+ if (fd != -1) {
+ if (fstat(fd, &st) == 0 &&
+# ifdef __COMPCERT__
+ 1
+# elif defined(S_ISNAM)
+ (S_ISNAM(st.st_mode) || S_ISCHR(st.st_mode))
+# else
+ S_ISCHR(st.st_mode)
+# endif
+ ) {
+# if defined(F_SETFD) && defined(FD_CLOEXEC)
+ (void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+# endif
+ return fd;
+ }
+ (void) close(fd);
+ } else if (errno == EINTR) {
+ continue;
+ }
+ device++;
+ } while (*device != NULL);
+
+ errno = EIO;
+ return -1;
+/* LCOV_EXCL_STOP */
+}
+
+# if defined(__dietlibc__) || (defined(SYS_getrandom) && defined(__NR_getrandom))
+static int
+_randombytes_linux_getrandom(void * const buf, const size_t size)
+{
+ int readnb;
+
+ assert(size <= 256U);
+ do {
+# ifdef __dietlibc__
+ readnb = getrandom(buf, size, 0);
+# else
+ readnb = syscall(SYS_getrandom, buf, (int) size, 0);
+# endif
+ } while (readnb < 0 && (errno == EINTR || errno == EAGAIN));
+
+ return (readnb == (int) size) - 1;
+}
+
+static int
+randombytes_linux_getrandom(void * const buf_, size_t size)
+{
+ unsigned char *buf = (unsigned char *) buf_;
+ size_t chunk_size = 256U;
+
+ do {
+ if (size < chunk_size) {
+ chunk_size = size;
+ assert(chunk_size > (size_t) 0U);
+ }
+ if (_randombytes_linux_getrandom(buf, chunk_size) != 0) {
+ return -1;
+ }
+ size -= chunk_size;
+ buf += chunk_size;
+ } while (size > (size_t) 0U);
+
+ return 0;
+}
+# endif
+
+static void
+randombytes_sysrandom_init(void)
+{
+ const int errno_save = errno;
+
+# if defined(SYS_getrandom) && defined(__NR_getrandom)
+ {
+ unsigned char fodder[16];
+
+ if (randombytes_linux_getrandom(fodder, sizeof fodder) == 0) {
+ stream.getrandom_available = 1;
+ errno = errno_save;
+ return;
+ }
+ stream.getrandom_available = 0;
+ }
+# endif
+
+ if ((stream.random_data_source_fd =
+ randombytes_sysrandom_random_dev_open()) == -1) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+ errno = errno_save;
+}
+
+#else /* _WIN32 */
+
+static void
+randombytes_sysrandom_init(void)
+{
+}
+#endif
+
+static void
+randombytes_sysrandom_stir(void)
+{
+ if (stream.initialized == 0) {
+ randombytes_sysrandom_init();
+ stream.initialized = 1;
+ }
+}
+
+static void
+randombytes_sysrandom_stir_if_needed(void)
+{
+ if (stream.initialized == 0) {
+ randombytes_sysrandom_stir();
+ }
+}
+
+static int
+randombytes_sysrandom_close(void)
+{
+ int ret = -1;
+
+#ifndef _WIN32
+ if (stream.random_data_source_fd != -1 &&
+ close(stream.random_data_source_fd) == 0) {
+ stream.random_data_source_fd = -1;
+ stream.initialized = 0;
+ ret = 0;
+ }
+# if defined(SYS_getrandom) && defined(__NR_getrandom)
+ if (stream.getrandom_available != 0) {
+ ret = 0;
+ }
+# endif
+#else /* _WIN32 */
+ if (stream.initialized != 0) {
+ stream.initialized = 0;
+ ret = 0;
+ }
+#endif
+ return ret;
+}
+
+static void
+randombytes_sysrandom_buf(void * const buf, const size_t size)
+{
+ randombytes_sysrandom_stir_if_needed();
+#if defined(ULONG_LONG_MAX) && defined(SIZE_MAX)
+# if SIZE_MAX > ULONG_LONG_MAX
+ /* coverity[result_independent_of_operands] */
+ assert(size <= ULONG_LONG_MAX);
+# endif
+#endif
+#ifndef _WIN32
+# if defined(SYS_getrandom) && defined(__NR_getrandom)
+ if (stream.getrandom_available != 0) {
+ if (randombytes_linux_getrandom(buf, size) != 0) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+ return;
+ }
+# endif
+ if (stream.random_data_source_fd == -1 ||
+ safe_read(stream.random_data_source_fd, buf, size) != (ssize_t) size) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+#else
+ COMPILER_ASSERT(randombytes_BYTES_MAX <= 0xffffffffUL);
+ if (size > (size_t) 0xffffffffUL) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+ if (! RtlGenRandom((PVOID) buf, (ULONG) size)) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+#endif
+}
+
+static uint32_t
+randombytes_sysrandom(void)
+{
+ uint32_t r;
+
+ randombytes_sysrandom_buf(&r, sizeof r);
+
+ return r;
+}
+
+#endif /* __OpenBSD__ */
+
+static const char *
+randombytes_sysrandom_implementation_name(void)
+{
+ return "sysrandom";
+}
+
+struct randombytes_implementation randombytes_sysrandom_implementation = {
+ SODIUM_C99(.implementation_name =) randombytes_sysrandom_implementation_name,
+ SODIUM_C99(.random =) randombytes_sysrandom,
+ SODIUM_C99(.stir =) randombytes_sysrandom_stir,
+ SODIUM_C99(.uniform =) NULL,
+ SODIUM_C99(.buf =) randombytes_sysrandom_buf,
+ SODIUM_C99(.close =) randombytes_sysrandom_close
+};
diff --git a/libs/libsodium/src/sodium/codecs.c b/libs/libsodium/src/sodium/codecs.c
new file mode 100644
index 0000000000..77fa464cc4
--- /dev/null
+++ b/libs/libsodium/src/sodium/codecs.c
@@ -0,0 +1,333 @@
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "core.h"
+#include "utils.h"
+
+/* Derived from original code by CodesInChaos */
+char *
+sodium_bin2hex(char *const hex, const size_t hex_maxlen,
+ const unsigned char *const bin, const size_t bin_len)
+{
+ size_t i = (size_t) 0U;
+ unsigned int x;
+ int b;
+ int c;
+
+ if (bin_len >= SIZE_MAX / 2 || hex_maxlen <= bin_len * 2U) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+ while (i < bin_len) {
+ c = bin[i] & 0xf;
+ b = bin[i] >> 4;
+ x = (unsigned char) (87U + c + (((c - 10U) >> 8) & ~38U)) << 8 |
+ (unsigned char) (87U + b + (((b - 10U) >> 8) & ~38U));
+ hex[i * 2U] = (char) x;
+ x >>= 8;
+ hex[i * 2U + 1U] = (char) x;
+ i++;
+ }
+ hex[i * 2U] = 0U;
+
+ return hex;
+}
+
+int
+sodium_hex2bin(unsigned char *const bin, const size_t bin_maxlen,
+ const char *const hex, const size_t hex_len,
+ const char *const ignore, size_t *const bin_len,
+ const char **const hex_end)
+{
+ size_t bin_pos = (size_t) 0U;
+ size_t hex_pos = (size_t) 0U;
+ int ret = 0;
+ unsigned char c;
+ unsigned char c_acc = 0U;
+ unsigned char c_alpha0, c_alpha;
+ unsigned char c_num0, c_num;
+ unsigned char c_val;
+ unsigned char state = 0U;
+
+ while (hex_pos < hex_len) {
+ c = (unsigned char) hex[hex_pos];
+ c_num = c ^ 48U;
+ c_num0 = (c_num - 10U) >> 8;
+ c_alpha = (c & ~32U) - 55U;
+ c_alpha0 = ((c_alpha - 10U) ^ (c_alpha - 16U)) >> 8;
+ if ((c_num0 | c_alpha0) == 0U) {
+ if (ignore != NULL && state == 0U && strchr(ignore, c) != NULL) {
+ hex_pos++;
+ continue;
+ }
+ break;
+ }
+ c_val = (c_num0 & c_num) | (c_alpha0 & c_alpha);
+ if (bin_pos >= bin_maxlen) {
+ ret = -1;
+ errno = ERANGE;
+ break;
+ }
+ if (state == 0U) {
+ c_acc = c_val * 16U;
+ } else {
+ bin[bin_pos++] = c_acc | c_val;
+ }
+ state = ~state;
+ hex_pos++;
+ }
+ if (state != 0U) {
+ hex_pos--;
+ errno = EINVAL;
+ ret = -1;
+ }
+ if (ret != 0) {
+ bin_pos = (size_t) 0U;
+ }
+ if (hex_end != NULL) {
+ *hex_end = &hex[hex_pos];
+ } else if (hex_pos != hex_len) {
+ errno = EINVAL;
+ ret = -1;
+ }
+ if (bin_len != NULL) {
+ *bin_len = bin_pos;
+ }
+ return ret;
+}
+
+/*
+ * Some macros for constant-time comparisons. These work over values in
+ * the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
+ *
+ * Original code by Thomas Pornin.
+ */
+#define EQ(x, y) \
+ ((((0U - ((unsigned int) (x) ^ (unsigned int) (y))) >> 8) & 0xFF) ^ 0xFF)
+#define GT(x, y) ((((unsigned int) (y) - (unsigned int) (x)) >> 8) & 0xFF)
+#define GE(x, y) (GT(y, x) ^ 0xFF)
+#define LT(x, y) GT(y, x)
+#define LE(x, y) GE(y, x)
+
+static int
+b64_byte_to_char(unsigned int x)
+{
+ return (LT(x, 26) & (x + 'A')) |
+ (GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
+ (GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
+ (EQ(x, 63) & '/');
+}
+
+static unsigned int
+b64_char_to_byte(int c)
+{
+ const unsigned int x =
+ (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
+ (GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) |
+ (GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) |
+ (EQ(c, '/') & 63);
+
+ return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF));
+}
+
+static int
+b64_byte_to_urlsafe_char(unsigned int x)
+{
+ return (LT(x, 26) & (x + 'A')) |
+ (GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
+ (GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '-') |
+ (EQ(x, 63) & '_');
+}
+
+static unsigned int
+b64_urlsafe_char_to_byte(int c)
+{
+ const unsigned x =
+ (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
+ (GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) |
+ (GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '-') & 62) |
+ (EQ(c, '_') & 63);
+
+ return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF));
+}
+
+
+#define VARIANT_NO_PADDING_MASK 0x2U
+#define VARIANT_URLSAFE_MASK 0x4U
+
+static void
+sodium_base64_check_variant(const int variant)
+{
+ if ((((unsigned int) variant) & ~ 0x6U) != 0x1U) {
+ sodium_misuse();
+ }
+}
+
+size_t
+sodium_base64_encoded_len(const size_t bin_len, const int variant)
+{
+ sodium_base64_check_variant(variant);
+
+ return sodium_base64_ENCODED_LEN(bin_len, variant);
+}
+
+char *
+sodium_bin2base64(char * const b64, const size_t b64_maxlen,
+ const unsigned char * const bin, const size_t bin_len,
+ const int variant)
+{
+ size_t acc_len = (size_t) 0;
+ size_t b64_len;
+ size_t b64_pos = (size_t) 0;
+ size_t bin_pos = (size_t) 0;
+ size_t nibbles;
+ size_t remainder;
+ unsigned int acc = 0U;
+
+ sodium_base64_check_variant(variant);
+ nibbles = bin_len / 3;
+ remainder = bin_len - 3 * nibbles;
+ b64_len = nibbles * 4;
+ if (remainder != 0) {
+ if ((((unsigned int) variant) & VARIANT_NO_PADDING_MASK) == 0U) {
+ b64_len += 4;
+ } else {
+ b64_len += 2 + (remainder >> 1);
+ }
+ }
+ if (b64_maxlen <= b64_len) {
+ sodium_misuse();
+ }
+ if ((((unsigned int) variant) & VARIANT_URLSAFE_MASK) != 0U) {
+ while (bin_pos < bin_len) {
+ acc = (acc << 8) + bin[bin_pos++];
+ acc_len += 8;
+ while (acc_len >= 6) {
+ acc_len -= 6;
+ b64[b64_pos++] = (char) b64_byte_to_urlsafe_char((acc >> acc_len) & 0x3F);
+ }
+ }
+ if (acc_len > 0) {
+ b64[b64_pos++] = (char) b64_byte_to_urlsafe_char((acc << (6 - acc_len)) & 0x3F);
+ }
+ } else {
+ while (bin_pos < bin_len) {
+ acc = (acc << 8) + bin[bin_pos++];
+ acc_len += 8;
+ while (acc_len >= 6) {
+ acc_len -= 6;
+ b64[b64_pos++] = (char) b64_byte_to_char((acc >> acc_len) & 0x3F);
+ }
+ }
+ if (acc_len > 0) {
+ b64[b64_pos++] = (char) b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
+ }
+ }
+ assert(b64_pos <= b64_len);
+ while (b64_pos < b64_len) {
+ b64[b64_pos++] = '=';
+ }
+ do {
+ b64[b64_pos++] = 0U;
+ } while (b64_pos < b64_maxlen);
+
+ return b64;
+}
+
+static int
+_sodium_base642bin_skip_padding(const char * const b64, const size_t b64_len,
+ size_t * const b64_pos_p,
+ const char * const ignore, size_t padding_len)
+{
+ int c;
+
+ while (padding_len > 0) {
+ if (*b64_pos_p >= b64_len) {
+ errno = ERANGE;
+ return -1;
+ }
+ c = b64[*b64_pos_p];
+ if (c == '=') {
+ padding_len--;
+ } else if (ignore == NULL || strchr(ignore, c) == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ (*b64_pos_p)++;
+ }
+ return 0;
+}
+
+int
+sodium_base642bin(unsigned char * const bin, const size_t bin_maxlen,
+ const char * const b64, const size_t b64_len,
+ const char * const ignore, size_t * const bin_len,
+ const char ** const b64_end, const int variant)
+{
+ size_t acc_len = (size_t) 0;
+ size_t b64_pos = (size_t) 0;
+ size_t bin_pos = (size_t) 0;
+ int is_urlsafe;
+ int ret = 0;
+ unsigned int acc = 0U;
+ unsigned int d;
+ char c;
+
+ sodium_base64_check_variant(variant);
+ is_urlsafe = ((unsigned int) variant) & VARIANT_URLSAFE_MASK;
+ while (b64_pos < b64_len) {
+ c = b64[b64_pos];
+ if (is_urlsafe) {
+ d = b64_urlsafe_char_to_byte(c);
+ } else {
+ d = b64_char_to_byte(c);
+ }
+ if (d == 0xFF) {
+ if (ignore != NULL && strchr(ignore, c) != NULL) {
+ b64_pos++;
+ continue;
+ }
+ break;
+ }
+ acc = (acc << 6) + d;
+ acc_len += 6;
+ if (acc_len >= 8) {
+ acc_len -= 8;
+ if (bin_pos >= bin_maxlen) {
+ errno = ERANGE;
+ ret = -1;
+ break;
+ }
+ bin[bin_pos++] = (acc >> acc_len) & 0xFF;
+ }
+ b64_pos++;
+ }
+ if (acc_len > 4U || (acc & ((1U << acc_len) - 1U)) != 0U) {
+ ret = -1;
+ } else if (ret == 0 &&
+ (((unsigned int) variant) & VARIANT_NO_PADDING_MASK) == 0U) {
+ ret = _sodium_base642bin_skip_padding(b64, b64_len, &b64_pos, ignore,
+ acc_len / 2);
+ }
+ if (ret != 0) {
+ bin_pos = (size_t) 0U;
+ } else if (ignore != NULL) {
+ while (b64_pos < b64_len && strchr(ignore, b64[b64_pos]) != NULL) {
+ b64_pos++;
+ }
+ }
+ if (b64_end != NULL) {
+ *b64_end = &b64[b64_pos];
+ } else if (b64_pos != b64_len) {
+ errno = EINVAL;
+ ret = -1;
+ }
+ if (bin_len != NULL) {
+ *bin_len = bin_pos;
+ }
+ return ret;
+}
diff --git a/libs/libsodium/src/sodium/core.c b/libs/libsodium/src/sodium/core.c
new file mode 100644
index 0000000000..1ac29d09c8
--- /dev/null
+++ b/libs/libsodium/src/sodium/core.c
@@ -0,0 +1,231 @@
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#ifdef _WIN32
+# include <windows.h>
+#elif defined(HAVE_PTHREAD)
+# include <pthread.h>
+#endif
+
+#include "core.h"
+#include "crypto_generichash.h"
+#include "crypto_onetimeauth.h"
+#include "crypto_scalarmult.h"
+#include "crypto_stream_chacha20.h"
+#include "crypto_stream_salsa20.h"
+#include "randombytes.h"
+#include "runtime.h"
+#include "utils.h"
+#include "private/implementations.h"
+#include "private/mutex.h"
+
+#if !defined(_MSC_VER) && 0
+# warning *** This is unstable, untested, development code.
+# warning It might not compile. It might not work as expected.
+# warning It might be totally insecure.
+# warning Do not use this in production.
+# warning Use releases available at https://download.libsodium.org/libsodium/releases/ instead.
+# warning Alternatively, use the "stable" branch in the git repository.
+#endif
+
+#if !defined(_MSC_VER) && (!defined(CONFIGURED) || CONFIGURED != 1)
+# warning *** The library is being compiled using an undocumented method.
+# warning This is not supported. It has not been tested, it might not
+# warning work as expected, and performance is likely to be suboptimal.
+#endif
+
+static volatile int initialized;
+static volatile int locked;
+
+int
+sodium_init(void)
+{
+ if (sodium_crit_enter() != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ if (initialized != 0) {
+ if (sodium_crit_leave() != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return 1;
+ }
+ _sodium_runtime_get_cpu_features();
+ randombytes_stir();
+ _sodium_alloc_init();
+ _crypto_pwhash_argon2_pick_best_implementation();
+ _crypto_generichash_blake2b_pick_best_implementation();
+ _crypto_onetimeauth_poly1305_pick_best_implementation();
+ _crypto_scalarmult_curve25519_pick_best_implementation();
+ _crypto_stream_chacha20_pick_best_implementation();
+ _crypto_stream_salsa20_pick_best_implementation();
+ initialized = 1;
+ if (sodium_crit_leave() != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return 0;
+}
+
+#ifdef _WIN32
+
+static CRITICAL_SECTION _sodium_lock;
+static volatile LONG _sodium_lock_initialized;
+
+int
+_sodium_crit_init(void)
+{
+ LONG status = 0L;
+
+ while ((status = InterlockedCompareExchange(&_sodium_lock_initialized,
+ 1L, 0L)) == 1L) {
+ Sleep(0);
+ }
+
+ switch (status) {
+ case 0L:
+ InitializeCriticalSection(&_sodium_lock);
+ return InterlockedExchange(&_sodium_lock_initialized, 2L) == 1L ? 0 : -1;
+ case 2L:
+ return 0;
+ default: /* should never be reached */
+ return -1;
+ }
+}
+
+int
+sodium_crit_enter(void)
+{
+ if (_sodium_crit_init() != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ EnterCriticalSection(&_sodium_lock);
+ assert(locked == 0);
+ locked = 1;
+
+ return 0;
+}
+
+int
+sodium_crit_leave(void)
+{
+ if (locked == 0) {
+# ifdef EPERM
+ errno = EPERM;
+# endif
+ return -1;
+ }
+ locked = 0;
+ LeaveCriticalSection(&_sodium_lock);
+
+ return 0;
+}
+
+#elif defined(HAVE_PTHREAD) && !defined(__EMSCRIPTEN__)
+
+static pthread_mutex_t _sodium_lock = PTHREAD_MUTEX_INITIALIZER;
+
+int
+sodium_crit_enter(void)
+{
+ int ret;
+
+ if ((ret = pthread_mutex_lock(&_sodium_lock)) == 0) {
+ assert(locked == 0);
+ locked = 1;
+ }
+ return ret;
+}
+
+int
+sodium_crit_leave(void)
+{
+ int ret;
+
+ if (locked == 0) {
+# ifdef EPERM
+ errno = EPERM;
+# endif
+ return -1;
+ }
+ locked = 0;
+
+ return pthread_mutex_unlock(&_sodium_lock);
+}
+
+#elif defined(HAVE_ATOMIC_OPS) && !defined(__EMSCRIPTEN__) && !defined(__native_client__)
+
+static volatile int _sodium_lock;
+
+int
+sodium_crit_enter(void)
+{
+# ifdef HAVE_NANOSLEEP
+ struct timespec q;
+ memset(&q, 0, sizeof q);
+# endif
+ while (__sync_lock_test_and_set(&_sodium_lock, 1) != 0) {
+# ifdef HAVE_NANOSLEEP
+ (void) nanosleep(&q, NULL);
+# elif defined(__x86_64__) || defined(__i386__)
+ __asm__ __volatile__ ("pause");
+# endif
+ }
+ return 0;
+}
+
+int
+sodium_crit_leave(void)
+{
+ __sync_lock_release(&_sodium_lock);
+
+ return 0;
+}
+
+#else
+
+int
+sodium_crit_enter(void)
+{
+ return 0;
+}
+
+int
+sodium_crit_leave(void)
+{
+ return 0;
+}
+
+#endif
+
+static void (*_misuse_handler)(void);
+
+void
+sodium_misuse(void)
+{
+ void (*handler)(void);
+
+ (void) sodium_crit_leave();
+ if (sodium_crit_enter() == 0) {
+ handler = _misuse_handler;
+ if (handler != NULL) {
+ handler();
+ }
+ }
+/* LCOV_EXCL_START */
+ abort();
+}
+/* LCOV_EXCL_STOP */
+
+int
+sodium_set_misuse_handler(void (*handler)(void))
+{
+ if (sodium_crit_enter() != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ _misuse_handler = handler;
+ if (sodium_crit_leave() != 0) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ return 0;
+}
diff --git a/libs/libsodium/src/sodium/runtime.c b/libs/libsodium/src/sodium/runtime.c
new file mode 100644
index 0000000000..ba1000f4dc
--- /dev/null
+++ b/libs/libsodium/src/sodium/runtime.c
@@ -0,0 +1,286 @@
+#include <stddef.h>
+#include <stdint.h>
+#ifdef HAVE_ANDROID_GETCPUFEATURES
+# include <cpu-features.h>
+#endif
+
+#include "private/common.h"
+#include "runtime.h"
+
+typedef struct CPUFeatures_ {
+ int initialized;
+ int has_neon;
+ int has_sse2;
+ int has_sse3;
+ int has_ssse3;
+ int has_sse41;
+ int has_avx;
+ int has_avx2;
+ int has_avx512f;
+ int has_pclmul;
+ int has_aesni;
+ int has_rdrand;
+} CPUFeatures;
+
+static CPUFeatures _cpu_features;
+
+#define CPUID_EBX_AVX2 0x00000020
+#define CPUID_EBX_AVX512F 0x00010000
+
+#define CPUID_ECX_SSE3 0x00000001
+#define CPUID_ECX_PCLMUL 0x00000002
+#define CPUID_ECX_SSSE3 0x00000200
+#define CPUID_ECX_SSE41 0x00080000
+#define CPUID_ECX_AESNI 0x02000000
+#define CPUID_ECX_XSAVE 0x04000000
+#define CPUID_ECX_OSXSAVE 0x08000000
+#define CPUID_ECX_AVX 0x10000000
+#define CPUID_ECX_RDRAND 0x40000000
+
+#define CPUID_EDX_SSE2 0x04000000
+
+#define XCR0_SSE 0x00000002
+#define XCR0_AVX 0x00000004
+
+static int
+_sodium_runtime_arm_cpu_features(CPUFeatures * const cpu_features)
+{
+#ifndef __arm__
+ cpu_features->has_neon = 0;
+ return -1;
+#else
+# ifdef __APPLE__
+# ifdef __ARM_NEON__
+ cpu_features->has_neon = 1;
+# else
+ cpu_features->has_neon = 0;
+# endif
+# elif defined(HAVE_ANDROID_GETCPUFEATURES) && \
+ defined(ANDROID_CPU_ARM_FEATURE_NEON)
+ cpu_features->has_neon =
+ (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0x0;
+# else
+ cpu_features->has_neon = 0;
+# endif
+ return 0;
+#endif
+}
+
+static void
+_cpuid(unsigned int cpu_info[4U], const unsigned int cpu_info_type)
+{
+#if defined(_MSC_VER) && \
+ (defined(_M_X64) || defined(_M_AMD64) || defined(_M_IX86))
+ __cpuid((int *) cpu_info, cpu_info_type);
+#elif defined(HAVE_CPUID)
+ cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0;
+# ifdef __i386__
+ __asm__ __volatile__(
+ "pushfl; pushfl; "
+ "popl %0; "
+ "movl %0, %1; xorl %2, %0; "
+ "pushl %0; "
+ "popfl; pushfl; popl %0; popfl"
+ : "=&r"(cpu_info[0]), "=&r"(cpu_info[1])
+ : "i"(0x200000));
+ if (((cpu_info[0] ^ cpu_info[1]) & 0x200000) == 0x0) {
+ return; /* LCOV_EXCL_LINE */
+ }
+# endif
+# ifdef __i386__
+ __asm__ __volatile__("xchgl %%ebx, %k1; cpuid; xchgl %%ebx, %k1"
+ : "=a"(cpu_info[0]), "=&r"(cpu_info[1]),
+ "=c"(cpu_info[2]), "=d"(cpu_info[3])
+ : "0"(cpu_info_type), "2"(0U));
+# elif defined(__x86_64__)
+ __asm__ __volatile__("xchgq %%rbx, %q1; cpuid; xchgq %%rbx, %q1"
+ : "=a"(cpu_info[0]), "=&r"(cpu_info[1]),
+ "=c"(cpu_info[2]), "=d"(cpu_info[3])
+ : "0"(cpu_info_type), "2"(0U));
+# else
+ __asm__ __volatile__("cpuid"
+ : "=a"(cpu_info[0]), "=b"(cpu_info[1]),
+ "=c"(cpu_info[2]), "=d"(cpu_info[3])
+ : "0"(cpu_info_type), "2"(0U));
+# endif
+#else
+ (void) cpu_info_type;
+ cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0;
+#endif
+}
+
+static int
+_sodium_runtime_intel_cpu_features(CPUFeatures * const cpu_features)
+{
+ unsigned int cpu_info[4];
+ unsigned int id;
+
+ _cpuid(cpu_info, 0x0);
+ if ((id = cpu_info[0]) == 0U) {
+ return -1; /* LCOV_EXCL_LINE */
+ }
+ _cpuid(cpu_info, 0x00000001);
+#ifdef HAVE_EMMINTRIN_H
+ cpu_features->has_sse2 = ((cpu_info[3] & CPUID_EDX_SSE2) != 0x0);
+#else
+ cpu_features->has_sse2 = 0;
+#endif
+
+#ifdef HAVE_PMMINTRIN_H
+ cpu_features->has_sse3 = ((cpu_info[2] & CPUID_ECX_SSE3) != 0x0);
+#else
+ cpu_features->has_sse3 = 0;
+#endif
+
+#ifdef HAVE_TMMINTRIN_H
+ cpu_features->has_ssse3 = ((cpu_info[2] & CPUID_ECX_SSSE3) != 0x0);
+#else
+ cpu_features->has_ssse3 = 0;
+#endif
+
+#ifdef HAVE_SMMINTRIN_H
+ cpu_features->has_sse41 = ((cpu_info[2] & CPUID_ECX_SSE41) != 0x0);
+#else
+ cpu_features->has_sse41 = 0;
+#endif
+
+ cpu_features->has_avx = 0;
+#ifdef HAVE_AVXINTRIN_H
+ if ((cpu_info[2] & (CPUID_ECX_AVX | CPUID_ECX_XSAVE | CPUID_ECX_OSXSAVE)) ==
+ (CPUID_ECX_AVX | CPUID_ECX_XSAVE | CPUID_ECX_OSXSAVE)) {
+ uint32_t xcr0 = 0U;
+# if defined(HAVE__XGETBV) || \
+ (defined(_MSC_VER) && defined(_XCR_XFEATURE_ENABLED_MASK) && _MSC_FULL_VER >= 160040219)
+ xcr0 = (uint32_t) _xgetbv(0);
+# elif defined(_MSC_VER) && defined(_M_IX86)
+ __asm {
+ xor ecx, ecx
+ _asm _emit 0x0f _asm _emit 0x01 _asm _emit 0xd0
+ mov xcr0, eax
+ }
+# elif defined(HAVE_AVX_ASM)
+ __asm__ __volatile__(".byte 0x0f, 0x01, 0xd0" /* XGETBV */
+ : "=a"(xcr0)
+ : "c"((uint32_t) 0U)
+ : "%edx");
+# endif
+ if ((xcr0 & (XCR0_SSE | XCR0_AVX)) == (XCR0_SSE | XCR0_AVX)) {
+ cpu_features->has_avx = 1;
+ }
+ }
+#endif
+
+ cpu_features->has_avx2 = 0;
+#ifdef HAVE_AVX2INTRIN_H
+ if (cpu_features->has_avx) {
+ unsigned int cpu_info7[4];
+
+ _cpuid(cpu_info7, 0x00000007);
+ cpu_features->has_avx2 = ((cpu_info7[1] & CPUID_EBX_AVX2) != 0x0);
+ }
+#endif
+
+ cpu_features->has_avx512f = 0;
+#ifdef HAVE_AVX512FINTRIN_H
+ if (cpu_features->has_avx2) {
+ unsigned int cpu_info7[4];
+
+ _cpuid(cpu_info7, 0x00000007);
+ cpu_features->has_avx512f = ((cpu_info7[1] & CPUID_EBX_AVX512F) != 0x0);
+ }
+#endif
+
+#ifdef HAVE_WMMINTRIN_H
+ cpu_features->has_pclmul = ((cpu_info[2] & CPUID_ECX_PCLMUL) != 0x0);
+ cpu_features->has_aesni = ((cpu_info[2] & CPUID_ECX_AESNI) != 0x0);
+#else
+ cpu_features->has_pclmul = 0;
+ cpu_features->has_aesni = 0;
+#endif
+
+#ifdef HAVE_RDRAND
+ cpu_features->has_rdrand = ((cpu_info[2] & CPUID_ECX_RDRAND) != 0x0);
+#else
+ cpu_features->has_rdrand = 0;
+#endif
+
+ return 0;
+}
+
+int
+_sodium_runtime_get_cpu_features(void)
+{
+ int ret = -1;
+
+ ret &= _sodium_runtime_arm_cpu_features(&_cpu_features);
+ ret &= _sodium_runtime_intel_cpu_features(&_cpu_features);
+ _cpu_features.initialized = 1;
+
+ return ret;
+}
+
+int
+sodium_runtime_has_neon(void)
+{
+ return _cpu_features.has_neon;
+}
+
+int
+sodium_runtime_has_sse2(void)
+{
+ return _cpu_features.has_sse2;
+}
+
+int
+sodium_runtime_has_sse3(void)
+{
+ return _cpu_features.has_sse3;
+}
+
+int
+sodium_runtime_has_ssse3(void)
+{
+ return _cpu_features.has_ssse3;
+}
+
+int
+sodium_runtime_has_sse41(void)
+{
+ return _cpu_features.has_sse41;
+}
+
+int
+sodium_runtime_has_avx(void)
+{
+ return _cpu_features.has_avx;
+}
+
+int
+sodium_runtime_has_avx2(void)
+{
+ return _cpu_features.has_avx2;
+}
+
+int
+sodium_runtime_has_avx512f(void)
+{
+ return _cpu_features.has_avx512f;
+}
+
+int
+sodium_runtime_has_pclmul(void)
+{
+ return _cpu_features.has_pclmul;
+}
+
+int
+sodium_runtime_has_aesni(void)
+{
+ return _cpu_features.has_aesni;
+}
+
+int
+sodium_runtime_has_rdrand(void)
+{
+ return _cpu_features.has_rdrand;
+}
diff --git a/libs/libsodium/src/sodium/utils.c b/libs/libsodium/src/sodium/utils.c
new file mode 100644
index 0000000000..85aad29200
--- /dev/null
+++ b/libs/libsodium/src/sodium/utils.c
@@ -0,0 +1,737 @@
+#ifndef __STDC_WANT_LIB_EXT1__
+# define __STDC_WANT_LIB_EXT1__ 1
+#endif
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+
+#ifdef _WIN32
+# include <windows.h>
+# include <wincrypt.h>
+#else
+# include <unistd.h>
+#endif
+
+#ifndef HAVE_C_VARARRAYS
+# ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+# elif !defined(alloca)
+# if defined(__GNUC__)
+# define alloca __builtin_alloca
+# elif defined _AIX
+# define alloca __alloca
+# elif defined _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# include <stddef.h>
+# ifdef __cplusplus
+extern "C"
+# endif
+void *alloca (size_t);
+# endif
+# endif
+#endif
+
+#include "core.h"
+#include "randombytes.h"
+#include "utils.h"
+
+#ifndef ENOSYS
+# define ENOSYS ENXIO
+#endif
+
+#if defined(_WIN32) && \
+ (!defined(WINAPI_FAMILY) || WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)
+# define WINAPI_DESKTOP
+#endif
+
+#define CANARY_SIZE 16U
+#define GARBAGE_VALUE 0xdb
+
+#ifndef MAP_NOCORE
+# define MAP_NOCORE 0
+#endif
+#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
+# define MAP_ANON MAP_ANONYMOUS
+#endif
+#if defined(WINAPI_DESKTOP) || (defined(MAP_ANON) && defined(HAVE_MMAP)) || \
+ defined(HAVE_POSIX_MEMALIGN)
+# define HAVE_ALIGNED_MALLOC
+#endif
+#if defined(HAVE_MPROTECT) && \
+ !(defined(PROT_NONE) && defined(PROT_READ) && defined(PROT_WRITE))
+# undef HAVE_MPROTECT
+#endif
+#if defined(HAVE_ALIGNED_MALLOC) && \
+ (defined(WINAPI_DESKTOP) || defined(HAVE_MPROTECT))
+# define HAVE_PAGE_PROTECTION
+#endif
+#if !defined(MADV_DODUMP) && defined(MADV_CORE)
+# define MADV_DODUMP MADV_CORE
+# define MADV_DONTDUMP MADV_NOCORE
+#endif
+
+static size_t page_size;
+static unsigned char canary[CANARY_SIZE];
+
+/* LCOV_EXCL_START */
+#ifdef HAVE_WEAK_SYMBOLS
+__attribute__((weak)) void
+_sodium_dummy_symbol_to_prevent_memzero_lto(void *const pnt,
+ const size_t len);
+__attribute__((weak)) void
+_sodium_dummy_symbol_to_prevent_memzero_lto(void *const pnt,
+ const size_t len)
+{
+ (void) pnt; /* LCOV_EXCL_LINE */
+ (void) len; /* LCOV_EXCL_LINE */
+}
+#endif
+/* LCOV_EXCL_STOP */
+
+void
+sodium_memzero(void *const pnt, const size_t len)
+{
+#ifdef _WIN32
+ SecureZeroMemory(pnt, len);
+#elif defined(HAVE_MEMSET_S)
+ if (len > 0U && memset_s(pnt, (rsize_t) len, 0, (rsize_t) len) != 0) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+#elif defined(HAVE_EXPLICIT_BZERO)
+ explicit_bzero(pnt, len);
+#elif HAVE_WEAK_SYMBOLS
+ memset(pnt, 0, len);
+ _sodium_dummy_symbol_to_prevent_memzero_lto(pnt, len);
+# ifdef HAVE_AMD64_ASM
+ __asm__ __volatile__ ("" : : "p"(pnt));
+# endif
+#else
+ volatile unsigned char *volatile pnt_ =
+ (volatile unsigned char *volatile) pnt;
+ size_t i = (size_t) 0U;
+
+ while (i < len) {
+ pnt_[i++] = 0U;
+ }
+#endif
+}
+
+void
+sodium_stackzero(const size_t len)
+{
+#ifdef HAVE_C_VARARRAYS
+ unsigned char fodder[len];
+ sodium_memzero(fodder, len);
+#elif HAVE_ALLOCA
+ sodium_memzero(alloca(len), len);
+#endif
+}
+
+#ifdef HAVE_WEAK_SYMBOLS
+__attribute__((weak)) void
+_sodium_dummy_symbol_to_prevent_memcmp_lto(const unsigned char *b1,
+ const unsigned char *b2,
+ const size_t len);
+__attribute__((weak)) void
+_sodium_dummy_symbol_to_prevent_memcmp_lto(const unsigned char *b1,
+ const unsigned char *b2,
+ const size_t len)
+{
+ (void) b1;
+ (void) b2;
+ (void) len;
+}
+#endif
+
+int
+sodium_memcmp(const void *const b1_, const void *const b2_, size_t len)
+{
+#ifdef HAVE_WEAK_SYMBOLS
+ const unsigned char *b1 = (const unsigned char *) b1_;
+ const unsigned char *b2 = (const unsigned char *) b2_;
+#else
+ const volatile unsigned char *volatile b1 =
+ (const volatile unsigned char *volatile) b1_;
+ const volatile unsigned char *volatile b2 =
+ (const volatile unsigned char *volatile) b2_;
+#endif
+ size_t i;
+ volatile unsigned char d = 0U;
+
+#if HAVE_WEAK_SYMBOLS
+ _sodium_dummy_symbol_to_prevent_memcmp_lto(b1, b2, len);
+#endif
+ for (i = 0U; i < len; i++) {
+ d |= b1[i] ^ b2[i];
+ }
+ return (1 & ((d - 1) >> 8)) - 1;
+}
+
+#ifdef HAVE_WEAK_SYMBOLS
+__attribute__((weak)) void
+_sodium_dummy_symbol_to_prevent_compare_lto(const unsigned char *b1,
+ const unsigned char *b2,
+ const size_t len);
+__attribute__((weak)) void
+_sodium_dummy_symbol_to_prevent_compare_lto(const unsigned char *b1,
+ const unsigned char *b2,
+ const size_t len)
+{
+ (void) b1;
+ (void) b2;
+ (void) len;
+}
+#endif
+
+int
+sodium_compare(const unsigned char *b1_, const unsigned char *b2_, size_t len)
+{
+#ifdef HAVE_WEAK_SYMBOLS
+ const unsigned char *b1 = b1_;
+ const unsigned char *b2 = b2_;
+#else
+ const volatile unsigned char *volatile b1 =
+ (const volatile unsigned char *volatile) b1_;
+ const volatile unsigned char *volatile b2 =
+ (const volatile unsigned char *volatile) b2_;
+#endif
+ size_t i;
+ volatile unsigned char gt = 0U;
+ volatile unsigned char eq = 1U;
+ uint16_t x1, x2;
+
+#if HAVE_WEAK_SYMBOLS
+ _sodium_dummy_symbol_to_prevent_compare_lto(b1, b2, len);
+#endif
+ i = len;
+ while (i != 0U) {
+ i--;
+ x1 = b1[i];
+ x2 = b2[i];
+ gt |= ((x2 - x1) >> 8) & eq;
+ eq &= ((x2 ^ x1) - 1) >> 8;
+ }
+ return (int) (gt + gt + eq) - 1;
+}
+
+int
+sodium_is_zero(const unsigned char *n, const size_t nlen)
+{
+ size_t i;
+ volatile unsigned char d = 0U;
+
+ for (i = 0U; i < nlen; i++) {
+ d |= n[i];
+ }
+ return 1 & ((d - 1) >> 8);
+}
+
+void
+sodium_increment(unsigned char *n, const size_t nlen)
+{
+ size_t i = 0U;
+ uint_fast16_t c = 1U;
+
+#ifdef HAVE_AMD64_ASM
+ uint64_t t64, t64_2;
+ uint32_t t32;
+
+ if (nlen == 12U) {
+ __asm__ __volatile__(
+ "xorq %[t64], %[t64] \n"
+ "xorl %[t32], %[t32] \n"
+ "stc \n"
+ "adcq %[t64], (%[out]) \n"
+ "adcl %[t32], 8(%[out]) \n"
+ : [t64] "=&r"(t64), [t32] "=&r"(t32)
+ : [out] "D"(n)
+ : "memory", "flags", "cc");
+ return;
+ } else if (nlen == 24U) {
+ __asm__ __volatile__(
+ "movq $1, %[t64] \n"
+ "xorq %[t64_2], %[t64_2] \n"
+ "addq %[t64], (%[out]) \n"
+ "adcq %[t64_2], 8(%[out]) \n"
+ "adcq %[t64_2], 16(%[out]) \n"
+ : [t64] "=&r"(t64), [t64_2] "=&r"(t64_2)
+ : [out] "D"(n)
+ : "memory", "flags", "cc");
+ return;
+ } else if (nlen == 8U) {
+ __asm__ __volatile__("incq (%[out]) \n"
+ :
+ : [out] "D"(n)
+ : "memory", "flags", "cc");
+ return;
+ }
+#endif
+ for (; i < nlen; i++) {
+ c += (uint_fast16_t) n[i];
+ n[i] = (unsigned char) c;
+ c >>= 8;
+ }
+}
+
+void
+sodium_add(unsigned char *a, const unsigned char *b, const size_t len)
+{
+ size_t i = 0U;
+ uint_fast16_t c = 0U;
+
+#ifdef HAVE_AMD64_ASM
+ uint64_t t64, t64_2, t64_3;
+ uint32_t t32;
+
+ if (len == 12U) {
+ __asm__ __volatile__(
+ "movq (%[in]), %[t64] \n"
+ "movl 8(%[in]), %[t32] \n"
+ "addq %[t64], (%[out]) \n"
+ "adcl %[t32], 8(%[out]) \n"
+ : [t64] "=&r"(t64), [t32] "=&r"(t32)
+ : [in] "S"(b), [out] "D"(a)
+ : "memory", "flags", "cc");
+ return;
+ } else if (len == 24U) {
+ __asm__ __volatile__(
+ "movq (%[in]), %[t64] \n"
+ "movq 8(%[in]), %[t64_2] \n"
+ "movq 16(%[in]), %[t64_3] \n"
+ "addq %[t64], (%[out]) \n"
+ "adcq %[t64_2], 8(%[out]) \n"
+ "adcq %[t64_3], 16(%[out]) \n"
+ : [t64] "=&r"(t64), [t64_2] "=&r"(t64_2), [t64_3] "=&r"(t64_3)
+ : [in] "S"(b), [out] "D"(a)
+ : "memory", "flags", "cc");
+ return;
+ } else if (len == 8U) {
+ __asm__ __volatile__(
+ "movq (%[in]), %[t64] \n"
+ "addq %[t64], (%[out]) \n"
+ : [t64] "=&r"(t64)
+ : [in] "S"(b), [out] "D"(a)
+ : "memory", "flags", "cc");
+ return;
+ }
+#endif
+ for (; i < len; i++) {
+ c += (uint_fast16_t) a[i] + (uint_fast16_t) b[i];
+ a[i] = (unsigned char) c;
+ c >>= 8;
+ }
+}
+
+int
+_sodium_alloc_init(void)
+{
+#ifdef HAVE_ALIGNED_MALLOC
+# if defined(_SC_PAGESIZE)
+ long page_size_ = sysconf(_SC_PAGESIZE);
+ if (page_size_ > 0L) {
+ page_size = (size_t) page_size_;
+ }
+# elif defined(WINAPI_DESKTOP)
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ page_size = (size_t) si.dwPageSize;
+# endif
+ if (page_size < CANARY_SIZE || page_size < sizeof(size_t)) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+#endif
+ randombytes_buf(canary, sizeof canary);
+
+ return 0;
+}
+
+int
+sodium_mlock(void *const addr, const size_t len)
+{
+#if defined(MADV_DONTDUMP) && defined(HAVE_MADVISE)
+ (void) madvise(addr, len, MADV_DONTDUMP);
+#endif
+#ifdef HAVE_MLOCK
+ return mlock(addr, len);
+#elif defined(WINAPI_DESKTOP)
+ return -(VirtualLock(addr, len) == 0);
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+int
+sodium_munlock(void *const addr, const size_t len)
+{
+ sodium_memzero(addr, len);
+#if defined(MADV_DODUMP) && defined(HAVE_MADVISE)
+ (void) madvise(addr, len, MADV_DODUMP);
+#endif
+#ifdef HAVE_MLOCK
+ return munlock(addr, len);
+#elif defined(WINAPI_DESKTOP)
+ return -(VirtualUnlock(addr, len) == 0);
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+static int
+_mprotect_noaccess(void *ptr, size_t size)
+{
+#ifdef HAVE_MPROTECT
+ return mprotect(ptr, size, PROT_NONE);
+#elif defined(WINAPI_DESKTOP)
+ DWORD old;
+ return -(VirtualProtect(ptr, size, PAGE_NOACCESS, &old) == 0);
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+static int
+_mprotect_readonly(void *ptr, size_t size)
+{
+#ifdef HAVE_MPROTECT
+ return mprotect(ptr, size, PROT_READ);
+#elif defined(WINAPI_DESKTOP)
+ DWORD old;
+ return -(VirtualProtect(ptr, size, PAGE_READONLY, &old) == 0);
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+static int
+_mprotect_readwrite(void *ptr, size_t size)
+{
+#ifdef HAVE_MPROTECT
+ return mprotect(ptr, size, PROT_READ | PROT_WRITE);
+#elif defined(WINAPI_DESKTOP)
+ DWORD old;
+ return -(VirtualProtect(ptr, size, PAGE_READWRITE, &old) == 0);
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+#ifdef HAVE_ALIGNED_MALLOC
+
+__attribute__((noreturn)) static void
+_out_of_bounds(void)
+{
+# ifdef SIGSEGV
+ raise(SIGSEGV);
+# elif defined(SIGKILL)
+ raise(SIGKILL);
+# endif
+ abort(); /* not something we want any higher-level API to catch */
+} /* LCOV_EXCL_LINE */
+
+static inline size_t
+_page_round(const size_t size)
+{
+ const size_t page_mask = page_size - 1U;
+
+ return (size + page_mask) & ~page_mask;
+}
+
+static __attribute__((malloc)) unsigned char *
+_alloc_aligned(const size_t size)
+{
+ void *ptr;
+
+# if defined(MAP_ANON) && defined(HAVE_MMAP)
+ if ((ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE | MAP_NOCORE, -1, 0)) ==
+ MAP_FAILED) {
+ ptr = NULL; /* LCOV_EXCL_LINE */
+ } /* LCOV_EXCL_LINE */
+# elif defined(HAVE_POSIX_MEMALIGN)
+ if (posix_memalign(&ptr, page_size, size) != 0) {
+ ptr = NULL; /* LCOV_EXCL_LINE */
+ } /* LCOV_EXCL_LINE */
+# elif defined(WINAPI_DESKTOP)
+ ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+# else
+# error Bug
+# endif
+ return (unsigned char *) ptr;
+}
+
+static void
+_free_aligned(unsigned char *const ptr, const size_t size)
+{
+# if defined(MAP_ANON) && defined(HAVE_MMAP)
+ (void) munmap(ptr, size);
+# elif defined(HAVE_POSIX_MEMALIGN)
+ free(ptr);
+# elif defined(WINAPI_DESKTOP)
+ VirtualFree(ptr, 0U, MEM_RELEASE);
+# else
+# error Bug
+#endif
+}
+
+static unsigned char *
+_unprotected_ptr_from_user_ptr(void *const ptr)
+{
+ uintptr_t unprotected_ptr_u;
+ unsigned char *canary_ptr;
+ size_t page_mask;
+
+ canary_ptr = ((unsigned char *) ptr) - sizeof canary;
+ page_mask = page_size - 1U;
+ unprotected_ptr_u = ((uintptr_t) canary_ptr & (uintptr_t) ~page_mask);
+ if (unprotected_ptr_u <= page_size * 2U) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+ return (unsigned char *) unprotected_ptr_u;
+}
+
+#endif /* HAVE_ALIGNED_MALLOC */
+
+#ifndef HAVE_ALIGNED_MALLOC
+static __attribute__((malloc)) void *
+_sodium_malloc(const size_t size)
+{
+ return malloc(size > (size_t) 0U ? size : (size_t) 1U);
+}
+#else
+static __attribute__((malloc)) void *
+_sodium_malloc(const size_t size)
+{
+ void *user_ptr;
+ unsigned char *base_ptr;
+ unsigned char *canary_ptr;
+ unsigned char *unprotected_ptr;
+ size_t size_with_canary;
+ size_t total_size;
+ size_t unprotected_size;
+
+ if (size >= (size_t) SIZE_MAX - page_size * 4U) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ if (page_size <= sizeof canary || page_size < sizeof unprotected_size) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+ size_with_canary = (sizeof canary) + size;
+ unprotected_size = _page_round(size_with_canary);
+ total_size = page_size + page_size + unprotected_size + page_size;
+ if ((base_ptr = _alloc_aligned(total_size)) == NULL) {
+ return NULL; /* LCOV_EXCL_LINE */
+ }
+ unprotected_ptr = base_ptr + page_size * 2U;
+ _mprotect_noaccess(base_ptr + page_size, page_size);
+# ifndef HAVE_PAGE_PROTECTION
+ memcpy(unprotected_ptr + unprotected_size, canary, sizeof canary);
+# endif
+ _mprotect_noaccess(unprotected_ptr + unprotected_size, page_size);
+ sodium_mlock(unprotected_ptr, unprotected_size);
+ canary_ptr =
+ unprotected_ptr + _page_round(size_with_canary) - size_with_canary;
+ user_ptr = canary_ptr + sizeof canary;
+ memcpy(canary_ptr, canary, sizeof canary);
+ memcpy(base_ptr, &unprotected_size, sizeof unprotected_size);
+ _mprotect_readonly(base_ptr, page_size);
+ assert(_unprotected_ptr_from_user_ptr(user_ptr) == unprotected_ptr);
+
+ return user_ptr;
+}
+#endif /* !HAVE_ALIGNED_MALLOC */
+
+__attribute__((malloc)) void *
+sodium_malloc(const size_t size)
+{
+ void *ptr;
+
+ if ((ptr = _sodium_malloc(size)) == NULL) {
+ return NULL;
+ }
+ memset(ptr, (int) GARBAGE_VALUE, size);
+
+ return ptr;
+}
+
+__attribute__((malloc)) void *
+sodium_allocarray(size_t count, size_t size)
+{
+ size_t total_size;
+
+ if (count > (size_t) 0U && size >= (size_t) SIZE_MAX / count) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ total_size = count * size;
+
+ return sodium_malloc(total_size);
+}
+
+#ifndef HAVE_ALIGNED_MALLOC
+void
+sodium_free(void *ptr)
+{
+ free(ptr);
+}
+#else
+void
+sodium_free(void *ptr)
+{
+ unsigned char *base_ptr;
+ unsigned char *canary_ptr;
+ unsigned char *unprotected_ptr;
+ size_t total_size;
+ size_t unprotected_size;
+
+ if (ptr == NULL) {
+ return;
+ }
+ canary_ptr = ((unsigned char *) ptr) - sizeof canary;
+ unprotected_ptr = _unprotected_ptr_from_user_ptr(ptr);
+ base_ptr = unprotected_ptr - page_size * 2U;
+ memcpy(&unprotected_size, base_ptr, sizeof unprotected_size);
+ total_size = page_size + page_size + unprotected_size + page_size;
+ _mprotect_readwrite(base_ptr, total_size);
+ if (sodium_memcmp(canary_ptr, canary, sizeof canary) != 0) {
+ _out_of_bounds();
+ }
+# ifndef HAVE_PAGE_PROTECTION
+ if (sodium_memcmp(unprotected_ptr + unprotected_size, canary,
+ sizeof canary) != 0) {
+ _out_of_bounds();
+ }
+# endif
+ sodium_munlock(unprotected_ptr, unprotected_size);
+ _free_aligned(base_ptr, total_size);
+}
+#endif /* HAVE_ALIGNED_MALLOC */
+
+#ifndef HAVE_PAGE_PROTECTION
+static int
+_sodium_mprotect(void *ptr, int (*cb)(void *ptr, size_t size))
+{
+ (void) ptr;
+ (void) cb;
+ errno = ENOSYS;
+ return -1;
+}
+#else
+static int
+_sodium_mprotect(void *ptr, int (*cb)(void *ptr, size_t size))
+{
+ unsigned char *base_ptr;
+ unsigned char *unprotected_ptr;
+ size_t unprotected_size;
+
+ unprotected_ptr = _unprotected_ptr_from_user_ptr(ptr);
+ base_ptr = unprotected_ptr - page_size * 2U;
+ memcpy(&unprotected_size, base_ptr, sizeof unprotected_size);
+
+ return cb(unprotected_ptr, unprotected_size);
+}
+#endif
+
+int
+sodium_mprotect_noaccess(void *ptr)
+{
+ return _sodium_mprotect(ptr, _mprotect_noaccess);
+}
+
+int
+sodium_mprotect_readonly(void *ptr)
+{
+ return _sodium_mprotect(ptr, _mprotect_readonly);
+}
+
+int
+sodium_mprotect_readwrite(void *ptr)
+{
+ return _sodium_mprotect(ptr, _mprotect_readwrite);
+}
+
+int
+sodium_pad(size_t *padded_buflen_p, unsigned char *buf,
+ size_t unpadded_buflen, size_t blocksize, size_t max_buflen)
+{
+ unsigned char *tail;
+ size_t i;
+ size_t xpadlen;
+ size_t xpadded_len;
+ volatile unsigned char mask;
+ unsigned char barrier_mask;
+
+ if (blocksize <= 0U) {
+ return -1;
+ }
+ xpadlen = blocksize - 1U;
+ if ((blocksize & (blocksize - 1U)) == 0U) {
+ xpadlen -= unpadded_buflen & (blocksize - 1U);
+ } else {
+ xpadlen -= unpadded_buflen % blocksize;
+ }
+ if ((size_t) SIZE_MAX - unpadded_buflen <= xpadlen) {
+ sodium_misuse();
+ }
+ xpadded_len = unpadded_buflen + xpadlen;
+ if (xpadded_len >= max_buflen) {
+ return -1;
+ }
+ tail = &buf[xpadded_len];
+ if (padded_buflen_p != NULL) {
+ *padded_buflen_p = xpadded_len + 1U;
+ }
+ mask = 0U;
+ for (i = 0; i < blocksize; i++) {
+ barrier_mask = (unsigned char) (((i ^ xpadlen) - 1U) >> 8);
+ tail[-i] = (tail[-i] & mask) | (0x80 & barrier_mask);
+ mask |= barrier_mask;
+ }
+ return 0;
+}
+
+int
+sodium_unpad(size_t *unpadded_buflen_p, const unsigned char *buf,
+ size_t padded_buflen, size_t blocksize)
+{
+ const unsigned char *tail;
+ unsigned char acc = 0U;
+ unsigned char c;
+ unsigned char valid = 0U;
+ volatile size_t pad_len = 0U;
+ size_t i;
+ size_t is_barrier;
+
+ if (padded_buflen < blocksize || blocksize <= 0U) {
+ return -1;
+ }
+ tail = &buf[padded_buflen - 1U];
+
+ for (i = 0U; i < blocksize; i++) {
+ c = tail[-i];
+ is_barrier =
+ (( (acc - 1U) & (pad_len - 1U) & ((c ^ 0x80) - 1U) ) >> 8) & 1U;
+ acc |= c;
+ pad_len |= i & (1U + ~is_barrier);
+ valid |= (unsigned char) is_barrier;
+ }
+ *unpadded_buflen_p = padded_buflen - 1U - pad_len;
+
+ return (int) (valid - 1U);
+}
diff --git a/libs/libsodium/src/sodium/version.c b/libs/libsodium/src/sodium/version.c
new file mode 100644
index 0000000000..4e584a6ea0
--- /dev/null
+++ b/libs/libsodium/src/sodium/version.c
@@ -0,0 +1,30 @@
+
+#include "version.h"
+
+const char *
+sodium_version_string(void)
+{
+ return SODIUM_VERSION_STRING;
+}
+
+int
+sodium_library_version_major(void)
+{
+ return SODIUM_LIBRARY_VERSION_MAJOR;
+}
+
+int
+sodium_library_version_minor(void)
+{
+ return SODIUM_LIBRARY_VERSION_MINOR;
+}
+
+int
+sodium_library_minimal(void)
+{
+#ifdef SODIUM_LIBRARY_MINIMAL
+ return 1;
+#else
+ return 0;
+#endif
+}
diff --git a/libs/libsodium/src/stdafx.cxx b/libs/libsodium/src/stdafx.cxx
new file mode 100644
index 0000000000..1647228cd0
--- /dev/null
+++ b/libs/libsodium/src/stdafx.cxx
@@ -0,0 +1,2 @@
+
+#include "stdafx.h" \ No newline at end of file
diff --git a/libs/libsodium/src/stdafx.h b/libs/libsodium/src/stdafx.h
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/libs/libsodium/src/stdafx.h
diff --git a/libs/pthreads/docs/ANNOUNCE b/libs/pthreads/docs/ANNOUNCE
new file mode 100644
index 0000000000..950c86ff03
--- /dev/null
+++ b/libs/pthreads/docs/ANNOUNCE
@@ -0,0 +1,483 @@
+PTHREADS-WIN32 RELEASE 2.9.0 (2012-05-25)
+-----------------------------------------
+Web Site: http://sourceware.org/pthreads-win32/
+FTP Site: ftp://sourceware.org/pub/pthreads-win32
+Maintainer: Ross Johnson <ross.johnson@loungebythelake.net>
+
+
+We are pleased to announce the availability of a new release of
+Pthreads-win32, an Open Source Software implementation of the
+Threads component of the POSIX 1003.1 2001 Standard for Microsoft's
+Win32 environment. Some functions from other sections of POSIX
+1003.1 2001 are also supported including semaphores and scheduling
+functions.
+
+Some common non-portable functions are also implemented for
+additional compatibility, as are a few functions specific
+to pthreads-win32 for easier integration with Win32 applications.
+
+Pthreads-win32 is free software, distributed under the GNU Lesser
+General Public License (LGPL).
+
+
+Acknowledgements
+----------------
+This library is based originally on a Win32 pthreads
+implementation contributed by John Bossom.
+
+The implementation of Condition Variables uses algorithms developed
+by Alexander Terekhov and Louis Thomas.
+
+The implementation of POSIX mutexes has been improved by Thomas Pfaff
+and later by Alexander Terekhov.
+
+The implementation of Spinlocks and Barriers was contributed
+by Ross Johnson.
+
+The implementation of read/write locks was contributed by
+Aurelio Medina and improved by Alexander Terekhov.
+
+Many others have contributed significant time and effort to solve crutial
+problems in order to make the library workable, robust and reliable.
+
+Thanks to Xavier Leroy for granting permission to use and modify his
+LinuxThreads manual pages.
+
+Thanks to The Open Group for making the Single Unix Specification
+publicly available - many of the manual pages included in the package
+were extracted from it.
+
+There is also a separate CONTRIBUTORS file. This file and others are
+on the web site:
+
+ http://sourceware.org/pthreads-win32
+
+As much as possible, the ChangeLog file acknowledges contributions to the
+code base in more detail.
+
+
+Changes since the last release
+------------------------------
+These are now documented in the NEWS file.
+See the ChangeLog file also.
+
+
+Known Bugs
+----------
+These are now documented in the BUGS file.
+
+
+Level of standards conformance
+------------------------------
+
+The following POSIX 1003.1 2001 options are defined and set to 200112L:
+
+ _POSIX_THREADS
+ _POSIX_THREAD_SAFE_FUNCTIONS
+ _POSIX_THREAD_ATTR_STACKSIZE
+ _POSIX_THREAD_PRIORITY_SCHEDULING
+ _POSIX_SEMAPHORES
+ _POSIX_READER_WRITER_LOCKS
+ _POSIX_SPIN_LOCKS
+ _POSIX_BARRIERS
+
+
+The following POSIX 1003.1 2001 options are defined and set to -1:
+
+ _POSIX_THREAD_ATTR_STACKADDR
+ _POSIX_THREAD_PRIO_INHERIT
+ _POSIX_THREAD_PRIO_PROTECT
+ _POSIX_THREAD_PROCESS_SHARED
+
+
+The following POSIX 1003.1 2001 limits are defined and set:
+
+ _POSIX_THREAD_THREADS_MAX
+ _POSIX_SEM_VALUE_MAX
+ _POSIX_SEM_NSEMS_MAX
+ _POSIX_THREAD_KEYS_MAX
+ _POSIX_THREAD_DESTRUCTOR_ITERATIONS
+ PTHREAD_STACK_MIN
+ PTHREAD_THREADS_MAX
+ SEM_VALUE_MAX
+ SEM_NSEMS_MAX
+ PTHREAD_KEYS_MAX
+ PTHREAD_DESTRUCTOR_ITERATIONS
+
+
+The following functions are implemented:
+
+ ---------------------------
+ PThreads
+ ---------------------------
+ pthread_attr_init
+ pthread_attr_destroy
+ pthread_attr_getdetachstate
+ pthread_attr_getstackaddr
+ pthread_attr_getstacksize
+ pthread_attr_setdetachstate
+ pthread_attr_setstackaddr
+ pthread_attr_setstacksize
+
+ pthread_create
+ pthread_detach
+ pthread_equal
+ pthread_exit
+ pthread_join
+ pthread_once
+ pthread_self
+
+ pthread_cancel
+ pthread_cleanup_pop
+ pthread_cleanup_push
+ pthread_setcancelstate
+ pthread_setcanceltype
+ pthread_testcancel
+
+ ---------------------------
+ Thread Specific Data
+ ---------------------------
+ pthread_key_create
+ pthread_key_delete
+ pthread_setspecific
+ pthread_getspecific
+
+ ---------------------------
+ Mutexes
+ ---------------------------
+ pthread_mutexattr_init
+ pthread_mutexattr_destroy
+ pthread_mutexattr_getpshared
+ pthread_mutexattr_setpshared
+ pthread_mutexattr_gettype
+ pthread_mutexattr_settype (types: PTHREAD_MUTEX_DEFAULT
+ PTHREAD_MUTEX_NORMAL
+ PTHREAD_MUTEX_ERRORCHECK
+ PTHREAD_MUTEX_RECURSIVE )
+ pthread_mutexattr_getrobust
+ pthread_mutexattr_setrobust (values: PTHREAD_MUTEX_STALLED
+ PTHREAD_MUTEX_ROBUST)
+ pthread_mutex_init
+ pthread_mutex_destroy
+ pthread_mutex_lock
+ pthread_mutex_trylock
+ pthread_mutex_timedlock
+ pthread_mutex_unlock
+ pthread_mutex_consistent
+
+ ---------------------------
+ Condition Variables
+ ---------------------------
+ pthread_condattr_init
+ pthread_condattr_destroy
+ pthread_condattr_getpshared
+ pthread_condattr_setpshared
+
+ pthread_cond_init
+ pthread_cond_destroy
+ pthread_cond_wait
+ pthread_cond_timedwait
+ pthread_cond_signal
+ pthread_cond_broadcast
+
+ ---------------------------
+ Read/Write Locks
+ ---------------------------
+ pthread_rwlock_init
+ pthread_rwlock_destroy
+ pthread_rwlock_tryrdlock
+ pthread_rwlock_trywrlock
+ pthread_rwlock_rdlock
+ pthread_rwlock_timedrdlock
+ pthread_rwlock_rwlock
+ pthread_rwlock_timedwrlock
+ pthread_rwlock_unlock
+ pthread_rwlockattr_init
+ pthread_rwlockattr_destroy
+ pthread_rwlockattr_getpshared
+ pthread_rwlockattr_setpshared
+
+ ---------------------------
+ Spin Locks
+ ---------------------------
+ pthread_spin_init
+ pthread_spin_destroy
+ pthread_spin_lock
+ pthread_spin_unlock
+ pthread_spin_trylock
+
+ ---------------------------
+ Barriers
+ ---------------------------
+ pthread_barrier_init
+ pthread_barrier_destroy
+ pthread_barrier_wait
+ pthread_barrierattr_init
+ pthread_barrierattr_destroy
+ pthread_barrierattr_getpshared
+ pthread_barrierattr_setpshared
+
+ ---------------------------
+ Semaphores
+ ---------------------------
+ sem_init
+ sem_destroy
+ sem_post
+ sem_wait
+ sem_trywait
+ sem_timedwait
+ sem_getvalue (# free if +ve, # of waiters if -ve)
+ sem_open (returns an error ENOSYS)
+ sem_close (returns an error ENOSYS)
+ sem_unlink (returns an error ENOSYS)
+
+ ---------------------------
+ RealTime Scheduling
+ ---------------------------
+ pthread_attr_getschedparam
+ pthread_attr_setschedparam
+ pthread_attr_getinheritsched
+ pthread_attr_setinheritsched
+ pthread_attr_getschedpolicy (only supports SCHED_OTHER)
+ pthread_attr_setschedpolicy (only supports SCHED_OTHER)
+ pthread_getschedparam
+ pthread_setschedparam
+ pthread_getconcurrency
+ pthread_setconcurrency
+ pthread_attr_getscope
+ pthread_attr_setscope (only supports PTHREAD_SCOPE_SYSTEM)
+ sched_get_priority_max
+ sched_get_priority_min
+ sched_rr_get_interval (returns an error ENOTSUP)
+ sched_setscheduler (only supports SCHED_OTHER)
+ sched_getscheduler (only supports SCHED_OTHER)
+ sched_yield
+
+ ---------------------------
+ Signals
+ ---------------------------
+ pthread_sigmask
+ pthread_kill (only supports zero sig value,
+ for thread validity checking)
+
+ ---------------------------
+ Non-portable routines (see the README.NONPORTABLE file for usage)
+ ---------------------------
+ pthread_getw32threadhandle_np
+ pthread_timechange_handler_np
+ pthread_delay_np
+ pthread_getunique_np
+ pthread_mutexattr_getkind_np
+ pthread_mutexattr_setkind_np (types: PTHREAD_MUTEX_FAST_NP,
+ PTHREAD_MUTEX_ERRORCHECK_NP,
+ PTHREAD_MUTEX_RECURSIVE_NP,
+ PTHREAD_MUTEX_ADAPTIVE_NP,
+ PTHREAD_MUTEX_TIMED_NP)
+ pthread_num_processors_np
+ (The following four routines may be required when linking statically.
+ The process_* routines should not be needed for MSVC or GCC.)
+ pthread_win32_process_attach_np
+ pthread_win32_process_detach_np
+ (The following routines should only be needed to manage implicit
+ POSIX handles i.e. when Win native threads call POSIX thread routines
+ (other than pthread_create))
+ pthread_win32_thread_attach_np
+ pthread_win32_thread_detach_np
+
+ ---------------------------
+ Static Initializers
+ ---------------------------
+ PTHREAD_ONCE_INIT
+ PTHREAD_MUTEX_INITIALIZER
+ PTHREAD_RECURSIVE_MUTEX_INITIALIZER
+ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+ PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
+ PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
+ PTHREAD_COND_INITIALIZER
+ PTHREAD_RWLOCK_INITIALIZER
+ PTHREAD_SPINLOCK_INITIALIZER
+
+
+The library includes two non-API functions for creating cancellation
+points in applications and libraries:
+
+ pthreadCancelableWait
+ pthreadCancelableTimedWait
+
+
+The following functions are not implemented:
+
+ ---------------------------
+ RealTime Scheduling
+ ---------------------------
+ pthread_mutex_getprioceiling
+ pthread_mutex_setprioceiling
+ pthread_mutex_attr_getprioceiling
+ pthread_mutex_attr_getprotocol
+ pthread_mutex_attr_setprioceiling
+ pthread_mutex_attr_setprotocol
+
+ ---------------------------
+ Fork Handlers
+ ---------------------------
+ pthread_atfork
+
+ ---------------------------
+ Stdio
+ ---------------------------
+ flockfile
+ ftrylockfile
+ funlockfile
+ getc_unlocked
+ getchar_unlocked
+ putc_unlocked
+ putchar_unlocked
+
+ ---------------------------
+ Thread-Safe C Runtime Library
+ ---------------------------
+ readdir_r
+ getgrgid_r
+ getgrnam_r
+ getpwuid_r
+ getpwnam_r
+
+ ---------------------------
+ Signals
+ ---------------------------
+ sigtimedwait
+ sigwait
+ sigwaitinfo
+
+ ---------------------------
+ General
+ ---------------------------
+ sysconf
+
+ ---------------------------
+ Thread-Safe C Runtime Library (macros)
+ ---------------------------
+ strtok_r
+ asctime_r
+ ctime_r
+ gmtime_r
+ localtime_r
+ rand_r
+
+
+Availability
+------------
+
+The prebuilt DLL, export libs (for both MSVC and Mingw32), and the header
+files (pthread.h, semaphore.h, sched.h) are available along with the
+complete source code.
+
+The source code can be found at:
+
+ ftp://sources.redhat.com/pub/pthreads-win32
+
+and as individual source code files at
+
+ ftp://sources.redhat.com/pub/pthreads-win32/source
+
+The pre-built DLL, export libraries and include files can be found at:
+
+ ftp://sources.redhat.com/pub/pthreads-win32/dll-latest
+
+
+
+Mailing List
+------------
+
+There is a mailing list for discussing pthreads on Win32. To join,
+send email to:
+
+ pthreads-win32-subscribe@sourceware.cygnus.com
+
+
+Application Development Environments
+------------------------------------
+
+See the README file for more information.
+
+MSVC:
+MSVC using SEH works. Distribute pthreadVSE.dll with your application.
+MSVC using C++ EH works. Distribute pthreadVCE.dll with your application.
+MSVC using C setjmp/longjmp works. Distribute pthreadVC.dll with your application.
+
+
+Mingw32:
+See the FAQ, Questions 6 and 10.
+
+Mingw using C++ EH works. Distribute pthreadGCE.dll with your application.
+Mingw using C setjmp/longjmp works. Distribute pthreadGC.dll with your application.
+
+
+Cygwin: (http://sourceware.cygnus.com/cygwin/)
+Developers using Cygwin do not need pthreads-win32 since it has POSIX threads
+support. Refer to its documentation for details and extent.
+
+
+UWIN:
+UWIN is a complete Unix-like environment for Windows from AT&T. Pthreads-win32
+doesn't currently support UWIN (and vice versa), but that may change in the
+future.
+
+Generally:
+For convenience, the following pre-built files are available on the FTP site
+(see Availability above):
+
+ pthread.h - for POSIX threads
+ semaphore.h - for POSIX semaphores
+ sched.h - for POSIX scheduling
+ pthreadVCE.dll - built with MSVC++ compiler using C++ EH
+ pthreadVCE.lib
+ pthreadVC.dll - built with MSVC compiler using C setjmp/longjmp
+ pthreadVC.lib
+ pthreadVSE.dll - built with MSVC compiler using SEH
+ pthreadVSE.lib
+ pthreadGCE.dll - built with Mingw32 G++ 2.95.2-1
+ pthreadGC.dll - built with Mingw32 GCC 2.95.2-1 using setjmp/longjmp
+ libpthreadGCE.a - derived from pthreadGCE.dll
+ libpthreadGC.a - derived from pthreadGC.dll
+ gcc.dll - needed if distributing applications that use
+ pthreadGCE.dll (but see the FAQ Q 10 for the latest
+ related information)
+
+These are the only files you need in order to build POSIX threads
+applications for Win32 using either MSVC or Mingw32.
+
+See the FAQ file in the source tree for additional information.
+
+
+Documentation
+-------------
+
+For the authoritative reference, see the online POSIX
+standard reference at:
+
+ http://www.OpenGroup.org
+
+For POSIX Thread API programming, several reference books are
+available:
+
+ Programming with POSIX Threads
+ David R. Butenhof
+ Addison-Wesley (pub)
+
+ Pthreads Programming
+ By Bradford Nichols, Dick Buttlar & Jacqueline Proulx Farrell
+ O'Reilly (pub)
+
+On the web: see the links at the bottom of the pthreads-win32 site:
+
+ http://sources.redhat.com/pthreads-win32/
+
+ Currently, there is no documentation included in the package apart
+ from the copious comments in the source code.
+
+
+
+Enjoy!
+
+Ross Johnson
diff --git a/libs/pthreads/docs/BUGS b/libs/pthreads/docs/BUGS
new file mode 100644
index 0000000000..285ba4eb98
--- /dev/null
+++ b/libs/pthreads/docs/BUGS
@@ -0,0 +1,141 @@
+----------
+Known bugs
+----------
+
+1. Not strictly a bug, more of a gotcha.
+
+ Under MS VC++ (only tested with version 6.0), a term_func
+ set via the standard C++ set_terminate() function causes the
+ application to abort.
+
+ Notes from the MSVC++ manual:
+ 1) A term_func() should call exit(), otherwise
+ abort() will be called on return to the caller.
+ A call to abort() raises SIGABRT and the default signal handler
+ for all signals terminates the calling program with
+ exit code 3.
+ 2) A term_func() must not throw an exception. Therefore
+ term_func() should not call pthread_exit(), which
+ works by throwing an exception (pthreadVCE or pthreadVSE)
+ or by calling longjmp (pthreadVC).
+
+ Workaround: avoid using pthread_exit() in C++ applications. Exit
+ threads by dropping through the end of the thread routine.
+
+2. Cancellation problems in C++ builds
+ - Milan Gardian
+
+ [Note: It's not clear if this problem isn't simply due to the context
+ switch in pthread_cancel() which occurs unless the QueueUserAPCEx
+ library and driver are installed and used. Just like setjmp/longjmp,
+ this is probably not going to work well in C++. In any case, unless for
+ some very unusual reason you really must use the C++ build then please
+ use the C build pthreadVC2.dll or pthreadGC2.dll, i.e. for C++
+ applications.]
+
+ This is suspected to be a compiler bug in VC6.0, and also seen in
+ VC7.0 and VS .NET 2003. The GNU C++ compiler does not have a problem
+ with this, and it has been reported that the Intel C++ 8.1 compiler
+ and Visual C++ 2005 Express Edition Beta2 pass tests\semaphore4.c
+ (which exposes the bug).
+
+ Workaround [rpj - 2 Feb 2002]
+ -----------------------------
+ [Please note: this workaround did not solve a similar problem in
+ snapshot-2004-11-03 or later, even though similar symptoms were seen.
+ tests\semaphore4.c fails in that snapshot for the VCE version of the
+ DLL.]
+
+ The problem disappears when /Ob0 is used, i.e. /O2 /Ob0 works OK,
+ but if you want to use inlining optimisation you can be much more
+ specific about where it's switched off and on by using a pragma.
+
+ So the inlining optimisation is interfering with the way that cleanup
+ handlers are run. It appears to relate to auto-inlining of class methods
+ since this is the only auto inlining that is performed at /O1 optimisation
+ (functions with the "inline" qualifier are also inlined, but the problem
+ doesn't appear to involve any such functions in the library or testsuite).
+
+ In order to confirm the inlining culprit, the following use of pragmas
+ eliminate the problem but I don't know how to make it transparent, putting
+ it in, say, pthread.h where pthread_cleanup_push defined as a macro.
+
+ #pragma inline_depth(0)
+ pthread_cleanup_push(handlerFunc, (void *) &arg);
+
+ /* ... */
+
+ pthread_cleanup_pop(0);
+ #pragma inline_depth()
+
+ Note the empty () pragma value after the pop macro. This resets depth to the
+ default. Or you can specify a non-zero depth here.
+
+ The pragma is also needed (and now used) within the library itself wherever
+ cleanup handlers are used (condvar.c and rwlock.c).
+
+ Use of these pragmas allows compiler optimisations /O1 and /O2 to be
+ used for either or both the library and applications.
+
+ Experimenting further, I found that wrapping the actual cleanup handler
+ function with #pragma auto_inline(off|on) does NOT work.
+
+ MSVC6.0 doesn't appear to support the C99 standard's _Pragma directive,
+ however, later versions may. This form is embeddable inside #define
+ macros, which would be ideal because it would mean that it could be added
+ to the push/pop macro definitions in pthread.h and hidden from the
+ application programmer.
+
+ [/rpj]
+
+ Original problem description
+ ----------------------------
+
+ The cancellation (actually, cleanup-after-cancel) tests fail when using VC
+ (professional) optimisation switches (/O1 or /O2) in pthreads library. I
+ have not investigated which concrete optimisation technique causes this
+ problem (/Og, /Oi, /Ot, /Oy, /Ob1, /Gs, /Gf, /Gy, etc.), but here is a
+ summary of builds and corresponding failures:
+
+ * pthreads VSE (optimised tests): OK
+ * pthreads VCE (optimised tests): Failed "cleanup1" test (runtime)
+
+ * pthreads VSE (DLL in CRT, optimised tests): OK
+ * pthreads VCE (DLL in CRT, optimised tests): Failed "cleanup1" test
+ (runtime)
+
+ Please note that while in VSE version of the pthreads library the
+ optimisation does not really have any impact on the tests (they pass OK), in
+ VCE version addition of optimisation (/O2 in this case) causes the tests to
+ fail uniformly - either in "cleanup0" or "cleanup1" test cases.
+
+ Please note that all the tests above use default pthreads DLL (no
+ optimisations, linked with either static or DLL CRT, based on test type).
+ Therefore the problem lies not within the pthreads DLL but within the
+ compiled client code (the application using pthreads -> involvement of
+ "pthread.h").
+
+ I think the message of this section is that usage of VCE version of pthreads
+ in applications relying on cancellation/cleanup AND using optimisations for
+ creation of production code is highly unreliable for the current version of
+ the pthreads library.
+
+3. The Borland Builder 5.5 version of the library produces memory read exceptions
+in some tests.
+
+4. pthread_barrier_wait() can deadlock if the number of potential calling
+threads for a particular barrier is greater than the barrier count parameter
+given to pthread_barrier_init() for that barrier.
+
+This is due to the very lightweight implementation of pthread-win32 barriers.
+To cope with more than "count" possible waiters, barriers must effectively
+implement all the same safeguards as condition variables, making them much
+"heavier" than at present.
+
+The workaround is to ensure that no more than "count" threads attempt to wait
+at the barrier.
+
+5. Canceling a thread blocked on pthread_once appears not to work in the MSVC++
+version of the library "pthreadVCE.dll". The test case "once3.c" hangs. I have no
+clues on this at present. All other versions pass this test ok - pthreadsVC.dll,
+pthreadsVSE.dll, pthreadsGC.dll and pthreadsGCE.dll.
diff --git a/libs/pthreads/docs/Bmakefile b/libs/pthreads/docs/Bmakefile
new file mode 100644
index 0000000000..ea25dec4fd
--- /dev/null
+++ b/libs/pthreads/docs/Bmakefile
@@ -0,0 +1,268 @@
+# This makefile is compatible with BCB make. Use "make -fBMakefile" to compile.
+#
+# The variables $DLLDEST and $LIBDEST hold the destination directories for the
+# dll and the lib, respectively. Probably all that needs to change is $DEVROOT.
+#
+# Currently only the recommended pthreadBC.dll is built by this makefile.
+#
+
+
+DLL_VER = 2
+
+DEVROOT = .
+
+DLLDEST = $(DEVROOT)\DLL
+LIBDEST = $(DEVROOT)\DLL
+
+DLLS = pthreadBC$(DLL_VER).dll
+
+OPTIM = /O2
+
+RC = brcc32
+RCFLAGS = -i.
+
+CFLAGS = /q /I. /D_WIN32_WINNT=0x400 /DHAVE_PTW32_CONFIG_H=1 /4 /tWD /tWM \
+ /w-aus /w-asc /w-par
+
+#C cleanup code
+BCFLAGS = $(PTW32_FLAGS) $(CFLAGS)
+
+# Agregate modules for inlinability
+DLL_OBJS = \
+ attr.obj \
+ barrier.obj \
+ cancel.obj \
+ cleanup.obj \
+ condvar.obj \
+ create.obj \
+ dll.obj \
+ errno.obj \
+ exit.obj \
+ fork.obj \
+ global.obj \
+ misc.obj \
+ mutex.obj \
+ nonportable.obj \
+ private.obj \
+ rwlock.obj \
+ sched.obj \
+ semaphore.obj \
+ signal.obj \
+ spin.obj \
+ sync.obj \
+ tsd.obj
+
+INCL = config.h implement.h semaphore.h pthread.h need_errno.h
+
+ATTR_SRCS = \
+ pthread_attr_init.c \
+ pthread_attr_destroy.c \
+ pthread_attr_getdetachstate.c \
+ pthread_attr_setdetachstate.c \
+ pthread_attr_getstackaddr.c \
+ pthread_attr_setstackaddr.c \
+ pthread_attr_getstacksize.c \
+ pthread_attr_setstacksize.c \
+ pthread_attr_getscope.c \
+ pthread_attr_setscope.c
+
+BARRIER_SRCS = \
+ pthread_barrier_init.c \
+ pthread_barrier_destroy.c \
+ pthread_barrier_wait.c \
+ pthread_barrierattr_init.c \
+ pthread_barrierattr_destroy.c \
+ pthread_barrierattr_setpshared.c \
+ pthread_barrierattr_getpshared.c
+
+CANCEL_SRCS = \
+ pthread_setcancelstate.c \
+ pthread_setcanceltype.c \
+ pthread_testcancel.c \
+ pthread_cancel.c
+
+CONDVAR_SRCS = \
+ ptw32_cond_check_need_init.c \
+ pthread_condattr_destroy.c \
+ pthread_condattr_getpshared.c \
+ pthread_condattr_init.c \
+ pthread_condattr_setpshared.c \
+ pthread_cond_destroy.c \
+ pthread_cond_init.c \
+ pthread_cond_signal.c \
+ pthread_cond_wait.c
+
+EXIT_SRCS = \
+ pthread_exit.c
+
+MISC_SRCS = \
+ pthread_equal.c \
+ pthread_getconcurrency.c \
+ pthread_once.c \
+ pthread_self.c \
+ pthread_setconcurrency.c \
+ ptw32_calloc.c \
+ ptw32_MCS_lock.c \
+ ptw32_new.c \
+ w32_CancelableWait.c
+
+MUTEX_SRCS = \
+ ptw32_mutex_check_need_init.c \
+ pthread_mutex_init.c \
+ pthread_mutex_destroy.c \
+ pthread_mutexattr_init.c \
+ pthread_mutexattr_destroy.c \
+ pthread_mutexattr_getpshared.c \
+ pthread_mutexattr_setpshared.c \
+ pthread_mutexattr_settype.c \
+ pthread_mutexattr_gettype.c \
+ pthread_mutexattr_setrobust.c \
+ pthread_mutexattr_getrobust.c \
+ pthread_mutex_lock.c \
+ pthread_mutex_timedlock.c \
+ pthread_mutex_unlock.c \
+ pthread_mutex_trylock.c \
+ pthread_mutex_consistent.c
+
+NONPORTABLE_SRCS = \
+ pthread_mutexattr_setkind_np.c \
+ pthread_mutexattr_getkind_np.c \
+ pthread_getw32threadhandle_np.c \
+ pthread_delay_np.c \
+ pthread_num_processors_np.c \
+ pthread_win32_attach_detach_np.c \
+ pthread_timechange_handler_np.c
+
+PRIVATE_SRCS = \
+ ptw32_is_attr.c \
+ ptw32_processInitialize.c \
+ ptw32_processTerminate.c \
+ ptw32_threadStart.c \
+ ptw32_threadDestroy.c \
+ ptw32_tkAssocCreate.c \
+ ptw32_tkAssocDestroy.c \
+ ptw32_callUserDestroyRoutines.c \
+ ptw32_timespec.c \
+ ptw32_relmillisecs.c \
+ ptw32_throw.c \
+ ptw32_getprocessors.c
+
+RWLOCK_SRCS = \
+ ptw32_rwlock_check_need_init.c \
+ ptw32_rwlock_cancelwrwait.c \
+ pthread_rwlock_init.c \
+ pthread_rwlock_destroy.c \
+ pthread_rwlockattr_init.c \
+ pthread_rwlockattr_destroy.c \
+ pthread_rwlockattr_getpshared.c \
+ pthread_rwlockattr_setpshared.c \
+ pthread_rwlock_rdlock.c \
+ pthread_rwlock_timedrdlock.c \
+ pthread_rwlock_wrlock.c \
+ pthread_rwlock_timedwrlock.c \
+ pthread_rwlock_unlock.c \
+ pthread_rwlock_tryrdlock.c \
+ pthread_rwlock_trywrlock.c
+
+SCHED_SRCS = \
+ pthread_attr_setschedpolicy.c \
+ pthread_attr_getschedpolicy.c \
+ pthread_attr_setschedparam.c \
+ pthread_attr_getschedparam.c \
+ pthread_attr_setinheritsched.c \
+ pthread_attr_getinheritsched.c \
+ pthread_setschedparam.c \
+ pthread_getschedparam.c \
+ sched_get_priority_max.c \
+ sched_get_priority_min.c \
+ sched_setscheduler.c \
+ sched_getscheduler.c \
+ sched_yield.c
+
+SEMAPHORE_SRCS = \
+ sem_init.c \
+ sem_destroy.c \
+ sem_trywait.c \
+ sem_timedwait.c \
+ sem_wait.c \
+ sem_post.c \
+ sem_post_multiple.c \
+ sem_getvalue.c \
+ sem_open.c \
+ sem_close.c \
+ sem_unlink.c
+
+SPIN_SRCS = \
+ ptw32_spinlock_check_need_init.c \
+ pthread_spin_init.c \
+ pthread_spin_destroy.c \
+ pthread_spin_lock.c \
+ pthread_spin_unlock.c \
+ pthread_spin_trylock.c
+
+SYNC_SRCS = \
+ pthread_detach.c \
+ pthread_join.c
+
+TSD_SRCS = \
+ pthread_key_create.c \
+ pthread_key_delete.c \
+ pthread_setspecific.c \
+ pthread_getspecific.c
+
+
+all: clean $(DLLS)
+
+realclean: clean
+ if exist pthread*.dll del pthread*.dll
+ if exist pthread*.lib del pthread*.lib
+ if exist *.stamp del *.stamp
+
+clean:
+ if exist *.obj del *.obj
+ if exist *.ilk del *.ilk
+ if exist *.ilc del *.ilc
+ if exist *.ild del *.ild
+ if exist *.ilf del *.ilf
+ if exist *.ils del *.ils
+ if exist *.tds del *.tds
+ if exist *.pdb del *.pdb
+ if exist *.exp del *.exp
+ if exist *.map del *.map
+ if exist *.o del *.o
+ if exist *.i del *.i
+ if exist *.res del *.res
+
+
+install: $(DLLS)
+ copy pthread*.dll $(DLLDEST)
+ copy pthread*.lib $(LIBDEST)
+
+$(DLLS): $(DLL_OBJS) version.res
+ ilink32 /Tpd /Gi c0d32x.obj $(DLL_OBJS), \
+ $@, ,\
+ cw32mti.lib import32.lib, ,\
+ version.res
+
+.c.obj:
+ $(CC) $(OPTIM) $(BCFLAGS) -c $<
+
+.rc.res:
+ $(RC) $(RCFLAGS) $<
+
+attr.obj: attr.c $(ATTR_SRCS) $(INCL)
+barrier.obj: barrier.c $(BARRIER_SRCS) $(INCL)
+cancel.obj: cancel.c $(CANCEL_SRCS) $(INCL)
+condvar.obj: condvar.c $(CONDVAR_SRCS) $(INCL)
+exit.obj: exit.c $(EXIT_SRCS) $(INCL)
+misc.obj: misc.c $(MISC_SRCS) $(INCL)
+mutex.obj: mutex.c $(MUTEX_SRCS) $(INCL)
+nonportable.obj: nonportable.c $(NONPORTABLE_SRCS) $(INCL)
+private.obj: private.c $(PRIVATE_SRCS) $(INCL)
+rwlock.obj: rwlock.c $(RWLOCK_SRCS) $(INCL)
+sched.obj: sched.c $(SCHED_SRCS) $(INCL)
+semaphore.obj: semaphore.c $(SEMAPHORE_SRCS) $(INCL)
+spin.obj: spin.c $(SPIN_SRCS) $(INCL)
+sync.obj: sync.c $(SYNC_SRCS) $(INCL)
+tsd.obj: tsd.c $(TSD_SRCS) $(INCL)
+version.res: version.rc $(INCL)
diff --git a/libs/pthreads/docs/CONTRIBUTORS b/libs/pthreads/docs/CONTRIBUTORS
new file mode 100644
index 0000000000..da31ff266c
--- /dev/null
+++ b/libs/pthreads/docs/CONTRIBUTORS
@@ -0,0 +1,140 @@
+Contributors (in approximate order of appearance)
+
+[See also the ChangeLog file where individuals are
+attributed in log entries. Likewise in the FAQ file.]
+
+Ben Elliston bje at cygnus dot com
+ Initiated the project;
+ setup the project infrastructure (CVS, web page, etc.);
+ early prototype routines.
+Ross Johnson Ross dot Johnson at dot homemail dot com dot au
+ early prototype routines;
+ ongoing project coordination/maintenance;
+ implementation of spin locks and barriers;
+ various enhancements;
+ bug fixes;
+ documentation;
+ testsuite.
+Robert Colquhoun rjc at trump dot net dot au
+ Early bug fixes.
+John E. Bossom John dot Bossom at cognos dot com
+ Contributed substantial original working implementation;
+ bug fixes;
+ ongoing guidance and standards interpretation.
+Anders Norlander anorland at hem2 dot passagen dot se
+ Early enhancements and runtime checking for supported
+ Win32 routines.
+Tor Lillqvist tml at iki dot fi
+ General enhancements;
+ early bug fixes to condition variables.
+Scott Lightner scott at curriculum dot com
+ Bug fix.
+Kevin Ruland Kevin dot Ruland at anheuser-busch dot com
+ Various bug fixes.
+Mike Russo miker at eai dot com
+ Bug fix.
+Mark E. Armstrong avail at pacbell dot net
+ Bug fixes.
+Lorin Hochstein lmh at xiphos dot ca
+ general bug fixes; bug fixes to condition variables.
+Peter Slacik Peter dot Slacik at tatramed dot sk
+ Bug fixes.
+Mumit Khan khan at xraylith dot wisc dot edu
+ Fixes to work with Mingw32.
+Milan Gardian mg at tatramed dot sk
+ Bug fixes and reports/analyses of obscure problems.
+Aurelio Medina aureliom at crt dot com
+ First implementation of read-write locks.
+Graham Dumpleton Graham dot Dumpleton at ra dot pad dot otc dot telstra dot com dot au
+ Bug fix in condition variables.
+Tristan Savatier tristan at mpegtv dot com
+ WinCE port.
+Erik Hensema erik at hensema dot xs4all dot nl
+ Bug fixes.
+Rich Peters rpeters at micro-magic dot com
+Todd Owen towen at lucidcalm dot dropbear dot id dot au
+ Bug fixes to dll loading.
+Jason Nye jnye at nbnet dot nb dot ca
+ Implementation of async cancelation.
+Fred Forester fforest at eticomm dot net
+Kevin D. Clark kclark at cabletron dot com
+David Baggett dmb at itasoftware dot com
+ Bug fixes.
+Paul Redondo paul at matchvision dot com
+Scott McCaskill scott at 3dfx dot com
+ Bug fixes.
+Jef Gearhart jgearhart at tpssys dot com
+ Bug fix.
+Arthur Kantor akantor at bexusa dot com
+ Mutex enhancements.
+Steven Reddie smr at essemer dot com dot au
+ Bug fix.
+Alexander Terekhov TEREKHOV at de dot ibm dot com
+ Re-implemented and improved read-write locks;
+ (with Louis Thomas) re-implemented and improved
+ condition variables;
+ enhancements to semaphores;
+ enhancements to mutexes;
+ new mutex implementation in 'futex' style;
+ suggested a robust implementation of pthread_once
+ similar to that implemented by V.Kliathcko;
+ system clock change handling re CV timeouts;
+ bug fixes.
+Thomas Pfaff tpfaff at gmx dot net
+ Changes to make C version usable with C++ applications;
+ re-implemented mutex routines to avoid Win32 mutexes
+ and TryEnterCriticalSection;
+ procedure to fix Mingw32 thread-safety issues.
+Franco Bez franco dot bez at gmx dot de
+ procedure to fix Mingw32 thread-safety issues.
+Louis Thomas lthomas at arbitrade dot com
+ (with Alexander Terekhov) re-implemented and improved
+ condition variables.
+David Korn dgk at research dot att dot com
+ Ported to UWIN.
+Phil Frisbie, Jr. phil at hawksoft dot com
+ Bug fix.
+Ralf Brese Ralf dot Brese at pdb4 dot siemens dot de
+ Bug fix.
+prionx at juno dot com prionx at juno dot com
+ Bug fixes.
+Max Woodbury mtew at cds dot duke dot edu
+ POSIX versioning conditionals;
+ reduced namespace pollution;
+ idea to separate routines to reduce statically
+ linked image sizes.
+Rob Fanner rfanner at stonethree dot com
+ Bug fix.
+Michael Johnson michaelj at maine dot rr dot com
+ Bug fix.
+Nicolas Barry boozai at yahoo dot com
+ Bug fixes.
+Piet van Bruggen pietvb at newbridges dot nl
+ Bug fix.
+Makoto Kato raven at oldskool dot jp
+ AMD64 port.
+Panagiotis E. Hadjidoukas peh at hpclab dot ceid dot upatras dot gr
+ phadjido at cs dot uoi dot gr
+ Contributed the QueueUserAPCEx package which
+ makes preemptive async cancelation possible.
+Will Bryant will dot bryant at ecosm dot com
+ Borland compiler patch and makefile.
+Anuj Goyal anuj dot goyal at gmail dot com
+ Port to Digital Mars compiler.
+Gottlob Frege gottlobfrege at gmail dot com
+ re-implemented pthread_once (version 2)
+ (pthread_once cancellation added by rpj).
+Vladimir Kliatchko vladimir at kliatchko dot com
+ reimplemented pthread_once with the same form
+ as described by A.Terekhov (later version 2);
+ implementation of MCS (Mellor-Crummey/Scott) locks.
+Ramiro Polla ramiro.polla at gmail dot com
+ static library auto init/cleanup on application
+ start/exit via RT hooks (MSC and GCC compilers only).
+Daniel Richard G. skunk at iSKUNK dot org
+ Patches and cleanups for x86 and x64, particularly
+ across a range of MS build environments.
+John Kamp john dot kamp at globalgraphics dot com
+ Patches to fix various problems on x64; brutal testing
+ particularly using high memory run environments.
+
diff --git a/libs/pthreads/docs/COPYING b/libs/pthreads/docs/COPYING
new file mode 100644
index 0000000000..5cfea0d0ed
--- /dev/null
+++ b/libs/pthreads/docs/COPYING
@@ -0,0 +1,150 @@
+ pthreads-win32 - a POSIX threads library for Microsoft Windows
+
+
+This file is Copyrighted
+------------------------
+
+ This file is covered under the following Copyright:
+
+ Copyright (C) 2001,2006 Ross P. Johnson
+ All rights reserved.
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+Pthreads-win32 is covered by the GNU Lesser General Public License
+------------------------------------------------------------------
+
+ Pthreads-win32 is open software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation version 2.1 of the
+ License.
+
+ Pthreads-win32 is several binary link libraries, several modules,
+ associated interface definition files and scripts used to control
+ its compilation and installation.
+
+ Pthreads-win32 is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ A copy of the GNU Lesser General Public License is distributed with
+ pthreads-win32 under the filename:
+
+ COPYING.LIB
+
+ You should have received a copy of the version 2.1 GNU Lesser General
+ Public License with pthreads-win32; if not, write to:
+
+ Free Software Foundation, Inc.
+ 59 Temple Place
+ Suite 330
+ Boston, MA 02111-1307
+ USA
+
+ The contact addresses for pthreads-win32 is as follows:
+
+ Web: http://sources.redhat.com/pthreads-win32
+ Email: Ross Johnson
+ Please use: Firstname.Lastname@homemail.com.au
+
+
+
+Pthreads-win32 copyrights and exception files
+---------------------------------------------
+
+ With the exception of the files listed below, Pthreads-win32
+ is covered under the following GNU Lesser General Public License
+ Copyrights:
+
+ Pthreads-win32 - POSIX Threads Library for Win32
+ Copyright(C) 1998 John E. Bossom
+ Copyright(C) 1999,2006 Pthreads-win32 contributors
+
+ The current list of contributors is contained
+ in the file CONTRIBUTORS included with the source
+ code distribution. The current list of CONTRIBUTORS
+ can also be seen at the following WWW location:
+ http://sources.redhat.com/pthreads-win32/contributors.html
+
+ Contact Email: Ross Johnson
+ Please use: Firstname.Lastname@homemail.com.au
+
+ These files are not covered under one of the Copyrights listed above:
+
+ COPYING
+ COPYING.LIB
+ tests/rwlock7.c
+
+ This file, COPYING, is distributed under the Copyright found at the
+ top of this file. It is important to note that you may distribute
+ verbatim copies of this file but you may not modify this file.
+
+ The file COPYING.LIB, which contains a copy of the version 2.1
+ GNU Lesser General Public License, is itself copyrighted by the
+ Free Software Foundation, Inc. Please note that the Free Software
+ Foundation, Inc. does NOT have a copyright over Pthreads-win32,
+ only the COPYING.LIB that is supplied with pthreads-win32.
+
+ The file tests/rwlock7.c is derived from code written by
+ Dave Butenhof for his book 'Programming With POSIX(R) Threads'.
+ The original code was obtained by free download from his website
+ http://home.earthlink.net/~anneart/family/Threads/source.html
+ and did not contain a copyright or author notice. It is assumed to
+ be freely distributable.
+
+ In all cases one may use and distribute these exception files freely.
+ And because one may freely distribute the LGPL covered files, the
+ entire pthreads-win32 source may be freely used and distributed.
+
+
+
+General Copyleft and License info
+---------------------------------
+
+ For general information on Copylefts, see:
+
+ http://www.gnu.org/copyleft/
+
+ For information on GNU Lesser General Public Licenses, see:
+
+ http://www.gnu.org/copyleft/lesser.html
+ http://www.gnu.org/copyleft/lesser.txt
+
+
+Why pthreads-win32 did not use the GNU General Public License
+-------------------------------------------------------------
+
+ The goal of the pthreads-win32 project has been to
+ provide a quality and complete implementation of the POSIX
+ threads API for Microsoft Windows within the limits imposed
+ by virtue of it being a stand-alone library and not
+ linked directly to other POSIX compliant libraries. For
+ example, some functions and features, such as those based
+ on POSIX signals, are missing.
+
+ Pthreads-win32 is a library, available in several different
+ versions depending on supported compilers, and may be used
+ as a dynamically linked module or a statically linked set of
+ binary modules. It is not an application on it's own.
+
+ It was fully intended that pthreads-win32 be usable with
+ commercial software not covered by either the GPL or the LGPL
+ licenses. Pthreads-win32 has many contributors to it's
+ code base, many of whom have done so because they have
+ used the library in commercial or proprietry software
+ projects.
+
+ Releasing pthreads-win32 under the LGPL ensures that the
+ library can be used widely, while at the same time ensures
+ that bug fixes and improvements to the pthreads-win32 code
+ itself is returned to benefit all current and future users
+ of the library.
+
+ Although pthreads-win32 makes it possible for applications
+ that use POSIX threads to be ported to Win32 platforms, the
+ broader goal of the project is to encourage the use of open
+ standards, and in particular, to make it just a little easier
+ for developers writing Win32 applications to consider
+ widening the potential market for their products.
diff --git a/libs/pthreads/docs/ChangeLog b/libs/pthreads/docs/ChangeLog
new file mode 100644
index 0000000000..42abcc457a
--- /dev/null
+++ b/libs/pthreads/docs/ChangeLog
@@ -0,0 +1,5211 @@
+2012-03-18 Ross Johnson <ross dot johnson at homemail dot com dot au>
+
+ * create.c (pthread_create): add __cdecl attribute to thread routine
+ arg
+ * implement.h (pthread_key_t): add __cdecl attribute to destructor
+ element
+ (ThreadParms): likewise for start element
+ * pthread.h (pthread_create): add __cdecl to prototype start arg
+ (pthread_once): likewise for init_routine arg
+ (pthread_key_create): likewise for destructor arg
+ (ptw32_cleanup_push): replace type of routine arg with previously
+ defined ptw32_cleanup_callback_t
+ * pthread_key_create.c: add __cdecl attribute to destructor arg
+ * pthread_once.c: add __cdecl attribute to init_routine arg
+ * ptw32_threadStart.c (start): add __cdecl to start variable type
+
+
+2011-07-06 Ross Johnson <ross dot johnson at homemail dot com dot au>
+
+ * pthread_cond_wait.c (pragma inline_depth): this is almost redundant
+ now nevertheless fixed thei controlling MSC_VER from "< 800" to
+ "< 1400" (i.e. any prior to VC++ 8.0).
+ * pthread_once.ci (pragma inline_depth): Likewise.
+ * pthread_rwlock_timedwrlock.ci (pragma inline_depth): Likewise.
+ * pthread_rwlock_wrlock.ci (pragma inline_depth): Likewise.
+ * sem_timedwait.ci (pragma inline_depth): Likewise.
+ * sem_wait.ci (pragma inline_depth): Likewise.
+
+2011-07-05 Ross Johnson <ross dot johnson at homemail dot com dot au>
+
+ * pthread_win32_attach_detach_np.c: Use strncat_s if available
+ to removei a compile warning; MingW supports this routine but we
+ continue to use strncat anyway there because it is secure if
+ given the correct parameters; fix strncat param 3 to avoid
+ buffer overrun exploitation potential.
+
+2011-07-03 Ross Johnson <ross dot johnson at homemail dot com dot au>
+
+ * pthread_spin_unlock.c (EPERM): Return success if unlocking a lock
+ that is not locked, because single CPU machines wrap a
+ PTHREAD_MUTEX_NORMAL mutex, which returns success in this case.
+ * pthread_win32_attach_detach_np.c (QUSEREX.DLL): Load from an
+ absolute path only which must be the Windows System folder.
+
+2011-07-03 Daniel Richard G. <skunk at iskunk dot org>
+
+ * Makefile (_WIN32_WINNT): Removed; duplicate definition in
+ implement.h; more cleanup and enhancements.
+
+2011-07-02 Daniel Richard G. <skunk at iskunk dot org>
+
+ * Makefile: Cleanups and implovements.
+ * ptw32_MCS_locks.c: Casting fixes.
+ * implement.h: Interlocked call and argument casting macro fixes
+ to support older and newer build environments.
+
+2011-07-01 Ross Johnson <ross dot johnson at homemail dot com dot au>
+
+ * *.[ch] (PTW32_INTERLOCKED_*): Redo 23 and 64 bit versions of these
+ macros and re-apply in code to undo the incorrect changes from
+ 2011-06-29; remove some size_t casts which should not be required
+ and may be problematic.a
+ There are now two sets of macros:
+ PTW32_INTERLOCKED_*_LONG which work only on 32 bit integer variables;
+ PTW32_INTERLOCKED_*_SIZE which work on size_t integer variables, i.e.
+ LONG for 32 bit systems and LONGLONG for 64 bit systems.
+ * implement.h (MCS locks): nextFlag and waitFlag are now HANDLE type.
+ * ptw32_MCS_locks.c: Likewise.
+ * pthread.h (#include <setjmp.h>): Removed.
+ * ptw32_throw.c (#include <setjmp.h>): Added.
+ * ptw32_threadStart.c (#include <setjmp.h>): Added.
+ * implement.h (#include <setjmp.h>): Added.
+
+2011-06-30 Ross Johnson <ross dot johnson at homemail dot com dot au>
+
+ * pthread_once.c: Tighten 'if' statement casting; fix interlocked
+ pointer cast for 64 bit compatibility (missed yesterday); remove
+ the superfluous static cleanup routine and call the release routine
+ directly if popped.
+ * create.c (stackSize): Now type size_t.
+ * pthread.h (struct ptw32_thread_t_): Rearrange to fix element alignments.
+
+2011-06-29 Daniel Richard G. <skunk at iskunk dot org>
+
+ * ptw32_relmillisecs.c (ftime):
+ _ftime64_s() is only available in MSVC 2005 or later;
+ _ftime64() is available in MinGW or MSVC 2002 or later;
+ _ftime() is always available.
+ * pthread.h (long long): Not defined in older MSVC 6.
+ * implement.h (long long): Likewise.
+ * pthread_getunique_np.c (long long): Likewise.
+
+2011-06-29 Ross Johnson <ross dot johnson at homemail dot com dot au>
+
+ * *.[ch] (PTW32_INTERLOCKED_*): These macros should now work for
+ both 32 and 64 bit builds. The MingW versions are all inlined asm
+ while the MSVC versions expand to their Interlocked* or Interlocked*64
+ counterparts appropriately. The argument type have also been changed
+ to cast to the appropriate value or pointer size for the architecture.
+
+2011-05-29 Ross Johnson <ross dot johnson at homemail dot com dot au>
+
+ * *.[ch] (#ifdef): Extended cleanup to whole project.
+
+2011-05-29 Daniel Richard G. <skunk at iskunk dot org>
+
+ * Makefile (CC): Define CC to allow use of other compatible
+ compilers such as the Intel compilter icl.
+ * implement.h (#if): Fix forms like #if HAVE_SOMETHING.
+ * pthread.h: Likewise.
+ * sched.h: Likewise; PTW32_LEVEL_* becomes PTW32_SCHED_LEVEL_*.
+ * semaphore.h: Likewise.
+
+2011-05-11 Ross Johnson <ross.johnson at homemail.com.au>
+
+ * ptw32_callUserDestroyRoutines.c (terminate): Altered includes
+ to match ptw32_threadStart.c.
+ * GNUmakefile (GCE-inlined-debug, DOPT): Fixed.
+
+2011-04-31 Ross Johnson <ross.johnson at homemail.com.au>
+
+ * (robust mutexes): Added this API. The API is not
+ mandatory for implementations that don't support PROCESS_SHARED
+ mutexes, nevertheless it was considered useful both functionally
+ and for source-level compatibility.
+
+2011-03-26 Ross Johnson <ross.johnson at homemail.com.au>
+
+ * pthread_getunique_np.c: New non-POSIX interface for compatibility
+ with some other implementations; returns a 64 bit sequence number
+ that is unique to each thread in the process.
+ * pthread.h (pthread_getunique_np): Added.
+ * global.c: Add global sequence counter for above.
+ * implement.h: Likewise.
+
+2011-03-25 Ross Johnson <ross.johnson at homemail.com.au>
+
+ * (cancelLock): Convert to an MCS lock and rename to stateLock.
+ * (threadLock): Likewise.
+ * (keyLock): Likewise.
+ * pthread_mutex*.c: First working robust mutexes.
+
+2011-03-11 Ross Johnson <ross.johnson at homemail.com.au>
+
+ * implement.h (PTW32_INTERLOCKED_*CREMENT macros): increment/decrement
+ using ++/-- instead of add/subtract 1.
+ * ptw32_MCS_lock.c: Make casts consistent.
+
+2011-03-09 Ross Johnson <ross.johnson at homemail.com.au>
+
+ * implement.h (ptw32_thread_t_): Add process unique sequence number.
+ * global.c: Replace global Critical Section objects with MCS
+ queue locks.
+ * implement.h: Likewise.
+ * pthread_cond_destroy.c: Likewise.
+ * pthread_cond_init.c: Likewise.
+ * pthread_detach.c: Likewise.
+ * pthread_join.c: Likewise.
+ * pthread_kill.c: Likewise.
+ * pthread_mutex_destroy.c: Likewise.
+ * pthread_rwlock_destroy.c: Likewise.
+ * pthread_spin_destroy.c: Likewise.
+ * pthread_timechange_handler_np.c: Likewise.
+ * ptw32_cond_check_need_init.c: Likewise.
+ * ptw32_mutex_check_need_init.c: Likewise.
+ * ptw32_processInitialize.c: Likewise.
+ * ptw32_processTerminate.c: Likewise.
+ * ptw32_reuse.c: Likewise.
+ * ptw32_rwlock_check_need_init.c: Likewise.
+ * ptw32_spinlock_check_need_init.c: Likewise.
+
+2011-03-06 Ross Johnson <ross.johnson at homemail.com.au>
+
+ * several (MINGW64): Cast and call fixups for 64 bit compatibility;
+ clean build via x86_64-w64-mingw32 cross toolchain on Linux i686
+ targeting x86_64 win64.
+ * ptw32_threadStart.c (ptw32_threadStart): Routine no longer attempts
+ to pass [unexpected C++] exceptions out of scope but ends the thread
+ normally setting EINTR as the exit status.
+ * ptw32_throw.c: Fix C++ exception throwing warnings; ignore
+ informational warning.
+ * implement.h: Likewise with the corresponding header definition.
+
+2011-03-04 Ross Johnson <ross.johnson at homemail.com.au>
+
+ * implement.h (PTW32_INTERLOCKED_*): Mingw32 does not provide
+ the __sync_* intrinsics so implemented them here as macro
+ assembler routines. MSVS Interlocked* are emmitted as intrinsics
+ wherever possible, so we want mingw to match it; Extended to
+ include all interlocked routines used by the library; implemented
+ x86_64 versions also.
+ * ptw32_InterlockedCompareExchange.c: No code remaining here.
+ * ptw32_MCS_lock.c: Converted interlocked calls to use new macros.
+ * pthread_barrier_wait.c: Likewise.
+ * pthread_once.c: Likewise.
+ * ptw32_MCS_lock.c (ptw32_mcs_node_substitute): Name changed to
+ ptw32_mcs_node_transfer.
+
+2011-02-28 Ross Johnson <ross.johnson at homemail.com.au>
+
+ * ptw32_relmillisecs.c: If possible, use _ftime64_s or _ftime64
+ before resorting to _ftime.
+
+2011-02-27 Ross Johnson <ross.johnson at homemail.com.au>
+
+ * sched_setscheduler.c: Ensure the handle is closed after use.
+ * sched_getscheduler.c: Likewise.
+ * pthread.h: Remove POSIX compatibility macros; don't define
+ timespec if already defined.
+ * context.h: Changes for 64 bit.
+ * pthread_cancel.c: Likewise.
+ * pthread_exit.c: Likewise.
+ * pthread_spin_destroy.c: Likewise.
+ * pthread_timechange_handler_np.c: Likewise.
+ * ptw32_MCS_lock.c: Likewise; some of these changes may
+ not be compatible with pre Windows 2000 systems; reverse the order of
+ the includes.
+ * ptw32_threadStart.c: Likewise.
+ * ptw32_throw.c: Likewise.
+
+2011-02-13 Ross Johnson <ross.johnson at homemail.com.au>
+
+ * pthread_self: Add comment re returning 'nil' value to
+ indicate failure only to win32 threads that call us.
+ * pthread_attr_setstackaddr: Fix comments; note this
+ function and it's compliment are now removed from SUSv4.
+
+2011-02-12 Ross Johnson <ross.johnson at homemail.com.au>
+
+ README.NONPORTABLE: Record a description of an obvious
+ method for nulling/comparing/hashing pthread_t using a
+ union; plus and investigation of a change of type for
+ pthread_t (to a union) to neutralise any padding bits and
+ bytes if they occur in pthread_t (the current pthread_t struct
+ does not contain padding AFAIK, but porting the library to a
+ future architecture may introduce them). Padding affects
+ byte-by-byte copies and compare operations.
+
+2010-11-16 Ross Johnson <ross.johnson at homemail.com.au>
+
+ * ChangeLog: Add this entry ;-)
+ Restore entries from 2007 through 2009 that went missing
+ at the last update.
+
+2010-06-19 Ross Johnson <ross.johnson at homemail.com.au>
+
+ * ptw32_MCS_lock.c (ptw32_mcs_node_substitute): Fix variable
+ names to avoid using C++ keyword ("new").
+ * implement.h (ptw32_mcs_node_substitute): Likewise.
+ * pthread_barrier_wait.c: Fix signed/unsigned comparison warning.
+
+2010-06-18 Ramiro Polla <ramiro.polla at gmail.com >
+
+ * autostatic.c: New file; call pthread_win32_process_*()
+ libary init/cleanup routines automatically on application start
+ when statically linked.
+ * pthread.c (autostatic.c): Included.
+ * pthread.h (declspec): Remove import/export defines if compiler
+ is MINGW.
+ * sched.h (declspec): Likewise.
+ * semaphore.h (declspec): Likewise.
+ * need_errno.h (declspec): Likewise.
+ * Makefile (autostatic.obj): Add for small static builds.
+ * GNUmakefile (autostatic.o): Likewise.
+ * NEWS (Version 2.9.0): Add changes.
+ * README.NONPORTABLE (pthread_win32_process_*): Update
+ description.
+
+2010-06-15 Ramiro Polla <ramiro.polla at gmail.com >
+
+ * Makefile: Remove linkage with the winsock library by default.
+ * GNUmakefile: Likewise.
+ * pthread_getspecific.c: Likewise by removing calls to WSA
+ functions.
+ * config.h (RETAIN_WSALASTERROR): Can be defined if necessary.
+
+2010-01-26 Ross Johnson <ross.johnson at homemail.com.au>
+
+ * ptw32_MCS_lock.c (ptw32_mcs_node_substitute): New routine
+ to allow relocating the lock owners thread-local node to somewhere
+ else, e.g. to global space so that another thread can release the
+ lock. Used in pthread_barrier_wait.
+ (ptw32_mcs_lock_try_acquire): New routine.
+ * pthread_barrier_init: Only one semaphore is used now.
+ * pthread_barrier_wait: Added an MCS guard lock with the last thread
+ to leave the barrier releasing the lock. This removes a deadlock bug
+ observed when there are greater than barrier-count threads
+ attempting to cross.
+ * pthread_barrier_destroy: Added an MCS guard lock.
+
+2009-03-03 Stephan O'Farrill <stephan dot ofarrill at gmail dot com>
+
+ * pthread_attr_getschedpolicy.c: Add "const" to function parameter
+ in accordance with SUSv3 (POSIX).
+ * pthread_attr_getinheritsched.c: Likewise.
+ * pthread_mutexattr_gettype.c: Likewise.
+
+2008-06-06 Robert Kindred <RKindred at SwRI dot edu>
+
+ * ptw32_throw.c (ptw32_throw): Remove possible reference to NULL
+ pointer. (At the same time made the switch block conditionally
+ included only if exitCode is needed - RPJ.)
+ * pthread_testcancel.c (pthread_testcancel): Remove duplicate and
+ misplaced pthread_mutex_unlock().
+
+2008-02-21 Sebastian Gottschalk <seppig_relay at gmx dot de>
+
+ * pthread_attr_getdetachstate.c (pthread_attr_getdetachstate):
+ Remove potential and superfluous null pointer assignment.
+
+2007-11-22 Ivan Pizhenko <ivanp4 at ua dot fm>
+
+ * pthread.h (gmtime_r): gmtime returns 0 if tm represents a time
+ prior to 1/1/1970. Notice this to prevent raising an exception.
+ * pthread.h (localtime_r): Likewise for localtime.
+
+2007-07-14 Marcel Ruff <mr at marcelruff dot info>
+
+ * errno.c (_errno): Fix test for pthread_self() success.
+ * need_errno.h: Remove unintentional line wrap from #if line.
+
+2007-07-14 Mike Romanchuk <mromanchuk at empirix dot com>
+
+ * pthread.h (timespec): Fix tv_sec type.
+
+2007-01-07 Sinan Kaya <sinan.kaya at siemens dot com>
+
+ * need_errno.h: Fix declaration of _errno - the local version of
+ _errno() is used, e.g. by WinCE.
+
+2007-01-06 Ross Johnson <ross.johnson at homemail dot com dot au>
+
+ * ptw32_semwait.c: Add check for invalid sem_t after acquiring the
+ sem_t state guard mutex and before affecting changes to sema state.
+
+2007-01-06 Marcel Ruff <mr at marcelruff dot info>
+
+ * error.c: Fix reference to pthread handle exitStatus member for
+ builds that use NEED_ERRNO (i.e. WINCE).
+ * context.h: Add support for ARM processor (WinCE).
+ * mutex.c (process.h): Exclude for WINCE.
+ * create.c: Likewise.
+ * exit.c: Likewise.
+ * implement.h: Likewise.
+ * pthread_detach.c (signal.h): Exclude for WINCE.
+ * pthread_join.c: Likewise.
+ * pthread_kill.c: Likewise.
+ * pthread_rwlock_init.c (errno.h): Remove - included by pthread.h.
+ * pthread_rwlock_destroy.c: Likewise.
+ * pthread_rwlock_rdlock.c: Likewise.
+ * pthread_rwlock_timedrdlock.c: Likewise.
+ * pthread_rwlock_timedwrlock.c: Likewise.
+ * pthread_rwlock_tryrdlock.c: Likewise.
+ * pthread_rwlock_trywrlock.c: likewise.
+ * pthread_rwlock_unlock.c: Likewise.
+ * pthread_rwlock_wrlock.c: Likewise.
+ * pthread_rwlockattr_destroy.c: Likewise.
+ * pthread_rwlockattr_getpshared.c: Likewise.
+ * pthread_rwlockattr_init.c: Likewise.
+ * pthread_rwlockattr_setpshared.c: Likewise.
+
+2007-01-06 Romano Paolo Tenca <rotenca at telvia dot it>
+
+ * pthread_cond_destroy.c: Replace sem_wait() with non-cancelable
+ ptw32_semwait() since pthread_cond_destroy() is not a cancelation
+ point.
+ * implement.h (ptw32_spinlock_check_need_init): Add prototype.
+ * ptw32_MCS_lock.c: Reverse order of includes.
+
+2007-01-06 Eric Berge <eric dot berge at quantum dot com>
+
+ * pthread_cond_destroy.c: Add LeaveCriticalSection before returning
+ after errors.
+
+2007-01-04 Ross Johnson <ross.johnson at homemail dot com dot au>
+
+ * ptw32_InterlockedCompareExchange.c: Conditionally skip for
+ Win64 as not required.
+ * pthread_win32_attach_detach_np.c (pthread_win32_process_attach_np):
+ Test for InterlockedCompareExchange is not required for Win64.
+ * context.h: New file. Included by pthread_cancel.h and any tests
+ that need it (e.g. context1.c).
+ * pthread_cancel.c: Architecture-dependent context macros moved
+ to context.h.
+
+2007-01-04 Kip Streithorst <KSTREITH at ball dot com>
+
+ * implement.h (PTW32_INTERLOCKED_COMPARE_EXCHANGE): Add Win64
+ support.
+
+2006-12-20 Ross Johnson <ross.johnson at homemail.com.au>
+
+ * sem_destroy.c: Fix the race involving invalidation of the sema;
+ fix incorrect return of EBUSY resulting from the mutex trylock
+ on the private mutex guard.
+ * sem_wait.c: Add check for invalid sem_t after acquiring the
+ sem_t state guard mutex and before affecting changes to sema state.
+ * sem_trywait.c: Likewise.
+ * sem_timedwait.c: Likewise.
+ * sem_getvalue.c: Likewise.
+ * sem_post.c: Similar.
+ * sem_post_multiple.c: Likewise.
+ * sem_init.c: Set max Win32 semaphore count to SEM_VALUE_MAX (was
+ _POSIX_SEM_VALUE_MAX, which is a lower value - the minimum).
+
+ * pthread_win32_attach_detach_np.c (pthread_win32_process_attach_np):
+ Load COREDLL.DLL under WINCE to check existence of
+ InterlockedCompareExchange() routine. This used to be done to test
+ for TryEnterCriticalSection() but was removed when this was no
+ longer needed.
+
+2006-01-25 Prashant Thakre <prashant.thakre at gmail.com>
+
+ * pthread_cancel.c: Added _M_IA64 register context support.
+
+2005-05-13 Ross Johnson <ross at callisto.canberra.edu.au>
+
+ * pthread_kill.c (pthread_kill): Remove check for Win32 thread
+ priority (to confirm HANDLE validity). Useless since thread HANDLEs
+ a not recycle-unique.
+
+2005-05-30 Vladimir Kliatchko <vladimir at kliatchko.com>
+
+ * pthread_once.c: Re-implement using an MCS queue-based lock. The form
+ of pthread_once is as proposed by Alexander Terekhov (see entry of
+ 2005-03-13). The MCS lock implementation does not require a unique
+ 'name' to identify the lock between threads. Attempts to get the Event
+ or Semaphore based versions of pthread_once to a satisfactory level
+ of robustness have thus far failed. The last problem (avoiding races
+ involving non recycle-unique Win32 HANDLEs) was giving everyone
+ grey hair trying to solve it.
+
+ * ptw32_MCS_lock.c: New MCS queue-based lock implementation. These
+ locks are efficient: they have very low overhead in the uncontended case;
+ are efficient in contention and minimise cache-coherence updates in
+ managing the user level FIFO queue; do not require an ABI change in the
+ library.
+
+2005-05-27 Alexander Gottwald <alexander.gottwald at s1999.tu-chemnitz.de>
+
+ * pthread.h: Some things, like HANDLE, were only defined if
+ PTW32_LEVEL was >= 3. They should always be defined.
+
+2005-05-25 Vladimir Kliatchko <vladimir at kliatchko.com>
+
+ * pthread_once.c: Eliminate all priority operations and other
+ complexity by replacing the event with a semaphore. The advantage
+ of the change is the ability to release just one waiter if the
+ init_routine thread is cancelled yet still release all waiters when
+ done. Simplify once_control state checks to improve efficiency
+ further.
+
+2005-05-24 Mikael Magnusson <mikaelmagnusson at glocalnet.net>
+
+ * GNUmakefile: Patched to allow cross-compile with mingw32 on Linux.
+ It uses macros instead of referencing dlltool, gcc and g++ directly;
+ added a call to ranlib. For example the GC static library can be
+ built with:
+ make CC=i586-mingw32msvc-gcc RC=i586-mingw32msvc-windres \
+ RANLIB=i586-mingw32msvc-ranlib clean GC-static
+
+2005-05-13 Ross Johnson <ross at callisto.canberra.edu.au>
+
+ * pthread_win32_attach_detach_np.c (pthread_win32_thread_detach_np):
+ Move on-exit-only stuff from ptw32_threadDestroy() to here.
+ * ptw32_threadDestroy.c: It's purpose is now only to reclaim thread
+ resources for detached threads, or via pthread_join() or
+ pthread_detach() on joinable threads.
+ * ptw32_threadStart.c: Calling user destruct routines has moved to
+ pthread_win32_thread_detach_np(); call pthread_win32_thread_detach_np()
+ directly if statically linking, otherwise do so via dllMain; store
+ thread return value in thread struct for all cases, including
+ cancellation and exception exits; thread abnormal exits go via
+ pthread_win32_thread_detach_np.
+ * pthread_join.c (pthread_join): Don't try to get return code from
+ Win32 thread - always get it from he thread struct.
+ * pthread_detach.c (pthread_detach): reduce extent of the thread
+ existence check since we now don't care if the Win32 thread HANDLE has
+ been closed; reclaim thread resources if the thread has exited already.
+ * ptw32_throw.c (ptw32_throw): For Win32 threads that are not implicit,
+ only Call thread cleanup if statically linking, otherwise leave it to
+ dllMain.
+ * sem_post.c (_POSIX_SEM_VALUE_MAX): Change to SEM_VALUE_MAX.
+ * sem_post_multiple.c: Likewise.
+ * sem_init.c: Likewise.
+
+2005-05-10 Ross Johnson <ross at callisto.canberra.edu.au>
+
+ * pthread_join.c (pthread_join): Add missing check for thread ID
+ reference count in thread existence test; reduce extent of the
+ existence test since we don't care if the Win32 thread HANDLE has
+ been closed.
+
+2005-05-09 Ross Johnson <ross at callisto.canberra.edu.au>
+
+ * ptw32_callUserDestroyRoutines.c: Run destructor process (i.e.
+ loop over all keys calling destructors) up to
+ PTHREAD_DESTRUCTOR_ITERATIONS times if TSD value isn't NULL yet;
+ modify assoc management.
+ * pthread_key_delete.c: Modify assoc management.
+ * ptw32_tkAssocDestroy.c: Fix error in assoc removal from chains.
+ * pthread.h
+ (_POSIX_THREAD_DESTRUCTOR_ITERATIONS): Define to value specified by
+ POSIX.
+ (_POSIX_THREAD_KEYS_MAX): Define to value specified by POSIX.
+ (PTHREAD_KEYS_MAX): Redefine [upward] to minimum required by POSIX.
+ (SEM_NSEMS_MAX): Define to implementation value.
+ (SEM_VALUE_MAX): Define to implementation value.
+ (_POSIX_SEM_NSEMS_MAX): Redefine to value specified by POSIX.
+ (_POSIX_SEM_VALUE_MAX): Redefine to value specified by POSIX.
+
+2005-05-06 Ross Johnson <ross at callisto.canberra.edu.au>
+
+ * signal.c (sigwait): Add a cancellation point to this otherwise
+ no-op.
+ * sem_init.c (sem_init): Check for and return ERANGE error.
+ * sem_post.c (sem_post): Likewise.
+ * sem_post_multiple.c (sem_post_multiple): Likewise.
+ * manual (directory): Added; see ChangeLog inside.
+
+2005-05-02 Ross Johnson <ross at callisto.canberra.edu.au>
+
+ * implement.h (struct pthread_key_t_): Change threadsLock to keyLock
+ so as not to be confused with the per thread lock 'threadlock';
+ change all references to it.
+ * implement.h (struct ThreadKeyAssoc): Remove lock; add prevKey
+ and prevThread pointers; re-implemented all routines that use this
+ struct. The effect of this is to save one handle per association,
+ which could potentially equal the number of keys multiplied by the
+ number of threads, accumulating over time - and to free the
+ association memory as soon as it is no longer referenced by either
+ the key or the thread. Previously, the handle and memory were
+ released only after BOTH key and thread no longer referenced the
+ association. That is, often no association resources were released
+ until the process itself exited. In addition, at least one race
+ condition has been removed - where two threads could attempt to
+ release the association resources simultaneously - one via
+ ptw32_callUserDestroyRoutines and the other via
+ pthread_key_delete.
+ - thanks to Richard Hughes at Aculab for discovering the problem.
+ * pthread_key_create.c: See above.
+ * pthread_key_delete.c: See above.
+ * pthread_setspecific.c: See above.
+ * ptw32_callUserDestroyRoutines.c: See above.
+ * ptw32_tkAssocCreate.c: See above.
+ * ptw32_tkAssocDestroy.c: See above.
+
+2005-04-27 Ross Johnson <ross at callisto.canberra.edu.au>
+
+ * sem_wait.c (ptw32_sem_wait_cleanup): after cancellation re-attempt
+ to acquire the semaphore to avoid a race with a late sem_post.
+ * sem_timedwait.c: Modify comments.
+
+2005-04-25 Ross Johnson <ross at callisto.canberra.edu.au>
+
+ * ptw32_relmillisecs.c: New module; converts future abstime to
+ milliseconds relative to 'now'.
+ * pthread_mutex_timedlock.c: Use new ptw32_relmillisecs routine in
+ place of internal code; remove the NEED_SEM code - this routine is now
+ implemented for builds that define NEED_SEM (WinCE etc)
+ * sem_timedwait.c: Likewise; after timeout or cancellation,
+ re-attempt to acquire the semaphore in case one has been posted since
+ the timeout/cancel occurred. Thanks to Stefan Mueller.
+ * Makefile: Add ptw32_relmillisecs.c module; remove
+ ptw32_{in,de}crease_semaphore.c modules.
+ * GNUmakefile: Likewise.
+ * Bmakefile: Likewise.
+
+ * sem_init.c: Re-write the NEED_SEM code to be consistent with the
+ non-NEED_SEM code, but retaining use of an event in place of the w32 sema
+ for w32 systems that don't include semaphores (WinCE);
+ the NEED_SEM versions of semaphores has been broken for a long time but is
+ now fixed and supports all of the same routines as the non-NEED_SEM case.
+ * sem_destroy.c: Likewise.
+ * sem_wait.c: Likewise.
+ * sem_post.c: Likewise.
+ * sem_post_multple.c: Likewise.
+ * implement.h: Likewise.
+ * sem_timedwait.c: Likewise; this routine is now
+ implemented for builds that define NEED_SEM (WinCE etc).
+ * sem_trywait.c: Likewise.
+ * sem_getvalue.c: Likewise.
+
+ * pthread_once.c: Yet more changes, reverting closer to Gottlob Frege's
+ first design, but retaining cancellation, priority boosting, and adding
+ preservation of W32 error codes to make pthread_once transparent to
+ GetLastError.
+
+2005-04-11 Ross Johnson <ross at callisto.canberra.edu.au>
+
+ * pthread_once.c (pthread_once): Added priority boosting to
+ solve starvation problem after once_routine cancellation.
+ See notes in file.
+
+2005-04-06 Kevin Lussier <Kevin at codegreennetworks.com>
+
+ * Makefile: Added debug targets for all versions of the library.
+
+2005-04-01 Ross Johnson <ross at callisto.canberra.edu.au>
+
+ * GNUmakefile: Add target to build libpthreadGC1.a as a static link
+ library.
+ * Makefile: Likewise for pthreadGC1.lib.
+
+2005-04-01 Kevin Lussier <Kevin at codegreennetworks.com>
+
+ * sem_timedwait.c (sem_timedwait): Increase size of temp variables to
+ avoid int overflows for large timeout values.
+ * implement.h (int64_t): Include or define.
+
+2005-03-31 Dimitar Panayotov <develop at mail.bg>^M
+
+ * pthread.h: Fix conditional defines for static linking.
+ * sched.h: Liekwise.
+ * semaphore.h: Likewise.
+ * dll.c (PTW32_STATIC_LIB): Module is conditionally included
+ in the build.
+
+2005-03-16 Ross Johnson <ross at callisto.canberra.edu.au>^M
+
+ * pthread_setcancelstate.c: Undo the last change.
+
+2005-03-16 Ross Johnson <ross at callisto.canberra.edu.au>^M
+
+ * pthread_setcancelstate.c: Don't check for an async cancel event
+ if the library is using alertable async cancel..
+
+2005-03-14 Ross Johnson <ross at callisto.canberra.edu.au>
+
+ * pthread_once.c (pthread_once): Downgrade interlocked operations to simple
+ memory operations where these are protected by the critical section; edit
+ comments.
+
+2005-03-13 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * pthread_once.c (pthread_once): Completely redesigned; a change was
+ required to the ABI (pthread_once_t_), and resulting in a version
+ compatibility index increment.
+
+ NOTES:
+ The design (based on pseudo code contributed by Gottlob Frege) avoids
+ creating a kernel object if there is no contention. See URL for details:-
+ http://sources.redhat.com/ml/pthreads-win32/2005/msg00029.html
+ This uses late initialisation similar to the technique already used for
+ pthreads-win32 mutexes and semaphores (from Alexander Terekhov).
+
+ The subsequent cancelation cleanup additions (by rpj) could not be implemented
+ without sacrificing some of the efficiency in Gottlob's design. In particular,
+ although each once_control uses it's own event to block on, a global CS is
+ required to manage it - since the event must be either re-usable or
+ re-creatable under cancelation. This is not needed in the non-cancelable
+ design because it is able to mark the event as closed (forever).
+
+ When uncontested, a CS operation is equivalent to an Interlocked operation
+ in speed. So, in the final design with cancelability, an uncontested
+ once_control operation involves a minimum of five interlocked operations
+ (including the LeaveCS operation).
+
+ ALTERNATIVES:
+ An alternative design from Alexander Terekhov proposed using a named mutex,
+ as sketched below:-
+
+ if (!once_control) { // May be in TLS
+ named_mutex::guard guard(&once_control2);
+ if (!once_control2) {
+ <init>
+ once_control2 = true;
+ }
+ once_control = true;
+ }
+
+ A more detailed description of this can be found here:-
+ http://groups.yahoo.com/group/boost/message/15442
+
+ [Although the definition of a suitable PTHREAD_ONCE_INIT precludes use of the
+ TLS located flag, this is not critical.]
+
+ There are three primary concerns though:-
+ 1) The [named] mutex is 'created' even in the uncontended case.
+ 2) A system wide unique name must be generated.
+ 3) Win32 mutexes are VERY slow even in the uncontended case. An uncontested
+ Win32 mutex lock operation can be 50 (or more) times slower than an
+ uncontested EnterCS operation.
+
+ Ultimately, the named mutex trick is making use of the global locks maintained
+ by the kernel.
+
+ * pthread.h (pthread_once_t_): One flag and an event HANDLE added.
+ (PTHREAD_ONCE_INIT): Additional values included.
+
+2005-03-08 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * pthread_once.c (pthread_once): Redesigned to elliminate potential
+ starvation problem.
+ - reported by Gottlob Frege <gottlobfrege at gmail.com>
+
+ * ptw32_threadDestroy.c (ptw32_threadDestroy): Implicit threads were
+ not closing their Win32 thread duplicate handle.
+ - reported by Dmitrii Semii <bogolt at gmail.com>
+
+2005-01-25 Ralf Kubis <RKubis at mc.com>
+
+ * Attempted acquisition of recursive mutex was causing waiting
+ threads to not be woken when the mutex is released.
+
+ * GNUmakefile (GCE): Generate correct version resource comments.
+
+2005-01-01 Konstantin Voronkov <beowinkle at yahoo.com>
+
+ * pthread_mutex_lock.c (pthread_mutex_lock): The new atomic exchange
+ mutex algorithm is known to allow a thread to steal the lock off
+ FIFO waiting threads. The next waiting FIFO thread gets a spurious
+ wake-up and must attempt to re-acquire the lock. The woken thread
+ was setting itself as the mutex's owner before the re-acquisition.
+
+2004-11-22 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * pthread_cond_wait.c (ptw32_cond_wait_cleanup): Undo change
+ from 2004-11-02.
+ * Makefile (DLL_VER): Added for DLL naming suffix - see README.
+ * GNUmakefile (DLL_VER): Likewise.
+ * Wmakefile (DLL_VER): Likewise.
+ * Bmakefile (DLL_VER): Likewise.
+ * pthread.dsw (version.rc): Added to MSVS workspace.
+
+2004-11-20 Boudewijn Dekker <b.dekker at ellipsis.nl>
+
+ * pthread_getspecific.c (pthread_getspecific): Check for
+ invalid (NULL) key argument.
+
+2004-11-19 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * config.h (PTW32_THREAD_ID_REUSE_INCREMENT): Added to allow
+ building the library for either unique thread IDs like Solaris
+ or non-unique thread IDs like Linux; allows application developers
+ to override the library's default insensitivity to some apps
+ that may not be strictly POSIX compliant.
+ * version.rc: New resource module to encode version information
+ within the DLL.
+ * pthread.h: Added PTW32_VERSION* defines and grouped sections
+ required by resource compiler together; bulk of file is skipped
+ if RC_INVOKED. Defined some error numbers and other names for
+ Borland compiler.
+
+2004-11-02 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * pthread_cond_wait.c (ptw32_cond_wait_cleanup): Lock CV mutex at
+ start of cleanup handler rather than at the end.
+ * implement.h (PTW32_THREAD_REUSE_EMPTY): Renamed from *_BOTTOM.
+ (ptw32_threadReuseBottom): New global variable.
+ * global.c (ptw32_threadReuseBottom): Declare new variable.
+ * ptw32_reuse.c (ptw32_reuse): Change reuse LIFO stack to LILO queue
+ to more evenly distribute use of reusable thread IDs; use renamed
+ PTW32_THREAD_REUSE_EMPTY.
+ * ptw32_processTerminate.c (ptw2_processTerminate): Use renamed
+ PTW32_THREAD_REUSE_EMPTY.
+
+2004-10-31 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * implement.h (PThreadState): Add new state value
+ 'PThreadStateCancelPending'.
+ * pthread_testcancel.c (pthread_testcancel): Use new thread
+ 'PThreadStateCancelPending' state as short cut to avoid entering
+ kernel space via WaitForSingleObject() call. This was obviated
+ by user space sema acquisition in sem_wait() and sem_timedwait(),
+ which are also cancelation points. A call to pthread_testcancel()
+ was required, which introduced a kernel call, effectively nullifying
+ any gains made by the user space sem acquisition checks.
+ * pthread_cancel.c (pthread_cancel): Set new thread
+ 'PThreadStateCancelPending' state.
+
+2004-10-29 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * implement.h (pthread_t): Renamed to ptw32_thread_t; struct contains
+ all thread state.
+ * pthread.h (ptw32_handle_t): New general purpose struct to serve
+ as a handle for various reusable object IDs - currently only used
+ by pthread_t; contains a pointer to ptw32_thread_t (thread state)
+ and a general purpose uint for use as a reuse counter or flags etc.
+ (pthread_t): typedef'ed to ptw32_handle_t; the uint is the reuse
+ counter that allows the library to maintain unique POSIX thread IDs.
+ When the pthread struct reuse stack was introduced, threads would
+ often acquire an identical ID to a previously destroyed thread. The
+ same was true for the pre-reuse stack library, by virtue of pthread_t
+ being the address of the thread struct. The new pthread_t retains
+ the reuse stack but provides virtually unique thread IDs.
+ * sem_wait.c (ptw32_sem_wait_cleanup): New routine used for
+ cancelation cleanup.
+ * sem_timedwait.c (ptw32_sem_timedwait_cleanup): Likewise.
+
+2004-10-22 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * sem_init.c (sem_init): Introduce a 'lock' element in order to
+ replace the interlocked operations with conventional serialisation.
+ This is needed in order to be able to atomically modify the sema
+ value and perform Win32 sema release operations. Win32 semaphores are
+ used instead of events in order to support efficient multiple posting.
+ If the whole modify/release isn't atomic, a race between
+ sem_timedwait() and sem_post() could result in a release when there is
+ no waiting semaphore, which would cause too many threads to proceed.
+ * sem_wait.c (sem_wait): Use new 'lock'element.
+ * sem_timedwait.c (sem_timedwait): Likewise.
+ * sem_trywait.c (sem_trywait): Likewise.
+ * sem_post.c (sem_post): Likewise.
+ * sem_post_multiple.c (sem_post_multiple): Likewise.
+ * sem_getvalue.c (sem_getvalue): Likewise.
+ * ptw32_semwait.c (ptw32_semwait): Likewise.
+ * sem_destroy.c (sem_destroy): Likewise; also tightened the conditions
+ for semaphore destruction; in particular, a semaphore will not be
+ destroyed if it has waiters.
+ * sem_timedwait.c (sem_timedwait): Added cancel cleanup handler to
+ restore sema value when cancelled.
+ * sem_wait.c (sem_wait): Likewise.
+
+2004-10-21 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * pthread_mutex_unlock.c (pthread_mutex_unlock): Must use PulseEvent()
+ rather than SetEvent() to reset the event if there are no waiters.
+
+2004-10-19 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * sem_init.c (sem_init): New semaphore model based on the same idea
+ as mutexes, i.e. user space interlocked check to avoid
+ unnecessarily entering kernel space. Wraps the Win32 semaphore and
+ keeps it's own counter. Although the motivation to do this has existed
+ for a long time, credit goes to Alexander Terekhov for providing
+ the logic. I have deviated slightly from AT's logic to add the waiters
+ count, which has made the code more complicated by adding cancelation
+ cleanup. This also appears to have broken the VCE (C++ EH) version of
+ the library (the same problem as previously reported - see BUGS #2),
+ only apparently not fixable using the usual workaround, nor by turning
+ all optimisation off. The GCE version works fine, so it is presumed to
+ be a bug in MSVC++ 6.0. The cancelation exception is thrown and caught
+ correctly, but the cleanup class destructor is never called. The failing
+ test is tests\semaphore4.c.
+ * sem_wait.c (sem_wait): Implemented user space check model.
+ * sem_post.c (sem_post): Likewise.
+ * sem_trywait.c (sem_trywait): Likewise.
+ * sem_timedwait.c (sem_timedwait): Likewise.
+ * sem_post_multiple.c (sem_post_multiple): Likewise.
+ * sem_getvalue.c (sem_getvalue): Likewise.
+ * ptw32_semwait.c (ptw32_semwait): Likewise.
+ * implement.h (sem_t_): Add counter element.
+
+2004-10-15 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * implement.h (pthread_mutex_t_): Use an event in place of
+ the POSIX semaphore.
+ * pthread_mutex_init.c: Create the event; remove semaphore init.
+ * pthread_mutex_destroy.c: Delete the event.
+ * pthread_mutex_lock.c: Replace the semaphore wait with the event wait.
+ * pthread_mutex_trylock.c: Likewise.
+ * pthread_mutex_timedlock.c: Likewise.
+ * pthread_mutex_unlock.c: Set the event.
+
+2004-10-14 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * pthread_mutex_lock.c (pthread_mutex_lock): New algorithm using
+ Terekhov's xchg based variation of Drepper's cmpxchg model.
+ Theoretically, xchg uses fewer clock cycles than cmpxchg (using IA-32
+ as a reference), however, in my opinion bus locking dominates the
+ equation on smp systems, so the model with the least number of bus
+ lock operations in the execution path should win, which is Terekhov's
+ variant. On IA-32 uni-processor systems, it's faster to use the
+ CMPXCHG instruction without locking the bus than to use the XCHG
+ instruction, which always locks the bus. This makes the two variants
+ equal for the non-contended lock (fast lane) execution path on up
+ IA-32. Testing shows that the xchg variant is faster on up IA-32 as
+ well if the test forces higher lock contention frequency, even though
+ kernel calls should be dominating the times (on up IA-32, both
+ variants used CMPXCHG instructions and neither locked the bus).
+ * pthread_mutex_timedlock.c pthread_mutex_timedlock(): Similarly.
+ * pthread_mutex_trylock.c (pthread_mutex_trylock): Similarly.
+ * pthread_mutex_unlock.c (pthread_mutex_unlock): Similarly.
+ * ptw32_InterlockedCompareExchange.c (ptw32_InterlockExchange): New
+ function.
+ (PTW32_INTERLOCKED_EXCHANGE): Sets up macro to use inlined
+ ptw32_InterlockedExchange.
+ * implement.h (PTW32_INTERLOCKED_EXCHANGE): Set default to
+ InterlockedExchange().
+ * Makefile: Building using /Ob2 so that asm sections within inline
+ functions are inlined.
+
+2004-10-08 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * pthread_mutex_destroy.c (pthread_mutex_destroy): Critical Section
+ element is no longer required.
+ * pthread_mutex_init.c (pthread_mutex_init): Likewise.
+ * pthread_mutex_lock.c (pthread_mutex_lock): New algorithm following
+ Drepper's paper at http://people.redhat.com/drepper/futex.pdf, but
+ using the existing semaphore in place of the futex described in the
+ paper. Idea suggested by Alexander Terekhov - see:
+ http://sources.redhat.com/ml/pthreads-win32/2003/msg00108.html
+ * pthread_mutex_timedlock.c pthread_mutex_timedlock(): Similarly.
+ * pthread_mutex_trylock.c (pthread_mutex_trylock): Similarly.
+ * pthread_mutex_unlock.c (pthread_mutex_unlock): Similarly.
+ * pthread_barrier_wait.c (pthread_barrier_wait): Use inlined version
+ of InterlockedCompareExchange() if possible - determined at
+ build-time.
+ * pthread_spin_destroy.c pthread_spin_destroy(): Likewise.
+ * pthread_spin_lock.c pthread_spin_lock():Likewise.
+ * pthread_spin_trylock.c (pthread_spin_trylock):Likewise.
+ * pthread_spin_unlock.c (pthread_spin_unlock):Likewise.
+ * ptw32_InterlockedCompareExchange.c: Sets up macro for inlined use.
+ * implement.h (pthread_mutex_t_): Remove Critical Section element.
+ (PTW32_INTERLOCKED_COMPARE_EXCHANGE): Set to default non-inlined
+ version of InterlockedCompareExchange().
+ * private.c: Include ptw32_InterlockedCompareExchange.c first for
+ inlining.
+ * GNUmakefile: Add commandline option to use inlined
+ InterlockedCompareExchange().
+ * Makefile: Likewise.
+
+2004-09-27 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * pthread_mutex_lock.c (pthread_mutex_lock): Separate
+ PTHREAD_MUTEX_NORMAL logic since we do not need to keep or check some
+ state required by other mutex types; do not check mutex pointer arg
+ for validity - leave this to the system since we are only checking
+ for NULL pointers. This should improve speed of NORMAL mutexes and
+ marginally improve speed of other type.
+ * pthread_mutex_trylock.c (pthread_mutex_trylock): Likewise.
+ * pthread_mutex_unlock.c (pthread_mutex_unlock): Likewise; also avoid
+ entering the critical section for the no-waiters case, with approx.
+ 30% reduction in lock/unlock overhead for this case.
+ * pthread_mutex_timedlock.c (pthread_mutex_timedlock): Likewise; also
+ no longer keeps mutex if post-timeout second attempt succeeds - this
+ will assist applications that wish to impose strict lock deadlines,
+ rather than simply to escape from frozen locks.
+
+2004-09-09 Tristan Savatier <tristan at mpegtv.com>
+ * pthread.h (struct pthread_once_t_): Qualify the 'done' element
+ as 'volatile'.
+ * pthread_once.c: Concerned about possible race condition,
+ specifically on MPU systems re concurrent access to multibyte types.
+ [Maintainer's note: the race condition is harmless on SPU systems
+ and only a problem on MPU systems if concurrent access results in an
+ exception (presumably generated by a hardware interrupt). There are
+ other instances of similar harmless race conditions that have not
+ been identified as issues.]
+
+2004-09-09 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * pthread.h: Declare additional types as volatile.
+
+2004-08-27 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * pthread_barrier_wait.c (pthread_barrier_wait): Remove excessive code
+ by substituting the internal non-cancelable version of sem_wait
+ (ptw32_semwait).
+
+2004-08-25 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * pthread_join.c (pthread_join): Rewrite and re-order the conditional
+ tests in an attempt to improve efficiency and remove a race
+ condition.
+
+2004-08-23 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * create.c (pthread_create): Don't create a thread if the thread
+ id pointer location (first arg) is inaccessible. A memory
+ protection fault will result if the thread id arg isn't an accessible
+ location. This is consistent with GNU/Linux but different to
+ Solaris or MKS (and possibly others), which accept NULL as meaning
+ 'don't return the created thread's ID'. Applications that run
+ using pthreads-win32 will run on all other POSIX threads
+ implementations, at least w.r.t. this feature.
+
+ It was decided not to copy the Solaris et al behaviour because,
+ although it would have simplified some application porting (but only
+ from Solaris to Windows), the feature is not technically necessary,
+ and the alternative segfault behaviour helps avoid buggy application
+ code.
+
+2004-07-01 Anuj Goyal <anuj.goyal at gmail.com>
+
+ * builddmc.bat: New; Windows bat file to build the library.
+ * config.h (__DMC__): Support for Digital Mars compiler.
+ * create.c (__DMC__): Likewise.
+ * pthread_exit.c (__DMC__): Likewise.
+ * pthread_join.c (__DMC__): Likewise.
+ * ptw32_threadDestroy.c (__DMC__): Likewise.
+ * ptw32_threadStart.c (__DMC__): Likewise.
+ * ptw32_throw.c (__DMC__): Likewise.
+
+2004-06-29 Anuj Goyal <anuj.goyal at gmail.com>
+
+ * pthread.h (__DMC__): Initial support for Digital Mars compiler.
+
+2004-06-29 Will Bryant <will.bryant at ecosm.com>
+
+ * README.Borland: New; description of Borland changes.
+ * Bmakefile: New makefile for the Borland make utility.
+ * ptw32_InterlockedCompareExchange.c:
+ Add Borland compatible asm code.
+
+2004-06-26 Jason Bard <BardJA at Npt.NUWC.Navy.Mil>
+
+ * pthread.h (HAVE_STRUCT_TIMESPEC): If undefined, define it
+ to avoid timespec struct redefined errors elsewhere in an
+ application.
+
+2004-06-21 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * pthread.h (PTHREAD_RECURSIVE_MUTEX_INITIALIZER): Mutex
+ initialiser added for compatibility with Linux threads and
+ others; currently not included in SUSV3.
+ * pthread.h (PTHREAD_ERRORCHECK_MUTEX_INITIALIZER): Likewise.
+ * pthread.h (PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP): Likewise.
+ * pthread.h (PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP): Likewise.
+
+ * ptw32_mutex_check_need_init.c (ptw32_mutex_check_need_init):
+ Add new initialisers.
+
+ * pthread_mutex_lock.c (pthread_mutex_lock): Check for new
+ initialisers.
+ * pthread_mutex_trylock.c (pthread_mutex_trylock): Likewise.
+ * pthread_mutex_timedlock.c (pthread_mutex_timedlock): Likewise.
+ * pthread_mutex_unlock.c (pthread_mutex_unlock): Likewise.
+ * pthread_mutex_destroy.c (pthread_mutex_destroy): Likewise.
+
+2004-05-20 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * README.NONPORTABLE: Document pthread_win32_test_features_np().
+ * FAQ: Update various answers.
+
+2004-05-19 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * Makefile: Don't define _WIN32_WINNT on compiler command line.
+ * GNUmakefile: Likewise.
+
+2004-05-16 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * pthread_cancel.c (pthread_cancel): Adapted to use auto-detected
+ QueueUserAPCEx features at run-time.
+ (ptw32_RegisterCancelation): Drop in replacement for QueueUserAPCEx()
+ if it can't be used. Provides older style non-preemptive async
+ cancelation.
+ * pthread_win32_attach_detach_np.c (pthread_win32_attach_np):
+ Auto-detect quserex.dll and the availability of alertdrv.sys;
+ initialise and close on process attach/detach.
+ * global.c (ptw32_register_cancelation): Pointer to either
+ QueueUserAPCEx() or ptw32_RegisterCancelation() depending on
+ availability. QueueUserAPCEx makes pre-emptive async cancelation
+ possible.
+ * implement.h: Add definitions and prototypes related to QueueUserAPC.
+
+2004-05-16 Panagiotis E. Hadjidoukas <peh at hpclab.ceid.upatras.gr>
+
+ * QueueUserAPCEx (separate contributed package): Provides preemptive
+ APC feature.
+ * pthread_cancel.c (pthread_cancel): Initial integration of
+ QueueUserAPCEx into pthreads-win32 to provide true pre-emptive
+ async cancelation of threads, including blocked threads.
+
+2004-05-06 Makoto Kato <raven at oldskool.jp>
+
+ * pthread.h (DWORD_PTR): Define typedef for older MSVC.
+ * pthread_cancel.c (AMD64): Add architecture specific Context register.
+ * ptw32_getprocessors.c: Use correct types (DWORD_PTR) for mask
+ variables.
+
+2004-04-06 P. van Bruggen <pietvb at newbridges.nl>
+
+ * ptw32_threadDestroy.c: Destroy threadLock mutex to
+ close a memory leak.
+
+2004-02-13 Gustav Hallberg <gustav at virtutech.com>
+
+ * pthread_equal.c: Remove redundant equality logic.
+
+2003-12-10 Philippe Di Cristo <philipped at voicebox.com>
+
+ * sem_timedwait.c (sem_timedwait): Fix timeout calculations.
+
+2003-10-20 Alexander Terekhov <TEREKHOV at de.ibm.com>
+
+ * pthread_mutex_timedlock.c (ptw32_semwait): Move to individual module.
+ * ptw32_semwait.c: New module.
+ * pthread_cond_wait.c (ptw32_cond_wait_cleanup): Replace cancelable
+ sem_wait() call with non-cancelable ptw32_semwait() call.
+ * pthread.c (private.c): Re-order for inlining. GNU C warned that
+ function ptw32_semwait() was defined 'inline' after it was called.
+ * pthread_cond_signal.c (ptw32_cond_unblock): Likewise.
+ * pthread_delay_np.c: Disable Watcom warning with comment.
+ * *.c (process.h): Remove include from .c files. This is conditionally
+ included by the common project include files.
+
+2003-10-20 James Ewing <james.ewing at sveasoft.com>
+
+ * ptw32_getprocessors.c: Some Win32 environments don't have
+ GetProcessAffinityMask(), so always return CPU count = 1 for them.
+ * config.h (NEED_PROCESSOR_AFFINITY_MASK): Define for WinCE.
+
+2003-10-15 Ross Johnson <ross at callisto.canberra.edu.au>
+
+ * Re-indented all .c files using default GNU style to remove assorted
+ editor ugliness (used GNU indent utility in default style).
+
+2003-10-15 Alex Blanco <Alex.Blanco at motorola.com>
+
+ * sem_init.c (sem_init): Would call CreateSemaphore even if the sema
+ struct calloc failed; was not freeing calloced memory if either
+ CreateSemaphore or CreateEvent failed.
+
+2003-10-14 Ross Johnson <ross at callisto.canberra.edu.au>
+
+ * pthread.h: Add Watcom compiler compatibility. Esssentially just add
+ the cdecl attribute to all exposed function prototypes so that Watcom
+ generates function call code compatible with non-Watcom built libraries.
+ By default, Watcom uses registers to pass function args if possible rather
+ than pushing to stack.
+ * semaphore.h: Likewise.
+ * sched.h: Likewise.
+ * pthread_cond_wait.c (ptw32_cond_wait_cleanup): Define with cdecl attribute
+ for Watcom compatibility. This routine is called via pthread_cleanup_push so
+ it had to match function arg definition.
+ * Wmakefile: New makefile for Watcom builds.
+
+2003-09-14 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * pthread_setschedparam.c (pthread_setschedparam): Attempt to map
+ all priority levels between max and min (as returned by
+ sched_get_priority_min/max) to reasonable Win32 priority levels - i.e.
+ levels between THREAD_PRIORITY_LOWEST/IDLE to THREAD_PRIORITY_LOWEST and
+ between THREAD_PRIORITY_HIGHEST/TIME_CRITICAL to THREAD_PRIORITY_HIGHEST
+ while others remain unchanged; record specified thread priority level
+ for return by pthread_getschedparam.
+
+ Note that, previously, specified levels not matching Win32 priority levels
+ would silently leave the current thread priority unaltered.
+
+ * pthread_getschedparam.c (pthread_getschedparam): Return the priority
+ level specified by the latest pthread_setschedparam or pthread_create rather
+ than the actual running thread priority as returned by GetThreadPriority - as
+ required by POSIX. I.e. temporary or adjusted actual priority levels are not
+ returned by this routine.
+
+ * pthread_create.c (pthread_create): For priority levels specified via
+ pthread attributes, attempt to map all priority levels between max and
+ min (as returned by sched_get_priority_min/max) to reasonable Win32
+ priority levels; record priority level given via attributes, or
+ inherited from parent thread, for later return by pthread_getschedparam.
+
+ * ptw32_new.c (ptw32_new): Initialise pthread_t_ sched_priority element.
+
+ * pthread_self.c (pthread_self): Set newly created implicit POSIX thread
+ sched_priority to Win32 thread's current actual priority. Temporarily
+ altered priorities can't be avoided in this case.
+
+ * implement.h (struct pthread_t_): Add new sched_priority element.
+
+2003-09-12 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * sched_get_priority_min.c (sched_get_priority_min): On error should return -1
+ with errno set.
+ * sched_get_priority_max.c (sched_get_priority_max): Likewise.
+
+2003-09-03 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * w32_cancelableWait.c (ptw32_cancelable_wait): Allow cancelation
+ of implicit POSIX threads as well.
+
+2003-09-02 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * pthread_win32_attach_detach_np.c (pthread_win32_thread_detach_np):
+ Add comment.
+
+ * pthread_exit.c (pthread_exit): Fix to recycle the POSIX thread handle in
+ addition to calling user TSD destructors. Move the implicit POSIX thread exit
+ handling to ptw32_throw to centralise the logic.
+
+ * ptw32_throw.c (ptw32_throw): Implicit POSIX threads have no point
+ to jump or throw to, so cleanup and exit the thread here in this case. For
+ processes using the C runtime, the exit code will be set to the POSIX
+ reason for the throw (i.e. PTHREAD_CANCEL or the value given to pthread_exit).
+ Note that pthread_exit() already had similar logic, which has been moved to
+ here.
+
+ * ptw32_threadDestroy.c (ptw32_threadDestroy): Don't close the Win32 handle
+ of implicit POSIX threads - expect this to be done by Win32?
+
+2003-09-01 Ross Johnson <rpj at callisto.canberra.edu.au>
+
+ * pthread_self.c (pthread_self): The newly aquired pthread_t must be
+ assigned to the reuse stack, not freed, if the routine fails somehow.
+
+2003-08-13 Ross Johnson <rpj at ise.canberra.edu.au>
+
+ * pthread_getschedparam.c (pthread_getschedparam): An invalid thread ID
+ parameter was returning an incorrect error value; now uses a more exhaustive
+ check for validity.
+
+ * pthread_setschedparam.c (pthread_setschedparam): Likewise.
+
+ * pthread_join.c (pthread_join): Now uses a more exhaustive
+ check for validity.
+
+ * pthread_detach.c (pthread_detach): Likewise.
+
+ * pthread_cancel.c (pthread_cancel): Likewise.
+
+ * ptw32_threadDestroy.c (ptw32_threadDestroy): pthread_t structs are
+ never freed - push them onto a stack for reuse.
+
+ * ptw32_new.c (ptw32_new): Check for reusable pthread_t before dynamically
+ allocating new memory for the struct.
+
+ * pthread_kill.c (pthread_kill): New file; new routine; takes only a zero
+ signal arg so that applications can check the thread arg for validity; checks
+ that the underlying Win32 thread HANDLE is valid.
+
+ * pthread.h (pthread_kill): Add prototype.
+
+ * ptw32_reuse.c (ptw32_threadReusePop): New file; new routine; pop a
+ pthread_t off the reuse stack. pthread_t_ structs that have been destroyed, i.e.
+ have exited detached or have been joined, are cleaned up and put onto a reuse
+ stack. Consequently, thread IDs are no longer freed once calloced. The library
+ will attempt to get a struct off this stack before asking the system to alloc
+ new memory when creating threads. The stack is guarded by a global mutex.
+ (ptw32_threadReusePush): New routine; push a pthread_t onto the reuse stack.
+
+ * implement.h (ptw32_threadReusePush): Add new prototype.
+ (ptw32_threadReusePop): Likewise.
+ (pthread_t): Add new element.
+
+ * ptw32_processTerminate.c (ptw32_processTerminate): Delete the thread
+ reuse lock; free all thread ID structs on the thread reuse stack.
+
+ * ptw32_processInitialize.c (ptw32_processInitialize): Initialise the
+ thread reuse lock.
+
+2003-07-19 Ross Johnson <rpj at ise.canberra.edu.au>
+
+ * GNUmakefile: modified to work under MsysDTK environment.
+ * pthread_spin_lock.c (pthread_spin_lock): Check for NULL arg.
+ * pthread_spin_unlock.c (pthread_spin_unlock): Likewise.
+ * pthread_spin_trylock.c (pthread_spin_trylock): Likewise;
+ fix incorrect pointer value if lock is dynamically initialised by
+ this function.
+ * sem_init.c (sem_init): Initialise sem_t value to quell compiler warning.
+ * sem_destroy.c (sem_destroy): Likewise.
+ * ptw32_threadStart.c (non-MSVC code sections): Include <exception> rather
+ than old-style <new.h>; fix all std:: namespace entities such as
+ std::terminate_handler instances and associated methods.
+ * ptw32_callUserDestroyRoutines.c (non-MSVC code sections): Likewise.
+
+2003-06-24 Piet van Bruggen <pietvb at newbridges.nl>
+
+ * pthread_spin_destroy.c (pthread_spin_destroy): Was not freeing the
+ spinlock struct.
+
+2003-06-22 Nicolas Barry <boozai at yahoo.com>
+
+ * pthread_mutex_destroy.c (pthread_mutex_destroy): When called
+ with a recursive mutex that was locked by the current thread, the
+ function was failing with a success return code.
+
+2003-05-15 Steven Reddie <Steven.Reddie at ca.com>
+
+ * pthread_win32_attach_detach_np.c (pthread_win32_process_detach_np):
+ NULLify ptw32_selfThreadKey after the thread is destroyed, otherwise
+ destructors calling pthreads routines might resurrect it again, creating
+ memory leaks. Call the underlying Win32 Tls routine directly rather than
+ pthread_setspecific().
+ (pthread_win32_thread_detach_np): Likewise.
+
+2003-05-14 Viv <vcotirlea at hotmail.com>
+
+ * pthread.dsp: Change /MT compile flag to /MD.
+
+2003-03-04 Alexander Terekhov <TEREKHOV at de.ibm.com>
+
+ * pthread_mutex_timedlock.c (pthread_mutex_timedlock): Fix failure to
+ set ownership of mutex on second grab after abstime timeout.
+ - bug reported by Robert Strycek <strycek at posam.sk>
+
+2002-12-17 Thomas Pfaff <tpfaff at gmx.net>
+
+ * pthread_mutex_lock.c (ptw32_semwait): New static routine to provide
+ a non-cancelable sem_wait() function. This is consistent with the
+ way that pthread_mutex_timedlock.c does it.
+ (pthread_mutex_lock): Use ptw32_semwait() instead of sem_wait().
+
+2002-12-11 Thomas Pfaff <tpfaff at gmx.net>
+
+ * pthread_mutex_trylock.c: Should return EBUSY rather than EDEADLK.
+ * pthread_mutex_destroy.c: Remove redundant ownership test (the
+ trylock call does this for us); do not destroy a recursively locked
+ mutex.
+
+2002-09-20 Michael Johnson <michaelj at maine.rr.com>
+
+ * pthread_cond_destroy.c (pthread_cond_destroy):
+ When two different threads exist, and one is attempting to
+ destroy a condition variable while the other is attempting to
+ initialize a condition variable that was created with
+ PTHREAD_COND_INITIALIZER, a deadlock can occur. Shrink
+ the ptw32_cond_list_lock critical section to fix it.
+
+2002-07-31 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * ptw32_threadStart.c (ptw32_threadStart): Thread cancelLock
+ destruction moved to ptw32_threadDestroy().
+
+ * ptw32_threadDestroy.c (ptw32_threadDestroy): Destroy
+ the thread's cancelLock. Moved here from ptw32_threadStart.c
+ to cleanup implicit threads as well.
+
+2002-07-30 Alexander Terekhov <TEREKHOV at de.ibm.com>
+
+ * pthread_cond_wait.c (ptw32_cond_wait_cleanup):
+ Remove code designed to avoid/prevent spurious wakeup
+ problems. It is believed that the sem_timedwait() call
+ is consuming a CV signal that it shouldn't and this is
+ breaking the avoidance logic.
+
+2002-07-30 Ross Johnson <rpj at ise.canberra.edu.au>
+
+ * sem_timedwait.c (sem_timedwait): Tighten checks for
+ unreasonable abstime values - that would result in
+ unexpected timeout values.
+
+ * w32_CancelableWait.c (ptw32_cancelable_wait):
+ Tighten up return value checking and add comments.
+
+
+2002-06-08 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * sem_getvalue.c (sem_getvalue): Now returns a value for the
+ NEED_SEM version (i.e. earlier versions of WinCE).
+
+
+2002-06-04 Rob Fanner <rfanner at stonethree.com>
+
+ * sem_getvalue.c (sem_getvalue): The Johnson M. Hart
+ approach didn't work - we are forced to take an
+ intrusive approach. We try to decrement the sema
+ and then immediately release it again to get the
+ value. There is a small probability that this may
+ block other threads, but only momentarily.
+
+2002-06-03 Ross Johnson <rpj at ise.canberra.edu.au>
+
+ * sem_init.c (sem_init): Initialise Win32 semaphores
+ to _POSIX_SEM_VALUE_MAX (which this implementation
+ defines in pthread.h) so that sem_getvalue() can use
+ the trick described in the comments in sem_getvalue().
+ * pthread.h (_POSIX_SEM_VALUE_MAX): Defined.
+ (_POSIX_SEM_NSEMS_MAX): Defined - not used but may be
+ useful for source code portability.
+
+2002-06-03 Rob Fanner <rfanner at stonethree.com>
+
+ * sem_getvalue.c (sem_getvalue): Did not work on NT.
+ Use approach suggested by Johnson M. Hart in his book
+ "Win32 System Programming".
+
+2002-02-28 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * errno.c: Compiler directive was incorrectly including code.
+ * pthread.h: Conditionally added some #defines from config.h
+ needed when not building the library. e.g. NEED_ERRNO, NEED_SEM.
+ (PTW32_DLLPORT): Now only defined if _DLL defined.
+ (_errno): Compiler directive was incorrectly including prototype.
+ * sched.h: Conditionally added some #defines from config.h
+ needed when not building the library.
+ * semaphore.h: Replace an instance of NEED_SEM that should
+ have been NEED_ERRNO. This change currently has nil effect.
+
+ * GNUmakefile: Correct some recent changes.
+
+ * Makefile: Add rule to generate pre-processor output.
+
+2002-02-23 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * pthread_rwlock_timedrdlock.c: New - untested.
+ * pthread_rwlock_timedwrlock.c: New - untested.
+
+ * Testsuite passed (except known MSVC++ problems)
+
+ * pthread_cond_destroy.c: Expand the time change
+ critical section to solve deadlock problem.
+
+ * pthread.c: Add all remaining C modules.
+ * pthread.h: Use dllexport/dllimport attributes on functions
+ to avoid using pthread.def.
+ * sched.h: Likewise.
+ * semaphore.h: Likewise.
+ * GNUmakefile: Add new targets for single translation
+ unit build to maximise inlining potential; generate
+ pthread.def automatically.
+ * Makefile: Likewise, but no longer uses pthread.def.
+
+2002-02-20 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * pthread_cond_destroy.c (pthread_cond_destroy):
+ Enter the time change critical section earlier.
+
+2002-02-17 Ross Johnson <rpj at setup1.ise.canberra.edu.au
+
+ * Testsuite passed.
+
+ * pthread_timechange_handler_np.c: New; following
+ a suggestion from Alexander Terekhov that CVs should
+ be broadcast so that they all re-evaluate their
+ condition variables and reset a new timeout if
+ required, whenever an application receives a
+ WM_TIMECHANGE message. This message indicates that
+ the system time has been changed. Therefore, CVs
+ waiting for a timeout set as an abs_time will possibly
+ not wake up at the expected time. Some applications
+ may not be tolerant of this.
+ * pthread_cond_init.c: Add CV to linked list.
+ * pthread_cond_destroy.c: Remove CV from linked list.
+ * global.c (ptw32_cond_list_head): New variable.
+ (ptw32_cond_list_tail): New variable.
+ (ptw32_cond_list_cs): New critical section.
+ * ptw32_processInitialize (ptw32_cond_list_cs): Initialize.
+ * ptw32_processTerminate (ptw32_cond_list_cs): Delete.
+
+
+ * Reduce executable size.
+ -----------------------
+ When linking with the static library, only those
+ routines actually called, either directly or indirectly
+ should be included.
+
+ [Gcc has the -ffunction-segments option to do this but MSVC
+ doesn't have this feature as far as I can determine. Other
+ compilers are undetermined as well. - rpj]
+
+ * spin.c: Split file into function segments.
+ * ptw32_spinlock_check_need_init.c: Separated routine from spin.c.
+ * pthread_spin_init.c: Likewise.
+ * pthread_spin_destroy.c: Likewise.
+ * pthread_spin_lock.c: Likewise.
+ * pthread_spin_unlock.c: Likewise.
+ * pthread_spin_trylock.c: Likewise.
+
+ * sync.c: Split file into function segments.
+ * pthread_detach.c: Separated routine from sync.c.
+ * pthread_join.c: Likewise.
+
+ * tsd.c: Split file into function segments.
+ * pthread_key_create.c: Separated routine from tsd.c.
+ * pthread_key_delete.c: Likewise.
+ * pthread_setspecific.c: Likewise.
+ * pthread_getspecific.c: Likewise.
+
+ * sched.c: Split file into function segments.
+ * pthread_attr_setschedpolicy.c: Separated routine from sched.c.
+ * pthread_attr_getschedpolicy.c: Likewise.
+ * pthread_attr_setschedparam.c: Likewise.
+ * pthread_attr_getschedparam.c: Likewise.
+ * pthread_attr_setinheritsched.c: Likewise.
+ * pthread_attr_getinheritsched.c: Likewise.
+ * pthread_setschedparam.c: Likewise.
+ * pthread_getschedparam.c: Likewise.
+ * sched_get_priority_max.c: Likewise.
+ * sched_get_priority_min.c: Likewise.
+ * sched_setscheduler.c: Likewise.
+ * sched_getscheduler.c: Likewise.
+ * sched_yield.c: Likewise.
+
+
+2002-02-16 Ross Johnson <rpj at setup1.ise.canberra.edu.au
+
+ Reduce executable size.
+ -----------------------
+ When linking with the static library, only those
+ routines actually called, either directly or indirectly
+ should be included.
+
+ [Gcc has the -ffunction-segments option to do this but MSVC
+ doesn't have this feature as far as I can determine. Other
+ compilers are undetermined as well. - rpj]
+
+ * mutex.c: Split file into function segments.
+ * pthread_mutexattr_destroy.c: Separated routine from mutex.c
+ * pthread_mutexattr_getpshared.c: Likewise.
+ * pthread_mutexattr_gettype.c: Likewise.
+ * pthread_mutexattr_init.c: Likewise.
+ * pthread_mutexattr_setpshared.c: Likewise.
+ * pthread_mutexattr_settype.c: Likewise.
+ * ptw32_mutex_check_need_init.c: Likewise.
+ * pthread_mutex_destroy.c: Likewise.
+ * pthread_mutex_init.c: Likewise.
+ * pthread_mutex_lock.c: Likewise.
+ * pthread_mutex_timedlock.c: Likewise.
+ * pthread_mutex_trylock.c: Likewise.
+ * pthread_mutex_unlock.c: Likewise.
+
+ * private.c: Split file into function segments.
+ * ptw32_InterlockedCompareExchange.c: Separated routine from private.c
+ * ptw32_callUserDestroyRoutines.c: Likewise.
+ * ptw32_getprocessors.c: Likewise.
+ * ptw32_processInitialize.c: Likewise.
+ * ptw32_processTerminate.c: Likewise.
+ * ptw32_threadDestroy.c: Likewise.
+ * ptw32_threadStart.c: Likewise.
+ * ptw32_throw.c: Likewise.
+ * ptw32_timespec.c: Likewise.
+ * ptw32_tkAssocCreate.c: Likewise.
+ * ptw32_tkAssocDestroy.c: Likewise.
+
+ * rwlock.c: Split file into function segments.
+ * pthread_rwlockattr_destroy.c: Separated routine from rwlock.c
+ * pthread_rwlockattr_getpshared.c: Likewise.
+ * pthread_rwlockattr_init.c: Likewise.
+ * pthread_rwlockattr_setpshared.c: Likewise.
+ * ptw32_rwlock_check_need_init.c: Likewise.
+ * pthread_rwlock_destroy.c: Likewise.
+ * pthread_rwlock_init.c: Likewise.
+ * pthread_rwlock_rdlock.c: Likewise.
+ * pthread_rwlock_tryrdlock.c: Likewise.
+ * pthread_rwlock_trywrlock.c: Likewise.
+ * pthread_rwlock_unlock.c: Likewise.
+ * pthread_rwlock_wrlock.c: Likewise.
+
+2002-02-10 Ross Johnson <rpj at setup1.ise.canberra.edu.au
+
+ Reduce executable size.
+ -----------------------
+ When linking with the static library, only those
+ routines actually called, either directly or indirectly
+ should be included.
+
+ [Gcc has the -ffunction-segments option to do this but MSVC
+ doesn't have this feature as far as I can determine. Other
+ compilers are undetermined as well. - rpj]
+
+ * nonportable.c: Split file into function segments.
+ * np_delay.c: Separated routine from nonportable.c
+ * np_getw32threadhandle.c: Likewise.
+ * np_mutexattr_setkind.c: Likewise.
+ * np_mutexattr_getkind.c: Likewise.
+ * np_num_processors.c: Likewise.
+ * np_win32_attach_detach.c: Likewise.
+
+ * misc.c: Split file into function segments.
+ * pthread_equal.c: Separated routine from nonportable.c.
+ * pthread_getconcurrency.c: Likewise.
+ * pthread_once.c: Likewise.
+ * pthread_self.c: Likewise.
+ * pthread_setconcurrency.c: Likewise.
+ * ptw32_calloc.c: Likewise.
+ * ptw32_new.c: Likewise.
+ * w32_CancelableWait.c: Likewise.
+
+2002-02-09 Ross Johnson <rpj at setup1.ise.canberra.edu.au
+
+ Reduce executable size.
+ -----------------------
+ When linking with the static library, only those
+ routines actually called, either directly or indirectly
+ should be included.
+
+ [Gcc has the -ffunction-segments option to do this but MSVC
+ doesn't have this feature as far as I can determine. Other
+ compilers are undetermined as well. - rpj]
+
+ * condvar.c: Split file into function segments.
+ * pthread_condattr_destroy.c: Separated routine from condvar.c.
+ * pthread_condattr_getpshared.c: Likewise.
+ * pthread_condattr_init.c: Likewise.
+ * pthread_condattr_setpshared.c: Likewise.
+ * ptw32_cond_check_need_init.c: Likewise.
+ * pthread_cond_destroy.c: Likewise.
+ * pthread_cond_init.c: Likewise.
+ * pthread_cond_signal.c: Likewise.
+ * pthread_cond_wait.c: Likewise.
+
+2002-02-07 Alexander Terekhov<TEREKHOV at de.ibm.com>
+
+ * nonportable.c (pthread_delay_np): Make a true
+ cancelation point. Deferred cancels will interrupt the
+ wait.
+
+2002-02-07 Ross Johnson <rpj at setup1.ise.canberra.edu.au
+
+ * misc.c (ptw32_new): Add creation of cancelEvent so that
+ implicit POSIX threads (Win32 threads with a POSIX face)
+ are cancelable; mainly so that pthread_delay_np doesn't fail
+ if called from the main thread.
+ * create.c (pthread_create): Remove creation of cancelEvent
+ from here; now in ptw32_new().
+
+ Reduce executable size.
+ -----------------------
+ When linking with the static library, only those
+ routines actually called, either directly or indirectly
+ should be included.
+
+ [Gcc has the -ffunction-segments option to do this but MSVC
+ doesn't have this feature as far as I can determine. Other
+ compilers are undetermined as well. - rpj]
+
+ * barrier.c: All routines are now in separate compilation units;
+ This file is used to congregate the separate modules for
+ potential inline optimisation and backward build compatibility.
+ * cancel.c: Likewise.
+ * pthread_barrierattr_destroy.c: Separated routine from cancel.c.
+ * pthread_barrierattr_getpshared.c: Likewise.
+ * pthread_barrierattr_init.c: Likewise.
+ * pthread_barrierattr_setpshared.c: Likewise.
+ * pthread_barrier_destroy.c: Likewise.
+ * pthread_barrier_init.c: Likewise.
+ * pthread_barrier_wait.c: Likewise.
+ * pthread_cancel.c: Likewise.
+ * pthread_setcancelstate.c: Likewise.
+ * pthread_setcanceltype.c: Likewise.
+ * pthread_testcancel.c: Likewise.
+
+2002-02-04 Max Woodbury <mtew at cds.duke.edu>
+
+ Reduced name space pollution.
+ -----------------------------
+ When the appropriate symbols are defined, the headers
+ will restrict the definitions of new names. In particular,
+ it must be possible to NOT include the <windows.h>
+ header and related definitions with some combination
+ of symbol definitions. Secondly, it should be possible
+ that additional definitions should be limited to POSIX
+ compliant symbols by the definition of appropriate symbols.
+
+ * pthread.h: POSIX conditionals.
+ * sched.h: POSIX conditionals.
+ * semaphore.h: POSIX conditionals.
+
+ * semaphore.c: Included <limits.h>.
+ (sem_init): Changed magic 0x7FFFFFFFL to INT_MAX.
+ (sem_getvalue): Trial version.
+
+ Reduce executable size.
+ -----------------------
+ When linking with the static library, only those
+ routines actually called, either directly or indirectly
+ should be included.
+
+ [Gcc has the -ffunction-segments option to do this but MSVC
+ doesn't have this feature as far as I can determine. Other
+ compilers are undetermined as well. - rpj]
+
+ * semaphore.c: All routines are now in separate compilation units;
+ This file is used to congregate the separate modules for
+ potential inline optimisation and backward build compatibility.
+ * sem_close.c: Separated routine from semaphore.c.
+ * ptw32_decrease_semaphore.c: Likewise.
+ * sem_destroy.c: Likewise.
+ * sem_getvalue.c: Likewise.
+ * ptw32_increase_semaphore.c: Likewise.
+ * sem_init.c: Likewise.
+ * sem_open.c: Likewise.
+ * sem_post.c: Likewise.
+ * sem_post_multiple.c: Likewise.
+ * sem_timedwait.c: Likewise.
+ * sem_trywait.c: Likewise.
+ * sem_unlink.c: Likewise.
+ * sem_wait.c: Likewise.
+
+2002-02-04 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ The following extends the idea above to the rest of pthreads-win32 - rpj
+
+ * attr.c: All routines are now in separate compilation units;
+ This file is used to congregate the separate modules for
+ potential inline optimisation and backward build compatibility.
+ * pthread_attr_destroy.c: Separated routine from attr.c.
+ * pthread_attr_getdetachstate.c: Likewise.
+ * pthread_attr_getscope.c: Likewise.
+ * pthread_attr_getstackaddr.c: Likewise.
+ * pthread_attr_getstacksize.c: Likewise.
+ * pthread_attr_init.c: Likewise.
+ * pthread_attr_is_attr.c: Likewise.
+ * pthread_attr_setdetachstate.c: Likewise.
+ * pthread_attr_setscope.c: Likewise.
+ * pthread_attr_setstackaddr.c: Likewise.
+ * pthread_attr_setstacksize.c: Likewise.
+
+ * pthread.c: Agregation of agregate modules for super-inlineability.
+
+2002-02-02 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * cancel.c: Rearranged some code and introduced checks
+ to disable cancelation at the start of a thread's cancelation
+ run to prevent double cancelation. The main problem
+ arises if a thread is canceling and then receives a subsequent
+ async cancel request.
+ * private.c: Likewise.
+ * condvar.c: Place pragmas around cleanup_push/pop to turn
+ off inline optimisation (/Obn where n>0 - MSVC only). Various
+ optimisation switches in MSVC turn this on, which interferes with
+ the way that cleanup handlers are run in C++ EH and SEH
+ code. Application code compiled with inline optimisation must
+ also wrap cleanup_push/pop blocks with the pragmas, e.g.
+ #pragma inline_depth(0)
+ pthread_cleanup_push(...)
+ ...
+ pthread_cleanup_pop(...)
+ #pragma inline_depth(8)
+ * rwlock.c: Likewise.
+ * mutex.c: Remove attempts to inline some functions.
+ * signal.c: Modify misleading comment.
+
+2002-02-01 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * semaphore.c (sem_trywait): Fix missing errno return
+ for systems that define NEED_SEM (e.g. early WinCE).
+ * mutex.c (pthread_mutex_timedlock): Return ENOTSUP
+ for systems that define NEED_SEM since they don't
+ have sem_trywait().
+
+2002-01-27 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * mutex.c (pthread_mutex_timedlock): New function suggested by
+ Alexander Terekhov. The logic required to implement this
+ properly came from Alexander, with some collaboration
+ with Thomas Pfaff.
+ (pthread_mutex_unlock): Wrap the waiters check and sema
+ post in a critical section to prevent a race with
+ pthread_mutex_timedlock.
+ (ptw32_timed_semwait): New function;
+ returns a special result if the absolute timeout parameter
+ represents a time already passed when called; used by
+ pthread_mutex_timedwait(). Have deliberately not reused
+ the name "ptw32_sem_timedwait" because they are not the same
+ routine.
+ * condvar.c (ptw32_cond_timedwait): Use the new sem_timedwait()
+ instead of ptw32_sem_timedwait(), which now has a different
+ function. See previous.
+ * implement.h: Remove prototype for ptw32_sem_timedwait.
+ See next.
+ (pthread_mutex_t_): Add critical section element for access
+ to lock_idx during mutex post-timeout processing.
+ * semaphore.h (sem_timedwait): See next.
+ * semaphore.c (sem_timedwait): See next.
+ * private.c (ptw32_sem_timedwait): Move to semaphore.c
+ and rename as sem_timedwait().
+
+2002-01-18 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * sync.c (pthread_join): Was getting the exit code from the
+ calling thread rather than the joined thread if
+ defined(__MINGW32__) && !defined(__MSVCRT__).
+
+2002-01-15 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * pthread.h: Unless the build explicitly defines __CLEANUP_SEH,
+ __CLEANUP_CXX, or __CLEANUP_C, then the build defaults to
+ __CLEANUP_C style cleanup. This style uses setjmp/longjmp
+ in the cancelation and thread exit implementations and therefore
+ won't do stack unwinding if linked to applications that have it
+ (e.g. C++ apps). This is currently consistent with most/all
+ commercial Unix POSIX threads implementations.
+
+ * spin.c (pthread_spin_init): Edit renamed function call.
+ * nonportable.c (pthread_num_processors_np): New.
+ (pthread_getprocessors_np): Renamed to ptw32_getprocessors
+ and moved to private.c.
+ * private.c (pthread_getprocessors): Moved here from
+ nonportable.c.
+ * pthread.def (pthread_getprocessors_np): Removed
+ from export list.
+
+ * rwlock.c (pthread_rwlockattr_init): New.
+ (pthread_rwlockattr_destroy): New.
+ (pthread_rwlockattr_getpshared): New.
+ (pthread_rwlockattr_setpshared): New.
+
+2002-01-14 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * attr.c (pthread_attr_setscope): Fix struct pointer
+ indirection error introduced 2002-01-04.
+ (pthread_attr_getscope): Likewise.
+
+2002-01-12 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * pthread.dsp (SOURCE): Add missing source files.
+
+2002-01-08 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * mutex.c (pthread_mutex_trylock): use
+ ptw32_interlocked_compare_exchange function pointer
+ rather than ptw32_InterlockedCompareExchange() directly
+ to retain portability to non-iX86 processors,
+ e.g. WinCE etc. The pointer will point to the native
+ OS version of InterlockedCompareExchange() if the
+ OS supports it (see ChangeLog entry of 2001-10-17).
+
+2002-01-07 Thomas Pfaff <tpfaff at gmx.net>, Alexander Terekhov <TEREKHOV at de.ibm.com>
+
+ * mutex.c (pthread_mutex_init): Remove critical
+ section calls.
+ (pthread_mutex_destroy): Likewise.
+ (pthread_mutex_unlock): Likewise.
+ (pthread_mutex_trylock): Likewise; uses
+ ptw32_InterlockedCompareExchange() to avoid need for
+ critical section; library is no longer i386 compatible;
+ recursive mutexes now increment the lock count rather
+ than return EBUSY; errorcheck mutexes return EDEADLCK
+ rather than EBUSY. This behaviour is consistent with the
+ Solaris pthreads implementation.
+ * implement.h (pthread_mutex_t_): Remove critical
+ section element - no longer needed.
+
+
+2002-01-04 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * attr.c (pthread_attr_setscope): Add more error
+ checking and actually store the scope value even
+ though it's not really necessary.
+ (pthread_attr_getscope): Return stored value.
+ * implement.h (pthread_attr_t_): Add new scope element.
+ * ANNOUNCE: Fix out of date comment next to
+ pthread_attr_setscope in conformance section.
+
+2001-12-21 Alexander Terekhov <TEREKHOV at de.ibm.com>
+
+ * mutex.c (pthread_mutex_lock): Decrementing lock_idx was
+ not thread-safe.
+ (pthread_mutex_trylock): Likewise.
+
+2001-10-26 prionx@juno.com
+
+ * semaphore.c (sem_init): Fix typo and missing bracket
+ in conditionally compiled code. Only older versions of
+ WinCE require this code, hence it doesn't normally get
+ tested; somehow when sem_t reverted to an opaque struct
+ the calloc NULL check was left in the conditionally included
+ section.
+ (sem_destroy): Likewise, the calloced sem_t wasn't being freed.
+
+2001-10-25 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * GNUmakefile (libwsock32): Add to linker flags for
+ WSAGetLastError() and WSASetLastError().
+ * Makefile (wsock32.lib): Likewise.
+ * create.c: Minor mostly inert changes.
+ * implement.h (PTW32_MAX): Move into here and renamed
+ from sched.h.
+ (PTW32_MIN): Likewise.
+ * GNUmakefile (TEST_ICE): Define if testing internal
+ implementation of InterlockedCompareExchange.
+ * Makefile (TEST_ICE): Likewise.
+ * private.c (TEST_ICE): Likewise.
+
+2001-10-24 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * attr.c (pthread_attr_setstacksize): Quell warning
+ from LCC by conditionally compiling the stacksize
+ validity check. LCC correctly warns that the condition
+ (stacksize < PTHREAD_STACK_MIN) is suspicious
+ because STACK_MIN is 0 and stacksize is of type
+ size_t (or unsigned int).
+
+2001-10-17 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * barrier.c: Move _LONG and _LPLONG defines into
+ implement.h; rename to PTW32_INTERLOCKED_LONG and
+ PTW32_INTERLOCKED_LPLONG respectively.
+ * spin.c: Likewise; ptw32_interlocked_compare_exchange used
+ in place of InterlockedCompareExchange directly.
+ * global.c (ptw32_interlocked_compare_exchange): Add
+ prototype for this new routine pointer to be used when
+ InterlockedCompareExchange isn't supported by Windows.
+ * nonportable.c (pthread_win32_process_attach_np): Check for
+ support of InterlockedCompareExchange in kernel32 and assign its
+ address to ptw32_interlocked_compare_exchange if it exists, or
+ our own ix86 specific implementation ptw32_InterlockedCompareExchange.
+ *private.c (ptw32_InterlockedCompareExchange): An
+ implementation of InterlockedCompareExchange() which is
+ specific to ix86; written directly in assembler for either
+ MSVC or GNU C; needed because Windows 95 doesn't support
+ InterlockedCompareExchange().
+
+ * sched.c (sched_get_priority_min): Extend to return
+ THREAD_PRIORITY_IDLE.
+ (sched_get_priority_max): Extend to return
+ THREAD_PRIORITY_CRITICAL.
+
+2001-10-15 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * spin.c (pthread_spin_lock): PTHREAD_SPINLOCK_INITIALIZER
+ was causing a program fault.
+ (pthread_spin_init): Could have alloced memory
+ without freeing under some error conditions.
+
+ * mutex.c (pthread_mutex_init): Move memory
+ allocation of mutex struct after checking for
+ PROCESS_SHARED.
+
+2001-10-12 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * spin.c (pthread_spin_unlock): Was not returning
+ EPERM if the spinlock was not locked, for multi CPU
+ machines.
+
+2001-10-08 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * spin.c (pthread_spin_trylock): Was not returning
+ EBUSY for multi CPU machines.
+
+2001-08-24 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * condvar.c (pthread_cond_destroy): Remove cv element
+ that is no longer used.
+ * implement.h: Likewise.
+
+2001-08-23 Alexander Terekhov <TEREKHOV at de.ibm.com>
+
+ * condvar.c (pthread_cond_destroy): fix bug with
+ respect to deadlock in the case of concurrent
+ _destroy/_unblock; a condition variable can be destroyed
+ immediately after all the threads that are blocked on
+ it are awakened.
+
+2001-08-23 Phil Frisbie, Jr. <phil at hawksoft.com>
+
+ * tsd.c (pthread_getspecific): Preserve the last
+ winsock error [from WSAGetLastError()].
+
+2001-07-18 Scott McCaskill <scott at magruder.org>
+
+ * mutex.c (pthread_mutexattr_init): Return ENOMEM
+ immediately and don't dereference the NULL pointer
+ if calloc fails.
+ (pthread_mutexattr_getpshared): Don't dereference
+ a pointer that is possibly NULL.
+ * barrier.c (pthread_barrierattr_init): Likewise
+ (pthread_barrierattr_getpshared): Don't dereference
+ a pointer that is possibly NULL.
+ * condvar.c (pthread_condattr_getpshared): Don't dereference
+ a pointer that is possibly NULL.
+
+2001-07-15 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * rwlock.c (pthread_rwlock_wrlock): Is allowed to be
+ a cancelation point; re-enable deferred cancelability
+ around the CV call.
+
+2001-07-10 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * barrier.c: Still more revamping. The exclusive access
+ mutex isn't really needed so it has been removed and replaced
+ by an InterlockedDecrement(). nSerial has been removed.
+ iStep is now dual-purpose. The process shared attribute
+ is now stored in the barrier struct.
+ * implement.h (pthread_barrier_t_): Lost some/gained one
+ elements.
+ * private.c (ptw32_threadStart): Removed some comments.
+
+2001-07-10 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * barrier.c: Revamped to fix the race condition. Two alternating
+ semaphores are used instead of the PulseEvent. Also improved
+ overall throughput by returning PTHREAD_BARRIER_SERIAL_THREAD
+ to the first waking thread.
+ * implement.h (pthread_barrier_t_): Revamped.
+
+2001-07-09 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * barrier.c: Fix several bugs in all routines. Now passes
+ tests/barrier5.c which is fairly rigorous. There is still
+ a non-optimal work-around for a race condition between
+ the barrier breeched event signal and event wait. Basically
+ the last (signalling) thread to hit the barrier yields
+ to allow any other threads, which may have lost the race,
+ to complete.
+
+2001-07-07 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * barrier.c: Changed synchronisation mechanism to a
+ Win32 manual reset Event and use PulseEvent to signal
+ waiting threads. If the implementation continued to use
+ a semaphore it would require a second semaphore and
+ some management to use them alternately as barriers. A
+ single semaphore allows threads to cascade from one barrier
+ through the next, leaving some threads blocked at the first.
+ * implement.h (pthread_barrier_t_): As per above.
+ * general: Made a number of other routines inlinable.
+
+2001-07-07 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * spin.c: Revamped and working; included static initialiser.
+ Now beta level.
+ * barrier.c: Likewise.
+ * condvar.c: Macro constant change; inline auto init routine.
+ * mutex.c: Likewise.
+ * rwlock.c: Likewise.
+ * private.c: Add support for spinlock initialiser.
+ * global.c: Likewise.
+ * implement.h: Likewise.
+ * pthread.h (PTHREAD_SPINLOCK_INITIALIZER): Fix typo.
+
+2001-07-05 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * barrier.c: Remove static initialisation - irrelevent
+ for this object.
+ * pthread.h (PTHREAD_BARRIER_INITIALIZER): Removed.
+ * rwlock.c (pthread_rwlock_wrlock): This routine is
+ not a cancelation point - disable deferred
+ cancelation around call to pthread_cond_wait().
+
+2001-07-05 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * spin.c: New module implementing spin locks.
+ * barrier.c: New module implementing barriers.
+ * pthread.h (_POSIX_SPIN_LOCKS): defined.
+ (_POSIX_BARRIERS): Defined.
+ (pthread_spin_*): Defined.
+ (pthread_barrier*): Defined.
+ (PTHREAD_BARRIER_SERIAL_THREAD): Defined.
+ * implement.h (pthread_spinlock_t_): Defined.
+ (pthread_barrier_t_): Defined.
+ (pthread_barrierattr_t_): Defined.
+
+ * mutex.c (pthread_mutex_lock): Return with the error
+ if an auto-initialiser initialisation fails.
+
+ * nonportable.c (pthread_getprocessors_np): New; gets the
+ number of available processors for the current process.
+
+2001-07-03 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * pthread.h (_POSIX_READER_WRITER_LOCKS): Define it
+ if not already defined.
+
+2001-07-01 Alexander Terekhov <TEREKHOV at de.ibm.com>
+
+ * condvar.c: Fixed lost signal bug reported by Timur Aydin
+ (taydin@snet.net).
+ [RPJ (me) didn't translate the original algorithm
+ correctly.]
+ * semaphore.c: Added sem_post_multiple; this is a useful
+ routine, but it doesn't appear to be standard. For now it's
+ not an exported function.
+
+2001-06-25 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * create.c (pthread_create): Add priority inheritance
+ attributes.
+ * mutex.c (pthread_mutex_lock): Remove some overhead for
+ PTHREAD_MUTEX_NORMAL mutex types. Specifically, avoid
+ calling pthread_self() and pthread_equal() to check/set
+ the mutex owner. Introduce a new pseudo owner for this
+ type. Test results suggest increases in speed of up to
+ 90% for non-blocking locks.
+ This is the default type of mutex used internally by other
+ synchronising objects, ie. condition variables and
+ read-write locks. The test rwlock7.c shows about a
+ 30-35% speed increase over snapshot 2001-06-06. The
+ price of this is that the application developer
+ must ensure correct behaviour, or explicitly set the
+ mutex to a safer type such as PTHREAD_MUTEX_ERRORCHECK.
+ For example, PTHREAD_MUTEX_NORMAL (or PTHREAD_MUTEX_DEFAULT)
+ type mutexes will not return an error if a thread which is not
+ the owner calls pthread_mutex_unlock. The call will succeed
+ in unlocking the mutex if it is currently locked, but a
+ subsequent unlock by the true owner will then fail with EPERM.
+ This is however consistent with some other implementations.
+ (pthread_mutex_unlock): Likewise.
+ (pthread_mutex_trylock): Likewise.
+ (pthread_mutex_destroy): Likewise.
+ * attr.c (pthread_attr_init): PTHREAD_EXPLICIT_SCHED is the
+ default inheritance attribute; THREAD_PRIORITY_NORMAL is
+ the default priority for new threads.
+ * sched.c (pthread_attr_setschedpolicy): Added routine.
+ (pthread_attr_getschedpolicy): Added routine.
+ (pthread_attr_setinheritsched): Added routine.
+ (pthread_attr_getinheritsched): Added routine.
+ * pthread.h (sched_rr_set_interval): Added as a macro;
+ returns -1 with errno set to ENOSYS.
+
+2001-06-23 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ *sched.c (pthread_attr_setschedparam): Add priority range
+ check.
+ (sched_setscheduler): New function; checks for a valid
+ pid and policy; checks for permission to set information
+ in the target process; expects pid to be a Win32 process ID,
+ not a process handle; the only scheduler policy allowed is
+ SCHED_OTHER.
+ (sched_getscheduler): Likewise, but checks for permission
+ to query.
+ * pthread.h (SCHED_*): Moved to sched.h as defined in the
+ POSIX standard.
+ * sched.h (SCHED_*): Moved from pthread.h.
+ (pid_t): Defined if necessary.
+ (sched_setscheduler): Defined.
+ (sched_getscheduler): Defined.
+ * pthread.def (sched_setscheduler): Exported.
+ (sched_getscheduler): Likewise.
+
+2001-06-23 Ralf Brese <Ralf.Brese at pdb4.siemens.de>
+
+ * create.c (pthread_create): Set thread priority from
+ thread attributes.
+
+2001-06-18 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * Made organisational-only changes to UWIN additions.
+ * dll.c (dllMain): Moved UWIN process attach code
+ to pthread_win32_process_attach_np(); moved
+ instance of pthread_count to global.c.
+ * global.c (pthread_count): Moved from dll.c.
+ * nonportable.c (pthread_win32_process_attach_np):
+ Moved _UWIN code to here from dll.c.
+ * implement.h (pthread_count): Define extern int.
+ * create.c (pthread_count): Remove extern int.
+ * private.c (pthread_count): Likewise.
+ * exit.c (pthread_count): Likewise.
+
+2001-06-18 David Korn <dgk at research.att.com>
+
+ * dll.c: Added changes necessary to work with UWIN.
+ * create.c: Likewise.
+ * pthread.h: Likewise.
+ * misc.c: Likewise.
+ * exit.c: Likewise.
+ * private.c: Likewise.
+ * implement.h: Likewise.
+ There is some room at the start of struct pthread_t_
+ to implement the signal semantics in UWIN's posix.dll
+ although this is not yet complete.
+ * Nmakefile: Compatible with UWIN's Nmake utility.
+ * Nmakefile.tests: Likewise - for running the tests.
+
+2001-06-08 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * semaphore.h (sem_t): Fixed for compile and test.
+ * implement.h (sem_t_): Likewise.
+ * semaphore.c: Likewise.
+ * private.c (ptw32_sem_timedwait): Updated to use new
+ opaque sem_t.
+
+2001-06-06 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * semaphore.h (sem_t): Is now an opaque pointer;
+ moved actual definition to implement.h.
+ * implement.h (sem_t_): Move here from semaphore.h;
+ was the definition of sem_t.
+ * semaphore.c: Wherever necessary, changed use of sem
+ from that of a pointer to a pointer-pointer; added
+ extra checks for a valid sem_t; NULL sem_t when
+ it is destroyed; added extra checks when creating
+ and destroying sem_t elements in the NEED_SEM
+ code branches; changed from using a pthread_mutex_t
+ ((*sem)->mutex) to CRITICAL_SECTION ((*sem)->sem_lock_cs)
+ in NEED_SEM branches for access serialisation.
+
+2001-06-06 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * mutex.c (pthread_mutexattr_init): Remove
+ ptw32_mutex_default_kind.
+
+2001-06-05 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * nonportable.c (pthread_mutex_setdefaultkind_np):
+ Remove - should not have been included in the first place.
+ (pthread_mutex_getdefaultkind_np): Likewise.
+ * global.c (ptw32_mutex_default_kind): Likewise.
+ * mutex.c (pthread_mutex_init): Remove use of
+ ptw32_mutex_default_kind.
+ * pthread.h (pthread_mutex_setdefaultkind_np): Likewise.
+ (pthread_mutex_getdefaultkind_np): Likewise.
+ * pthread.def (pthread_mutexattr_setkind_np): Added.
+ (pthread_mutexattr_getkind_np): Likewise.
+
+ * README: Many changes that should have gone in before
+ the last snapshot.
+ * README.NONPORTABLE: New - referred to by ANNOUNCE
+ but never created; documents the non-portable routines
+ included in the library - moved from README with new
+ routines added.
+ * ANNOUNCE (pthread_mutexattr_setkind_np): Added to
+ compliance list.
+ (pthread_mutexattr_getkind_np): Likewise.
+
+2001-06-04 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * condvar.c: Add original description of the algorithm as
+ developed by Terekhov and Thomas, plus reference to
+ README.CV.
+
+2001-06-03 Alexander Terekhov <TEREKHOV at de.ibm.com>, Louis Thomas <lthomas at arbitrade.com>
+
+ * condvar.c (pthread_cond_init): Completely revamped.
+ (pthread_cond_destroy): Likewise.
+ (ptw32_cond_wait_cleanup): Likewise.
+ (ptw32_cond_timedwait): Likewise.
+ (ptw32_cond_unblock): New general signaling routine.
+ (pthread_cond_signal): Now calls ptw32_cond_unblock.
+ (pthread_cond_broadcast): Likewise.
+ * implement.h (pthread_cond_t_): Revamped.
+ * README.CV: New; explanation of the above changes.
+
+2001-05-30 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * pthread.h (rand_r): Fake using _seed argument to quell
+ compiler warning (compiler should optimise this away later).
+
+ * GNUmakefile (OPT): Leave symbolic information out of the library
+ and increase optimisation level - for smaller faster prebuilt
+ dlls.
+
+2001-05-29 Milan Gardian <Milan.Gardian at LEIBINGER.com>
+
+ * Makefile: fix typo.
+ * pthreads.h: Fix problems with stdcall/cdecl conventions, in particular
+ remove the need for PT_STDCALL everywhere; remove warning supression.
+ * (errno): Fix the longstanding "inconsistent dll linkage" problem
+ with errno; now also works with /MD debugging libs -
+ warnings emerged when compiling pthreads library with /MD (or /MDd)
+ compiler switch, instead of /MT (or /MTd) (i.e. when compiling pthreads
+ using Multithreaded DLL CRT instead of Multithreaded statically linked
+ CRT).
+ * create.c (pthread_create): Likewise; fix typo.
+ * private.c (ptw32_threadStart): Eliminate use of terminate() which doesn't
+ throw exceptions.
+ * Remove unnecessary #includes from a number of modules -
+ [I had to #include malloc.h in implement.h for gcc - rpj].
+
+2001-05-29 Thomas Pfaff <tpfaff at gmx.net>
+
+ * pthread.h (PTHREAD_MUTEX_DEFAULT): New; equivalent to
+ PTHREAD_MUTEX_DEFAULT_NP.
+ * (PTHREAD_MUTEX_NORMAL): Similarly.
+ * (PTHREAD_MUTEX_ERRORCHECK): Similarly.
+ * (PTHREAD_MUTEX_RECURSIVE): Similarly.
+ * (pthread_mutex_setdefaultkind_np): New; Linux compatibility stub
+ for pthread_mutexattr_settype.
+ * (pthread_mutexattr_getkind_np): New; Linux compatibility stub
+ for pthread_mutexattr_gettype.
+ * mutex.c (pthread_mutexattr_settype): New; allow
+ the following types of mutex:
+ PTHREAD_MUTEX_DEFAULT_NP
+ PTHREAD_MUTEX_NORMAL_NP
+ PTHREAD_MUTEX_ERRORCHECK_NP
+ PTHREAD_MUTEX_RECURSIVE_NP
+ * Note that PTHREAD_MUTEX_DEFAULT is equivalent to
+ PTHREAD_MUTEX_NORMAL - ie. mutexes should no longer
+ be recursive by default, and a thread will deadlock if it
+ tries to relock a mutex it already owns. This is inline with
+ other pthreads implementations.
+ * (pthread_mutex_lock): Process the lock request
+ according to the mutex type.
+ * (pthread_mutex_init): Eliminate use of Win32 mutexes as the
+ basis of POSIX mutexes - instead, a combination of one critical section
+ and one semaphore are used in conjunction with Win32 Interlocked* routines.
+ * (pthread_mutex_destroy): Likewise.
+ * (pthread_mutex_lock): Likewise.
+ * (pthread_mutex_trylock): Likewise.
+ * (pthread_mutex_unlock): Likewise.
+ * Use longjmp/setjmp to implement cancelation when building the library
+ using a C compiler which doesn't support exceptions, e.g. gcc -x c (note
+ that gcc -x c++ uses exceptions).
+ * Also fixed some of the same typos and eliminated PT_STDCALL as
+ Milan Gardian's patches above.
+
+2001-02-07 Alexander Terekhov <TEREKHOV at de.ibm.com>
+
+ * rwlock.c: Revamped.
+ * implement.h (pthread_rwlock_t_): Redefined.
+ This implementation does not have reader/writer starvation problem.
+ Rwlock attempts to behave more like a normal mutex with
+ races and scheduling policy determining who is more important;
+ It also supports recursive locking,
+ has less synchronization overhead (no broadcasts at all,
+ readers are not blocked on any condition variable) and seem to
+ be faster than the current implementation [W98 appears to be
+ approximately 15 percent faster at least - on top of speed increase
+ from Thomas Pfaff's changes to mutex.c - rpj].
+
+2000-12-29 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * Makefile: Back-out "for" loops which don't work.
+
+ * GNUmakefile: Remove the fake.a target; add the "realclean"
+ target; don't remove built libs under the "clean" target.
+
+ * config.h: Add a guard against multiple inclusion.
+
+ * semaphore.h: Add some defines from config.h to make
+ semaphore.h independent of config.h when building apps.
+
+ * pthread.h (_errno): Back-out previous fix until we know how to
+ fix it properly.
+
+ * implement.h (lockCount): Add missing element to pthread_mutex_t_.
+
+ * sync.c (pthread_join): Spelling fix in comment.
+
+ * private.c (ptw32_threadStart): Reset original termination
+ function (C++).
+ (ptw32_threadStart): Cleanup detached threads early in case
+ the library is statically linked.
+ (ptw32_callUserDestroyRoutines): Remove [SEH] __try block from
+ destructor call so that unhandled exceptions will be passed through
+ to the system; call terminate() from [C++] try block for the same
+ reason.
+
+ * tsd.c (pthread_getspecific): Add comment.
+
+ * mutex.c (pthread_mutex_init): Initialise new elements in
+ pthread_mutex_t.
+ (pthread_mutex_unlock): Invert "pthread_equal()" test.
+
+2000-12-28 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * semaphore.c (mode_t): Use ifndef HAVE_MODE_T to include definition.
+
+ * config.h.in (HAVE_MODE_T): Added.
+ (_UWIN): Start adding defines for the UWIN package.
+
+ * private.c (ptw32_threadStart): Unhandled exceptions are
+ now passed through to the system to deal with. This is consistent
+ with normal Windows behaviour. C++ applications may use
+ set_terminate() to override the default behaviour which is
+ to call ptw32_terminate(). Ptw32_terminate() cleans up some
+ POSIX thread stuff before calling the system default function
+ which calls abort(). The users termination function should conform
+ to standard C++ semantics which is to not return. It should
+ exit the thread (call pthread_exit()) or exit the application.
+ * private.c (ptw32_terminate): Added as the default set_terminate()
+ function. It calls the system default function after cleaning up
+ some POSIX thread stuff.
+
+ * implement.h (ptw32_try_enter_critical_section): Move
+ declaration.
+ * global.c (ptw32_try_enter_critical_section): Moved
+ from dll.c.
+ * dll.c: Move process and thread attach/detach code into
+ functions in nonportable.c.
+ * nonportable.c (pthread_win32_process_attach_np): Process
+ attach code from dll.c is now available to static linked
+ applications.
+ * nonportable.c (pthread_win32_process_detach_np): Likewise.
+ * nonportable.c (pthread_win32_thread_attach_np): Likewise.
+ * nonportable.c (pthread_win32_thread_detach_np): Likewise.
+
+ * pthread.h: Add new non-portable prototypes for static
+ linked applications.
+
+ * GNUmakefile (OPT): Increase optimisation flag and remove
+ debug info flag.
+
+ * pthread.def: Add new non-portable exports for static
+ linked applications.
+
+2000-12-11 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * FAQ: Update Answer 6 re getting a fully working
+ Mingw32 built library.
+
+2000-10-10 Steven Reddie <smr at essemer.com.au>
+
+ * misc.c (pthread_self): Restore Win32 "last error"
+ cleared by TlsGetValue() call in
+ pthread_getspecific()
+
+2000-09-20 Arthur Kantor <akantor at bexusa.com>
+
+ * mutex.c (pthread_mutex_lock): Record the owner
+ of the mutex. This requires also keeping count of
+ recursive locks ourselves rather than leaving it
+ to Win32 since we need to know when to NULL the
+ thread owner when the mutex is unlocked.
+ (pthread_mutex_trylock): Likewise.
+ (pthread_mutex_unlock): Check that the calling
+ thread owns the mutex, decrement the recursive
+ lock count, and NULL the owner if zero. Return
+ EPERM if the mutex is owned by another thread.
+ * implement.h (pthread_mutex_t_): Add ownerThread
+ and lockCount members.
+
+2000-09-13 Jef Gearhart <jgearhart at tpssys.com>
+
+ * mutex.c (pthread_mutex_init): Call
+ TryEnterCriticalSection through the pointer
+ rather than directly so that the dll can load
+ on Windows versions that can't resolve the
+ function, eg. Windows 95
+
+2000-09-09 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * pthread.h (ctime_r): Fix arg.
+
+2000-09-08 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * GNUmakefile(_WIN32_WINNT=0x400): Define in CFLAGS;
+ doesn't seem to be needed though.
+
+ * cancel.c (pthread_cancel): Must get "self" through
+ calling pthread_self() which will ensure a POSIX thread
+ struct is built for non-POSIX threads; return an error
+ if this fails
+ - Ollie Leahy <ollie at mpt.ie>
+ (pthread_setcancelstate): Likewise.
+ (pthread_setcanceltype): Likewise.
+ * misc.c (ptw32_cancelable_wait): Likewise.
+
+ * private.c (ptw32_tkAssocCreate): Remove unused #if 0
+ wrapped code.
+
+ * pthread.h (ptw32_get_exception_services_code):
+ Needed to be forward declared unconditionally.
+
+2000-09-06 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * cancel.c (pthread_cancel): If called from the main
+ thread "self" would be NULL; get "self" via pthread_self()
+ instead of directly from TLS so that an implicit
+ pthread object is created.
+
+ * misc.c (pthread_equal): Strengthen test for NULLs.
+
+2000-09-02 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * condvar.c (ptw32_cond_wait_cleanup): Ensure that all
+ waking threads check if they are the last, and notify
+ the broadcaster if so - even if an error occurs in the
+ waiter.
+
+ * semaphore.c (_decrease_semaphore): Should be
+ a call to ptw32_decrease_semaphore.
+ (_increase_semaphore): Should be a call to
+ ptw32_increase_semaphore.
+
+ * misc.c (ptw32_cancelable_wait): Renamed from
+ CancelableWait.
+ * rwlock.c (_rwlock_check*): Renamed to
+ ptw32_rwlock_check*.
+ * mutex.c (_mutex_check*): Renamed to ptw32_mutex_check*.
+ * condvar.c (cond_timed*): Renamed to ptw32_cond_timed*.
+ (_cond_check*): Renamed to ptw32_cond_check*.
+ (cond_wait_cleanup*): Rename to ptw32_cond_wait_cleanup*.
+ (ptw32_cond_timedwait): Add comments.
+
+2000-08-22 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * private.c (ptw32_throw): Fix exception test;
+ move exceptionInformation declaration.
+
+ * tsd.c (pthread_key_create): newkey wrongly declared.
+
+ * pthread.h: Fix comment block.
+
+2000-08-18 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * mutex.c (pthread_mutex_destroy): Check that the mutex isn't
+ held; invalidate the mutex as early as possible to avoid
+ contention; not perfect - FIXME!
+
+ * rwlock.c (pthread_rwlock_init): Remove redundant assignment
+ to "rw".
+ (pthread_rwlock_destroy): Invalidate the rwlock before
+ freeing up any of it's resources - to avoid contention.
+
+ * private.c (ptw32_tkAssocCreate): Change assoc->lock
+ to use a dynamically initialised mutex - only consumes
+ a W32 mutex or critical section when first used,
+ not before.
+
+ * mutex.c (pthread_mutex_init): Remove redundant assignment
+ to "mx".
+ (pthread_mutexattr_destroy): Set attribute to NULL
+ before freeing it's memory - to avoid contention.
+
+ * implement.h (PTW32_EPS_CANCEL/PTW32_EPS_EXIT):
+ Must be defined for all compilers - used as generic
+ exception selectors by ptw32_throw().
+
+ * Several: Fix typos from scripted edit session
+ yesterday.
+
+ * nonportable.c (pthread_mutexattr_setforcecs_np):
+ Moved this function from mutex.c.
+ (pthread_getw32threadhandle_np): New function to
+ return the win32 thread handle that the POSIX
+ thread is using.
+ * mutex.c (pthread_mutexattr_setforcecs_np):
+ Moved to new file "nonportable.c".
+
+ * pthread.h (PTW32_BUILD): Only redefine __except
+ and catch compiler keywords if we aren't building
+ the library (ie. PTW32_BUILD is not defined) -
+ this is safer than defining and then undefining
+ if not building the library.
+ * implement.h: Remove __except and catch undefines.
+ * Makefile (CFLAGS): Define PTW32_BUILD.
+ * GNUmakefile (CFLAGS): Define PTW32_BUILD.
+
+ * All appropriate: Change Pthread_exception* to
+ ptw32_exception* to be consistent with internal
+ identifier naming.
+
+ * private.c (ptw32_throw): New function to provide
+ a generic exception throw for all internal
+ exceptions and EH schemes.
+ (ptw32_threadStart): pthread_exit() value is now
+ returned via the thread structure exitStatus
+ element.
+ * exit.c (pthread_exit): pthread_exit() value is now
+ returned via the thread structure exitStatus
+ element.
+ * cancel.c (ptw32_cancel_self): Now uses ptw32_throw.
+ (pthread_setcancelstate): Ditto.
+ (pthread_setcanceltype): Ditto.
+ (pthread_testcancel): Ditto.
+ (pthread_cancel): Ditto.
+ * misc.c (CancelableWait): Ditto.
+ * exit.c (pthread_exit): Ditto.
+ * All applicable: Change PTW32_ prefix to
+ PTW32_ prefix to remove leading underscores
+ from private library identifiers.
+
+2000-08-17 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * All applicable: Change _pthread_ prefix to
+ ptw32_ prefix to remove leading underscores
+ from private library identifiers (single
+ and double leading underscores are reserved in the
+ ANSI C standard for compiler implementations).
+
+ * tsd.c (pthread_create_key): Initialise temporary
+ key before returning it's address to avoid race
+ conditions.
+
+2000-08-13 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * errno.c: Add _MD precompile condition; thus far
+ had no effect when using /MD compile option but I
+ thnk it should be there.
+
+ * exit.c: Add __cplusplus to various #if lines;
+ was compiling SEH code even when VC++ had
+ C++ compile options.
+
+ * private.c: ditto.
+
+ * create.c (pthread_create): Add PT_STDCALL macro to
+ function pointer arg in _beginthread().
+
+ * pthread.h: PT_STDCALL really does need to be defined
+ in both this and impliment.h; don't set it to __cdecl
+ - this macro is only used to extend function pointer
+ casting for functions that will be passed as parameters.
+ (~PThreadCleanup): add cast and group expression.
+ (_errno): Add _MD compile conditional.
+ (PtW32NoCatchWarn): Change pragma message.
+
+ * implement.h: Move and change PT_STDCALL define.
+
+ * need_errno.h: Add _MD to compilation conditional.
+
+ * GNUmakefile: Substantial rewrite for new naming
+ convention; set for nil optimisation (turn it up
+ when we have a working library build; add target
+ "fake.a" to build a libpthreadw32.a from the VC++
+ built DLL pthreadVCE.dll.
+
+ * pthread.def (LIBRARY): Don't specify in the .def
+ file - it is specified on the linker command line
+ since we now use the same .def file for variously
+ named .dlls.
+
+ * Makefile: Substantial rewrite for new naming
+ convention; default nmake target only issues a
+ help message; run nmake with specific target
+ corresponding to the EH scheme being used.
+
+ * README: Update information; add naming convention
+ explanation.
+
+ * ANNOUNCE: Update information.
+
+2000-08-12 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * pthread.h: Add compile-time message when using
+ MSC_VER compiler and C++ EH to warn application
+ programmers to use PtW32Catch instead of catch(...)
+ if they want cancelation and pthread_exit to work.
+
+ * implement.h: Remove #include <semaphore.h>; we
+ use our own local semaphore.h.
+
+2000-08-10 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * cleanup.c (pthread_pop_cleanup): Remove _pthread
+ prefix from __except and catch keywords; implement.h
+ now simply undefines ptw32__except and
+ ptw32_catch if defined; VC++ was not textually
+ substituting ptw32_catch etc back to catch as
+ it was redefined; the reason for using the prefixed
+ version was to make it clear that it was not using
+ the pthread.h redefined catch keyword.
+
+ * private.c (ptw32_threadStart): Ditto.
+ (ptw32_callUserDestroyRoutines): Ditto.
+
+ * implement.h (ptw32__except): Remove #define.
+ (ptw32_catch): Remove #define.
+
+ * GNUmakefile (pthread.a): New target to build
+ libpthread32.a from pthread.dll using dlltool.
+
+ * buildlib.bat: Duplicate cl commands with args to
+ build C++ EH version of pthread.dll; use of .bat
+ files is redundant now that nmake compatible
+ Makefile is included; used as a kludge only now.
+
+ * Makefile: Localise some macros and fix up the clean:
+ target to extend it and work properly.
+
+ * CONTRIBUTORS: Add contributors.
+
+ * ANNOUNCE: Updated.
+
+ * README: Updated.
+
+2000-08-06 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * pthread.h: Remove #warning - VC++ doesn't accept it.
+
+2000-08-05 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * pthread.h (PtW32CatchAll): Add macro. When compiling
+ applications using VC++ with C++ EH rather than SEH
+ 'PtW32CatchAll' must be used in place of any 'catch( ... )'
+ if the application wants pthread cancelation or
+ pthread_exit() to work.
+
+2000-08-03 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * pthread.h: Add a base class ptw32_exception for
+ library internal exceptions and change the "catch"
+ re-define macro to use it.
+
+2000-08-02 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * GNUmakefile (CFLAGS): Add -mthreads.
+ Add new targets to generate cpp and asm output.
+
+ * sync.c (pthread_join): Remove dead code.
+
+2000-07-25 Tristan Savatier <tristan at mpegtv.com>
+
+ * sched.c (sched_get_priority_max): Handle different WinCE and
+ Win32 priority values together.
+ (sched_get_priority_min): Ditto.
+
+2000-07-25 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * create.c (pthread_create): Force new threads to wait until
+ pthread_create has the new thread's handle; we also retain
+ a local copy of the handle for internal use until
+ pthread_create returns.
+
+ * private.c (ptw32_threadStart): Initialise ei[].
+ (ptw32_threadStart): When beginthread is used to start the
+ thread, force waiting until the creator thread had the
+ thread handle.
+
+ * cancel.c (ptw32_cancel_thread): Include context switch
+ code for defined(_X86_) environments in addition to _M_IX86.
+
+ * rwlock.c (pthread_rwlock_destroy): Assignment changed
+ to avoid compiler warning.
+
+ * private.c (ptw32_get_exception_services_code): Cast
+ NULL return value to avoid compiler warning.
+
+ * cleanup.c (pthread_pop_cleanup): Initialise "cleanup" variable
+ to avoid compiler warnings.
+
+ * misc.c (ptw32_new): Change "new" variable to "t" to avoid
+ confusion with the C++ keyword of the same name.
+
+ * condvar.c (cond_wait_cleanup): Initialise lastWaiter variable.
+ (cond_timedwait): Remove unused local variables. to avoid
+ compiler warnings.
+
+ * dll.c (dllMain): Remove 2000-07-21 change - problem
+ appears to be in pthread_create().
+
+2000-07-22 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * tsd.c (pthread_key_create): If a destructor was given
+ and the pthread_mutex_init failed, then would try to
+ reference a NULL pointer (*key); eliminate this section of
+ code by using a dynamically initialised mutex
+ (PTHREAD_MUTEX_INITIALIZER).
+
+ * tsd.c (pthread_setspecific): Return an error if
+ unable to set the value; simplify cryptic conditional.
+
+ * tsd.c (pthread_key_delete): Locking threadsLock relied
+ on mutex_lock returning an error if the key has no destructor.
+ ThreadsLock is only initialised if the key has a destructor.
+ Making this mutex a static could reduce the number of mutexes
+ used by an application since it is actually created only at
+ first use and it's often destroyed soon after.
+
+2000-07-22 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * FAQ: Added Q5 and Q6.
+
+2000-07-21 David Baggett <dmb at itasoftware.com>
+
+ * dll.c: Include resource leakage work-around. This is a
+ partial FIXME which doesn't stop all leakage. The real
+ problem needs to be found and fixed.
+
+2000-07-21 Ross Johnson <rpj at setup1.ise.canberra.edu.au>
+
+ * create.c (pthread_create): Set threadH to 0 (zero)
+ everywhere. Some assignments were using NULL. Maybe
+ it should be NULL everywhere - need to check. (I know
+ they are nearly always the same thing - but not by
+ definition.)
+
+ * misc.c (pthread_self): Try to catch NULL thread handles
+ at the point where they might be generated, even though
+ they should always be valid at this point.
+
+ * tsd.c (pthread_setspecific): return an error value if
+ pthread_self() returns NULL.
+
+ * sync.c (pthread_join): return an error value if
+ pthread_self() returns NULL.
+
+ * signal.c (pthread_sigmask): return an error value if
+ pthread_self() returns NULL.
+
+2000-03-02 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * attr.c (pthread_attr_init): Set default stacksize to zero (0)
+ rather than PTHREAD_STACK_MIN even though these are now the same.
+
+ * pthread.h (PTHREAD_STACK_MIN): Lowered to 0.
+
+2000-01-28 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * mutex.c (pthread_mutex_init): Free mutex if it has been alloced;
+ if critical sections can be used instead of Win32 mutexes, test
+ that the critical section works and return an error if not.
+
+2000-01-07 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * cleanup.c (pthread_pop_cleanup): Include SEH code only if MSC is not
+ compiling as C++.
+ (pthread_push_cleanup): Include SEH code only if MSC is not
+ compiling as C++.
+
+ * pthread.h: Include SEH code only if MSC is not
+ compiling as C++.
+
+ * implement.h: Include SEH code only if MSC is not
+ compiling as C++.
+
+ * cancel.c (ptw32_cancel_thread): Add _M_IX86 check.
+ (pthread_testcancel): Include SEH code only if MSC is not
+ compiling as C++.
+ (ptw32_cancel_self): Include SEH code only if MSC is not
+ compiling as C++.
+
+2000-01-06 Erik Hensema <erik.hensema at group2000.nl>
+
+ * Makefile: Remove inconsistencies in 'cl' args
+
+2000-01-04 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * private.c (ptw32_get_exception_services_code): New; returns
+ value of EXCEPTION_PTW32_SERVICES.
+ (ptw32_processInitialize): Remove initialisation of
+ ptw32_exception_services which is no longer needed.
+
+ * pthread.h (ptw32_exception_services): Remove extern.
+ (ptw32_get_exception_services_code): Add function prototype;
+ use this to return EXCEPTION_PTW32_SERVICES value instead of
+ using the ptw32_exception_services variable which I had
+ trouble exporting through pthread.def.
+
+ * global.c (ptw32_exception_services): Remove declaration.
+
+1999-11-22 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * implement.h: Forward declare ptw32_new();
+
+ * misc.c (ptw32_new): New; alloc and initialise a new pthread_t.
+ (pthread_self): New thread struct is generated by new routine
+ ptw32_new().
+
+ * create.c (pthread_create): New thread struct is generated
+ by new routine ptw32_new().
+
+1999-11-21 Ross Johnson <rpj at special.ise.canberra.edu.au>
+
+ * global.c (ptw32_exception_services): Declare new variable.
+
+ * private.c (ptw32_threadStart): Destroy thread's
+ cancelLock mutex; make 'catch' and '__except' usageimmune to
+ redfinitions in pthread.h.
+ (ptw32_processInitialize): Init new constant ptw32_exception_services.
+
+ * create.c (pthread_create): Initialise thread's cancelLock
+ mutex.
+
+ * cleanup.c (pthread_pop_cleanup): Make 'catch' and '__except'
+ usage immune to redfinition s in pthread.h.
+
+ * private.c: Ditto.
+
+ * pthread.h (catch): Redefine 'catch' so that C++ applications
+ won't catch our internal exceptions.
+ (__except): ditto for __except.
+
+ * implement.h (ptw32_catch): Define internal version
+ of 'catch' because 'catch' is redefined by pthread.h.
+ (__except): ditto for __except.
+ (struct pthread_t_): Add cancelLock mutex for async cancel
+ safety.
+
+1999-11-21 Jason Nye <jnye at nbnet.nb.ca>, Erik Hensema <erik.hensema at group2000.nl>
+
+ * cancel.c (ptw32_cancel_self): New; part of the async
+ cancellation implementation.
+ (ptw32_cancel_thread): Ditto; this function is X86
+ processor specific.
+ (pthread_setcancelstate): Add check for pending async
+ cancel request and cancel the calling thread if
+ required; add async-cancel safety lock.
+ (pthread_setcanceltype): Ditto.
+
+1999-11-13 Erik Hensema <erik.hensema at group2000.nl>
+
+ * configure.in (AC_OUTPUT): Put generated output into GNUmakefile
+ rather than Makefile. Makefile will become the MSC nmake compatible
+ version
+
+1999-11-13 John Bossom (John.Bossom@cognos.com>
+
+ * misc.c (pthread_self): Add a note about GetCurrentThread
+ returning a pseudo-handle
+
+1999-11-10 Todd Owen <towen at lucidcalm.dropbear.id.au>
+
+ * dll.c (dllMain): Free kernel32 ASAP.
+ If TryEnterCriticalSection is not being used, then free
+ the kernel32.dll handle now, rather than leaving it until
+ DLL_PROCESS_DETACH.
+
+ Note: this is not a pedantic exercise in freeing unused
+ resources! It is a work-around for a bug in Windows 95
+ (see microsoft knowledge base article, Q187684) which
+ does Bad Things when FreeLibrary is called within
+ the DLL_PROCESS_DETACH code, in certain situations.
+ Since w95 just happens to be a platform which does not
+ provide TryEnterCriticalSection, the bug will be
+ effortlessly avoided.
+
+1999-11-10 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * sync.c (pthread_join): Make it a deferred cancelation point.
+
+ * misc.c (pthread_self): Explicitly initialise implicitly
+ created thread state to default values.
+
+1999-11-05 Tristan Savatier <tristan at mpegtv.com>
+
+ * pthread.h (winsock.h): Include unconditionally.
+ (ETIMEDOUT): Change fallback value to that defined by winsock.h.
+
+ * general: Patched for portability to WinCE. The details are
+ described in the file WinCE-PORT. Follow the instructions
+ in README.WinCE to make the appropriate changes in config.h.
+
+1999-10-30 Erik Hensema <erik.hensema at group2000.nl>
+
+ * create.c (pthread_create): Explicitly initialise thread state to
+ default values.
+
+ * cancel.c (pthread_setcancelstate): Check for NULL 'oldstate'
+ for compatibility with Solaris pthreads;
+ (pthread_setcanceltype): ditto:
+
+1999-10-23 Erik Hensema <erik.hensema at group2000.nl>
+
+ * pthread.h (ctime_r): Fix incorrect argument "_tm"
+
+1999-10-21 Aurelio Medina <aureliom at crt.com>
+
+ * pthread.h (_POSIX_THREADS): Only define it if it isn't
+ already defined. Projects may need to define this on
+ the CC command line under Win32 as it doesn't have unistd.h
+
+1999-10-17 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * rwlock.c (pthread_rwlock_destroy): Add cast to remove compile
+ warning.
+
+ * condvar.c (pthread_cond_broadcast): Only release semaphores
+ if there are waiting threads.
+
+1999-10-15 Lorin Hochstein <lmh at xiphos.ca>, Peter Slacik <Peter.Slacik at tatramed.sk>
+
+ * condvar.c (cond_wait_cleanup): New static cleanup handler for
+ cond_timedwait;
+ (cond_timedwait): pthread_cleanup_push args changed;
+ canceling a thread while it's in pthread_cond_wait
+ will now decrement the waiters count and cleanup if it's the
+ last waiter.
+
+1999-10-15 Graham Dumpleton <Graham.Dumpleton at ra.pad.otc.telstra.com.au>
+
+ * condvar.c (cond_wait_cleanup): the last waiter will now reset the CV's
+ wasBroadcast flag
+
+Thu Sep 16 1999 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * rwlock.c (pthread_rwlock_destroy): Add serialisation.
+ (_rwlock_check_need_init): Check for detroyed rwlock.
+ * rwlock.c: Check return codes from _rwlock_check_need_init();
+ modify comments; serialise access to rwlock objects during
+ operations; rename rw_mutex to rw_lock.
+ * implement.h: Rename rw_mutex to rw_lock.
+ * mutex.c (pthread_mutex_destroy): Add serialisation.
+ (_mutex_check_need_init): Check for detroyed mutex.
+ * condvar.c (pthread_cond_destroy): Add serialisation.
+ (_cond_check_need_init): Check for detroyed condvar.
+ * mutex.c: Modify comments.
+ * condvar.c: Modify comments.
+
+1999-08-10 Aurelio Medina <aureliom at crt.com>
+
+ * implement.h (pthread_rwlock_t_): Add.
+ * pthread.h (pthread_rwlock_t): Add.
+ (PTHREAD_RWLOCK_INITIALIZER): Add.
+ Add rwlock function prototypes.
+ * rwlock.c: New module.
+ * pthread.def: Add new rwlock functions.
+ * private.c (ptw32_processInitialize): initialise
+ ptw32_rwlock_test_init_lock critical section.
+ * global.c (ptw32_rwlock_test_init_lock): Add.
+
+ * mutex.c (pthread_mutex_destroy): Don't free mutex memory
+ if mutex is PTHREAD_MUTEX_INITIALIZER and has not been
+ initialised yet.
+
+1999-08-08 Milan Gardian <mg at tatramed.sk>
+
+ * mutex.c (pthread_mutex_destroy): Free mutex memory.
+
+1999-08-22 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * exit.c (pthread_exit): Fix reference to potentially
+ uninitialised pointer.
+
+1999-08-21 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * private.c (ptw32_threadStart): Apply fix of 1999-08-19
+ this time to C++ and non-trapped C versions. Ommitted to
+ do this the first time through.
+
+1999-08-19 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * private.c (ptw32_threadStart): Return exit status from
+ the application thread startup routine.
+ - Milan Gardian <mg at tatramed.sk>
+
+1999-08-18 John Bossom <john.Bossom at cognos.com>
+
+ * exit.c (pthread_exit): Put status into pthread_t->exitStatus
+ * private.c (ptw32_threadStart): Set pthread->exitStatus
+ on exit of try{} block.
+ * sync.c (pthread_join): use pthread_exitStatus value if the
+ thread exit doesn't return a value (for Mingw32 CRTDLL
+ which uses endthread instead of _endthreadex).
+
+Tue Aug 17 20:17:58 CDT 1999 Mumit Khan <khan at xraylith.wisc.edu>
+
+ * create.c (pthread_create): Add CRTDLL suppport.
+ * exit.c (pthread_exit): Likewise.
+ * private.c (ptw32_threadStart): Likewise.
+ (ptw32_threadDestroy): Likewise.
+ * sync.c (pthread_join): Likewise.
+ * tests/join1.c (main): Warn about partial support for CRTDLL.
+
+Tue Aug 17 20:00:08 1999 Mumit Khan <khan at xraylith.wisc.edu>
+
+ * Makefile.in (LD): Delete entry point.
+ * acconfig.h (STDCALL): Delete unused macro.
+ * configure.in: Remove test for STDCALL.
+ * config.h.in: Regenerate.
+ * errno.c (_errno): Fix self type.
+ * pthread.h (PT_STDCALL): Move from here to
+ * implement.h (PT_STDCALL): here.
+ (ptw32_threadStart): Fix prototype.
+ * private.c (ptw32_threadStart): Likewise.
+
+1999-08-14 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * exit.c (pthread_exit): Don't call pthread_self() but
+ get thread handle directly from TSD for efficiency.
+
+1999-08-12 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * private.c (ptw32_threadStart): ei[] only declared if _MSC_VER.
+
+ * exit.c (pthread_exit): Check for implicitly created threads
+ to avoid raising an unhandled exception.
+
+1999-07-12 Peter Slacik <Peter.Slacik at tatramed.sk>
+
+ * condvar.c (pthread_cond_destroy): Add critical section.
+ (cond_timedwait): Add critical section; check for timeout
+ waiting on semaphore.
+ (pthread_cond_broadcast): Add critical section.
+
+1999-07-09 Lorin Hochstein <lmh at xiphos.ca>, John Bossom <John.Bossom at Cognos.COM>
+
+ The problem was that cleanup handlers were not executed when
+ pthread_exit() was called.
+
+ * implement.h (pthread_t_): Add exceptionInformation element for
+ C++ per-thread exception information.
+ (general): Define and rename exceptions.
+
+1999-07-09 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * misc.c (CancelableWait): PTW32_EPS_CANCEL (SEH) and
+ ptw32_exception_cancel (C++) used to identify the exception.
+
+ * cancel.c (pthread_testcancel): PTW32_EPS_CANCEL (SEH) and
+ ptw32_exception_cancel (C++) used to identify the exception.
+
+ * exit.c (pthread_exit): throw/raise an exception to return to
+ ptw32_threadStart() to exit the thread. PTW32_EPS_EXIT (SEH)
+ and ptw32_exception_exit (C++) used to identify the exception.
+
+ * private.c (ptw32_threadStart): Add pthread_exit exception trap;
+ clean up and exit the thread directly rather than via pthread_exit().
+
+Sun May 30 00:25:02 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * semaphore.h (mode_t): Conditionally typedef it.
+
+Fri May 28 13:33:05 1999 Mark E. Armstrong <avail at pacbell.net>
+
+ * condvar.c (pthread_cond_broadcast): Fix possible memory fault
+
+Thu May 27 13:08:46 1999 Peter Slacik <Peter.Slacik at tatramed.sk>
+
+ * condvar.c (pthread_cond_broadcast): Fix logic bug
+
+Thu May 27 13:08:46 1999 Bossom, John <John.Bossom at Cognos.COM>
+
+ * condvar.c (pthread_cond_broadcast): optimise sem_post loop
+
+Fri May 14 12:13:18 1999 Mike Russo <miker at eai.com>
+
+ * attr.c (pthread_attr_setdetachstate): Fix logic bug
+
+Sat May 8 09:42:30 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * pthread.def (sem_open): Add.
+ (sem_close): Add.
+ (sem_unlink): Add.
+ (sem_getvalue): Add.
+
+ * FAQ (Question 3): Add.
+
+Thu Apr 8 01:16:23 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * semaphore.c (sem_open): New function; returns an error (ENOSYS).
+ (sem_close): ditto.
+ (sem_unlink): ditto.
+ (sem_getvalue): ditto.
+
+ * semaphore.h (_POSIX_SEMAPHORES): define.
+
+Wed Apr 7 14:09:52 1999 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * errno.c (_REENTRANT || _MT): Invert condition.
+
+ * pthread.h (_errno): Conditionally include prototype.
+
+Wed Apr 7 09:37:00 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * *.c (comments): Remove individual attributions - these are
+ documented sufficiently elsewhere.
+
+ * implement.h (pthread.h): Remove extraneous include.
+
+Sun Apr 4 11:05:57 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * sched.c (sched.h): Include.
+
+ * sched.h: New file for POSIX 1b scheduling.
+
+ * pthread.h: Move opaque structures to implement.h; move sched_*
+ prototypes out and into sched.h.
+
+ * implement.h: Add opaque structures from pthread.h.
+
+ * sched.c (sched_yield): New function.
+
+ * condvar.c (ptw32_sem_*): Rename to sem_*; except for
+ ptw32_sem_timedwait which is an private function.
+
+Sat Apr 3 23:28:00 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * Makefile.in (OBJS): Add errno.o.
+
+Fri Apr 2 11:08:50 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * implement.h (ptw32_sem_*): Remove prototypes now defined in
+ semaphore.h.
+
+ * pthread.h (sempahore.h): Include.
+
+ * semaphore.h: New file for POSIX 1b semaphores.
+
+ * semaphore.c (ptw32_sem_timedwait): Moved to private.c.
+
+ * pthread.h (ptw32_sem_t): Change to sem_t.
+
+ * private.c (ptw32_sem_timedwait): Moved from semaphore.c;
+ set errno on error.
+
+ * pthread.h (pthread_t_): Add per-thread errno element.
+
+Fri Apr 2 11:08:50 1999 John Bossom <jebossom at cognos.com>
+
+ * semaphore.c (ptw32_sem_*): Change to sem_*; these functions
+ will be exported from the library; set errno on error.
+
+ * errno.c (_errno): New file. New function.
+
+Fri Mar 26 14:11:45 1999 Tor Lillqvist <tml at iki.fi>
+
+ * semaphore.c (ptw32_sem_timedwait): Check for negative
+ milliseconds.
+
+Wed Mar 24 11:32:07 1999 John Bossom <jebossom at cognos.com>
+
+ * misc.c (CancelableWait): Initialise exceptionInformation[2].
+ (pthread_self): Get a real Win32 thread handle for implicit threads.
+
+ * cancel.c (pthread_testcancel): Initialise exceptionInformation[2].
+
+ * implement.h (SE_INFORMATION): Fix values.
+
+ * private.c (ptw32_threadDestroy): Close the thread handle.
+
+Fri Mar 19 12:57:27 1999 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * cancel.c (comments): Update and cleanup.
+
+Fri Mar 19 09:12:59 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * private.c (ptw32_threadStart): status returns PTHREAD_CANCELED.
+
+ * pthread.h (PTHREAD_CANCELED): defined.
+
+Tue Mar 16 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * all: Add GNU LGPL and Copyright and Warranty.
+
+Mon Mar 15 00:20:13 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * condvar.c (pthread_cond_init): fix possible uninitialised use
+ of cv.
+
+Sun Mar 14 21:01:59 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * condvar.c (pthread_cond_destroy): don't do full cleanup if
+ static initialised cv has never been used.
+ (cond_timedwait): check result of auto-initialisation.
+
+Thu Mar 11 09:01:48 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * pthread.h (pthread_mutex_t): revert to (pthread_mutex_t *);
+ define a value to serve as PTHREAD_MUTEX_INITIALIZER.
+ (pthread_mutex_t_): remove staticinit and valid elements.
+ (pthread_cond_t): revert to (pthread_cond_t_ *);
+ define a value to serve as PTHREAD_COND_INITIALIZER.
+ (pthread_cond_t_): remove staticinit and valid elements.
+
+ * mutex.c (pthread_mutex_t args): adjust indirection of references.
+ (all functions): check for PTHREAD_MUTEX_INITIALIZER value;
+ check for NULL (invalid).
+
+ * condvar.c (pthread_cond_t args): adjust indirection of references.
+ (all functions): check for PTHREAD_COND_INITIALIZER value;
+ check for NULL (invalid).
+
+Wed Mar 10 17:18:12 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * misc.c (CancelableWait): Undo changes from Mar 8 and 7.
+
+Mon Mar 8 11:18:59 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * misc.c (CancelableWait): Ensure cancelEvent handle is the lowest
+ indexed element in the handles array. Enhance test for abandoned
+ objects.
+
+ * pthread.h (PTHREAD_MUTEX_INITIALIZER): Trailing elements not
+ initialised are set to zero by the compiler. This avoids the
+ problem of initialising the opaque critical section element in it.
+ (PTHREAD_COND_INITIALIZER): Ditto.
+
+ * semaphore.c (ptw32_sem_timedwait): Check sem == NULL earlier.
+
+Sun Mar 7 12:31:14 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * condvar.c (pthread_cond_init): set semaphore initial value
+ to 0, not 1. cond_timedwait was returning signaled immediately.
+
+ * misc.c (CancelableWait): Place the cancel event handle first
+ in the handle table for WaitForMultipleObjects. This ensures that
+ the cancel event is recognised and acted apon if both objects
+ happen to be signaled together.
+
+ * private.c (ptw32_cond_test_init_lock): Initialise and destroy.
+
+ * implement.h (ptw32_cond_test_init_lock): Add extern.
+
+ * global.c (ptw32_cond_test_init_lock): Add declaration.
+
+ * condvar.c (pthread_cond_destroy): check for valid initialised CV;
+ flag destroyed CVs as invalid.
+ (pthread_cond_init): pthread_cond_t is no longer just a pointer.
+ This is because PTHREAD_COND_INITIALIZER needs state info to reside
+ in pthread_cond_t so that it can initialise on first use. Will work on
+ making pthread_cond_t (and other objects like it) opaque again, if
+ possible, later.
+ (cond_timedwait): add check for statically initialisation of
+ CV; initialise on first use.
+ (pthread_cond_signal): check for valid CV.
+ (pthread_cond_broadcast): check for valid CV.
+ (_cond_check_need_init): Add.
+
+ * pthread.h (PTHREAD_COND_INITIALIZER): Fix.
+ (pthread_cond_t): no longer a pointer to pthread_cond_t_.
+ (pthread_cond_t_): add 'staticinit' and 'valid' elements.
+
+Sat Mar 6 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * implement.h: Undate comments.
+
+Sun Feb 21 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * pthread.h (PTHREAD_MUTEX_INITIALIZER): missing braces around
+ cs element initialiser.
+
+1999-02-21 Ben Elliston <bje at cygnus.com>
+
+ * pthread.h (pthread_exit): The return type of this function is
+ void, not int.
+
+ * exit.c (pthread_exit): Do not return 0.
+
+Sat Feb 20 16:03:30 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * dll.c (DLLMain): Expand TryEnterCriticalSection support test.
+
+ * mutex.c (pthread_mutex_trylock): The check for
+ ptw32_try_enter_critical_section == NULL should have been
+ removed long ago.
+
+Fri Feb 19 16:03:30 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * sync.c (pthread_join): Fix pthread_equal() test.
+
+ * mutex.c (pthread_mutex_trylock): Check mutex != NULL before
+ using it.
+
+Thu Feb 18 16:17:30 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * misc.c (pthread_equal): Fix inverted result.
+
+ * Makefile.in: Use libpthread32.a as the name of the DLL export
+ library instead of pthread.lib.
+
+ * condvar.c (pthread_cond_init): cv could have been used unitialised;
+ initialise.
+
+ * create.c (pthread_create): parms could have been used unitialised;
+ initialise.
+
+ * pthread.h (struct pthread_once_t_): Remove redefinition.
+
+Sat Feb 13 03:03:30 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * pthread.h (struct pthread_once_t_): Replaced.
+
+ * misc.c (pthread_once): Replace with John Bossom's version;
+ has lighter weight serialisation; fixes problem of not holding
+ competing threads until after the init_routine completes.
+
+Thu Feb 11 13:34:14 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * misc.c (CancelableWait): Change C++ exception throw.
+
+ * sync.c (pthread_join): Change FIXME comment - issue resolved.
+
+Wed Feb 10 12:49:11 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * configure: Various temporary changes.
+ - Kevin Ruland <Kevin.Ruland at anheuser-busch.com>
+
+ * README: Update.
+
+ * pthread.def (pthread_attr_getstackaddr): uncomment
+ (pthread_attr_setstackaddr): uncomment
+
+Fri Feb 5 13:42:30 1999 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * semaphore.c: Comment format changes.
+
+Thu Feb 4 10:07:28 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * global.c: Remove ptw32_exception instantiation.
+
+ * cancel.c (pthread_testcancel): Change C++ exception throw.
+
+ * implement.h: Remove extern declaration.
+
+Wed Feb 3 13:04:44 1999 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * cleanup.c: Rename ptw32_*_cleanup() to pthread_*_cleanup().
+
+ * pthread.def: Ditto.
+
+ * pthread.h: Ditto.
+
+ * pthread.def (pthread_cleanup_push): Remove from export list;
+ the function is defined as a macro under all compilers.
+ (pthread_cleanup_pop): Ditto.
+
+ * pthread.h: Remove #if defined().
+
+Wed Feb 3 10:13:48 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * sync.c (pthread_join): Check for NULL value_ptr arg;
+ check for detached threads.
+
+Tue Feb 2 18:07:43 1999 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * implement.h: Add #include <pthread.h>.
+ Change sem_t to ptw32_sem_t.
+
+Tue Feb 2 18:07:43 1999 Kevin Ruland <Kevin.Ruland at anheuser-busch.com>
+
+ * signal.c (pthread_sigmask): Add and modify casts.
+ Reverse LHS/RHS bitwise assignments.
+
+ * pthread.h: Remove #include <semaphore.h>.
+ (PTW32_ATTR_VALID): Add cast.
+ (struct pthread_t_): Add sigmask element.
+
+ * dll.c: Add "extern C" for DLLMain.
+ (DllMain): Add cast.
+
+ * create.c (pthread_create): Set sigmask in thread.
+
+ * condvar.c: Remove #include. Change sem_* to ptw32_sem_*.
+
+ * attr.c: Changed #include.
+
+ * Makefile.in: Additional targets and changes to build the library
+ as a DLL.
+
+Fri Jan 29 11:56:28 1999 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * Makefile.in (OBJS): Add semaphore.o to list.
+
+ * semaphore.c (ptw32_sem_timedwait): Move from private.c.
+ Rename sem_* to ptw32_sem_*.
+
+ * pthread.h (pthread_cond_t): Change type of sem_t.
+ _POSIX_SEMAPHORES no longer defined.
+
+ * semaphore.h: Contents moved to implement.h.
+ Removed from source tree.
+
+ * implement.h: Add semaphore function prototypes and rename all
+ functions to prepend 'ptw32_'. They are
+ now private to the pthreads-win32 implementation.
+
+ * private.c: Change #warning.
+ Move ptw32_sem_timedwait() to semaphore.c.
+
+ * cleanup.c: Change #warning.
+
+ * misc.c: Remove #include <errno.h>
+
+ * pthread.def: Cleanup CVS merge conflicts.
+
+ * global.c: Ditto.
+
+ * ChangeLog: Ditto.
+
+ * cleanup.c: Ditto.
+
+Sun Jan 24 01:34:52 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * semaphore.c (sem_wait): Remove second arg to
+ pthreadCancelableWait() call.
+
+Sat Jan 23 17:36:40 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * pthread.def: Add new functions to export list.
+
+ * pthread.h (PTHREAD_MUTEX_AUTO_CS_NP): New.
+ (PTHREAD_MUTEX_FORCE_CS_NP): New.
+
+ * README: Updated.
+
+Fri Jan 22 14:31:59 1999 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * Makefile.in (CFLAGS): Remove -fhandle-exceptions. Not needed
+ with egcs. Add -g for debugging.
+
+ * create.c (pthread_create): Replace __stdcall with PT_STDCALL
+ macro. This is a hack and must be fixed.
+
+ * misc.c (CancelableWait): Remove redundant statement.
+
+ * mutex.c (pthread_mutexattr_init): Cast calloc return value.
+
+ * misc.c (CancelableWait): Add cast.
+ (pthread_self): Add cast.
+
+ * exit.c (pthread_exit): Add cast.
+
+ * condvar.c (pthread_condattr_init): Cast calloc return value.
+
+ * cleanup.c: Reorganise conditional compilation.
+
+ * attr.c (pthread_attr_init): Remove unused 'result'.
+ Cast malloc return value.
+
+ * private.c (ptw32_callUserDestroyRoutines): Redo conditional
+ compilation.
+
+ * misc.c (CancelableWait): C++ version uses 'throw'.
+
+ * cancel.c (pthread_testcancel): Ditto.
+
+ * implement.h (class ptw32_exception): Define for C++.
+
+ * pthread.h: Fix C, C++, and Win32 SEH condition compilation
+ mayhem around pthread_cleanup_* defines. C++ version now uses John
+ Bossom's cleanup handlers.
+ (pthread_attr_t): Make 'valid' unsigned.
+ Define '_timeb' as 'timeb' for Ming32.
+ Define PT_STDCALL as nothing for Mingw32. May be temporary.
+
+ * cancel.c (pthread_testcancel): Cast return value.
+
+Wed Jan 20 09:31:28 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * pthread.h (pthread_mutexattr_t): Changed to a pointer.
+
+ * mutex.c (pthread_mutex_init): Conditionally create Win32 mutex
+ - from John Bossom's implementation.
+ (pthread_mutex_destroy): Conditionally close Win32 mutex
+ - from John Bossom's implementation.
+ (pthread_mutexattr_init): Replaced by John Bossom's version.
+ (pthread_mutexattr_destroy): Ditto.
+ (pthread_mutexattr_getpshared): New function from John Bossom's
+ implementation.
+ (pthread_mutexattr_setpshared): New function from John Bossom's
+ implementation.
+
+Tue Jan 19 18:27:42 1999 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * pthread.h (pthreadCancelableTimedWait): New prototype.
+ (pthreadCancelableWait): Remove second argument.
+
+ * misc.c (CancelableWait): New static function is
+ pthreadCancelableWait() renamed.
+ (pthreadCancelableWait): Now just calls CancelableWait() with
+ INFINITE timeout.
+ (pthreadCancelableTimedWait): Just calls CancelableWait()
+ with passed in timeout.
+
+Tue Jan 19 18:27:42 1999 Scott Lightner <scott at curriculum.com>
+
+ * private.c (ptw32_sem_timedwait): 'abstime' arg really is
+ absolute time. Calculate relative time to wait from current
+ time before passing timeout to new routine
+ pthreadCancelableTimedWait().
+
+Tue Jan 19 10:27:39 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * pthread.h (pthread_mutexattr_setforcecs_np): New prototype.
+
+ * mutex.c (pthread_mutexattr_init): Init 'pshared' and 'forcecs'
+ attributes to 0.
+ (pthread_mutexattr_setforcecs_np): New function (not portable).
+
+ * pthread.h (pthread_mutex_t):
+ Add 'mutex' element. Set to NULL in PTHREAD_MUTEX_INITIALIZER.
+ The pthread_mutex_*() routines will try to optimise performance
+ by choosing either mutexes or critical sections as the basis
+ for pthread mutexes for each indevidual mutex.
+ (pthread_mutexattr_t_): Add 'forcecs' element.
+ Some applications may choose to force use of critical sections
+ if they know that:-
+ the mutex is PROCESS_PRIVATE and,
+ either the OS supports TryEnterCriticalSection() or
+ pthread_mutex_trylock() will never be called on the mutex.
+ This attribute will be setable via a non-portable routine.
+
+ Note: We don't yet support PROCESS_SHARED mutexes, so the
+ implementation as it stands will default to Win32 mutexes only if
+ the OS doesn't support TryEnterCriticalSection. On Win9x, and early
+ versions of NT 'forcecs' will need to be set in order to get
+ critical section based mutexes.
+
+Sun Jan 17 12:01:26 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * pthread.h (PTHREAD_MUTEX_INITIALIZER): Init new 'staticinit'
+ value to '1' and existing 'valid' value to '1'.
+
+ * global.c (ptw32_mutex_test_init_lock): Add.
+
+ * implement.h (ptw32_mutex_test_init_lock.): Add extern.
+
+ * private.c (ptw32_processInitialize): Init critical section for
+ global lock used by _mutex_check_need_init().
+ (ptw32_processTerminate): Ditto (:s/Init/Destroy/).
+
+ * dll.c (dllMain): Move call to FreeLibrary() so that it is only
+ called once when the process detaches.
+
+ * mutex.c (_mutex_check_need_init): New static function to test
+ and init PTHREAD_MUTEX_INITIALIZER mutexes. Provides serialised
+ access to the internal state of the uninitialised static mutex.
+ Called from pthread_mutex_trylock() and pthread_mutex_lock() which
+ do a quick unguarded test to check if _mutex_check_need_init()
+ needs to be called. This is safe as the test is conservative
+ and is repeated inside the guarded section of
+ _mutex_check_need_init(). Thus in all calls except the first
+ calls to lock static mutexes, the additional overhead to lock any
+ mutex is a single memory fetch and test for zero.
+
+ * pthread.h (pthread_mutex_t_): Add 'staticinit' member. Mutexes
+ initialised by PTHREAD_MUTEX_INITIALIZER aren't really initialised
+ until the first attempt to lock it. Using the 'valid'
+ flag (which flags the mutex as destroyed or not) to record this
+ information would be messy. It is possible for a statically
+ initialised mutex such as this to be destroyed before ever being
+ used.
+
+ * mutex.c (pthread_mutex_trylock): Call _mutex_check_need_init()
+ to test/init PTHREAD_MUTEX_INITIALIZER mutexes.
+ (pthread_mutex_lock): Ditto.
+ (pthread_mutex_unlock): Add check to ensure we don't try to unlock
+ an unitialised static mutex.
+ (pthread_mutex_destroy): Add check to ensure we don't try to delete
+ a critical section that we never created. Allows us to destroy
+ a static mutex that has never been locked (and hence initialised).
+ (pthread_mutex_init): Set 'staticinit' flag to 0 for the new mutex.
+
+Sun Jan 17 12:01:26 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * private.c (ptw32_sem_timedwait): Move from semaphore.c.
+
+ * semaphore.c : Remove redundant #includes.
+ (ptw32_sem_timedwait): Move to private.c.
+ (sem_wait): Add missing abstime arg to pthreadCancelableWait() call.
+
+Fri Jan 15 23:38:05 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * condvar.c (cond_timedwait): Remove comment.
+
+Fri Jan 15 15:41:28 1999 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * pthread.h: Add new 'abstime' arg to pthreadCancelableWait()
+ prototype.
+
+ * condvar.c (cond_timedwait): New generalised function called by
+ both pthread_cond_wait() and pthread_cond_timedwait(). This is
+ essentially pthread_cond_wait() renamed and modified to add the
+ 'abstime' arg and call the new ptw32_sem_timedwait() instead of
+ sem_wait().
+ (pthread_cond_wait): Now just calls the internal static
+ function cond_timedwait() with an INFINITE wait.
+ (pthread_cond_timedwait): Now implemented. Calls the internal
+ static function cond_timedwait().
+
+ * implement.h (ptw32_sem_timedwait): New internal function
+ prototype.
+
+ * misc.c (pthreadCancelableWait): Added new 'abstime' argument
+ to allow shorter than INFINITE wait.
+
+ * semaphore.c (ptw32_sem_timedwait): New function for internal
+ use. This is essentially sem_wait() modified to add the
+ 'abstime' arg and call the modified (see above)
+ pthreadCancelableWait().
+
+Thu Jan 14 14:27:13 1999 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * cleanup.c: Correct _cplusplus to __cplusplus wherever used.
+
+ * Makefile.in: Add CC=g++ and add -fhandle-exceptions to CFLAGS.
+ The derived Makefile will compile all units of the package as C++
+ so that those which include try/catch exception handling should work
+ properly. The package should compile ok if CC=gcc, however, exception
+ handling will not be included and thus thread cancellation, for
+ example, will not work.
+
+ * cleanup.c (ptw32_pop_cleanup): Add #warning to compile this
+ file as C++ if using a cygwin32 environment. Perhaps the whole package
+ should be compiled using g++ under cygwin.
+
+ * private.c (ptw32_threadStart): Change #error directive
+ into #warning and bracket for __CYGWIN__ and derivative compilers.
+
+Wed Jan 13 09:34:52 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * build.bat: Delete old binaries before compiling/linking.
+
+Tue Jan 12 09:58:38 1999 Tor Lillqvist <tml at iki.fi>
+
+ * dll.c: The Microsoft compiler pragmas probably are more
+ appropriately protected by _MSC_VER than by _WIN32.
+
+ * pthread.h: Define ETIMEDOUT. This should be returned by
+ pthread_cond_timedwait which is not implemented yet as of
+ snapshot-1999-01-04-1305. It was implemented in the older version.
+ The Microsoft compiler pragmas probably are more appropriately
+ protected by _MSC_VER than by _WIN32.
+
+ * pthread.def: pthread_mutex_destroy was missing from the def file
+
+ * condvar.c (pthread_cond_broadcast): Ensure we only wait on threads
+ if there were any waiting on the condition.
+ I think pthread_cond_broadcast should do the WaitForSingleObject
+ only if cv->waiters > 0? Otherwise it seems to hang, at least in the
+ testg thread program from glib.
+
+Tue Jan 12 09:58:38 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * condvar.c (pthread_cond_timedwait): Fix function description
+ comments.
+
+ * semaphore.c (sem_post): Correct typo in comment.
+
+Mon Jan 11 20:33:19 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * pthread.h: Re-arrange conditional compile of pthread_cleanup-*
+ macros.
+
+ * cleanup.c (ptw32_push_cleanup): Provide conditional
+ compile of cleanup->prev.
+
+1999-01-11 Tor Lillqvist <tml at iki.fi>
+
+ * condvar.c (pthread_cond_init): Invert logic when testing the
+ return value from calloc().
+
+Sat Jan 9 14:32:08 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * implement.h: Compile-time switch for CYGWIN derived environments
+ to use CreateThread instead of _beginthreadex. Ditto for ExitThread.
+ Patch provided by Anders Norlander <anorland at hem2.passagen.se>.
+
+Tue Jan 5 16:33:04 1999 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * cleanup.c (ptw32_pop_cleanup): Add C++ version of __try/__except
+ block. Move trailing "}" out of #ifdef _WIN32 block left there by
+ (rpj's) mistake.
+
+ * private.c: Remove #include <errno.h> which is included by pthread.h.
+
+1998-12-11 Ben Elliston <bje at toilet.to.cygnus.com>
+
+ * README: Update info about subscribing to the mailing list.
+
+Mon Jan 4 11:23:40 1999 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * all: No code changes, just cleanup.
+ - remove #if 0 /* Pre Bossom */ enclosed code.
+ - Remove some redundant #includes.
+ * pthread.h: Update implemented/unimplemented routines list.
+ * Tag the bossom merge branch getting ready to merge back to main
+ trunk.
+
+Tue Dec 29 13:11:16 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * implement.h: Move the following struct definitions to pthread.h:
+ pthread_t_, pthread_attr_t_, pthread_mutex_t_, pthread_mutex_t_,
+ pthread_mutexattr_t_, pthread_key_t_, pthread_cond_t_,
+ pthread_condattr_t_, pthread_once_t_.
+
+ * pthread.h: Add "_" prefix to pthread_push_cleanup and
+ pthread_pop_cleanup internal routines, and associated struct and
+ typedefs.
+
+ * buildlib.bat: Add compile command for semaphore.c
+
+ * pthread.def: Comment out pthread_atfork routine name.
+ Now unimplemented.
+
+ * tsd.c (pthread_setspecific): Rename tkAssocCreate to
+ ptw32_tkAssocCreate.
+ (pthread_key_delete): Rename tkAssocDestroy to
+ ptw32_tkAssocDestroy.
+
+ * sync.c (pthread_join): Rename threadDestroy to ptw32_threadDestroy
+
+ * sched.c (is_attr): attr is now **attr (was *attr), so add extra
+ NULL pointer test.
+ (pthread_attr_setschedparam): Increase redirection for attr which is
+ now a **.
+ (pthread_attr_getschedparam): Ditto.
+ (pthread_setschedparam): Change thread validation and rename "thread"
+ Win32 thread Handle element name to match John Bossom's version.
+ (pthread_getschedparam): Ditto.
+
+ * private.c (ptw32_threadDestroy): Rename call to
+ callUserDestroyRoutines() as ptw32_callUserDestroyRoutines()
+
+ * misc.c: Add #include "implement.h".
+
+ * dll.c: Remove defined(KLUDGE) wrapped code.
+
+ * fork.c: Remove redefinition of ENOMEM.
+ Remove pthread_atfork() and fork() with #if 0/#endif.
+
+ * create.c (pthread_create): Rename threadStart and threadDestroy calls
+ to ptw32_threadStart and ptw32_threadDestroy.
+
+ * implement.h: Rename "detachedstate" to "detachstate".
+
+ * attr.c: Rename "detachedstate" to "detachstate".
+
+Mon Dec 28 09:54:39 1998 John Bossom
+
+ * semaphore.c: Initial version.
+ * semaphore.h: Initial version.
+
+Mon Dec 28 09:54:39 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * pthread.h (pthread_attr_t_): Change to *pthread_attr_t.
+
+Mon Dec 28 09:54:39 1998 John Bossom, Ben Elliston
+
+ * attr.c (pthread_attr_setstacksize): Merge with John's version.
+ (pthread_attr_getstacksize): Merge with John's version.
+ (pthread_attr_setstackaddr): Merge with John's version.
+ (pthread_attr_getstackaddr): Merge with John's version.
+ (pthread_attr_init): Merge with John's version.
+ (pthread_attr_destroy): Merge with John's version.
+ (pthread_attr_getdetachstate): Merge with John's version.
+ (pthread_attr_setdetachstate): Merge with John's version.
+ (is_attr): attr is now **attr (was *attr), so add extra NULL pointer
+ test.
+
+Mon Dec 28 09:54:39 1998 Ross Johnson
+
+ * implement.h (pthread_attr_t_): Add and rename elements in JEB's
+ version to correspond to original, so that it can be used with
+ original attr routines.
+
+ * pthread.h: Add #endif at end which was truncated in merging.
+
+Sun Dec 20 14:51:58 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * misc.c (pthreadCancelableWait): New function by John Bossom. Non-standard
+ but provides a hook that can be used to implement cancellation points in
+ applications that use this library.
+
+ * pthread.h (pthread_cleanup_pop): C++ (non-WIN32) version uses
+ try/catch to emulate John Bossom's WIN32 __try/__finally behaviour.
+ In the WIN32 version __finally block, add a test for AbnormalTermination otherwise
+ cleanup is only run if the cleanup_pop execute arg is non-zero. Cancellation
+ should cause the cleanup to run irrespective of the execute arg.
+
+ * condvar.c (pthread_condattr_init): Replaced by John Bossom's version.
+ (pthread_condattr_destroy): Replaced by John Bossom's version.
+ (pthread_condattr_getpshared): Replaced by John Bossom's version.
+ (pthread_condattr_setpshared): Replaced by John Bossom's version.
+ (pthread_cond_init): Replaced by John Bossom's version.
+ Fix comment (refered to mutex rather than condition variable).
+ (pthread_cond_destroy): Replaced by John Bossom's version.
+ (pthread_cond_wait): Replaced by John Bossom's version.
+ (pthread_cond_timedwait): Replaced by John Bossom's version.
+ (pthread_cond_signal): Replaced by John Bossom's version.
+ (pthread_cond_broadcast): Replaced by John Bossom's version.
+
+Thu Dec 17 19:10:46 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * tsd.c (pthread_key_create): Replaced by John Bossom's version.
+ (pthread_key_delete): Replaced by John Bossom's version.
+ (pthread_setspecific): Replaced by John Bossom's version.
+ (pthread_getspecific): Replaced by John Bossom's version.
+
+Mon Dec 7 09:44:40 1998 John Bossom
+
+ * cancel.c (pthread_setcancelstate): Replaced.
+ (pthread_setcanceltype): Replaced.
+ (pthread_testcancel): Replaced.
+ (pthread_cancel): Replaced.
+
+ * exit.c (pthread_exit): Replaced.
+
+ * misc.c (pthread_self): Replaced.
+ (pthread_equal): Replaced.
+
+ * sync.c (pthread_detach): Replaced.
+ (pthread_join): Replaced.
+
+ * create.c (pthread_create): Replaced.
+
+ * private.c (ptw32_processInitialize): New.
+ (ptw32_processTerminate): New.
+ (ptw32_threadStart): New.
+ (ptw32_threadDestroy): New.
+ (ptw32_cleanupStack): New.
+ (ptw32_tkAssocCreate): New.
+ (ptw32_tkAssocDestroy): New.
+ (ptw32_callUserDestroyRoutines): New.
+
+ * implement.h: Added non-API structures and declarations.
+
+ * dll.c (PthreadsEntryPoint): Cast return value of GetProcAddress
+ to resolve compile warning from MSVC.
+
+ * dll.c (DLLmain): Replaced.
+ * dll.c (PthreadsEntryPoint):
+ Re-applied Anders Norlander's patch:-
+ Initialize ptw32_try_enter_critical_section at startup
+ and release kernel32 handle when DLL is being unloaded.
+
+Sun Dec 6 21:54:35 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * buildlib.bat: Fix args to CL when building the .DLL
+
+ * cleanup.c (ptw32_destructor_run_all): Fix TSD key management.
+ This is a tidy-up before TSD and Thread management is completely
+ replaced by John Bossom's code.
+
+ * tsd.c (pthread_key_create): Fix TSD key management.
+
+ * global.c (ptw32_key_virgin_next): Initialise.
+
+ * build.bat: New DOS script to compile and link a pthreads app
+ using Microsoft's CL compiler linker.
+ * buildlib.bat: New DOS script to compile all the object files
+ and create pthread.lib and pthread.dll using Microsoft's CL
+ compiler linker.
+
+1998-12-05 Anders Norlander <anorland at hem2.passagen.se>
+
+ * implement.h (ptw32_try_enter_critical_section): New extern
+ * dll.c (ptw32_try_enter_critical_section): New pointer to
+ TryEnterCriticalSection if it exists; otherwise NULL.
+ * dll.c (PthreadsEntryPoint):
+ Initialize ptw32_try_enter_critical_section at startup
+ and release kernel32 handle when DLL is being unloaded.
+ * mutex.c (pthread_mutex_trylock): Replaced check for NT with
+ a check if ptw32_try_enter_critical_section is valid
+ pointer to a function. Call ptw32_try_enter_critical_section
+ instead of TryEnterCriticalSection to avoid errors on Win95.
+
+Thu Dec 3 13:32:00 1998 Ross Johnson <rpj at ise.canberra.edu.au>
+
+ * README: Correct cygwin32 compatibility statement.
+
+Sun Nov 15 21:24:06 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * cleanup.c (ptw32_destructor_run_all): Declare missing void * arg.
+ Fixup CVS merge conflicts.
+
+1998-10-30 Ben Elliston <bje at cygnus.com>
+
+ * condvar.c (cond_wait): Fix semantic error. Test for equality
+ instead of making an assignment.
+
+Fri Oct 30 15:15:50 1998 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * cleanup.c (ptw32_handler_push): Fixed bug appending new
+ handler to list reported by Peter Slacik
+ <Peter.Slacik at leibinger.freinet.de>.
+ (new_thread): Rename poorly named local variable to
+ "new_handler".
+
+Sat Oct 24 18:34:59 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * global.c: Add TSD key management array and index declarations.
+
+ * implement.h: Ditto for externs.
+
+Fri Oct 23 00:08:09 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * implement.h (PTW32_TSD_KEY_REUSE): Add enum.
+
+ * private.c (ptw32_delete_thread): Add call to
+ ptw32_destructor_run_all() to clean up the threads keys.
+
+ * cleanup.c (ptw32_destructor_run_all): Check for no more dirty
+ keys to run destructors on. Assume that the destructor call always
+ succeeds and set the key value to NULL.
+
+Thu Oct 22 21:44:44 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * tsd.c (pthread_setspecific): Add key management code.
+ (pthread_key_create): Ditto.
+ (pthread_key_delete): Ditto.
+
+ * implement.h (struct ptw32_tsd_key): Add status member.
+
+ * tsd.c: Add description of pthread_key_delete() from the
+ standard as a comment.
+
+Fri Oct 16 17:38:47 1998 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * cleanup.c (ptw32_destructor_run_all): Fix and improve
+ stepping through the key table.
+
+Thu Oct 15 14:05:01 1998 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * private.c (ptw32_new_thread): Remove init of destructorstack.
+ No longer an element of pthread_t.
+
+ * tsd.c (pthread_setspecific): Fix type declaration and cast.
+ (pthread_getspecific): Ditto.
+ (pthread_getspecific): Change error return value to NULL if key
+ is not in use.
+
+Thu Oct 15 11:53:21 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * global.c (ptw32_tsd_key_table): Fix declaration.
+
+ * implement.h(ptw32_TSD_keys_TlsIndex): Add missing extern.
+ (ptw32_tsd_mutex): Ditto.
+
+ * create.c (ptw32_start_call): Fix "keys" array declaration.
+ Add comment.
+
+ * tsd.c (pthread_setspecific): Fix type declaration and cast.
+ (pthread_getspecific): Ditto.
+
+ * cleanup.c (ptw32_destructor_run_all): Declare missing loop
+ counter.
+
+Wed Oct 14 21:09:24 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * private.c (ptw32_new_thread): Increment ptw32_threads_count.
+ (ptw32_delete_thread): Decrement ptw32_threads_count.
+ Remove some comments.
+
+ * exit.c (ptw32_exit): : Fix two pthread_mutex_lock() calls that
+ should have been pthread_mutex_unlock() calls.
+ (ptw32_vacuum): Remove call to ptw32_destructor_pop_all().
+
+ * create.c (pthread_create): Fix two pthread_mutex_lock() calls that
+ should have been pthread_mutex_unlock() calls.
+
+ * global.c (ptw32_tsd_mutex): Add mutex for TSD operations.
+
+ * tsd.c (pthread_key_create): Add critical section.
+ (pthread_setspecific): Ditto.
+ (pthread_getspecific): Ditto.
+ (pthread_key_delete): Ditto.
+
+ * sync.c (pthread_join): Fix two pthread_mutex_lock() calls that
+ should have been pthread_mutex_unlock() calls.
+
+Mon Oct 12 00:00:44 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * implement.h (ptw32_tsd_key_table): New.
+
+ * create.c (ptw32_start_call): Initialise per-thread TSD keys
+ to NULL.
+
+ * misc.c (pthread_once): Correct typo in comment.
+
+ * implement.h (ptw32_destructor_push): Remove.
+ (ptw32_destructor_pop): Remove.
+ (ptw32_destructor_run_all): Rename from ptw32_destructor_pop_all.
+ (PTW32_TSD_KEY_DELETED): Add enum.
+ (PTW32_TSD_KEY_INUSE): Add enum.
+
+ * cleanup.c (ptw32_destructor_push): Remove.
+ (ptw32_destructor_pop): Remove.
+ (ptw32_destructor_run_all): Totally revamped TSD.
+
+ * dll.c (ptw32_TSD_keys_TlsIndex): Initialise.
+
+ * tsd.c (pthread_setspecific): Totally revamped TSD.
+ (pthread_getspecific): Ditto.
+ (pthread_create): Ditto.
+ (pthread_delete): Ditto.
+
+Sun Oct 11 22:44:55 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * global.c (ptw32_tsd_key_table): Add new global.
+
+ * implement.h (ptw32_tsd_key_t and struct ptw32_tsd_key):
+ Add.
+ (struct _pthread): Remove destructorstack.
+
+ * cleanup.c (ptw32_destructor_run_all): Rename from
+ ptw32_destructor_pop_all. The key destructor stack was made
+ global rather than per-thread. No longer removes destructor nodes
+ from the stack. Comments updated.
+
+1998-10-06 Ben Elliston <bje at cygnus.com>
+
+ * condvar.c (cond_wait): Use POSIX, not Win32 mutex calls.
+ (pthread_cond_broadcast): Likewise.
+ (pthread_cond_signal): Likewise.
+
+1998-10-05 Ben Elliston <bje at cygnus.com>
+
+ * pthread.def: Update. Some functions aren't available yet, others
+ are macros in <pthread.h>.
+
+ * tests/join.c: Remove; useless.
+
+Mon Oct 5 14:25:08 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * pthread.def: New file for building the DLL.
+
+1998-10-05 Ben Elliston <bje at cygnus.com>
+
+ * misc.c (pthread_equal): Correct inverted logic bug.
+ (pthread_once): Use the POSIX mutex primitives, not Win32. Remove
+ irrelevant FIXME comment.
+
+ * global.c (PTHREAD_MUTEX_INITIALIZER): Move to pthread.h.
+
+ * pthread.h (PTHREAD_MUTEX_INITIALIZER): Define.
+ (pthread_mutex_t): Reimplement as a struct containing a valid
+ flag. If the flag is ever down upon entry to a mutex operation,
+ we call pthread_mutex_create() to initialise the object. This
+ fixes the problem of how to handle statically initialised objects
+ that can't call InitializeCriticalSection() due to their context.
+ (PTHREAD_ONCE_INIT): Define.
+
+ * mutex.c (pthread_mutex_init): Set valid flag.
+ (pthread_mutex_destroy): Clear valid flag.
+ (pthread_mutex_lock): Check and handle the valid flag.
+ (pthread_mutex_unlock): Likewise.
+ (pthread_mutex_trylock): Likewise.
+
+ * tests/mutex3.c: New file; test for the static initialisation
+ macro. Passes.
+
+ * tests/create1.c: New file; test pthread_create(). Passes.
+
+ * tests/equal.c: Poor test; remove.
+
+ * tests/equal1.c New file; test pthread_equal(). Passes.
+
+ * tests/once1.c: New file; test for pthread_once(). Passes.
+
+ * tests/self.c: Remove; rename to self1.c.
+
+ * tests/self1.c: This is the old self.c.
+
+ * tests/self2.c: New file. Test pthread_self() with a single
+ thread. Passes.
+
+ * tests/self3.c: New file. Test pthread_self() with a couple of
+ threads to ensure their thread IDs differ. Passes.
+
+1998-10-04 Ben Elliston <bje at cygnus.com>
+
+ * tests/mutex2.c: Test pthread_mutex_trylock(). Passes.
+
+ * tests/mutex1.c: New basic test for mutex functions (it passes).
+ (main): Eliminate warning.
+
+ * configure.in: Test for __stdcall, not _stdcall. Typo.
+
+ * configure: Regenerate.
+
+ * attr.c (pthread_attr_setstackaddr): Remove FIXME comment. Win32
+ does know about ENOSYS after all.
+ (pthread_attr_setstackaddr): Likewise.
+
+1998-10-03 Ben Elliston <bje at cygnus.com>
+
+ * configure.in: Test for the `_stdcall' keyword. Define `STDCALL'
+ to `_stdcall' if we have it, null otherwise.
+
+ * configure: Regenerate.
+
+ * acconfig.h (STDCALL): New define.
+
+ * config.h.in: Regenerate.
+
+ * create.c (ptw32_start_call): Add STDCALL prefix.
+
+ * mutex.c (pthread_mutex_init): Correct function signature.
+
+ * attr.c (pthread_attr_init): Only zero out the `sigmask' member
+ if we have the sigset_t type.
+
+ * pthread.h: No need to include <unistd.h>. It doesn't even exist
+ on Win32! Again, an artifact of cross-compilation.
+ (pthread_sigmask): Only provide if we have the sigset_t type.
+
+ * process.h: Remove. This was a stand-in before we started doing
+ native compilation under Win32.
+
+ * pthread.h (pthread_mutex_init): Make `attr' argument const.
+
+1998-10-02 Ben Elliston <bje at cygnus.com>
+
+ * COPYING: Remove.
+
+ * COPYING.LIB: Add. This library is under the LGPL.
+
+1998-09-13 Ben Elliston <bje at cygnus.com>
+
+ * configure.in: Test for required system features.
+
+ * configure: Generate.
+
+ * acconfig.h: New file.
+
+ * config.h.in: Generate.
+
+ * Makefile.in: Renamed from Makefile.
+
+ * COPYING: Import from a recent GNU package.
+
+ * config.guess: Likewise.
+
+ * config.sub: Likewise.
+
+ * install-sh: Likewise.
+
+ * config.h: Remove.
+
+ * Makefile: Likewise.
+
+1998-09-12 Ben Elliston <bje at cygnus.com>
+
+ * windows.h: No longer needed; remove.
+
+ * windows.c: Likewise.
+
+Sat Sep 12 20:09:24 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * windows.h: Remove error number definitions. These are in <errno.h>
+
+ * tsd.c: Add comment explaining rationale for not building
+ POSIX TSD on top of Win32 TLS.
+
+1998-09-12 Ben Elliston <bje at cygnus.com>
+
+ * {most}.c: Include <errno.h> to get POSIX error values.
+
+ * signal.c (pthread_sigmask): Only provide if HAVE_SIGSET_T is
+ defined.
+
+ * config.h: #undef features, don't #define them. This will be
+ generated by autoconf very soon.
+
+1998-08-11 Ben Elliston <bje at cygnus.com>
+
+ * Makefile (LIB): Define.
+ (clean): Define target.
+ (all): Build a library not just the object files.
+
+ * pthread.h: Provide a definition for struct timespec if we don't
+ already have one.
+
+ * windows.c (TlsGetValue): Bug fix.
+
+Thu Aug 6 15:19:22 1998 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * misc.c (pthread_once): Fix arg 1 of EnterCriticalSection()
+ and LeaveCriticalSection() calls to pass address-of lock.
+
+ * fork.c (pthread_atfork): Typecast (void (*)(void *)) funcptr
+ in each ptw32_handler_push() call.
+
+ * exit.c (ptw32_exit): Fix attr arg in
+ pthread_attr_getdetachstate() call.
+
+ * private.c (ptw32_new_thread): Typecast (HANDLE) NULL.
+ (ptw32_delete_thread): Ditto.
+
+ * implement.h: (PTW32_MAX_THREADS): Add define. This keeps
+ changing in an attempt to make thread administration data types
+ opaque and cleanup DLL startup.
+
+ * dll.c (PthreadsEntryPoint):
+ (ptw32_virgins): Remove malloc() and free() calls.
+ (ptw32_reuse): Ditto.
+ (ptw32_win32handle_map): Ditto.
+ (ptw32_threads_mutex_table): Ditto.
+
+ * global.c (_POSIX_THREAD_THREADS_MAX): Initialise with
+ PTW32_MAX_THREADS.
+ (ptw32_virgins): Ditto.
+ (ptw32_reuse): Ditto.
+ (ptw32_win32handle_map): Ditto.
+ (ptw32_threads_mutex_table): Ditto.
+
+ * create.c (pthread_create): Typecast (HANDLE) NULL.
+ Typecast (unsigned (*)(void *)) start_routine.
+
+ * condvar.c (pthread_cond_init): Add address-of operator & to
+ arg 1 of pthread_mutex_init() call.
+ (pthread_cond_destroy): Add address-of operator & to
+ arg 1 of pthread_mutex_destroy() call.
+
+ * cleanup.c (ptw32_destructor_pop_all): Add (int) cast to
+ pthread_getspecific() arg.
+ (ptw32_destructor_pop): Add (void *) cast to "if" conditional.
+ (ptw32_destructor_push): Add (void *) cast to
+ ptw32_handler_push() "key" arg.
+ (malloc.h): Add include.
+
+ * implement.h (ptw32_destructor_pop): Add prototype.
+
+ * tsd.c (implement.h): Add include.
+
+ * sync.c (pthread_join): Remove target_thread_mutex and it's
+ initialisation. Rename getdetachedstate to getdetachstate.
+ Remove unused variable "exitcode".
+ (pthread_detach): Remove target_thread_mutex and it's
+ initialisation. Rename getdetachedstate to getdetachstate.
+ Rename setdetachedstate to setdetachstate.
+
+ * signal.c (pthread_sigmask): Rename SIG_SET to SIG_SETMASK.
+ Cast "set" to (long *) in assignment to passify compiler warning.
+ Add address-of operator & to thread->attr.sigmask in memcpy() call
+ and assignment.
+ (pthread_sigmask): Add address-of operator & to thread->attr.sigmask
+ in memcpy() call and assignment.
+
+ * windows.h (THREAD_PRIORITY_ERROR_RETURN): Add.
+ (THREAD_PRIORITY_LOWEST): Add.
+ (THREAD_PRIORITY_HIGHEST): Add.
+
+ * sched.c (is_attr): Add function.
+ (implement.h): Add include.
+ (pthread_setschedparam): Rename all instances of "sched_policy"
+ to "sched_priority".
+ (pthread_getschedparam): Ditto.
+
+Tue Aug 4 16:57:58 1998 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * private.c (ptw32_delete_thread): Fix typo. Add missing ';'.
+
+ * global.c (ptw32_virgins): Change types from pointer to
+ array pointer.
+ (ptw32_reuse): Ditto.
+ (ptw32_win32handle_map): Ditto.
+ (ptw32_threads_mutex_table): Ditto.
+
+ * implement.h(ptw32_virgins): Change types from pointer to
+ array pointer.
+ (ptw32_reuse): Ditto.
+ (ptw32_win32handle_map): Ditto.
+ (ptw32_threads_mutex_table): Ditto.
+
+ * private.c (ptw32_delete_thread): Fix "entry" should be "thread".
+
+ * misc.c (pthread_self): Add extern for ptw32_threadID_TlsIndex.
+
+ * global.c: Add comment.
+
+ * misc.c (pthread_once): Fix member -> dereferences.
+ Change ptw32_once_flag to once_control->flag in "if" test.
+
+Tue Aug 4 00:09:30 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * implement.h(ptw32_virgins): Add extern.
+ (ptw32_virgin_next): Ditto.
+ (ptw32_reuse): Ditto.
+ (ptw32_reuse_top): Ditto.
+ (ptw32_win32handle_map): Ditto.
+ (ptw32_threads_mutex_table): Ditto.
+
+ * global.c (ptw32_virgins): Changed from array to pointer.
+ Storage allocation for the array moved into dll.c.
+ (ptw32_reuse): Ditto.
+ (ptw32_win32handle_map): Ditto.
+ (ptw32_threads_mutex_table): Ditto.
+
+ * dll.c (PthreadsEntryPoint): Set up thread admin storage when
+ DLL is loaded.
+
+ * fork.c (pthread_atfork): Fix function pointer arg to all
+ ptw32_handler_push() calls. Change "arg" arg to NULL in child push.
+
+ * exit.c: Add windows.h and process.h includes.
+ (ptw32_exit): Add local detachstate declaration.
+ (ptw32_exit): Fix incorrect name for pthread_attr_getdetachstate().
+
+ * pthread.h (_POSIX_THREAD_ATTR_STACKSIZE): Move from global.c
+ (_POSIX_THREAD_ATTR_STACKADDR): Ditto.
+
+ * create.c (pthread_create): Fix #if should be #ifdef.
+ (ptw32_start_call): Remove usused variables.
+
+ * process.h: Create.
+
+ * windows.h: Move _beginthreadex and _endthreadex into
+ process.h
+
+Mon Aug 3 21:19:57 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * condvar.c (pthread_cond_init): Add NULL attr to
+ pthread_mutex_init() call - default attributes will be used.
+ (cond_wait): Fix typo.
+ (cond_wait): Fix typo - cv was ev.
+ (pthread_cond_broadcast): Fix two identical typos.
+
+ * cleanup.c (ptw32_destructor_pop_all): Remove _ prefix from
+ PTHREAD_DESTRUCTOR_ITERATIONS.
+
+ * pthread.h: Move _POSIX_* values into posix.h
+
+ * pthread.h: Fix typo in pthread_mutex_init() prototype.
+
+ * attr.c (pthread_attr_init): Fix error in priority member init.
+
+ * windows.h (THREAD_PRIORITY_NORMAL): Add.
+
+ * pthread.h (sched_param): Add missing ';' to struct definition.
+
+ * attr.c (pthread_attr_init): Remove obsolete pthread_attr_t
+ member initialisation - cancelstate, canceltype, cancel_pending.
+ (is_attr): Make arg "attr" a const.
+
+ * implement.h (PTW32_HANDLER_POP_LIFO): Remove definition.
+ (PTW32_HANDLER_POP_FIFO): Ditto.
+ (PTW32_VALID): Add missing newline escape (\).
+ (ptw32_handler_node): Make element "next" a pointer.
+
+1998-08-02 Ben Elliston <bje at cygnus.com>
+
+ * windows.h: Remove duplicate TlsSetValue() prototype. Add
+ TlsGetValue() prototype.
+ (FALSE): Define.
+ (TRUE): Likewise.
+ Add forgotten errno values. Guard against multiple #includes.
+
+ * windows.c: New file. Implement stubs for Win32 functions.
+
+ * Makefile (SRCS): Remove. Not explicitly needed.
+ (CFLAGS): Add -Wall for all warnings with GCC.
+
+Sun Aug 2 19:03:42 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * config.h: Create. This is a temporary stand-in for autoconf yet
+ to be done.
+ (HAVE_SIGNAL_H): Add.
+
+ * pthread.h: Minor rearrangement for temporary config.h.
+
+Fri Jul 31 14:00:29 1998 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * cleanup.c (ptw32_destructor_pop): Implement. Removes
+ destructors associated with a key without executing them.
+ (ptw32_destructor_pop_all): Add FIXME comment.
+
+ * tsd.c (pthread_key_delete): Add call to ptw32_destructor_pop().
+
+Fri Jul 31 00:05:45 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * tsd.c (pthread_key_create): Update to properly associate
+ the destructor routine with the key.
+ (pthread_key_delete): Add FIXME comment.
+
+ * exit.c (ptw32_vacuum): Add call to
+ ptw32_destructor_pop_all().
+
+ * implement.h (ptw32_handler_pop_all): Add prototype.
+ (ptw32_destructor_pop_all): Ditto.
+
+ * cleanup.c (ptw32_destructor_push): Implement. This is just a
+ call to ptw32_handler_push().
+ (ptw32_destructor_pop_all): Implement. This is significantly
+ different to ptw32_handler_pop_all().
+
+ * Makefile (SRCS): Create. Preliminary.
+
+ * windows.h: Create. Contains Win32 definitions for compile
+ testing. This is just a standin for the real one.
+
+ * pthread.h (SIG_UNBLOCK): Fix typo. Was SIG_BLOCK.
+ (windows.h): Add include. Required for CRITICAL_SECTION.
+ (pthread_cond_t): Move enum declaration outside of struct
+ definition.
+ (unistd.h): Add include - may be temporary.
+
+ * condvar.c (windows.h): Add include.
+
+ * implement.h (PTW32_THIS): Remove - no longer required.
+ (PTW32_STACK): Use pthread_self() instead of PTW32_THIS.
+
+Thu Jul 30 23:12:45 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * implement.h: Remove ptw32_find_entry() prototype.
+
+ * private.c: Extend comments.
+ Remove ptw32_find_entry() - no longer needed.
+
+ * create.c (ptw32_start_call): Add call to TlsSetValue() to
+ store the thread ID.
+
+ * dll.c (PthreadsEntryPoint): Implement. This is called
+ whenever a process loads the DLL. Used to initialise thread
+ local storage.
+
+ * implement.h: Add ptw32_threadID_TlsIndex.
+ Add ()s around PTW32_VALID expression.
+
+ * misc.c (pthread_self): Re-implement using Win32 TLS to store
+ the threads own ID.
+
+Wed Jul 29 11:39:03 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * private.c: Corrections in comments.
+ (ptw32_new_thread): Alter "if" flow to be more natural.
+
+ * cleanup.c (ptw32_handler_push): Same as below.
+
+ * create.c (pthread_create): Same as below.
+
+ * private.c (ptw32_new_thread): Rename "new" to "new_thread".
+ Since when has a C programmer been required to know C++?
+
+Tue Jul 28 14:04:29 1998 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * implement.h: Add PTW32_VALID macro.
+
+ * sync.c (pthread_join): Modify to use the new thread
+ type and ptw32_delete_thread(). Rename "target" to "thread".
+ Remove extra local variable "target".
+ (pthread_detach): Ditto.
+
+ * signal.c (pthread_sigmask): Move init of "us" out of inner block.
+ Fix instance of "this" should have been "us". Rename "us" to "thread".
+
+ * sched.c (pthread_setschedparam): Modify to use the new thread
+ type.
+ (pthread_getschedparam): Ditto.
+
+ * private.c (ptw32_find_thread): Fix return type and arg.
+
+ * implement.h: Remove PTW32_YES and PTW32_NO.
+ (ptw32_new_thread): Add prototype.
+ (ptw32_find_thread): Ditto.
+ (ptw32_delete_thread): Ditto.
+ (ptw32_new_thread_entry): Remove prototype.
+ (ptw32_find_thread_entry): Ditto.
+ (ptw32_delete_thread_entry): Ditto.
+ ( PTW32_NEW, PTW32_INUSE, PTW32_EXITED, PTW32_REUSE):
+ Add.
+
+
+ * create.c (pthread_create): Minor rename "us" to "new" (I need
+ these cues but it doesn't stop me coming out with some major bugs
+ at times).
+ Load start_routine and arg into the thread so the wrapper can
+ call it.
+
+ * exit.c (pthread_exit): Fix pthread_this should be pthread_self.
+
+ * cancel.c (pthread_setcancelstate): Change
+ ptw32_threads_thread_t * to pthread_t and init with
+ pthread_this().
+ (pthread_setcanceltype): Ditto.
+
+ * exit.c (ptw32_exit): Add new pthread_t arg.
+ Rename ptw32_delete_thread_entry to ptw32_delete_thread.
+ Rename "us" to "thread".
+ (pthread_exit): Call ptw32_exit with added thread arg.
+
+ * create.c (ptw32_start_call): Insert missing ")".
+ Add "us" arg to ptw32_exit() call.
+ (pthread_create): Modify to use new thread allocation scheme.
+
+ * private.c: Added detailed explanation of the new thread
+ allocation scheme.
+ (ptw32_new_thread): Totally rewritten to use
+ new thread allocation scheme.
+ (ptw32_delete_thread): Ditto.
+ (ptw32_find_thread): Obsolete.
+
+Mon Jul 27 17:46:37 1998 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * create.c (pthread_create): Start of rewrite. Not completed yet.
+
+ * private.c (ptw32_new_thread_entry): Start of rewrite. Not
+ complete.
+
+ * implement.h (ptw32_threads_thread): Rename, remove thread
+ member, add win32handle and ptstatus members.
+ (ptw32_t): Add.
+
+ * pthread.h: pthread_t is no longer mapped directly to a Win32
+ HANDLE type. This is so we can let the Win32 thread terminate and
+ reuse the HANDLE while pthreads holds it's own thread ID until
+ the last waiting join exits.
+
+Mon Jul 27 00:20:37 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * private.c (ptw32_delete_thread_entry): Destroy the thread
+ entry attribute object before deleting the thread entry itself.
+
+ * attr.c (pthread_attr_init): Initialise cancel_pending = FALSE.
+ (pthread_attr_setdetachstate): Rename "detached" to "detachedstate".
+ (pthread_attr_getdetachstate): Ditto.
+
+ * exit.c (ptw32_exit): Fix incorrect check for detachedstate.
+
+ * implement.h (ptw32_call_t): Remove env member.
+
+Sun Jul 26 13:06:12 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * implement.h (ptw32_new_thread_entry): Fix prototype.
+ (ptw32_find_thread_entry): Ditto.
+ (ptw32_delete_thread_entry): Ditto.
+ (ptw32_exit): Add prototype.
+
+ * exit.c (ptw32_exit): New function. Called from pthread_exit()
+ and ptw32_start_call() to exit the thread. It allows an extra
+ argument which is the return code passed to _endthreadex().
+ (ptw32_exit): Move thread entry delete call from ptw32_vacuum()
+ into here. Add more explanation of thread entry deletion.
+ (ptw32_exit): Clarify comment.
+
+ * create.c (ptw32_start_call): Change pthread_exit() call to
+ ptw32_exit() call.
+
+ * exit.c (ptw32_vacuum): Add thread entry deletion code
+ moved from ptw32_start_call(). See next item.
+ (pthread_exit): Remove longjmp(). Add mutex lock around thread table
+ manipulation code. This routine now calls _enthreadex().
+
+ * create.c (ptw32_start_call): Remove setjmp() call and move
+ cleanup code out. Call pthread_exit(NULL) to terminate the thread.
+
+1998-07-26 Ben Elliston <bje at cygnus.com>
+
+ * tsd.c (pthread_getspecific): Update comments.
+
+ * mutex.c (pthread_mutexattr_setpshared): Not supported; remove.
+ (pthread_mutexattr_getpshared): Likewise.
+
+ * pthread.h (pthread_mutexattr_setpshared): Remove prototype.
+ (pthread_mutexattr_getpshared): Likewise.
+
+Sun Jul 26 00:09:59 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * sync.c: Rename all instances of ptw32_count_mutex to
+ ptw32_table_mutex.
+
+ * implement.h: Rename ptw32_count_mutex to
+ ptw32_table_mutex.
+
+ * global.c: Rename ptw32_count_mutex to
+ ptw32_table_mutex.
+
+ * create.c (pthread_create): Add critical sections.
+ (ptw32_start_call): Rename ptw32_count_mutex to
+ ptw32_table_mutex.
+
+ * cancel.c (pthread_setcancelstate): Fix indirection bug and rename
+ "this" to "us".
+
+ * signal.c (pthread_sigmask): Rename "this" to "us" and fix some
+ minor syntax errors. Declare "us" and initialise it.
+
+ * sync.c (pthread_detach): Rename "this" to "target".
+
+ * pthread.h: Converting PTHREAD_* defines to alias the (const int)
+ values in global.c.
+
+ * global.c: Started converting PTHREAD_* defines to (const int) as
+ a part of making the eventual pthreads DLL binary compatible
+ through version changes.
+
+ * condvar.c (cond_wait): Add cancelation point. This applies the
+ point to both pthread_cond_wait() and pthread_cond_timedwait().
+
+ * exit.c (pthread_exit): Rename "this" to "us".
+
+ * implement.h: Add comment.
+
+ * sync.c (pthread_join): I've satisfied myself that pthread_detach()
+ does set the detached attribute in the thread entry attributes
+ to PTHREAD_CREATE_DETACHED. "if" conditions were changed to test
+ that attribute instead of a separate flag.
+
+ * create.c (pthread_create): Rename "this" to "us".
+ (pthread_create): cancelstate and canceltype are not attributes
+ so the copy to thread entry attribute storage was removed.
+ Only the thread itself can change it's cancelstate or canceltype,
+ ie. the thread must exist already.
+
+ * private.c (ptw32_delete_thread_entry): Mutex locks removed.
+ Mutexes must be applied at the caller level.
+ (ptw32_new_thread_entry): Ditto.
+ (ptw32_new_thread_entry): Init cancelstate, canceltype, and
+ cancel_pending to default values.
+ (ptw32_new_thread_entry): Rename "this" to "new".
+ (ptw32_find_thread_entry): Rename "this" to "entry".
+ (ptw32_delete_thread_entry): Rename "thread_entry" to "entry".
+
+ * create.c (ptw32_start_call): Mutexes changed to
+ ptw32_count_mutex. All access to the threads table entries is
+ under the one mutex. Otherwise chaos reigns.
+
+Sat Jul 25 23:16:51 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * implement.h (ptw32_threads_thread): Move cancelstate and
+ canceltype members out of pthread_attr_t into here.
+
+ * fork.c (fork): Add comment.
+
+1998-07-25 Ben Elliston <bje at cygnus.com>
+
+ * fork.c (fork): Autoconfiscate.
+
+Sat Jul 25 00:00:13 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * create.c (ptw32_start_call): Set thread priority. Ensure our
+ thread entry is removed from the thread table but only if
+ pthread_detach() was called and there are no waiting joins.
+ (pthread_create): Set detach flag in thread entry if the
+ thread is created PTHREAD_CREATE_DETACHED.
+
+ * pthread.h (pthread_attr_t): Rename member "detachedstate".
+
+ * attr.c (pthread_attr_init): Rename attr members.
+
+ * exit.c (pthread_exit): Fix indirection mistake.
+
+ * implement.h (PTW32_THREADS_TABLE_INDEX): Add.
+
+ * exit.c (ptw32_vacuum): Fix incorrect args to
+ ptw32_handler_pop_all() calls.
+ Make thread entry removal conditional.
+
+ * sync.c (pthread_join): Add multiple join and async detach handling.
+
+ * implement.h (PTW32_THREADS_TABLE_INDEX): Add.
+
+ * global.c (ptw32_threads_mutex_table): Add.
+
+ * implement.h (ptw32_once_flag): Remove.
+ (ptw32_once_lock): Ditto.
+ (ptw32_threads_mutex_table): Add.
+
+ * global.c (ptw32_once_flag): Remove.
+ (ptw32_once_lock): Ditto.
+
+ * sync.c (pthread_join): Fix tests involving new return value
+ from ptw32_find_thread_entry().
+ (pthread_detach): Ditto.
+
+ * private.c (ptw32_find_thread_entry): Failure return code
+ changed from -1 to NULL.
+
+Fri Jul 24 23:09:33 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * create.c (pthread_create): Change . to -> in sigmask memcpy() args.
+
+ * pthread.h: (pthread_cancel): Add function prototype.
+ (pthread_testcancel): Ditto.
+
+1998-07-24 Ben Elliston <bje at cygnus.com>
+
+ * pthread.h (pthread_condattr_t): Rename dummy structure member.
+ (pthread_mutexattr_t): Likewise.
+
+Fri Jul 24 21:13:55 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * cancel.c (pthread_cancel): Implement.
+ (pthread_testcancel): Implement.
+
+ * exit.c (pthread_exit): Add comment explaining the longjmp().
+
+ * implement.h (ptw32_threads_thread_t): New member cancelthread.
+ (PTW32_YES): Define.
+ (PTW32_NO): Define.
+ (RND_SIZEOF): Remove.
+
+ * create.c (pthread_create): Rename cancelability to cancelstate.
+
+ * pthread.h (pthread_attr_t): Rename cancelability to cancelstate.
+ (PTHREAD_CANCELED): Define.
+
+1998-07-24 Ben Elliston <bje at cygnus.com>
+
+ * pthread.h (SIG_BLOCK): Define if not already defined.
+ (SIG_UNBLOCK): Likewise.
+ (SIG_SETMASK): Likewise.
+ (pthread_attr_t): Add signal mask member.
+ (pthread_sigmask): Add function prototype.
+
+ * signal.c (pthread_sigmask): Implement.
+
+ * create.c: #include <string.h> to get a prototype for memcpy().
+ (pthread_create): New threads inherit their creator's signal
+ mask. Copy the signal mask to the new thread structure if we know
+ about signals.
+
+Fri Jul 24 16:33:17 1998 Ross Johnson <rpj at swan.canberra.edu.au>
+
+ * fork.c (pthread_atfork): Add all the necessary push calls.
+ Local implementation semantics:
+ If we get an ENOMEM at any time then ALL handlers
+ (including those from previous pthread_atfork() calls) will be
+ popped off each of the three atfork stacks before we return.
+ (fork): Add all the necessary pop calls. Add the thread cancellation
+ and join calls to the child fork.
+ Add #includes.
+
+ * implement.h: (ptw32_handler_push): Fix return type and stack arg
+ type in prototype.
+ (ptw32_handler_pop): Fix stack arg type in prototype.
+ (ptw32_handler_pop_all): Fix stack arg type in prototype.
+
+ * cleanup.c (ptw32_handler_push): Change return type to int and
+ return ENOMEM if malloc() fails.
+
+ * sync.c (pthread_detach): Use equality test, not assignment.
+
+ * create.c (ptw32_start_call): Add call to Win32 CloseHandle()
+ if thread is detached.
+
+1998-07-24 Ben Elliston <bje at cygnus.com>
+
+ * sync.c (pthread_detach): Close the Win32 thread handle to
+ emulate detached (or daemon) threads.
+
+Fri Jul 24 03:00:25 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * sync.c (pthread_join): Save valueptr arg in joinvalueptr for
+ pthread_exit() to use.
+
+ * private.c (ptw32_new_thread_entry): Initialise joinvalueptr to
+ NULL.
+
+ * create.c (ptw32_start_call): Rewrite to facilitate joins.
+ pthread_exit() will do a longjmp() back to here. Does appropriate
+ cleanup and exit/return from the thread.
+ (pthread_create): _beginthreadex() now passes a pointer to our
+ thread table entry instead of just the call member of that entry.
+
+ * implement.h (ptw32_threads_thread): New member
+ void ** joinvalueptr.
+ (ptw32_call_t): New member jmpbuf env.
+
+ * exit.c (pthread_exit): Major rewrite to handle joins and handing
+ value pointer to joining thread. Uses longjmp() back to
+ ptw32_start_call().
+
+ * create.c (pthread_create): Ensure values of new attribute members
+ are copied to the thread attribute object.
+
+ * attr.c (pthread_attr_destroy): Fix merge conflicts.
+ (pthread_attr_getdetachstate): Fix merge conflicts.
+ (pthread_attr_setdetachstate): Fix merge conflicts.
+
+ * pthread.h: Fix merge conflicts.
+
+ * sync.c (pthread_join): Fix merge conflicts.
+
+Fri Jul 24 00:21:21 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * sync.c (pthread_join): Add check for valid and joinable
+ thread.
+ (pthread_detach): Implement. After checking for a valid and joinable
+ thread, it's still a no-op.
+
+ * private.c (ptw32_find_thread_entry): Bug prevented returning
+ an error value in some cases.
+
+ * attr.c (pthread_attr_setdetachedstate): Implement.
+ (pthread_attr_getdetachedstate): Implement.
+
+ * implement.h: Move more hidden definitions into here from
+ pthread.h.
+
+1998-07-24 Ben Elliston <bje at cygnus.com>
+
+ * pthread.h (PTHREAD_CREATE_JOINABLE): Define.
+ (PTHREAD_CREATE_DETACHED): Likewise.
+ (pthread_attr_t): Add new structure member `detached'.
+ (pthread_attr_getdetachstate): Add function prototype.
+ (pthread_attr_setdetachstate): Likewise.
+
+ * sync.c (pthread_join): Return if the target thread is detached.
+
+ * attr.c (pthread_attr_init): Initialise cancelability and
+ canceltype structure members.
+ (pthread_attr_getdetachstate): Implement.
+ (pthread_attr_setdetachstate): Likewise.
+
+ * implement.h (PTW32_CANCEL_DEFAULTS): Remove. Bit fields
+ proved to be too cumbersome. Set the defaults in attr.c using the
+ public PTHREAD_CANCEL_* constants.
+
+ * cancel.c: New file.
+
+ * pthread.h (sched_param): Define this type.
+ (pthread_attr_getschedparam): Add function prototype.
+ (pthread_attr_setschedparam): Likewise.
+ (pthread_setcancelstate): Likewise.
+ (pthread_setcanceltype): Likewise.
+ (sched_get_priority_min): Likewise.
+ (sched_get_priority_max): Likewise.
+ (pthread_mutexattr_setprotocol): Remove; not supported.
+ (pthread_mutexattr_getprotocol): Likewise.
+ (pthread_mutexattr_setprioceiling): Likewise.
+ (pthread_mutexattr_getprioceiling): Likewise.
+ (pthread_attr_t): Add canceltype member. Update comments.
+ (SCHED_OTHER): Define this scheduling policy constant.
+ (SCHED_FIFO): Likewise.
+ (SCHED_RR): Likewise.
+ (SCHED_MIN): Define the lowest possible value for this constant.
+ (SCHED_MAX): Likewise, the maximum possible value.
+ (PTHREAD_CANCEL_ASYNCHRONOUS): Redefine.
+ (PTHREAD_CANCEL_DEFERRED): Likewise.
+
+ * sched.c: New file.
+ (pthread_setschedparam): Implement.
+ (pthread_getschedparam): Implement.
+ (sched_get_priority_max): Validate policy argument.
+ (sched_get_priority_min): Likewise.
+
+ * mutex.c (pthread_mutexattr_setprotocol): Remove; not supported.
+ (pthread_mutexattr_getprotocol): Likewise.
+ (pthread_mutexattr_setprioceiling): Likewise.
+ (pthread_mutexattr_getprioceiling): Likewise.
+
+Fri Jul 24 00:21:21 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * create.c (pthread_create): Arg to ptw32_new_thread_entry()
+ changed. See next entry. Move mutex locks out. Changes made yesterday
+ and today allow us to start the new thread running rather than
+ temporarily suspended.
+
+ * private.c (ptw32_new_thread_entry): ptw32_thread_table
+ was changed back to a table of thread structures rather than pointers.
+ As such we're trading storage for increaded speed. This routine
+ was modified to work with the new table. Mutex lock put in around
+ global data accesses.
+ (ptw32_find_thread_entry): Ditto
+ (ptw32_delete_thread_entry): Ditto
+
+Thu Jul 23 23:25:30 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * global.c: New. Global data objects declared here. These moved from
+ pthread.h.
+
+ * pthread.h: Move implementation hidden definitions into
+ implement.h.
+
+ * implement.h: Move implementation hidden definitions from
+ pthread.h. Add constants to index into the different handler stacks.
+
+ * cleanup.c (ptw32_handler_push): Simplify args. Restructure.
+ (ptw32_handler_pop): Simplify args. Restructure.
+ (ptw32_handler_pop_all): Simplify args. Restructure.
+
+Wed Jul 22 00:16:22 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * attr.c, implement.h, pthread.h, ChangeLog: Resolve CVS merge
+ conflicts.
+
+ * private.c (ptw32_find_thread_entry): Changes to return type
+ to support leaner ptw32_threads_table[] which now only stores
+ ptw32_thread_thread_t *.
+ (ptw32_new_thread_entry): Internal changes.
+ (ptw32_delete_thread_entry): Internal changes to avoid contention.
+ Calling routines changed accordingly.
+
+ * pthread.h: Modified cleanup macros to use new generic push and pop.
+ Added destructor and atfork stacks to ptw32_threads_thread_t.
+
+ * cleanup.c (ptw32_handler_push, ptw32_handler_pop,
+ ptw32_handler_pop_all): Renamed cleanup push and pop routines
+ and made generic to handle destructors and atfork handlers as
+ well.
+
+ * create.c (ptw32_start_call): New function is a wrapper for
+ all new threads. It allows us to do some cleanup when the thread
+ returns, ie. that is otherwise only done if the thread is cancelled.
+
+ * exit.c (ptw32_vacuum): New function contains code from
+ pthread_exit() that we need in the new ptw32_start_call()
+ as well.
+
+ * implement.h: Various additions and minor changes.
+
+ * pthread.h: Various additions and minor changes.
+ Change cleanup handler macros to use generic handler push and pop
+ functions.
+
+ * attr.c: Minor mods to all functions.
+ (is_attr): Implemented missing function.
+
+ * create.c (pthread_create): More clean up.
+
+ * private.c (ptw32_find_thread_entry): Implement.
+ (ptw32_delete_thread_entry): Implement.
+ (ptw32_new_thread_entry): Implement.
+ These functions manipulate the implementations internal thread
+ table and are part of general code cleanup and modularisation.
+ They replace ptw32_getthreadindex() which was removed.
+
+ * exit.c (pthread_exit): Changed to use the new code above.
+
+ * pthread.h: Add cancelability constants. Update comments.
+
+1998-07-22 Ben Elliston <bje at cygnus.com>
+
+ * attr.c (pthread_setstacksize): Update test of attr argument.
+ (pthread_getstacksize): Likewise.
+ (pthread_setstackaddr): Likewise.
+ (pthread_getstackaddr): Likewise.
+ (pthread_attr_init): No need to allocate any storage.
+ (pthread_attr_destroy): No need to free any storage.
+
+ * mutex.c (is_attr): Not likely to be needed; remove.
+ (remove_attr): Likewise.
+ (insert_attr): Likewise.
+
+ * implement.h (ptw32_mutexattr_t): Moved to a public definition
+ in pthread.h. There was little gain in hiding these details.
+ (ptw32_condattr_t): Likewise.
+ (ptw32_attr_t): Likewise.
+
+ * pthread.h (pthread_atfork): Add function prototype.
+ (pthread_attr_t): Moved here from implement.h.
+
+ * fork.c (pthread_atfork): Preliminary implementation.
+ (ptw32_fork): Likewise.
+
+Wed Jul 22 00:16:22 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * cleanup.c (ptw32_cleanup_push): Implement.
+ (ptw32_cleanup_pop): Implement.
+ (ptw32_do_cancellation): Implement.
+ These are private to the implementation. The real cleanup functions
+ are macros. See below.
+
+ * pthread.h (pthread_cleanup_push): Implement as a macro.
+ (pthread_cleanup_pop): Implement as a macro.
+ Because these are macros which start and end a block, the POSIX scoping
+ requirement is observed. See the comment in the file.
+
+ * exit.c (pthread_exit): Refine the code.
+
+ * create.c (pthread_create): Code cleanup.
+
+ * implement.h (RND_SIZEOF): Add RND_SIZEOF(T) to round sizeof(T)
+ up to multiple of DWORD.
+ Add function prototypes.
+
+ * private.c (ptw32_getthreadindex): "*thread" should have been
+ "thread". Detect empty slot fail condition.
+
+1998-07-20 Ben Elliston <bje at cygnus.com>
+
+ * misc.c (pthread_once): Implement. Don't use a per-application
+ flag and mutex--make `pthread_once_t' contain these elements in
+ their structure. The earlier version had incorrect semantics.
+
+ * pthread.h (ptw32_once_flag): Add new variable. Remove.
+ (ptw32_once_lock): Add new mutex lock to ensure integrity of
+ access to ptw32_once_flag. Remove.
+ (pthread_once): Add function prototype.
+ (pthread_once_t): Define this type.
+
+Mon Jul 20 02:31:05 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * private.c (ptw32_getthreadindex): Implement.
+
+ * pthread.h: Add application static data dependent on
+ _PTHREADS_BUILD_DLL define. This is needed to avoid allocating
+ non-sharable static data within the pthread DLL.
+
+ * implement.h: Add ptw32_cleanup_stack_t, ptw32_cleanup_node_t
+ and PTW32_HASH_INDEX.
+
+ * exit.c (pthread_exit): Begin work on cleanup and de-allocate
+ thread-private storage.
+
+ * create.c (pthread_create): Add thread to thread table.
+ Keep a thread-private copy of the attributes with default values
+ filled in when necessary. Same for the cleanup stack. Make
+ pthread_create C run-time library friendly by using _beginthreadex()
+ instead of CreateThread(). Fix error returns.
+
+Sun Jul 19 16:26:23 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * implement.h: Rename pthreads_thread_count to ptw32_threads_count.
+ Create ptw32_threads_thread_t struct to keep thread specific data.
+
+ * create.c: Rename pthreads_thread_count to ptw32_threads_count.
+ (pthread_create): Handle errors from CreateThread().
+
+1998-07-19 Ben Elliston <bje at cygnus.com>
+
+ * condvar.c (pthread_cond_wait): Generalise. Moved from here ..
+ (cond_wait): To here.
+ (pthread_cond_timedwait): Implement; use generalised cond_wait().
+
+ * pthread.h (pthread_key_t): Define this type.
+ (pthread_key_create): Add function prototype.
+ (pthread_setspecific): Likewise.
+ (pthread_getspecific): Likwise.
+ (pthread_key_delete): Likewise.
+
+ * tsd.c (pthread_key_create): Implement.
+ (pthread_setspecific): Likewise.
+ (pthread_getspecific): Likewise.
+ (pthread_key_delete): Likewise.
+
+ * mutex.c (pthread_mutex_trylock): Return ENOSYS if this function
+ is called on a Win32 platform which is not Windows NT.
+
+1998-07-18 Ben Elliston <bje at cygnus.com>
+
+ * condvar.c (pthread_condattr_init): Do not attempt to malloc any
+ storage; none is needed now that condattr_t is an empty struct.
+ (pthread_condattr_destory): Likewise; do not free storage.
+ (pthread_condattr_setpshared): No longer supported; return ENOSYS.
+ (pthread_condattr_getpshared): Likewise.
+ (pthread_cond_init): Implement with help from Douglas Schmidt.
+ Remember to initialise the cv's internal mutex.
+ (pthread_cond_wait): Likewise.
+ (pthread_cond_signal): Likewise.
+ (pthread_cond_broadcast): Likewise.
+ (pthread_cond_timedwait): Preliminary implementation, but I need
+ to see some API documentation for `WaitForMultipleObject'.
+ (pthread_destory): Implement.
+
+ * pthread.h (pthread_cond_init): Add function protoype.
+ (pthread_cond_broadcast): Likewise.
+ (pthread_cond_signal): Likewise.
+ (pthread_cond_timedwait): Likewise.
+ (pthread_cond_wait): Likewise.
+ (pthread_cond_destroy): Likewise.
+ (pthread_cond_t): Define this type. Fix for u_int. Do not assume
+ that the mutex contained withing the pthread_cond_t structure will
+ be a critical section. Use our new POSIX type!
+
+ * implement.h (ptw32_condattr_t): Remove shared attribute.
+
+1998-07-17 Ben Elliston <bje at cygnus.com>
+
+ * pthread.h (PTHREADS_PROCESS_PRIVATE): Remove.
+ (PTHREAD_PROCESS_SHARED): Likewise. No support for mutexes shared
+ across processes for now.
+ (pthread_mutex_t): Use a Win32 CRITICAL_SECTION type for better
+ performance.
+
+ * implement.h (ptw32_mutexattr_t): Remove shared attribute.
+
+ * mutex.c (pthread_mutexattr_setpshared): This optional function
+ is no longer supported, since we want to implement POSIX mutex
+ variables using the much more efficient Win32 critical section
+ primitives. Critical section objects in Win32 cannot be shared
+ between processes.
+ (pthread_mutexattr_getpshared): Likewise.
+ (pthread_mutexattr_init): No need to malloc any storage; the
+ attributes structure is now empty.
+ (pthread_mutexattr_destroy): This is now a nop.
+ (pthread_mutex_init): Use InitializeCriticalSection().
+ (pthread_mutex_destroy): Use DeleteCriticalSection().
+ (pthread_mutex_lock): Use EnterCriticalSection().
+ (pthread_mutex_trylock): Use TryEnterCriticalSection(). This is
+ not supported by Windows 9x, but trylock is a hack anyway, IMHO.
+ (pthread_mutex_unlock): Use LeaveCriticalSection().
+
+1998-07-14 Ben Elliston <bje at cygnus.com>
+
+ * attr.c (pthread_attr_setstacksize): Implement.
+ (pthread_attr_getstacksize): Likewise.
+ (pthread_attr_setstackaddr): Likewise.
+ (pthread_attr_getstackaddr): Likewise.
+ (pthread_attr_init): Likewise.
+ (pthread_attr_destroy): Likewise.
+
+ * condvar.c (pthread_condattr_init): Add `_cond' to function name.
+
+ * mutex.c (pthread_mutex_lock): Add `_mutex' to function name.
+ (pthread_mutex_trylock): Likewise.
+ (pthread_mutex_unlock): Likewise.
+
+ * pthread.h (pthread_condattr_setpshared): Fix typo.
+ (pthread_attr_init): Add function prototype.
+ (pthread_attr_destroy): Likewise.
+ (pthread_attr_setstacksize): Likewise.
+ (pthread_attr_getstacksize): Likewise.
+ (pthread_attr_setstackaddr): Likewise.
+ (pthread_attr_getstackaddr): Likewise.
+
+Mon Jul 13 01:09:55 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * implement.h: Wrap in #ifndef _IMPLEMENT_H
+
+ * create.c (pthread_create): Map stacksize attr to Win32.
+
+ * mutex.c: Include implement.h
+
+1998-07-13 Ben Elliston <bje at cygnus.com>
+
+ * condvar.c (pthread_condattr_init): Implement.
+ (pthread_condattr_destroy): Likewise.
+ (pthread_condattr_setpshared): Likewise.
+ (pthread_condattr_getpshared): Likewise.
+
+ * implement.h (PTHREAD_THREADS_MAX): Remove trailing semicolon.
+ (PTHREAD_STACK_MIN): Specify; needs confirming.
+ (ptw32_attr_t): Define this type.
+ (ptw32_condattr_t): Likewise.
+
+ * pthread.h (pthread_mutex_t): Define this type.
+ (pthread_condattr_t): Likewise.
+ (pthread_mutex_destroy): Add function prototype.
+ (pthread_lock): Likewise.
+ (pthread_trylock): Likewise.
+ (pthread_unlock): Likewise.
+ (pthread_condattr_init): Likewise.
+ (pthread_condattr_destroy): Likewise.
+ (pthread_condattr_setpshared): Likewise.
+ (pthread_condattr_getpshared): Likewise.
+
+ * mutex.c (pthread_mutex_init): Implement.
+ (pthread_mutex_destroy): Likewise.
+ (pthread_lock): Likewise.
+ (pthread_trylock): Likewise.
+ (pthread_unlock): Likewise.
+
+1998-07-12 Ben Elliston <bje at cygnus.com>
+
+ * implement.h (ptw32_mutexattr_t): Define this implementation
+ internal type. Application programmers only see a mutex attribute
+ object as a void pointer.
+
+ * pthread.h (pthread_mutexattr_t): Define this type.
+ (pthread_mutexattr_init): Add function prototype.
+ (pthread_mutexattr_destroy): Likewise.
+ (pthread_mutexattr_setpshared): Likewise.
+ (pthread_mutexattr_getpshared): Likewise.
+ (pthread_mutexattr_setprotocol): Likewise.
+ (pthread_mutexattr_getprotocol): Likewise.
+ (pthread_mutexattr_setprioceiling): Likewise.
+ (pthread_mutexattr_getprioceiling): Likewise.
+ (PTHREAD_PROCESS_PRIVATE): Define.
+ (PTHREAD_PROCESS_SHARED): Define.
+
+ * mutex.c (pthread_mutexattr_init): Implement.
+ (pthread_mutexattr_destroy): Implement.
+ (pthread_mutexattr_setprotocol): Implement.
+ (pthread_mutexattr_getprotocol): Likewise.
+ (pthread_mutexattr_setprioceiling): Likewise.
+ (pthread_mutexattr_getprioceiling): Likewise.
+ (pthread_mutexattr_setpshared): Likewise.
+ (pthread_mutexattr_getpshared): Likewise.
+ (insert_attr): New function; very preliminary implementation!
+ (is_attr): Likewise.
+ (remove_attr): Likewise.
+
+Sat Jul 11 14:48:54 1998 Ross Johnson <rpj at ixobrychus.canberra.edu.au>
+
+ * implement.h: Preliminary implementation specific defines.
+
+ * create.c (pthread_create): Preliminary implementation.
+
+1998-07-11 Ben Elliston <bje at cygnus.com>
+
+ * sync.c (pthread_join): Implement.
+
+ * misc.c (pthread_equal): Likewise.
+
+ * pthread.h (pthread_join): Add function prototype.
+ (pthread_equal): Likewise.
+
+1998-07-10 Ben Elliston <bje at cygnus.com>
+
+ * misc.c (pthread_self): Implement.
+
+ * exit.c (pthread_exit): Implement.
+
+ * pthread.h (pthread_exit): Add function prototype.
+ (pthread_self): Likewise.
+ (pthread_t): Define this type.
+
+1998-07-09 Ben Elliston <bje at cygnus.com>
+
+ * create.c (pthread_create): A dummy stub right now.
+
+ * pthread.h (pthread_create): Add function prototype.
diff --git a/libs/pthreads/docs/FAQ b/libs/pthreads/docs/FAQ
new file mode 100644
index 0000000000..cb1786c5ae
--- /dev/null
+++ b/libs/pthreads/docs/FAQ
@@ -0,0 +1,451 @@
+ =========================================
+ PTHREADS-WIN32 Frequently Asked Questions
+ =========================================
+
+INDEX
+-----
+
+Q 1 What is it?
+
+Q 2 Which of the several dll versions do I use?
+ or,
+ What are all these pthread*.dll and pthread*.lib files?
+
+Q 3 What is the library naming convention?
+
+Q 4 Cleanup code default style or: it used to work when I built
+ the library myself, but now it doesn't - why?
+
+Q 5 Why is the default library version now less exception-friendly?
+
+Q 6 Should I use Cygwin or Mingw32 as a development environment?
+
+Q 7 Now that pthreads-win32 builds under Mingw32, why do I get
+ memory access violations (segfaults)?
+
+Q 8 How do I use pthread.dll for Win32 (Visual C++ 5.0)
+
+Q 9 Cancelation doesn't work for me, why?
+
+Q 10 How do I generate pthreadGCE.dll and libpthreadw32.a for use
+ with Mingw32?
+
+Q 11 Why isn't pthread_t defined as a scalar (e.g. pointer or int)
+ like it is for other POSIX threads implementations?
+
+=============================================================================
+
+Q 1 What is it?
+---
+
+Pthreads-win32 is an Open Source Software implementation of the
+Threads component of the POSIX 1003.1c 1995 Standard for Microsoft's
+Win32 environment. Some functions from POSIX 1003.1b are also
+supported including semaphores. Other related functions include
+the set of read-write lock functions. The library also supports
+some of the functionality of the Open Group's Single Unix
+specification, version 2, namely mutex types.
+
+See the file "ANNOUNCE" for more information including standards
+conformance details and list of supported routines.
+
+
+------------------------------------------------------------------------------
+
+Q 2 Which of the several dll versions do I use?
+--- or,
+ What are all these pthread*.dll and pthread*.lib files?
+
+Simply, you only use one of them, but you need to choose carefully.
+
+The most important choice you need to make is whether to use a
+version that uses exceptions internally, or not (there are versions
+of the library that use exceptions as part of the thread
+cancelation and cleanup implementation, and one that uses
+setjmp/longjmp instead).
+
+There is some contension amongst POSIX threads experts as
+to how POSIX threads cancelation and exit should work
+with languages that include exceptions and handlers, e.g.
+C++ and even C (Microsoft's Structured Exceptions).
+
+The issue is: should cancelation of a thread in, say,
+a C++ application cause object destructors and C++ exception
+handlers to be invoked as the stack unwinds during thread
+exit, or not?
+
+There seems to be more opinion in favour of using the
+standard C version of the library (no EH) with C++ applications
+since this appears to be the assumption commercial pthreads
+implementations make. Therefore, if you use an EH version
+of pthreads-win32 then you may be under the illusion that
+your application will be portable, when in fact it is likely to
+behave very differently linked with other pthreads libraries.
+
+Now you may be asking: why have you kept the EH versions of
+the library?
+
+There are a couple of reasons:
+- there is division amongst the experts and so the code may
+ be needed in the future. (Yes, it's in the repository and we
+ can get it out anytime in the future, but ...)
+- pthreads-win32 is one of the few implementations, and possibly
+ the only freely available one, that has EH versions. It may be
+ useful to people who want to play with or study application
+ behaviour under these conditions.
+
+
+------------------------------------------------------------------------------
+
+Q 3 What is the library naming convention?
+---
+
+Because the library is being built using various exception
+handling schemes and compilers - and because the library
+may not work reliably if these are mixed in an application,
+each different version of the library has it's own name.
+
+Note 1: the incompatibility is really between EH implementations
+of the different compilers. It should be possible to use the
+standard C version from either compiler with C++ applications
+built with a different compiler. If you use an EH version of
+the library, then you must use the same compiler for the
+application. This is another complication and dependency that
+can be avoided by using only the standard C library version.
+
+Note 2: if you use a standard C pthread*.dll with a C++
+application, then any functions that you define that are
+intended to be called via pthread_cleanup_push() must be
+__cdecl.
+
+Note 3: the intention is to also name either the VC or GC
+version (it should be arbitrary) as pthread.dll, including
+pthread.lib and libpthread.a as appropriate.
+
+In general:
+ pthread[VG]{SE,CE,C}.dll
+ pthread[VG]{SE,CE,C}.lib
+
+where:
+ [VG] indicates the compiler
+ V - MS VC
+ G - GNU C
+
+ {SE,CE,C} indicates the exception handling scheme
+ SE - Structured EH
+ CE - C++ EH
+ C - no exceptions - uses setjmp/longjmp
+
+For example:
+ pthreadVSE.dll (MSVC/SEH)
+ pthreadGCE.dll (GNUC/C++ EH)
+ pthreadGC.dll (GNUC/not dependent on exceptions)
+
+The GNU library archive file names have changed to:
+
+ libpthreadGCE.a
+ libpthreadGC.a
+
+
+------------------------------------------------------------------------------
+
+Q 4 Cleanup code default style or: it used to work when I built
+--- the library myself, but now it doesn't - why?
+
+Up to and including snapshot 2001-07-12, if not defined, the cleanup
+style was determined automatically from the compiler used, and one
+of the following was defined accordingly:
+
+ __CLEANUP_SEH MSVC only
+ __CLEANUP_CXX C++, including MSVC++, GNU G++
+ __CLEANUP_C C, including GNU GCC, not MSVC
+
+These defines determine the style of cleanup (see pthread.h) and,
+most importantly, the way that cancelation and thread exit (via
+pthread_exit) is performed (see the routine ptw32_throw() in private.c).
+
+In short, the exceptions versions of the library throw an exception
+when a thread is canceled or exits (via pthread_exit()), which is
+caught by a handler in the thread startup routine, so that the
+the correct stack unwinding occurs regardless of where the thread
+is when it's canceled or exits via pthread_exit().
+
+After snapshot 2001-07-12, unless your build explicitly defines (e.g.
+via a compiler option) __CLEANUP_SEH, __CLEANUP_CXX, or __CLEANUP_C, then
+the build now ALWAYS defaults to __CLEANUP_C style cleanup. This style
+uses setjmp/longjmp in the cancelation and pthread_exit implementations,
+and therefore won't do stack unwinding even when linked to applications
+that have it (e.g. C++ apps). This is for consistency with most/all
+commercial Unix POSIX threads implementations.
+
+Although it was not clearly documented before, it is still necessary to
+build your application using the same __CLEANUP_* define as was
+used for the version of the library that you link with, so that the
+correct parts of pthread.h are included. That is, the possible
+defines require the following library versions:
+
+ __CLEANUP_SEH pthreadVSE.dll
+ __CLEANUP_CXX pthreadVCE.dll or pthreadGCE.dll
+ __CLEANUP_C pthreadVC.dll or pthreadGC.dll
+
+THE POINT OF ALL THIS IS: if you have not been defining one of these
+explicitly, then the defaults have been set according to the compiler
+and language you are using, as described at the top of this
+section.
+
+THIS NOW CHANGES, as has been explained above. For example:
+
+If you were building your application with MSVC++ i.e. using C++
+exceptions (rather than SEH) and not explicitly defining one of
+__CLEANUP_*, then __CLEANUP_C++ was defined for you in pthread.h.
+You should have been linking with pthreadVCE.dll, which does
+stack unwinding.
+
+If you now build your application as you had before, pthread.h will now
+set __CLEANUP_C as the default style, and you will need to link
+with pthreadVC.dll. Stack unwinding will now NOT occur when a
+thread is canceled, nor when the thread calls pthread_exit().
+
+Your application will now most likely behave differently to previous
+versions, and in non-obvious ways. Most likely is that local
+objects may not be destroyed or cleaned up after a thread
+is canceled.
+
+If you want the same behaviour as before, then you must now define
+__CLEANUP_C++ explicitly using a compiler option and link with
+pthreadVCE.dll as you did before.
+
+
+------------------------------------------------------------------------------
+
+Q 5 Why is the default library version now less exception-friendly?
+---
+
+Because most commercial Unix POSIX threads implementations don't allow you to
+choose to have stack unwinding. (Compaq's TRU64 Unix is possibly an exception.)
+
+Therefore, providing it in pthread-win32 as a default could be dangerous
+and non-portable. We still provide the choice but you must now consciously
+make it.
+
+WHY NOT REMOVE THE EXCEPTIONS VERSIONS OF THE LIBRARY ALTOGETHER?
+There are a few reasons:
+- because there are well respected POSIX threads people who believe
+ that POSIX threads implementations should be exceptions-aware and
+ do the expected thing in that context. (There are equally respected
+ people who believe it should not be easily accessible, if it's there
+ at all.)
+- because pthreads-win32 is one of the few implementations that has
+ the choice, perhaps the only freely available one, and so offers
+ a laboratory to people who may want to explore the effects;
+- although the code will always be around somewhere for anyone who
+ wants it, once it's removed from the current version it will not be
+ nearly as visible to people who may have a use for it.
+
+
+------------------------------------------------------------------------------
+
+Q 6 Should I use Cygwin or Mingw32 as a development environment?
+---
+
+Important: see Q7 also.
+
+Use Mingw32 with the MSVCRT library to build applications that use
+the pthreads DLL.
+
+Cygwin's own internal support for POSIX threads is growing.
+Consult that project's documentation for more information.
+
+------------------------------------------------------------------------------
+
+Q 7 Now that pthreads-win32 builds under Mingw32, why do I get
+--- memory access violations (segfaults)?
+
+The latest Mingw32 package has thread-safe exception handling (see Q10).
+Also, see Q6 above.
+
+------------------------------------------------------------------------------
+
+Q 8 How do I use pthread.dll for Win32 (Visual C++ 5.0)
+---
+
+>
+> I'm a "rookie" when it comes to your pthread implementation. I'm currently
+> desperately trying to install the prebuilt .dll file into my MSVC compiler.
+> Could you please provide me with explicit instructions on how to do this (or
+> direct me to a resource(s) where I can acquire such information)?
+>
+> Thank you,
+>
+
+You should have a .dll, .lib, .def, and three .h files. It is recommended
+that you use pthreadVC.dll, rather than pthreadVCE.dll or pthreadVSE.dll
+(see Q2 above).
+
+The .dll can go in any directory listed in your PATH environment
+variable, so putting it into C:\WINDOWS should work.
+
+The .lib file can go in any directory listed in your LIB environment
+variable.
+
+The .h files can go in any directory listed in your INCLUDE
+environment variable.
+
+Or you might prefer to put the .lib and .h files into a new directory
+and add its path to LIB and INCLUDE. You can probably do this easiest
+by editing the file:-
+
+C:\Program Files\DevStudio\vc\bin\vcvars32.bat
+
+The .def file isn't used by anything in the pre-compiled version but
+is included for information.
+
+Cheers.
+Ross
+
+------------------------------------------------------------------------------
+
+Q 9 Cancelation doesn't work for me, why?
+---
+
+> I'm investigating a problem regarding thread cancelation. The thread I want
+> to cancel has PTHREAD_CANCEL_ASYNCHRONOUS, however, this piece of code
+> blocks on the join():
+>
+> if ((retv = Pthread_cancel( recvThread )) == 0)
+> {
+> retv = Pthread_join( recvThread, 0 );
+> }
+>
+> Pthread_* are just macro's; they call pthread_*.
+>
+> The thread recvThread seems to block on a select() call. It doesn't get
+> cancelled.
+>
+> Two questions:
+>
+> 1) is this normal behaviour?
+>
+> 2) if not, how does the cancel mechanism work? I'm not very familliar to
+> win32 programming, so I don't really understand how the *Event() family of
+> calls work.
+
+The answer to your first question is, normal POSIX behaviour would
+be to asynchronously cancel the thread. However, even that doesn't
+guarantee cancelation as the standard only says it should be
+cancelled as soon as possible.
+
+Snapshot 99-11-02 or earlier only partially supports asynchronous cancellation.
+Snapshots since then simulate async cancelation by poking the address of
+a cancelation routine into the PC of the threads context. This requires
+the thread to be resumed in some way for the cancelation to actually
+proceed. This is not true async cancelation, but it is as close as we've
+been able to get to it.
+
+If the thread you're trying to cancel is blocked (for instance, it could be
+waiting for data from the network), it will only get cancelled when it unblocks
+(when the data arrives). For true pre-emptive cancelation in these cases,
+pthreads-win32 from snapshot 2004-05-16 can automatically recognise and use the
+QueueUserAPCEx package by Panagiotis E. Hadjidoukas. This package is available
+from the pthreads-win32 ftp site and is included in the pthreads-win32
+self-unpacking zip from 2004-05-16 onwards.
+
+Using deferred cancelation would normally be the way to go, however,
+even though the POSIX threads standard lists a number of C library
+functions that are defined as deferred cancelation points, there is
+no hookup between those which are provided by Windows and the
+pthreads-win32 library.
+
+Incidently, it's worth noting for code portability that the older POSIX
+threads standards cancelation point lists didn't include "select" because
+(as I read in Butenhof) it wasn't part of POSIX. However, it does appear in
+the SUSV3.
+
+Effectively, the only mandatory cancelation points that pthreads-win32
+recognises are those the library implements itself, ie.
+
+ pthread_testcancel
+ pthread_cond_wait
+ pthread_cond_timedwait
+ pthread_join
+ sem_wait
+ sem_timedwait
+ pthread_delay_np
+
+The following routines from the non-mandatory list in SUSV3 are
+cancelation points in pthreads-win32:
+
+ pthread_rwlock_wrlock
+ pthread_rwlock_timedwrlock
+
+The following routines from the non-mandatory list in SUSV3 are not
+cancelation points in pthreads-win32:
+
+ pthread_rwlock_rdlock
+ pthread_rwlock_timedrdlock
+
+Pthreads-win32 also provides two functions that allow you to create
+cancelation points within your application, but only for cases where
+a thread is going to block on a Win32 handle. These are:
+
+ pthreadCancelableWait(HANDLE waitHandle) /* Infinite wait */
+
+ pthreadCancelableTimedWait(HANDLE waitHandle, DWORD timeout)
+
+------------------------------------------------------------------------------
+
+
+Q 10 How do I create thread-safe applications using
+---- pthreadGCE.dll, libpthreadw32.a and Mingw32?
+
+This should not be a problem with recent versions of MinGW32.
+
+For early versions, see Thomas Pfaff's email at:
+http://sources.redhat.com/ml/pthreads-win32/2002/msg00000.html
+------------------------------------------------------------------------------
+
+Q 11 Why isn't pthread_t defined as a scalar (e.g. pointer or int)
+ like it is for other POSIX threads implementations?
+----
+
+Originally pthread_t was defined as a pointer (to the opaque pthread_t_
+struct) and later it was changed to a struct containing the original
+pointer plus a sequence counter. This is allowed under both the original
+POSIX Threads Standard and the current Single Unix Specification.
+
+When pthread_t is a simple pointer to a struct some very difficult to
+debug problems arise from the process of freeing and later allocing
+thread structs because new pthread_t handles can acquire the identity of
+previously detached threads. The change to a struct was made, along with
+some changes to their internal managment, in order to guarantee (for
+practical applications) that the pthread_t handle will be unique over the
+life of the running process.
+
+Where application code attempts to compare one pthread_t against another
+directly, a compiler error will be emitted because structs can't be
+compared at that level. This should signal a potentially serious problem
+in the code design, which would go undetected if pthread_t was a scalar.
+
+The POSIX Threading API provides a function named pthread_equal() to
+compare pthread_t thread handles.
+
+Other pthreads implementations, such as Sun's, use an int as the handle
+but do guarantee uniqueness within the process scope. Win32 scalar typed
+thread handles also guarantee uniqueness in system scope. It wasn't clear
+how well the internal management of these handles would scale as the
+number of threads and the fragmentation of the sequence numbering
+increased for applications where thousands or millions of threads are
+created and detached over time. The current management of threads within
+pthreads-win32 using structs for pthread_t, and reusing without ever
+freeing them, reduces the management time overheads to a constant, which
+could be important given that pthreads-win32 threads are built on top of
+Win32 threads and will therefore include that management overhead on top
+of their own. The cost is that the memory resources used for thread
+handles will remain at the peak level until the process exits.
+
+While it may be inconvenient for developers to be forced away from making
+assumptions about the internals of pthread_t, the advantage for the
+future development of pthread-win32, as well as those applications that
+use it and other pthread implementations, is that the library is free to
+change pthread_t internals and management as better methods arise.
+
diff --git a/libs/pthreads/docs/GNUmakefile b/libs/pthreads/docs/GNUmakefile
new file mode 100644
index 0000000000..e489f002ec
--- /dev/null
+++ b/libs/pthreads/docs/GNUmakefile
@@ -0,0 +1,593 @@
+#
+# --------------------------------------------------------------------------
+#
+# Pthreads-win32 - POSIX Threads Library for Win32
+# Copyright(C) 1998 John E. Bossom
+# Copyright(C) 1999,2005 Pthreads-win32 contributors
+#
+# Contact Email: rpj@callisto.canberra.edu.au
+#
+# The current list of contributors is contained
+# in the file CONTRIBUTORS included with the source
+# code distribution. The list can also be seen at the
+# following World Wide Web location:
+# http://sources.redhat.com/pthreads-win32/contributors.html
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library in the file COPYING.LIB;
+# if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+#
+
+DLL_VER = 2
+DLL_VERD= $(DLL_VER)d
+
+DEVROOT = C:\PTHREADS
+
+DLLDEST = $(DEVROOT)\DLL
+LIBDEST = $(DEVROOT)\DLL
+
+# If Running MsysDTK
+RM = rm -f
+MV = mv -f
+CP = cp -f
+
+# If not.
+#RM = erase
+#MV = rename
+#CP = copy
+
+# For cross compiling use e.g.
+# make CROSS=x86_64-w64-mingw32- clean GC-inlined
+CROSS =
+
+AR = $(CROSS)ar
+DLLTOOL = $(CROSS)dlltool
+CC = $(CROSS)gcc
+CXX = $(CROSS)g++
+RANLIB = $(CROSS)ranlib
+RC = $(CROSS)windres
+
+OPT = $(CLEANUP) -O3 # -finline-functions -findirect-inlining
+XOPT =
+
+RCFLAGS = --include-dir=.
+# Uncomment this if config.h defines RETAIN_WSALASTERROR
+#LFLAGS = -lws2_32
+
+# ----------------------------------------------------------------------
+# The library can be built with some alternative behaviour to
+# facilitate development of applications on Win32 that will be ported
+# to other POSIX systems. Nothing definable here will make the library
+# non-compliant, but applications that make assumptions that POSIX
+# does not garrantee may fail or misbehave under some settings.
+#
+# PTW32_THREAD_ID_REUSE_INCREMENT
+# Purpose:
+# POSIX says that applications should assume that thread IDs can be
+# recycled. However, Solaris and some other systems use a [very large]
+# sequence number as the thread ID, which provides virtual uniqueness.
+# Pthreads-win32 provides pseudo-unique IDs when the default increment
+# (1) is used, but pthread_t is not a scalar type like Solaris's.
+#
+# Usage:
+# Set to any value in the range: 0 <= value <= 2^wordsize
+#
+# Examples:
+# Set to 0 to emulate non recycle-unique behaviour like Linux or *BSD.
+# Set to 1 for recycle-unique thread IDs (this is the default).
+# Set to some other +ve value to emulate smaller word size types
+# (i.e. will wrap sooner).
+#
+#PTW32_FLAGS = "-DPTW32_THREAD_ID_REUSE_INCREMENT=0"
+#
+# ----------------------------------------------------------------------
+
+GC_CFLAGS = $(PTW32_FLAGS)
+GCE_CFLAGS = $(PTW32_FLAGS) -mthreads
+
+## Mingw
+MAKE ?= make
+CFLAGS = $(OPT) $(XOPT) -I. -DHAVE_PTW32_CONFIG_H -Wall
+
+DLL_INLINED_OBJS = \
+ pthread.o \
+ version.o
+
+# Agregate modules for inlinability
+DLL_OBJS = \
+ attr.o \
+ barrier.o \
+ cancel.o \
+ cleanup.o \
+ condvar.o \
+ create.o \
+ dll.o \
+ errno.o \
+ exit.o \
+ fork.o \
+ global.o \
+ misc.o \
+ mutex.o \
+ nonportable.o \
+ private.o \
+ rwlock.o \
+ sched.o \
+ semaphore.o \
+ signal.o \
+ spin.o \
+ sync.o \
+ tsd.o \
+ version.o
+
+# Separate modules for minimum size statically linked images
+SMALL_STATIC_OBJS = \
+ pthread_attr_init.o \
+ pthread_attr_destroy.o \
+ pthread_attr_getdetachstate.o \
+ pthread_attr_setdetachstate.o \
+ pthread_attr_getstackaddr.o \
+ pthread_attr_setstackaddr.o \
+ pthread_attr_getstacksize.o \
+ pthread_attr_setstacksize.o \
+ pthread_attr_getscope.o \
+ pthread_attr_setscope.o \
+ pthread_attr_setschedpolicy.o \
+ pthread_attr_getschedpolicy.o \
+ pthread_attr_setschedparam.o \
+ pthread_attr_getschedparam.o \
+ pthread_attr_setinheritsched.o \
+ pthread_attr_getinheritsched.o \
+ pthread_barrier_init.o \
+ pthread_barrier_destroy.o \
+ pthread_barrier_wait.o \
+ pthread_barrierattr_init.o \
+ pthread_barrierattr_destroy.o \
+ pthread_barrierattr_setpshared.o \
+ pthread_barrierattr_getpshared.o \
+ pthread_setcancelstate.o \
+ pthread_setcanceltype.o \
+ pthread_testcancel.o \
+ pthread_cancel.o \
+ cleanup.o \
+ pthread_condattr_destroy.o \
+ pthread_condattr_getpshared.o \
+ pthread_condattr_init.o \
+ pthread_condattr_setpshared.o \
+ pthread_cond_destroy.o \
+ pthread_cond_init.o \
+ pthread_cond_signal.o \
+ pthread_cond_wait.o \
+ create.o \
+ dll.o \
+ autostatic.o \
+ errno.o \
+ pthread_exit.o \
+ fork.o \
+ global.o \
+ pthread_mutex_init.o \
+ pthread_mutex_destroy.o \
+ pthread_mutexattr_init.o \
+ pthread_mutexattr_destroy.o \
+ pthread_mutexattr_getpshared.o \
+ pthread_mutexattr_setpshared.o \
+ pthread_mutexattr_settype.o \
+ pthread_mutexattr_gettype.o \
+ pthread_mutexattr_setrobust.o \
+ pthread_mutexattr_getrobust.o \
+ pthread_mutex_lock.o \
+ pthread_mutex_timedlock.o \
+ pthread_mutex_unlock.o \
+ pthread_mutex_trylock.o \
+ pthread_mutex_consistent.o \
+ pthread_mutexattr_setkind_np.o \
+ pthread_mutexattr_getkind_np.o \
+ pthread_getw32threadhandle_np.o \
+ pthread_getunique_np.o \
+ pthread_delay_np.o \
+ pthread_num_processors_np.o \
+ pthread_win32_attach_detach_np.o \
+ pthread_equal.o \
+ pthread_getconcurrency.o \
+ pthread_once.o \
+ pthread_self.o \
+ pthread_setconcurrency.o \
+ pthread_rwlock_init.o \
+ pthread_rwlock_destroy.o \
+ pthread_rwlockattr_init.o \
+ pthread_rwlockattr_destroy.o \
+ pthread_rwlockattr_getpshared.o \
+ pthread_rwlockattr_setpshared.o \
+ pthread_rwlock_rdlock.o \
+ pthread_rwlock_wrlock.o \
+ pthread_rwlock_unlock.o \
+ pthread_rwlock_tryrdlock.o \
+ pthread_rwlock_trywrlock.o \
+ pthread_setschedparam.o \
+ pthread_getschedparam.o \
+ pthread_timechange_handler_np.o \
+ ptw32_is_attr.o \
+ ptw32_cond_check_need_init.o \
+ ptw32_MCS_lock.o \
+ ptw32_mutex_check_need_init.o \
+ ptw32_processInitialize.o \
+ ptw32_processTerminate.o \
+ ptw32_threadStart.o \
+ ptw32_threadDestroy.o \
+ ptw32_tkAssocCreate.o \
+ ptw32_tkAssocDestroy.o \
+ ptw32_callUserDestroyRoutines.o \
+ ptw32_timespec.o \
+ ptw32_throw.o \
+ ptw32_getprocessors.o \
+ ptw32_calloc.o \
+ ptw32_new.o \
+ ptw32_reuse.o \
+ ptw32_semwait.o \
+ ptw32_relmillisecs.o \
+ ptw32_rwlock_check_need_init.o \
+ sched_get_priority_max.o \
+ sched_get_priority_min.o \
+ sched_setscheduler.o \
+ sched_getscheduler.o \
+ sched_yield.o \
+ sem_init.o \
+ sem_destroy.o \
+ sem_trywait.o \
+ sem_timedwait.o \
+ sem_wait.o \
+ sem_post.o \
+ sem_post_multiple.o \
+ sem_getvalue.o \
+ sem_open.o \
+ sem_close.o \
+ sem_unlink.o \
+ signal.o \
+ pthread_kill.o \
+ ptw32_spinlock_check_need_init.o \
+ pthread_spin_init.o \
+ pthread_spin_destroy.o \
+ pthread_spin_lock.o \
+ pthread_spin_unlock.o \
+ pthread_spin_trylock.o \
+ pthread_detach.o \
+ pthread_join.o \
+ pthread_key_create.o \
+ pthread_key_delete.o \
+ pthread_setspecific.o \
+ pthread_getspecific.o \
+ w32_CancelableWait.o \
+ version.o
+
+INCL = \
+ config.h \
+ implement.h \
+ semaphore.h \
+ pthread.h \
+ need_errno.h
+
+ATTR_SRCS = \
+ pthread_attr_init.c \
+ pthread_attr_destroy.c \
+ pthread_attr_getdetachstate.c \
+ pthread_attr_setdetachstate.c \
+ pthread_attr_getstackaddr.c \
+ pthread_attr_setstackaddr.c \
+ pthread_attr_getstacksize.c \
+ pthread_attr_setstacksize.c \
+ pthread_attr_getscope.c \
+ pthread_attr_setscope.c
+
+BARRIER_SRCS = \
+ pthread_barrier_init.c \
+ pthread_barrier_destroy.c \
+ pthread_barrier_wait.c \
+ pthread_barrierattr_init.c \
+ pthread_barrierattr_destroy.c \
+ pthread_barrierattr_setpshared.c \
+ pthread_barrierattr_getpshared.c
+
+CANCEL_SRCS = \
+ pthread_setcancelstate.c \
+ pthread_setcanceltype.c \
+ pthread_testcancel.c \
+ pthread_cancel.c
+
+CONDVAR_SRCS = \
+ ptw32_cond_check_need_init.c \
+ pthread_condattr_destroy.c \
+ pthread_condattr_getpshared.c \
+ pthread_condattr_init.c \
+ pthread_condattr_setpshared.c \
+ pthread_cond_destroy.c \
+ pthread_cond_init.c \
+ pthread_cond_signal.c \
+ pthread_cond_wait.c
+
+EXIT_SRCS = \
+ pthread_exit.c
+
+MISC_SRCS = \
+ pthread_equal.c \
+ pthread_getconcurrency.c \
+ pthread_kill.c \
+ pthread_once.c \
+ pthread_self.c \
+ pthread_setconcurrency.c \
+ ptw32_calloc.c \
+ ptw32_MCS_lock.c \
+ ptw32_new.c \
+ ptw32_reuse.c \
+ w32_CancelableWait.c
+
+MUTEX_SRCS = \
+ ptw32_mutex_check_need_init.c \
+ pthread_mutex_init.c \
+ pthread_mutex_destroy.c \
+ pthread_mutexattr_init.c \
+ pthread_mutexattr_destroy.c \
+ pthread_mutexattr_getpshared.c \
+ pthread_mutexattr_setpshared.c \
+ pthread_mutexattr_settype.c \
+ pthread_mutexattr_gettype.c \
+ pthread_mutexattr_setrobust.c \
+ pthread_mutexattr_getrobust.c \
+ pthread_mutex_lock.c \
+ pthread_mutex_timedlock.c \
+ pthread_mutex_unlock.c \
+ pthread_mutex_trylock.c \
+ pthread_mutex_consistent.c
+
+NONPORTABLE_SRCS = \
+ pthread_mutexattr_setkind_np.c \
+ pthread_mutexattr_getkind_np.c \
+ pthread_getw32threadhandle_np.c \
+ pthread_getunique_np.c \
+ pthread_delay_np.c \
+ pthread_num_processors_np.c \
+ pthread_win32_attach_detach_np.c \
+ pthread_timechange_handler_np.c
+
+PRIVATE_SRCS = \
+ ptw32_is_attr.c \
+ ptw32_processInitialize.c \
+ ptw32_processTerminate.c \
+ ptw32_threadStart.c \
+ ptw32_threadDestroy.c \
+ ptw32_tkAssocCreate.c \
+ ptw32_tkAssocDestroy.c \
+ ptw32_callUserDestroyRoutines.c \
+ ptw32_semwait.c \
+ ptw32_relmillisecs.c \
+ ptw32_timespec.c \
+ ptw32_throw.c \
+ ptw32_getprocessors.c
+
+RWLOCK_SRCS = \
+ ptw32_rwlock_check_need_init.c \
+ ptw32_rwlock_cancelwrwait.c \
+ pthread_rwlock_init.c \
+ pthread_rwlock_destroy.c \
+ pthread_rwlockattr_init.c \
+ pthread_rwlockattr_destroy.c \
+ pthread_rwlockattr_getpshared.c \
+ pthread_rwlockattr_setpshared.c \
+ pthread_rwlock_rdlock.c \
+ pthread_rwlock_timedrdlock.c \
+ pthread_rwlock_wrlock.c \
+ pthread_rwlock_timedwrlock.c \
+ pthread_rwlock_unlock.c \
+ pthread_rwlock_tryrdlock.c \
+ pthread_rwlock_trywrlock.c
+
+SCHED_SRCS = \
+ pthread_attr_setschedpolicy.c \
+ pthread_attr_getschedpolicy.c \
+ pthread_attr_setschedparam.c \
+ pthread_attr_getschedparam.c \
+ pthread_attr_setinheritsched.c \
+ pthread_attr_getinheritsched.c \
+ pthread_setschedparam.c \
+ pthread_getschedparam.c \
+ sched_get_priority_max.c \
+ sched_get_priority_min.c \
+ sched_setscheduler.c \
+ sched_getscheduler.c \
+ sched_yield.c
+
+SEMAPHORE_SRCS = \
+ sem_init.c \
+ sem_destroy.c \
+ sem_trywait.c \
+ sem_timedwait.c \
+ sem_wait.c \
+ sem_post.c \
+ sem_post_multiple.c \
+ sem_getvalue.c \
+ sem_open.c \
+ sem_close.c \
+ sem_unlink.c
+
+SPIN_SRCS = \
+ ptw32_spinlock_check_need_init.c \
+ pthread_spin_init.c \
+ pthread_spin_destroy.c \
+ pthread_spin_lock.c \
+ pthread_spin_unlock.c \
+ pthread_spin_trylock.c
+
+SYNC_SRCS = \
+ pthread_detach.c \
+ pthread_join.c
+
+TSD_SRCS = \
+ pthread_key_create.c \
+ pthread_key_delete.c \
+ pthread_setspecific.c \
+ pthread_getspecific.c
+
+
+GCE_DLL = pthreadGCE$(DLL_VER).dll
+GCED_DLL= pthreadGCE$(DLL_VERD).dll
+GCE_LIB = libpthreadGCE$(DLL_VER).a
+GCED_LIB= libpthreadGCE$(DLL_VERD).a
+GCE_INLINED_STAMP = pthreadGCE$(DLL_VER).stamp
+GCED_INLINED_STAMP = pthreadGCE$(DLL_VERD).stamp
+GCE_STATIC_STAMP = libpthreadGCE$(DLL_VER).stamp
+GCED_STATIC_STAMP = libpthreadGCE$(DLL_VERD).stamp
+
+GC_DLL = pthreadGC$(DLL_VER).dll
+GCD_DLL = pthreadGC$(DLL_VERD).dll
+GC_LIB = libpthreadGC$(DLL_VER).a
+GCD_LIB = libpthreadGC$(DLL_VERD).a
+GC_INLINED_STAMP = pthreadGC$(DLL_VER).stamp
+GCD_INLINED_STAMP = pthreadGC$(DLL_VERD).stamp
+GC_STATIC_STAMP = libpthreadGC$(DLL_VER).stamp
+GCD_STATIC_STAMP = libpthreadGC$(DLL_VERD).stamp
+
+PTHREAD_DEF = pthread.def
+
+help:
+ @ echo "Run one of the following command lines:"
+ @ echo "make clean GC (to build the GNU C dll with C cleanup code)"
+ @ echo "make clean GCE (to build the GNU C dll with C++ exception handling)"
+ @ echo "make clean GC-inlined (to build the GNU C inlined dll with C cleanup code)"
+ @ echo "make clean GCE-inlined (to build the GNU C inlined dll with C++ exception handling)"
+ @ echo "make clean GC-static (to build the GNU C inlined static lib with C cleanup code)"
+ @ echo "make clean GC-debug (to build the GNU C debug dll with C cleanup code)"
+ @ echo "make clean GCE-debug (to build the GNU C debug dll with C++ exception handling)"
+ @ echo "make clean GC-inlined-debug (to build the GNU C inlined debug dll with C cleanup code)"
+ @ echo "make clean GCE-inlined-debug (to build the GNU C inlined debug dll with C++ exception handling)"
+ @ echo "make clean GC-static-debug (to build the GNU C inlined static debug lib with C cleanup code)"
+
+all:
+ @ $(MAKE) clean GCE
+ @ $(MAKE) clean GC
+
+GC:
+ $(MAKE) CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_OBJS)" $(GC_DLL)
+
+GC-debug:
+ $(MAKE) CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_OBJS)" DLL_VER=$(DLL_VERD) OPT="-D__CLEANUP_C -g -O0" $(GCD_DLL)
+
+GCE:
+ $(MAKE) CC=$(CXX) CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_OBJS)" $(GCE_DLL)
+
+GCE-debug:
+ $(MAKE) CC=$(CXX) CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_OBJS)" DLL_VER=$(DLL_VERD) OPT="-D__CLEANUP_CXX -g -O0" $(GCED_DLL)
+
+GC-inlined:
+ $(MAKE) XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" $(GC_INLINED_STAMP)
+
+GC-inlined-debug:
+ $(MAKE) XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" DLL_VER=$(DLL_VERD) OPT="-D__CLEANUP_C -g -O0" $(GCD_INLINED_STAMP)
+
+GCE-inlined:
+ $(MAKE) CC=$(CXX) XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" $(GCE_INLINED_STAMP)
+
+GCE-inlined-debug:
+ $(MAKE) CC=$(CXX) XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" DLL_VER=$(DLL_VERD) OPT="-D__CLEANUP_CXX -g -O0" $(GCED_INLINED_STAMP)
+
+GC-static:
+ $(MAKE) XOPT="-DPTW32_BUILD_INLINED -DPTW32_STATIC_LIB" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" $(GC_STATIC_STAMP)
+
+GC-static-debug:
+ $(MAKE) XOPT="-DPTW32_BUILD_INLINED -DPTW32_STATIC_LIB" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" DLL_VER=$(DLL_VERD) OPT="-D__CLEANUP_C -g -O0" $(GCD_STATIC_STAMP)
+
+tests:
+ @ cd tests
+ @ $(MAKE) auto
+
+%.pre: %.c
+ $(CC) -E -o $@ $(CFLAGS) $^
+
+%.s: %.c
+ $(CC) -c $(CFLAGS) -DPTW32_BUILD_INLINED -Wa,-ahl $^ > $@
+
+%.o: %.rc
+ $(RC) $(RCFLAGS) $(CLEANUP) -o $@ -i $<
+
+.SUFFIXES: .dll .rc .c .o
+
+.c.o:; $(CC) -c -o $@ $(CFLAGS) $(XC_FLAGS) $<
+
+
+$(GC_DLL) $(GCD_DLL): $(DLL_OBJS)
+ $(CC) $(OPT) -shared -o $(GC_DLL) $(DLL_OBJS) $(LFLAGS)
+ $(DLLTOOL) -z pthread.def $(DLL_OBJS)
+ $(DLLTOOL) -k --dllname $@ --output-lib $(GC_LIB) --def $(PTHREAD_DEF)
+
+$(GCE_DLL): $(DLL_OBJS)
+ $(CC) $(OPT) -mthreads -shared -o $(GCE_DLL) $(DLL_OBJS) $(LFLAGS)
+ $(DLLTOOL) -z pthread.def $(DLL_OBJS)
+ $(DLLTOOL) -k --dllname $@ --output-lib $(GCE_LIB) --def $(PTHREAD_DEF)
+
+$(GC_INLINED_STAMP) $(GCD_INLINED_STAMP): $(DLL_INLINED_OBJS)
+ $(CC) $(OPT) $(XOPT) -shared -o $(GC_DLL) $(DLL_INLINED_OBJS) $(LFLAGS)
+ $(DLLTOOL) -z pthread.def $(DLL_INLINED_OBJS)
+ $(DLLTOOL) -k --dllname $(GC_DLL) --output-lib $(GC_LIB) --def $(PTHREAD_DEF)
+ echo touched > $(GC_INLINED_STAMP)
+
+$(GCE_INLINED_STAMP) $(GCED_INLINED_STAMP): $(DLL_INLINED_OBJS)
+ $(CC) $(OPT) $(XOPT) -mthreads -shared -o $(GCE_DLL) $(DLL_INLINED_OBJS) $(LFLAGS)
+ $(DLLTOOL) -z pthread.def $(DLL_INLINED_OBJS)
+ $(DLLTOOL) -k --dllname $(GCE_DLL) --output-lib $(GCE_LIB) --def $(PTHREAD_DEF)
+ echo touched > $(GCE_INLINED_STAMP)
+
+$(GC_STATIC_STAMP) $(GCD_STATIC_STAMP): $(DLL_INLINED_OBJS)
+ $(RM) $(GC_LIB)
+ $(AR) -rv $(GC_LIB) $(DLL_INLINED_OBJS)
+ $(RANLIB) $(GC_LIB)
+ echo touched > $(GC_STATIC_STAMP)
+
+clean:
+ -$(RM) *~
+ -$(RM) *.i
+ -$(RM) *.s
+ -$(RM) *.o
+ -$(RM) *.obj
+ -$(RM) *.exe
+ -$(RM) $(PTHREAD_DEF)
+
+realclean: clean
+ -$(RM) $(GC_LIB)
+ -$(RM) $(GCE_LIB)
+ -$(RM) $(GC_DLL)
+ -$(RM) $(GCE_DLL)
+ -$(RM) $(GC_INLINED_STAMP)
+ -$(RM) $(GCE_INLINED_STAMP)
+ -$(RM) $(GC_STATIC_STAMP)
+ -$(RM) $(GCD_LIB)
+ -$(RM) $(GCED_LIB)
+ -$(RM) $(GCD_DLL)
+ -$(RM) $(GCED_DLL)
+ -$(RM) $(GCD_INLINED_STAMP)
+ -$(RM) $(GCED_INLINED_STAMP)
+ -$(RM) $(GCD_STATIC_STAMP)
+
+attr.o: attr.c $(ATTR_SRCS) $(INCL)
+barrier.o: barrier.c $(BARRIER_SRCS) $(INCL)
+cancel.o: cancel.c $(CANCEL_SRCS) $(INCL)
+condvar.o: condvar.c $(CONDVAR_SRCS) $(INCL)
+exit.o: exit.c $(EXIT_SRCS) $(INCL)
+misc.o: misc.c $(MISC_SRCS) $(INCL)
+mutex.o: mutex.c $(MUTEX_SRCS) $(INCL)
+nonportable.o: nonportable.c $(NONPORTABLE_SRCS) $(INCL)
+private.o: private.c $(PRIVATE_SRCS) $(INCL)
+rwlock.o: rwlock.c $(RWLOCK_SRCS) $(INCL)
+sched.o: sched.c $(SCHED_SRCS) $(INCL)
+semaphore.o: semaphore.c $(SEMAPHORE_SRCS) $(INCL)
+spin.o: spin.c $(SPIN_SRCS) $(INCL)
+sync.o: sync.c $(SYNC_SRCS) $(INCL)
+tsd.o: tsd.c $(TSD_SRCS) $(INCL)
+version.o: version.rc $(INCL)
diff --git a/libs/pthreads/docs/MAINTAINERS b/libs/pthreads/docs/MAINTAINERS
new file mode 100644
index 0000000000..d253c1f69e
--- /dev/null
+++ b/libs/pthreads/docs/MAINTAINERS
@@ -0,0 +1,4 @@
+CVS Repository maintainers
+
+Ross Johnson rpj@ise.canberra.edu.au
+Ben Elliston bje@cygnus.com
diff --git a/libs/pthreads/docs/Makefile b/libs/pthreads/docs/Makefile
new file mode 100644
index 0000000000..472969cf9b
--- /dev/null
+++ b/libs/pthreads/docs/Makefile
@@ -0,0 +1,514 @@
+# This makefile is compatible with MS nmake and can be used as a
+# replacement for buildlib.bat. I've changed the target from an ordinary dll
+# (/LD) to a debugging dll (/LDd).
+#
+# The variables $DLLDEST and $LIBDEST hold the destination directories for the
+# dll and the lib, respectively. Probably all that needs to change is $DEVROOT.
+
+
+# DLL_VER:
+# See pthread.h and README - This number is computed as 'current - age'
+DLL_VER = 2
+DLL_VERD= $(DLL_VER)d
+
+DEVROOT = C:\pthreads
+
+DLLDEST = $(DEVROOT)\dll
+LIBDEST = $(DEVROOT)\lib
+HDRDEST = $(DEVROOT)\include
+
+DLLS = pthreadVCE$(DLL_VER).dll pthreadVSE$(DLL_VER).dll pthreadVC$(DLL_VER).dll \
+ pthreadVCE$(DLL_VERD).dll pthreadVSE$(DLL_VERD).dll pthreadVC$(DLL_VERD).dll
+INLINED_STAMPS = pthreadVCE$(DLL_VER).stamp pthreadVSE$(DLL_VER).stamp pthreadVC$(DLL_VER).stamp \
+ pthreadVCE$(DLL_VERD).stamp pthreadVSE$(DLL_VERD).stamp pthreadVC$(DLL_VERD).stamp
+STATIC_STAMPS = pthreadVCE$(DLL_VER).static pthreadVSE$(DLL_VER).static pthreadVC$(DLL_VER).static \
+ pthreadVCE$(DLL_VERD).static pthreadVSE$(DLL_VERD).static pthreadVC$(DLL_VERD).static
+
+CC = cl
+CPPFLAGS = /I. /DHAVE_PTW32_CONFIG_H
+XCFLAGS = /W3 /MD /nologo
+CFLAGS = /O2 /Ob2 $(XCFLAGS)
+CFLAGSD = /Z7 $(XCFLAGS)
+
+# Uncomment this if config.h defines RETAIN_WSALASTERROR
+#XLIBS = wsock32.lib
+
+# Default cleanup style
+CLEANUP = __CLEANUP_C
+
+# C++ Exceptions
+VCEFLAGS = /EHsc /TP $(CPPFLAGS) $(CFLAGS)
+VCEFLAGSD = /EHsc /TP $(CPPFLAGS) $(CFLAGSD)
+#Structured Exceptions
+VSEFLAGS = $(CPPFLAGS) $(CFLAGS)
+VSEFLAGSD = $(CPPFLAGS) $(CFLAGSD)
+#C cleanup code
+VCFLAGS = $(CPPFLAGS) $(CFLAGS)
+VCFLAGSD = $(CPPFLAGS) $(CFLAGSD)
+
+DLL_INLINED_OBJS = \
+ pthread.obj \
+ version.res
+
+# Aggregate modules for inlinability
+DLL_OBJS = \
+ attr.obj \
+ barrier.obj \
+ cancel.obj \
+ cleanup.obj \
+ condvar.obj \
+ create.obj \
+ dll.obj \
+ autostatic.obj \
+ errno.obj \
+ exit.obj \
+ fork.obj \
+ global.obj \
+ misc.obj \
+ mutex.obj \
+ nonportable.obj \
+ private.obj \
+ rwlock.obj \
+ sched.obj \
+ semaphore.obj \
+ signal.obj \
+ spin.obj \
+ sync.obj \
+ tsd.obj \
+ version.res
+
+# Separate modules for minimising the size of statically linked images
+SMALL_STATIC_OBJS = \
+ pthread_attr_init.obj \
+ pthread_attr_destroy.obj \
+ pthread_attr_getdetachstate.obj \
+ pthread_attr_setdetachstate.obj \
+ pthread_attr_getstackaddr.obj \
+ pthread_attr_setstackaddr.obj \
+ pthread_attr_getstacksize.obj \
+ pthread_attr_setstacksize.obj \
+ pthread_attr_getscope.obj \
+ pthread_attr_setscope.obj \
+ pthread_attr_setschedpolicy.obj \
+ pthread_attr_getschedpolicy.obj \
+ pthread_attr_setschedparam.obj \
+ pthread_attr_getschedparam.obj \
+ pthread_attr_setinheritsched.obj \
+ pthread_attr_getinheritsched.obj \
+ pthread_barrier_init.obj \
+ pthread_barrier_destroy.obj \
+ pthread_barrier_wait.obj \
+ pthread_barrierattr_init.obj \
+ pthread_barrierattr_destroy.obj \
+ pthread_barrierattr_setpshared.obj \
+ pthread_barrierattr_getpshared.obj \
+ pthread_setcancelstate.obj \
+ pthread_setcanceltype.obj \
+ pthread_testcancel.obj \
+ pthread_cancel.obj \
+ cleanup.obj \
+ pthread_condattr_destroy.obj \
+ pthread_condattr_getpshared.obj \
+ pthread_condattr_init.obj \
+ pthread_condattr_setpshared.obj \
+ pthread_cond_destroy.obj \
+ pthread_cond_init.obj \
+ pthread_cond_signal.obj \
+ pthread_cond_wait.obj \
+ create.obj \
+ dll.obj \
+ autostatic.obj \
+ errno.obj \
+ pthread_exit.obj \
+ fork.obj \
+ global.obj \
+ pthread_mutex_init.obj \
+ pthread_mutex_destroy.obj \
+ pthread_mutexattr_init.obj \
+ pthread_mutexattr_destroy.obj \
+ pthread_mutexattr_getpshared.obj \
+ pthread_mutexattr_setpshared.obj \
+ pthread_mutexattr_settype.obj \
+ pthread_mutexattr_gettype.obj \
+ pthread_mutexattr_setrobust.obj \
+ pthread_mutexattr_getrobust.obj \
+ pthread_mutex_lock.obj \
+ pthread_mutex_timedlock.obj \
+ pthread_mutex_unlock.obj \
+ pthread_mutex_trylock.obj \
+ pthread_mutex_consistent.obj \
+ pthread_mutexattr_setkind_np.obj \
+ pthread_mutexattr_getkind_np.obj \
+ pthread_getw32threadhandle_np.obj \
+ pthread_getunique_np.obj \
+ pthread_delay_np.obj \
+ pthread_num_processors_np.obj \
+ pthread_win32_attach_detach_np.obj \
+ pthread_equal.obj \
+ pthread_getconcurrency.obj \
+ pthread_once.obj \
+ pthread_self.obj \
+ pthread_setconcurrency.obj \
+ pthread_rwlock_init.obj \
+ pthread_rwlock_destroy.obj \
+ pthread_rwlockattr_init.obj \
+ pthread_rwlockattr_destroy.obj \
+ pthread_rwlockattr_getpshared.obj \
+ pthread_rwlockattr_setpshared.obj \
+ pthread_rwlock_rdlock.obj \
+ pthread_rwlock_wrlock.obj \
+ pthread_rwlock_unlock.obj \
+ pthread_rwlock_tryrdlock.obj \
+ pthread_rwlock_trywrlock.obj \
+ pthread_setschedparam.obj \
+ pthread_getschedparam.obj \
+ pthread_timechange_handler_np.obj \
+ ptw32_is_attr.obj \
+ ptw32_processInitialize.obj \
+ ptw32_processTerminate.obj \
+ ptw32_threadStart.obj \
+ ptw32_threadDestroy.obj \
+ ptw32_tkAssocCreate.obj \
+ ptw32_tkAssocDestroy.obj \
+ ptw32_callUserDestroyRoutines.obj \
+ ptw32_timespec.obj \
+ ptw32_throw.obj \
+ ptw32_getprocessors.obj \
+ ptw32_calloc.obj \
+ ptw32_new.obj \
+ ptw32_reuse.obj \
+ ptw32_rwlock_check_need_init.obj \
+ ptw32_cond_check_need_init.obj \
+ ptw32_mutex_check_need_init.obj \
+ ptw32_semwait.obj \
+ ptw32_relmillisecs.obj \
+ ptw32_MCS_lock.obj \
+ sched_get_priority_max.obj \
+ sched_get_priority_min.obj \
+ sched_setscheduler.obj \
+ sched_getscheduler.obj \
+ sched_yield.obj \
+ sem_init.obj \
+ sem_destroy.obj \
+ sem_trywait.obj \
+ sem_timedwait.obj \
+ sem_wait.obj \
+ sem_post.obj \
+ sem_post_multiple.obj \
+ sem_getvalue.obj \
+ sem_open.obj \
+ sem_close.obj \
+ sem_unlink.obj \
+ signal.obj \
+ pthread_kill.obj \
+ ptw32_spinlock_check_need_init.obj \
+ pthread_spin_init.obj \
+ pthread_spin_destroy.obj \
+ pthread_spin_lock.obj \
+ pthread_spin_unlock.obj \
+ pthread_spin_trylock.obj \
+ pthread_detach.obj \
+ pthread_join.obj \
+ pthread_key_create.obj \
+ pthread_key_delete.obj \
+ pthread_setspecific.obj \
+ pthread_getspecific.obj \
+ w32_CancelableWait.obj \
+ version.res
+
+INCL = config.h implement.h semaphore.h pthread.h need_errno.h
+
+ATTR_SRCS = \
+ pthread_attr_init.c \
+ pthread_attr_destroy.c \
+ pthread_attr_getdetachstate.c \
+ pthread_attr_setdetachstate.c \
+ pthread_attr_getstackaddr.c \
+ pthread_attr_setstackaddr.c \
+ pthread_attr_getstacksize.c \
+ pthread_attr_setstacksize.c \
+ pthread_attr_getscope.c \
+ pthread_attr_setscope.c
+
+BARRIER_SRCS = \
+ pthread_barrier_init.c \
+ pthread_barrier_destroy.c \
+ pthread_barrier_wait.c \
+ pthread_barrierattr_init.c \
+ pthread_barrierattr_destroy.c \
+ pthread_barrierattr_setpshared.c \
+ pthread_barrierattr_getpshared.c
+
+CANCEL_SRCS = \
+ pthread_setcancelstate.c \
+ pthread_setcanceltype.c \
+ pthread_testcancel.c \
+ pthread_cancel.c
+
+CONDVAR_SRCS = \
+ ptw32_cond_check_need_init.c \
+ pthread_condattr_destroy.c \
+ pthread_condattr_getpshared.c \
+ pthread_condattr_init.c \
+ pthread_condattr_setpshared.c \
+ pthread_cond_destroy.c \
+ pthread_cond_init.c \
+ pthread_cond_signal.c \
+ pthread_cond_wait.c
+
+EXIT_SRCS = \
+ pthread_exit.c
+
+MISC_SRCS = \
+ pthread_equal.c \
+ pthread_getconcurrency.c \
+ pthread_kill.c \
+ pthread_once.c \
+ pthread_self.c \
+ pthread_setconcurrency.c \
+ ptw32_calloc.c \
+ ptw32_MCS_lock.c \
+ ptw32_new.c \
+ ptw32_reuse.c \
+ ptw32_relmillisecs.c \
+ w32_CancelableWait.c
+
+MUTEX_SRCS = \
+ ptw32_mutex_check_need_init.c \
+ pthread_mutex_init.c \
+ pthread_mutex_destroy.c \
+ pthread_mutexattr_init.c \
+ pthread_mutexattr_destroy.c \
+ pthread_mutexattr_getpshared.c \
+ pthread_mutexattr_setpshared.c \
+ pthread_mutexattr_settype.c \
+ pthread_mutexattr_gettype.c \
+ pthread_mutexattr_setrobust.c \
+ pthread_mutexattr_getrobust.c \
+ pthread_mutex_lock.c \
+ pthread_mutex_timedlock.c \
+ pthread_mutex_unlock.c \
+ pthread_mutex_trylock.c \
+ pthread_mutex_consistent.c
+
+NONPORTABLE_SRCS = \
+ pthread_mutexattr_setkind_np.c \
+ pthread_mutexattr_getkind_np.c \
+ pthread_getw32threadhandle_np.c \
+ pthread_getunique_np.c \
+ pthread_delay_np.c \
+ pthread_num_processors_np.c \
+ pthread_win32_attach_detach_np.c \
+ pthread_timechange_handler_np.c
+
+PRIVATE_SRCS = \
+ ptw32_is_attr.c \
+ ptw32_processInitialize.c \
+ ptw32_processTerminate.c \
+ ptw32_threadStart.c \
+ ptw32_threadDestroy.c \
+ ptw32_tkAssocCreate.c \
+ ptw32_tkAssocDestroy.c \
+ ptw32_callUserDestroyRoutines.c \
+ ptw32_semwait.c \
+ ptw32_timespec.c \
+ ptw32_throw.c \
+ ptw32_getprocessors.c
+
+RWLOCK_SRCS = \
+ ptw32_rwlock_check_need_init.c \
+ ptw32_rwlock_cancelwrwait.c \
+ pthread_rwlock_init.c \
+ pthread_rwlock_destroy.c \
+ pthread_rwlockattr_init.c \
+ pthread_rwlockattr_destroy.c \
+ pthread_rwlockattr_getpshared.c \
+ pthread_rwlockattr_setpshared.c \
+ pthread_rwlock_rdlock.c \
+ pthread_rwlock_timedrdlock.c \
+ pthread_rwlock_wrlock.c \
+ pthread_rwlock_timedwrlock.c \
+ pthread_rwlock_unlock.c \
+ pthread_rwlock_tryrdlock.c \
+ pthread_rwlock_trywrlock.c
+
+SCHED_SRCS = \
+ pthread_attr_setschedpolicy.c \
+ pthread_attr_getschedpolicy.c \
+ pthread_attr_setschedparam.c \
+ pthread_attr_getschedparam.c \
+ pthread_attr_setinheritsched.c \
+ pthread_attr_getinheritsched.c \
+ pthread_setschedparam.c \
+ pthread_getschedparam.c \
+ sched_get_priority_max.c \
+ sched_get_priority_min.c \
+ sched_setscheduler.c \
+ sched_getscheduler.c \
+ sched_yield.c
+
+SEMAPHORE_SRCS = \
+ sem_init.c \
+ sem_destroy.c \
+ sem_trywait.c \
+ sem_timedwait.c \
+ sem_wait.c \
+ sem_post.c \
+ sem_post_multiple.c \
+ sem_getvalue.c \
+ sem_open.c \
+ sem_close.c \
+ sem_unlink.c
+
+SPIN_SRCS = \
+ ptw32_spinlock_check_need_init.c \
+ pthread_spin_init.c \
+ pthread_spin_destroy.c \
+ pthread_spin_lock.c \
+ pthread_spin_unlock.c \
+ pthread_spin_trylock.c
+
+SYNC_SRCS = \
+ pthread_detach.c \
+ pthread_join.c
+
+TSD_SRCS = \
+ pthread_key_create.c \
+ pthread_key_delete.c \
+ pthread_setspecific.c \
+ pthread_getspecific.c
+
+
+help:
+ @ echo Run one of the following command lines:
+ @ echo nmake clean VCE (to build the MSVC dll with C++ exception handling)
+ @ echo nmake clean VSE (to build the MSVC dll with structured exception handling)
+ @ echo nmake clean VC (to build the MSVC dll with C cleanup code)
+ @ echo nmake clean VCE-inlined (to build the MSVC inlined dll with C++ exception handling)
+ @ echo nmake clean VSE-inlined (to build the MSVC inlined dll with structured exception handling)
+ @ echo nmake clean VC-inlined (to build the MSVC inlined dll with C cleanup code)
+ @ echo nmake clean VC-static (to build the MSVC static lib with C cleanup code)
+ @ echo nmake clean VCE-debug (to build the debug MSVC dll with C++ exception handling)
+ @ echo nmake clean VSE-debug (to build the debug MSVC dll with structured exception handling)
+ @ echo nmake clean VC-debug (to build the debug MSVC dll with C cleanup code)
+ @ echo nmake clean VCE-inlined-debug (to build the debug MSVC inlined dll with C++ exception handling)
+ @ echo nmake clean VSE-inlined-debug (to build the debug MSVC inlined dll with structured exception handling)
+ @ echo nmake clean VC-inlined-debug (to build the debug MSVC inlined dll with C cleanup code)
+ @ echo nmake clean VC-static-debug (to build the debug MSVC static lib with C cleanup code)
+
+all:
+ @ $(MAKE) /E clean VCE-inlined
+ @ $(MAKE) /E clean VSE-inlined
+ @ $(MAKE) /E clean VC-inlined
+ @ $(MAKE) /E clean VCE-inlined-debug
+ @ $(MAKE) /E clean VSE-inlined-debug
+ @ $(MAKE) /E clean VC-inlined-debug
+
+VCE:
+ @ $(MAKE) /E /nologo EHFLAGS="$(VCEFLAGS)" CLEANUP=__CLEANUP_CXX pthreadVCE$(DLL_VER).dll
+
+VCE-debug:
+ @ $(MAKE) /E /nologo EHFLAGS="$(VCEFLAGSD)" CLEANUP=__CLEANUP_CXX pthreadVCE$(DLL_VERD).dll
+
+VSE:
+ @ $(MAKE) /E /nologo EHFLAGS="$(VSEFLAGS)" CLEANUP=__CLEANUP_SEH pthreadVSE$(DLL_VER).dll
+
+VSE-debug:
+ @ $(MAKE) /E /nologo EHFLAGS="$(VSEFLAGSD)" CLEANUP=__CLEANUP_SEH pthreadVSE$(DLL_VERD).dll
+
+VC:
+ @ $(MAKE) /E /nologo EHFLAGS="$(VCFLAGS)" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VER).dll
+
+VC-debug:
+ @ $(MAKE) /E /nologo EHFLAGS="$(VCFLAGSD)" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VERD).dll
+
+#
+# The so-called inlined DLL is just a single translation unit with
+# inlining optimisation turned on.
+#
+VCE-inlined:
+ @ $(MAKE) /E /nologo EHFLAGS="$(VCEFLAGS) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_CXX pthreadVCE$(DLL_VER).stamp
+
+VCE-inlined-debug:
+ @ $(MAKE) /E /nologo EHFLAGS="$(VCEFLAGSD) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_CXX pthreadVCE$(DLL_VERD).stamp
+
+VSE-inlined:
+ @ $(MAKE) /E /nologo EHFLAGS="$(VSEFLAGS) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_SEH pthreadVSE$(DLL_VER).stamp
+
+VSE-inlined-debug:
+ @ $(MAKE) /E /nologo EHFLAGS="$(VSEFLAGSD) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_SEH pthreadVSE$(DLL_VERD).stamp
+
+VC-inlined:
+ @ $(MAKE) /E /nologo EHFLAGS="$(VCFLAGS) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VER).stamp
+
+VC-inlined-debug:
+ @ $(MAKE) /E /nologo EHFLAGS="$(VCFLAGSD) /DPTW32_BUILD_INLINED" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VERD).stamp
+
+VC-static:
+ @ $(MAKE) /E /nologo EHFLAGS="$(VCFLAGS) /DPTW32_BUILD_INLINED /DPTW32_STATIC_LIB" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VER).static
+
+VC-static-debug:
+ @ $(MAKE) /E /nologo EHFLAGS="$(VCFLAGSD) /DPTW32_BUILD_INLINED /DPTW32_STATIC_LIB" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VERD).static
+
+realclean: clean
+ if exist pthread*.dll del pthread*.dll
+ if exist pthread*.lib del pthread*.lib
+ if exist *.manifest del *.manifest
+ if exist *.stamp del *.stamp
+
+clean:
+ if exist *.obj del *.obj
+ if exist *.def del *.def
+ if exist *.ilk del *.ilk
+ if exist *.pdb del *.pdb
+ if exist *.exp del *.exp
+ if exist *.map del *.map
+ if exist *.o del *.o
+ if exist *.i del *.i
+ if exist *.res del *.res
+
+
+install:
+ copy pthread*.dll $(DLLDEST)
+ copy pthread*.lib $(LIBDEST)
+ copy pthread.h $(HDRDEST)
+ copy sched.h $(HDRDEST)
+ copy semaphore.h $(HDRDEST)
+
+$(DLLS): $(DLL_OBJS)
+ $(CC) /LDd /Zi /nologo $(DLL_OBJS) /link /implib:$*.lib $(XLIBS) /out:$@
+
+$(INLINED_STAMPS): $(DLL_INLINED_OBJS)
+ $(CC) /LDd /Zi /nologo $(DLL_INLINED_OBJS) /link /implib:$*.lib $(XLIBS) /out:$*.dll
+
+$(STATIC_STAMPS): $(DLL_INLINED_OBJS)
+ if exist $*.lib del $*.lib
+ lib $(DLL_INLINED_OBJS) /out:$*.lib
+
+.c.obj:
+ $(CC) $(EHFLAGS) /D$(CLEANUP) -c $<
+
+# TARGET_CPU is an environment variable set by Visual Studio Command Prompt
+# as provided by the SDK
+.rc.res:
+ rc /dPTW32_ARCH$(TARGET_CPU) /dPTW32_RC_MSC /d$(CLEANUP) $<
+
+.c.i:
+ $(CC) /P /O2 /Ob1 $(VCFLAGS) $<
+
+attr.obj: attr.c $(ATTR_SRCS) $(INCL)
+barrier.obj: barrier.c $(BARRIER_SRCS) $(INCL)
+cancel.obj: cancel.c $(CANCEL_SRCS) $(INCL)
+condvar.obj: condvar.c $(CONDVAR_SRCS) $(INCL)
+exit.obj: exit.c $(EXIT_SRCS) $(INCL)
+misc.obj: misc.c $(MISC_SRCS) $(INCL)
+mutex.obj: mutex.c $(MUTEX_SRCS) $(INCL)
+nonportable.obj: nonportable.c $(NONPORTABLE_SRCS) $(INCL)
+private.obj: private.c $(PRIVATE_SRCS) $(INCL)
+rwlock.obj: rwlock.c $(RWLOCK_SRCS) $(INCL)
+sched.obj: sched.c $(SCHED_SRCS) $(INCL)
+semaphore.obj: semaphore.c $(SEMAPHORE_SRCS) $(INCL)
+spin.obj: spin.c $(SPIN_SRCS) $(INCL)
+sync.obj: sync.c $(SYNC_SRCS) $(INCL)
+tsd.obj: tsd.c $(TSD_SRCS) $(INCL)
+version.res: version.rc $(INCL)
diff --git a/libs/pthreads/docs/NEWS b/libs/pthreads/docs/NEWS
new file mode 100644
index 0000000000..d1b789635f
--- /dev/null
+++ b/libs/pthreads/docs/NEWS
@@ -0,0 +1,1241 @@
+RELEASE 2.9.0
+-------------
+(2012-05-25)
+
+General
+-------
+New bug fixes in this release since 2.8.0 have NOT been applied to the
+1.x.x series.
+
+Some changes post 2011-02-26 in CVS may not be compatible with pre
+Windows 2000 systems.
+
+Use of other than the "C" version of the library is now discouraged.
+That is, the "C++" version fails some tests and does not provide any
+additional functionality.
+
+Testing and verification
+------------------------
+This version has been tested on SMP architecture (Intel x64 Hex Core)
+by completing the included test suite, stress and bench tests.
+
+New Features
+------------
+DLL properties now properly includes the target architecture, i.e.
+right-click on the file pthreadVC2.dll in explorer and choose the Detail
+tab will show the compiler and architecture in the description field, e.g.
+"MS C x64" or "MS C x86".
+- Ross Johnson
+
+(MSC and GNU builds) The statically linked library now automatically
+initialises and cleans up on program start/exit, i.e. statically linked
+applications need not call the routines pthread_win32_process_attach_np()
+and pthread_win32_process_detach_np() explicitly. The per-thread routine
+pthread_win32_thread_detach_np() is also called at program exit to cleanup
+POSIX resources acquired by the primary Windows native thread, if I (RJ)
+understand the process correctly. Other Windows native threads that call
+POSIX API routines may need to call the thread detach routine on thread
+exit if the application depends on reclaimed POSIX resources or running
+POSIX TSD (TLS) destructors.
+See README.NONPORTABLE for descriptions of these routines.
+- Ramiro Polla
+
+Robust mutexes are implemented within the PROCESS_PRIVATE scope. NOTE that
+pthread_mutex_* functions may return different error codes for robust
+mutexes than they otherwise do in normal usage, e.g. pthread_mutex_unlock
+is required to check ownership for all mutex types when the mutex is
+robust, whereas this does not occur for the "normal" non-robust mutex type.
+- Ross Johnson
+
+pthread_getunique_np is implemented for source level compatibility
+with some other implementations. This routine returns a 64 bit
+sequence number that is uniquely associated with a thread. It can be
+used by applications to order or hash POSIX thread handles.
+- Ross Johnson
+
+Bug fixes
+---------
+Many more changes for 64 bit systems.
+- Kai Tietz
+
+Various modifications and fixes to build and test for WinCE.
+- Marcel Ruff, Sinan Kaya
+
+Fix pthread_cond_destroy() - should not be a cancellation point. Other
+minor build problems fixed.
+- Romano Paolo Tenca
+
+Remove potential deadlock condition from pthread_cond_destroy().
+- Eric Berge
+
+Various modifications to build and test for Win64.
+- Kip Streithorst
+
+Various fixes to the QueueUserAPCEx async cancellation helper DLL
+(this is a separate download) and pthreads code cleanups.
+- Sebastian Gottschalk
+
+Removed potential NULL pointer reference.
+- Robert Kindred
+
+Removed the requirement that applications restrict the number of threads
+calling pthread_barrier_wait to just the barrier count. Also reduced the
+contention between barrier_wait and barrier_destroy. This change will have
+slowed barriers down slightly but halves the number of semaphores consumed
+per barrier to one.
+- Ross Johnson
+
+Fixed a handle leak in sched_[gs]etscheduler.
+- Mark Pizzolato
+
+Removed all of the POSIX re-entrant function compatibility macros from pthread.h.
+Some were simply not semanticly correct.
+- Igor Lubashev
+
+Threads no longer attempt to pass uncaught exceptions out of thread scope (C++
+and SEH builds only). Uncaught exceptions now cause the thread to exit with
+the return code PTHREAD_CANCELED.
+- Ross Johnson
+
+Lots of casting fixes particularly for x64, Interlocked fixes and reworking
+for x64.
+- Daniel Richard G., John Kamp
+
+Other changes
+-------------
+Dependence on the winsock library is now discretionary via
+#define RETAIN_WSALASTERROR in config.h. It is undefined by default unless
+WINCE is defined (because RJ is unsure of the dependency there).
+- Ramiro Polla
+
+Several static POSIX mutexes used for internal management were replaced by
+MCS queue-based locks to reduce resource consumption, in particular use of Win32
+objects.
+- Ross Johnson
+
+For security, the QuserEx.dll if used must now be installed in the Windows System
+folder.
+- Ross Johnson
+
+New tests
+---------
+robust[1-5].c - Robust mutexes
+sequence1.c - per-thread unique sequence numbers
+
+Modified tests and benchtests
+-----------------------------
+All mutex*.c tests wherever appropriate have been modified to also test
+robust mutexes under the same conditions.
+Added robust mutex benchtests to benchtest*.c wherever appropriate.
+
+
+RELEASE 2.8.0
+-------------
+(2006-12-22)
+
+General
+-------
+New bug fixes in this release since 2.7.0 have not been applied to the
+version 1.x.x series. It is probably time to drop version 1.
+
+Testing and verification
+------------------------
+This release has not yet been tested on SMP architechtures. All tests pass
+on a uni-processor system.
+
+Bug fixes
+---------
+Sem_destroy could return EBUSY even though no threads were waiting on the
+semaphore. Other races around invalidating semaphore structs (internally)
+have been removed as well.
+
+New tests
+---------
+semaphore5.c - tests the bug fix referred to above.
+
+
+RELEASE 2.7.0
+-------------
+(2005-06-04)
+
+General
+-------
+All new features in this release have been back-ported in release 1.11.0,
+including the incorporation of MCS locks in pthread_once, however, versions
+1 and 2 remain incompatible even though they are now identical in
+performance and functionality.
+
+Testing and verification
+------------------------
+This release has been tested (passed the test suite) on both uni-processor
+and multi-processor systems.
+- Tim Theisen
+
+Bug fixes
+---------
+Pthread_once has been re-implemented to remove priority boosting and other
+complexity to improve robustness. Races for Win32 handles that are not
+recycle-unique have been removed. The general form of pthread_once is now
+the same as that suggested earlier by Alexander Terekhov, but instead of the
+'named mutex', a queue-based lock has been implemented which has the required
+properties of dynamic self initialisation and destruction. This lock is also
+efficient. The ABI is unaffected in as much as the size of pthread_once_t has
+not changed and PTHREAD_ONCE_INIT has not changed, however, applications that
+peek inside pthread_once_t, which is supposed to be opaque, will break.
+- Vladimir Kliatchko
+
+New features
+------------
+* Support for Mingw cross development tools added to GNUmakefile.
+Mingw cross tools allow building the libraries on Linux.
+- Mikael Magnusson
+
+
+RELEASE 2.6.0
+-------------
+(2005-05-19)
+
+General
+-------
+All of the bug fixes and new features in this release have been
+back-ported in release 1.10.0.
+
+Testing and verification
+------------------------
+This release has been tested (passed the test suite) on both uni-processor
+and multi-processor systems. Thanks to Tim Theisen at TomoTherapy for
+exhaustively running the MP tests and for providing crutial observations
+and data when faults are detected.
+
+Bugs fixed
+----------
+
+* pthread_detach() now reclaims remaining thread resources if called after
+the target thread has terminated. Previously, this routine did nothing in
+this case.
+
+New tests
+---------
+
+* detach1.c - tests that pthread_detach properly invalidates the target
+thread, which indicates that the thread resources have been reclaimed.
+
+
+RELEASE 2.5.0
+-------------
+(2005-05-09)
+
+General
+-------
+
+The package now includes a reference documentation set consisting of
+HTML formatted Unix-style manual pages that have been edited for
+consistency with Pthreads-w32. The set can also be read online at:
+http://sources.redhat.com/pthreads-win32/manual/index.html
+
+Thanks again to Tim Theisen for running the test suite pre-release
+on an MP system.
+
+All of the bug fixes and new features in this release have been
+back-ported in release 1.9.0.
+
+Bugs fixed
+----------
+
+* Thread Specific Data (TSD) key management has been ammended to
+eliminate a source of (what was effectively) resource leakage (a HANDLE
+plus memory for each key destruct routine/thread association). This was
+not a true leak because these resources were eventually reclaimed when
+pthread_key_delete was run AND each thread referencing the key had exited.
+The problem was that these two conditions are often not met until very
+late, and often not until the process is about to exit.
+
+The ammended implementation avoids the need for the problematic HANDLE
+and reclaims the memory as soon as either the key is deleted OR the
+thread exits, whichever is first.
+
+Thanks to Richard Hughes at Aculab for identifying and locating the leak.
+
+* TSD key destructors are now processed up to PTHREAD_DESTRUCTOR_ITERATIONS
+times instead of just once. PTHREAD_DESTRUCTOR_ITERATIONS has been
+defined in pthread.h for some time but not used.
+
+* Fix a semaphore accounting race between sem_post/sem_post_multiple
+and sem_wait cancellation. This is the same issue as with
+sem_timedwait that was fixed in the last release.
+
+* sem_init, sem_post, and sem_post_multiple now check that the
+semaphore count never exceeds _POSIX_SEM_VALUE_MAX.
+
+* Although sigwait() is nothing more than a no-op, it should at least
+be a cancellation point to be consistent with the standard.
+
+New tests
+---------
+
+* stress1.c - attempts to expose problems in condition variable
+and semaphore timed wait logic. This test was inspired by Stephan
+Mueller's sample test code used to identify the sem_timedwait bug
+from the last release. It's not a part of the regular test suite
+because it can take awhile to run. To run it:
+nmake clean VC-stress
+
+* tsd2.c - tests that key destructors are re-run if the tsd key value is
+not NULL after the destructor routine has run. Also tests that
+pthread_setspecific() and pthread_getspecific() are callable from
+destructors.
+
+
+RELEASE 2.4.0
+-------------
+(2005-04-26)
+
+General
+-------
+
+There is now no plan to release a version 3.0.0 to fix problems in
+pthread_once(). Other possible implementations of pthread_once
+will still be investigated for a possible future release in an attempt
+to reduce the current implementation's complexity.
+
+All of the bug fixes and new features in this release have been
+back-ported for release 1.8.0.
+
+Bugs fixed
+----------
+
+* Fixed pthread_once race (failures on an MP system). Thanks to
+Tim Theisen for running exhaustive pre-release testing on his MP system
+using a range of compilers:
+ VC++ 6
+ VC++ 7.1
+ Intel C++ version 8.0
+All tests passed.
+Some minor speed improvements were also done.
+
+* Fix integer overrun error in pthread_mutex_timedlock() - missed when
+sem_timedwait() was fixed in release 2.2.0. This routine no longer returns
+ENOTSUP when NEED_SEM is defined - it is supported (NEED_SEM is only
+required for WinCE versions prior to 3.0).
+
+* Fix timeout bug in sem_timedwait().
+- Thanks to Stephan Mueller for reporting, providing diagnostic output
+and test code.
+
+* Fix several problems in the NEED_SEM conditionally included code.
+NEED_SEM included code is provided for systems that don't implement W32
+semaphores, such as WinCE prior to version 3.0. An alternate implementation
+of POSIX semaphores is built using W32 events for these systems when
+NEED_SEM is defined. This code has been completely rewritten in this
+release to reuse most of the default POSIX semaphore code, and particularly,
+to implement all of the sem_* routines supported by pthreads-win32. Tim
+Theisen also run the test suite over the NEED_SEM code on his MP system. All
+tests passed.
+
+* The library now builds without errors for the Borland Builder 5.5 compiler.
+
+New features
+------------
+
+* pthread_mutex_timedlock() and all sem_* routines provided by
+pthreads-win32 are now implemented for WinCE versions prior to 3.0. Those
+versions did not implement W32 semaphores. Define NEED_SEM in config.h when
+building the library for these systems.
+
+Known issues in this release
+----------------------------
+
+* pthread_once is too complicated - but it works as far as testing can
+determine..
+
+* The Borland version of the dll fails some of the tests with a memory read
+exception. The cause is not yet known but a compiler bug has not been ruled
+out.
+
+
+RELEASE 2.3.0
+-------------
+(2005-04-12)
+
+General
+-------
+
+Release 1.7.0 is a backport of features and bug fixes new in
+this release. See earlier notes under Release 2.0.0/General.
+
+Bugs fixed
+----------
+
+* Fixed pthread_once potential for post once_routine cancellation
+hanging due to starvation. See comments in pthread_once.c.
+Momentary priority boosting is used to ensure that, after a
+once_routine is cancelled, the thread that will run the
+once_routine is not starved by higher priority waiting threads at
+critical times. Priority boosting occurs only AFTER a once_routine
+cancellation, and is applied only to that once_control. The
+once_routine is run at the thread's normal base priority.
+
+New tests
+---------
+
+* once4.c: Aggressively tests pthread_once() under realtime
+conditions using threads with varying priorities. Windows'
+random priority boosting does not occur for threads with realtime
+priority levels.
+
+
+RELEASE 2.2.0
+-------------
+(2005-04-04)
+
+General
+-------
+
+* Added makefile targets to build static link versions of the library.
+Both MinGW and MSVC. Please note that this does not imply any change
+to the LGPL licensing, which still imposes psecific conditions on
+distributing software that has been statically linked with this library.
+
+* There is a known bug in pthread_once(). Cancellation of the init_routine
+exposes a potential starvation (i.e. deadlock) problem if a waiting thread
+has a higher priority than the initting thread. This problem will be fixed
+in version 3.0.0 of the library.
+
+Bugs fixed
+----------
+
+* Fix integer overrun error in sem_timedwait().
+Kevin Lussier
+
+* Fix preprocessor directives for static linking.
+Dimitar Panayotov
+
+
+RELEASE 2.1.0
+-------------
+(2005-03-16)
+
+Bugs fixed
+----------
+
+* Reverse change to pthread_setcancelstate() in 2.0.0.
+
+
+RELEASE 2.0.0
+-------------
+(2005-03-16)
+
+General
+-------
+
+This release represents an ABI change and the DLL version naming has
+incremented from 1 to 2, e.g. pthreadVC2.dll.
+
+Version 1.4.0 back-ports the new functionality included in this
+release. Please distribute DLLs built from that version with updates
+to applications built on pthreads-win32 version 1.x.x.
+
+The package naming has changed, replacing the snapshot date with
+the version number + descriptive information. E.g. this
+release is "pthreads-w32-2-0-0-release".
+
+Bugs fixed
+----------
+
+* pthread_setcancelstate() no longer checks for a pending
+async cancel event if the library is using alertable async
+cancel. See the README file (Prerequisites section) for info
+on adding alertable async cancelation.
+
+New features
+------------
+
+* pthread_once() now supports init_routine cancellability.
+
+New tests
+---------
+
+* Agressively test pthread_once() init_routine cancellability.
+
+
+SNAPSHOT 2005-03-08
+-------------------
+Version 1.3.0
+
+Bug reports (fixed)
+-------------------
+
+* Implicitly created threads leave Win32 handles behind after exiting.
+- Dmitrii Semii
+
+* pthread_once() starvation problem.
+- Gottlob Frege
+
+New tests
+---------
+
+* More intense testing of pthread_once().
+
+
+SNAPSHOT 2005-01-25
+-------------------
+Version 1.2.0
+
+Bug fixes
+---------
+
+* Attempted acquisition of a recursive mutex could cause waiting threads
+to not be woken when the mutex was released.
+- Ralf Kubis <RKubis at mc.com>
+
+* Various package omissions have been fixed.
+
+
+SNAPSHOT 2005-01-03
+-------------------
+Version 1.1.0
+
+Bug fixes
+---------
+
+* Unlocking recursive or errorcheck mutexes would sometimes
+unexpectedly return an EPERM error (bug introduced in
+snapshot-2004-11-03).
+- Konstantin Voronkov <beowinkle at yahoo.com>
+
+
+SNAPSHOT 2004-11-22
+-------------------
+Version 1.0.0
+
+This snapshot primarily fixes the condvar bug introduced in
+snapshot-2004-11-03. DLL versioning has also been included to allow
+applications to runtime check the Microsoft compatible DLL version
+information, and to extend the DLL naming system for ABI and major
+(non-backward compatible) API changes. See the README file for details.
+
+Bug fixes
+---------
+
+* Condition variables no longer deadlock (bug introduced in
+snapshot-2004-11-03).
+- Alexander Kotliarov and Nicolas at saintmac
+
+* DLL naming extended to avoid 'DLL hell' in the future, and to
+accommodate the ABI change introduced in snapshot-2004-11-03. Snapshot
+2004-11-03 will be removed from FTP sites.
+
+New features
+------------
+
+* A Microsoft-style version resource has been added to the DLL for
+applications that wish to check DLL compatibility at runtime.
+
+* Pthreads-win32 DLL naming has been extended to allow incompatible DLL
+versions to co-exist in the same filesystem. See the README file for details,
+but briefly: while the version information inside the DLL will change with
+each release from now on, the DLL version names will only change if the new
+DLL is not backward compatible with older applications.
+
+The versioning scheme has been borrowed from GNU Libtool, and the DLL
+naming scheme is from Cygwin. Provided the Libtool-style numbering rules are
+honoured, the Cygwin DLL naming scheme automatcally ensures that DLL name
+changes are minimal and that applications will not load an incompatible
+pthreads-win32 DLL.
+
+Those who use the pre-built DLLs will find that the DLL/LIB names have a new
+suffix (1) in this snapshot. E.g. pthreadVC1.dll etc.
+
+* The POSIX thread ID reuse uniqueness feature introduced in the last snapshot
+has been kept as default, but the behaviour can now be controlled when the DLL
+is built to effectively switch it off. This makes the library much more
+sensitive to applications that assume that POSIX thread IDs are unique, i.e.
+are not strictly compliant with POSIX. See the PTW32_THREAD_ID_REUSE_INCREMENT
+macro comments in config.h for details.
+
+Other changes
+-------------
+Certain POSIX macros have changed.
+
+These changes are intended to conform to the Single Unix Specification version 3,
+which states that, if set to 0 (zero) or not defined, then applications may use
+sysconf() to determine their values at runtime. Pthreads-win32 does not
+implement sysconf().
+
+The following macros are no longer undefined, but defined and set to -1
+(not implemented):
+
+ _POSIX_THREAD_ATTR_STACKADDR
+ _POSIX_THREAD_PRIO_INHERIT
+ _POSIX_THREAD_PRIO_PROTECT
+ _POSIX_THREAD_PROCESS_SHARED
+
+The following macros are defined and set to 200112L (implemented):
+
+ _POSIX_THREADS
+ _POSIX_THREAD_SAFE_FUNCTIONS
+ _POSIX_THREAD_ATTR_STACKSIZE
+ _POSIX_THREAD_PRIORITY_SCHEDULING
+ _POSIX_SEMAPHORES
+ _POSIX_READER_WRITER_LOCKS
+ _POSIX_SPIN_LOCKS
+ _POSIX_BARRIERS
+
+The following macros are defined and set to appropriate values:
+
+ _POSIX_THREAD_THREADS_MAX
+ _POSIX_SEM_VALUE_MAX
+ _POSIX_SEM_NSEMS_MAX
+ PTHREAD_DESTRUCTOR_ITERATIONS
+ PTHREAD_KEYS_MAX
+ PTHREAD_STACK_MIN
+ PTHREAD_THREADS_MAX
+
+
+SNAPSHOT 2004-11-03
+-------------------
+
+DLLs produced from this snapshot cannot be used with older applications without
+recompiling the application, due to a change to pthread_t to provide unique POSIX
+thread IDs.
+
+Although this snapshot passes the extended test suite, many of the changes are
+fairly major, and some applications may show different behaviour than previously,
+so adopt with care. Hopefully, any changed behaviour will be due to the library
+being better at it's job, not worse.
+
+Bug fixes
+---------
+
+* pthread_create() no longer accepts NULL as the thread reference arg.
+A segfault (memory access fault) will result, and no thread will be
+created.
+
+* pthread_barrier_wait() no longer acts as a cancelation point.
+
+* Fix potential race condition in pthread_once()
+- Tristan Savatier <tristan at mpegtv.com>
+
+* Changes to pthread_cond_destroy() exposed some coding weaknesses in several
+test suite mini-apps because pthread_cond_destroy() now returns EBUSY if the CV
+is still in use.
+
+New features
+------------
+
+* Added for compatibility:
+PTHREAD_RECURSIVE_MUTEX_INITIALIZER,
+PTHREAD_ERRORCHECK_MUTEX_INITIALIZER,
+PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
+PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
+
+* Initial support for Digital Mars compiler
+- Anuj Goyal <anuj.goyal at gmail.com>
+
+* Faster Mutexes. These have been been rewritten following a model provided by
+Alexander Terekhov that reduces kernel space checks, and eliminates some additional
+critical sections used to manage a race between timedlock expiration and unlock.
+Please be aware that the new mutexes do not enforce strict absolute FIFO scheduling
+of mutexes, however any out-of-order lock acquisition should be very rare.
+
+* Faster semaphores. Following a similar model to mutexes above, these have been
+rewritten to use preliminary users space checks.
+
+* sem_getvalue() now returns the number of waiters.
+
+* The POSIX thread ID now has much stronger uniqueness characteristics. The library
+garrantees not to reuse the same thread ID for at least 2^(wordsize) thread
+destruction/creation cycles.
+
+New tests
+---------
+
+* semaphore4.c: Tests cancelation of the new sem_wait().
+
+* semaphore4t.c: Likewise for sem_timedwait().
+
+* rwlock8.c: Tests and times the slow execution paths of r/w locks, and the CVs,
+mutexes, and semaphores that they're built on.
+
+
+SNAPSHOT 2004-05-16
+-------------------
+
+Attempt to add Watcom to the list of compilers that can build the library.
+This failed in the end due to it's non-thread-aware errno. The library
+builds but the test suite fails. See README.Watcom for more details.
+
+Bug fixes
+---------
+* Bug and memory leak in sem_init()
+- Alex Blanco <Alex.Blanco at motorola.com>
+
+* ptw32_getprocessors() now returns CPU count of 1 for WinCE.
+- James Ewing <james.ewing at sveasoft.com>
+
+* pthread_cond_wait() could be canceled at a point where it should not
+be cancelable. Fixed.
+- Alexander Terekhov <TEREKHOV at de.ibm.com>
+
+* sem_timedwait() had an incorrect timeout calculation.
+- Philippe Di Cristo <philipped at voicebox.com>
+
+* Fix a memory leak left behind after threads are destroyed.
+- P. van Bruggen <pietvb at newbridges.nl>
+
+New features
+------------
+* Ported to AMD64.
+- Makoto Kato <raven at oldskool.jp>
+
+* True pre-emptive asynchronous cancelation of threads. This is optional
+and requires that Panagiotis E. Hadjidoukas's QueueUserAPCEx package be
+installed. This package is included in the pthreads-win32 self-unpacking
+Zip archive starting from this snapshot. See the README.txt file inside
+the package for installation details.
+
+Note: If you don't use async cancelation in your application, or don't need
+to cancel threads that are blocked on system resources such as network I/O,
+then the default non-preemptive async cancelation is probably good enough.
+However, pthreads-win32 auto-detects the availability of these components
+at run-time, so you don't need to rebuild the library from source if you
+change your mind later.
+
+All of the advice available in books and elsewhere on the undesirability
+of using async cancelation in any application still stands, but this
+feature is a welcome addition with respect to the library's conformance to
+the POSIX standard.
+
+SNAPSHOT 2003-09-18
+-------------------
+
+Cleanup of thread priority management. In particular, setting of thread
+priority now attempts to map invalid Win32 values within the range returned
+by sched_get_priority_min/max() to useful values. See README.NONPORTABLE
+under "Thread priority".
+
+Bug fixes
+---------
+* pthread_getschedparam() now returns the priority given by the most recent
+call to pthread_setschedparam() or established by pthread_create(), as
+required by the standard. Previously, pthread_getschedparam() incorrectly
+returned the running thread priority at the time of the call, which may have
+been adjusted or temporarily promoted/demoted.
+
+* sched_get_priority_min() and sched_get_priority_max() now return -1 on error
+and set errno. Previously, they incorrectly returned the error value directly.
+
+
+SNAPSHOT 2003-09-04
+-------------------
+
+Bug fixes
+---------
+* ptw32_cancelableWait() now allows cancelation of waiting implicit POSIX
+threads.
+
+New test
+--------
+* cancel8.c tests cancelation of Win32 threads waiting at a POSIX cancelation
+point.
+
+
+SNAPSHOT 2003-09-03
+-------------------
+
+Bug fixes
+---------
+* pthread_self() would free the newly created implicit POSIX thread handle if
+DuplicateHandle failed instead of recycle it (very unlikely).
+
+* pthread_exit() was neither freeing nor recycling the POSIX thread struct
+for implicit POSIX threads.
+
+New feature - Cancelation of/by Win32 (non-POSIX) threads
+---------------------------------------------------------
+Since John Bossom's original implementation, the library has allowed non-POSIX
+initialised threads (Win32 threads) to call pthreads-win32 routines and
+therefore interact with POSIX threads. This is done by creating an on-the-fly
+POSIX thread ID for the Win32 thread that, once created, allows fully
+reciprical interaction. This did not extend to thread cancelation (async or
+deferred). Now it does.
+
+Any thread can be canceled by any other thread (Win32 or POSIX) if the former
+thread's POSIX pthread_t value is known. It's TSD destructors and POSIX
+cleanup handlers will be run before the thread exits with an exit code of
+PTHREAD_CANCELED (retrieved with GetExitCodeThread()).
+
+This allows a Win32 thread to, for example, call POSIX CV routines in the same way
+that POSIX threads would/should, with pthread_cond_wait() cancelability and
+cleanup handlers (pthread_cond_wait() is a POSIX cancelation point).
+
+By adding cancelation, Win32 threads should now be able to call all POSIX
+threads routines that make sense including semaphores, mutexes, condition
+variables, read/write locks, barriers, spinlocks, tsd, cleanup push/pop,
+cancelation, pthread_exit, scheduling, etc.
+
+Note that these on-the-fly 'implicit' POSIX thread IDs are initialised as detached
+(not joinable) with deferred cancelation type. The POSIX thread ID will be created
+automatically by any POSIX routines that need a POSIX handle (unless the routine
+needs a pthread_t as a parameter of course). A Win32 thread can discover it's own
+POSIX thread ID by calling pthread_self(), which will create the handle if
+necessary and return the pthread_t value.
+
+New tests
+---------
+Test the above new feature.
+
+
+SNAPSHOT 2003-08-19
+-------------------
+
+This snapshot fixes some accidental corruption to new test case sources.
+There are no changes to the library source code.
+
+
+SNAPSHOT 2003-08-15
+-------------------
+
+Bug fixes
+---------
+
+* pthread.dsp now uses correct compile flags (/MD).
+- Viv <vcotirlea@hotmail.com>
+
+* pthread_win32_process_detach_np() fixed memory leak.
+- Steven Reddie <Steven.Reddie@ca.com>
+
+* pthread_mutex_destroy() fixed incorrect return code.
+- Nicolas Barry <boozai@yahoo.com>
+
+* pthread_spin_destroy() fixed memory leak.
+- Piet van Bruggen <pietvb@newbridges.nl>
+
+* Various changes to tighten arg checking, and to work with later versions of
+MinGW32 and MsysDTK.
+
+* pthread_getschedparam() etc, fixed dangerous thread validity checking.
+- Nicolas Barry <boozai@yahoo.com>
+
+* POSIX thread handles are now reused and their memory is not freed on thread exit.
+This allows for stronger thread validity checking.
+
+New standard routine
+--------------------
+
+* pthread_kill() added to provide thread validity checking to applications.
+It does not accept any non zero values for the signal arg.
+
+New test cases
+--------------
+
+* New test cases to confirm validity checking, pthread_kill(), and thread reuse.
+
+
+SNAPSHOT 2003-05-10
+-------------------
+
+Bug fixes
+---------
+
+* pthread_mutex_trylock() now returns correct error values.
+pthread_mutex_destroy() will no longer destroy a recursively locked mutex.
+pthread_mutex_lock() is no longer inadvertantly behaving as a cancelation point.
+- Thomas Pfaff <tpfaff@gmx.net>
+
+* pthread_mutex_timedlock() no longer occasionally sets incorrect mutex
+ownership, causing deadlocks in some applications.
+- Robert Strycek <strycek@posam.sk> and Alexander Terekhov <TEREKHOV@de.ibm.com>
+
+
+SNAPSHOT 2002-11-04
+-------------------
+
+Bug fixes
+---------
+
+* sem_getvalue() now returns the correct value under Win NT and WinCE.
+- Rob Fanner <rfanner@stonethree.com>
+
+* sem_timedwait() now uses tighter checks for unreasonable
+abstime values - that would result in unexpected timeout values.
+
+* ptw32_cond_wait_cleanup() no longer mysteriously consumes
+CV signals but may produce more spurious wakeups. It is believed
+that the sem_timedwait() call is consuming a CV signal that it
+shouldn't.
+- Alexander Terekhov <TEREKHOV@de.ibm.com>
+
+* Fixed a memory leak in ptw32_threadDestroy() for implicit threads.
+
+* Fixed potential for deadlock in pthread_cond_destroy().
+A deadlock could occur for statically declared CVs (PTHREAD_COND_INITIALIZER),
+when one thread is attempting to destroy the condition variable while another
+is attempting to dynamically initialize it.
+- Michael Johnson <michaelj@maine.rr.com>
+
+
+SNAPSHOT 2002-03-02
+-------------------
+
+Cleanup code default style. (IMPORTANT)
+----------------------------------------------------------------------
+Previously, if not defined, the cleanup style was determined automatically
+from the compiler/language, and one of the following was defined accordingly:
+
+ __CLEANUP_SEH MSVC only
+ __CLEANUP_CXX C++, including MSVC++, GNU G++
+ __CLEANUP_C C, including GNU GCC, not MSVC
+
+These defines determine the style of cleanup (see pthread.h) and,
+most importantly, the way that cancelation and thread exit (via
+pthread_exit) is performed (see the routine ptw32_throw() in private.c).
+
+In short, the exceptions versions of the library throw an exception
+when a thread is canceled or exits (via pthread_exit()), which is
+caught by a handler in the thread startup routine, so that the
+the correct stack unwinding occurs regardless of where the thread
+is when it's canceled or exits via pthread_exit().
+
+In this and future snapshots, unless the build explicitly defines (e.g.
+via a compiler option) __CLEANUP_SEH, __CLEANUP_CXX, or __CLEANUP_C, then
+the build NOW always defaults to __CLEANUP_C style cleanup. This style
+uses setjmp/longjmp in the cancelation and pthread_exit implementations,
+and therefore won't do stack unwinding even when linked to applications
+that have it (e.g. C++ apps). This is for consistency with most
+current commercial Unix POSIX threads implementations. Compaq's TRU64
+may be an exception (no pun intended) and possible future trend.
+
+Although it was not clearly documented before, it is still necessary to
+build your application using the same __CLEANUP_* define as was
+used for the version of the library that you link with, so that the
+correct parts of pthread.h are included. That is, the possible
+defines require the following library versions:
+
+ __CLEANUP_SEH pthreadVSE.dll
+ __CLEANUP_CXX pthreadVCE.dll or pthreadGCE.dll
+ __CLEANUP_C pthreadVC.dll or pthreadGC.dll
+
+E.g. regardless of whether your app is C or C++, if you link with
+pthreadVC.lib or libpthreadGC.a, then you must define __CLEANUP_C.
+
+
+THE POINT OF ALL THIS IS: if you have not been defining one of these
+explicitly, then the defaults as described at the top of this
+section were being used.
+
+THIS NOW CHANGES, as has been explained above, but to try to make this
+clearer here's an example:
+
+If you were building your application with MSVC++ i.e. using C++
+exceptions and not explicitly defining one of __CLEANUP_*, then
+__CLEANUP_C++ was automatically defined for you in pthread.h.
+You should have been linking with pthreadVCE.dll, which does
+stack unwinding.
+
+If you now build your application as you had before, pthread.h will now
+automatically set __CLEANUP_C as the default style, and you will need to
+link with pthreadVC.dll. Stack unwinding will now NOT occur when a thread
+is canceled, or the thread calls pthread_exit().
+
+Your application will now most likely behave differently to previous
+versions, and in non-obvious ways. Most likely is that locally
+instantiated objects may not be destroyed or cleaned up after a thread
+is canceled.
+
+If you want the same behaviour as before, then you must now define
+__CLEANUP_C++ explicitly using a compiler option and link with
+pthreadVCE.dll as you did before.
+
+
+WHY ARE WE MAKING THE DEFAULT STYLE LESS EXCEPTION-FRIENDLY?
+Because no commercial Unix POSIX threads implementation allows you to
+choose to have stack unwinding. Therefore, providing it in pthread-win32
+as a default is dangerous. We still provide the choice but unless
+you consciously choose to do otherwise, your pthreads applications will
+now run or crash in similar ways irrespective of the threads platform
+you use. Or at least this is the hope.
+
+
+WHY NOT REMOVE THE EXCEPTIONS VERSIONS OF THE LIBRARY ALTOGETHER?
+There are a few reasons:
+- because there are well respected POSIX threads people who believe
+ that POSIX threads implementations should be exceptions aware and
+ do the expected thing in that context. (There are equally respected
+ people who believe it should not be easily accessible, if it's there
+ at all, for unconditional conformity to other implementations.)
+- because pthreads-win32 is one of the few implementations that has
+ the choice, perhaps the only freely available one, and so offers
+ a laboratory to people who may want to explore the effects;
+- although the code will always be around somewhere for anyone who
+ wants it, once it's removed from the current version it will not be
+ nearly as visible to people who may have a use for it.
+
+
+Source module splitting
+-----------------------
+In order to enable smaller image sizes to be generated
+for applications that link statically with the library,
+most routines have been separated out into individual
+source code files.
+
+This is being done in such a way as to be backward compatible.
+The old source files are reused to congregate the individual
+routine files into larger translation units (via a bunch of
+# includes) so that the compiler can still optimise wherever
+possible, e.g. through inlining, which can only be done
+within the same translation unit.
+
+It is also possible to build the entire library by compiling
+the single file named "pthread.c", which just #includes all
+the secondary congregation source files. The compiler
+may be able to use this to do more inlining of routines.
+
+Although the GNU compiler is able to produce libraries with
+the necessary separation (the -ffunction-segments switch),
+AFAIK, the MSVC and other compilers don't have this feature.
+
+Finally, since I use makefiles and command-line compilation,
+I don't know what havoc this reorganisation may wreak amongst
+IDE project file users. You should be able to continue
+using your existing project files without modification.
+
+
+New non-portable functions
+--------------------------
+pthread_num_processors_np():
+ Returns the number of processors in the system that are
+ available to the process, as determined from the processor
+ affinity mask.
+
+pthread_timechange_handler_np():
+ To improve tolerance against operator or time service initiated
+ system clock changes.
+
+ This routine can be called by an application when it
+ receives a WM_TIMECHANGE message from the system. At present
+ it broadcasts all condition variables so that waiting threads
+ can wake up and re-evaluate their conditions and restart
+ their timed waits if required.
+ - Suggested by Alexander Terekhov
+
+
+Platform dependence
+-------------------
+As Win95 doesn't provide one, the library now contains
+it's own InterlockedCompareExchange() routine, which is used
+whenever Windows doesn't provide it. InterlockedCompareExchange()
+is used to implement spinlocks and barriers, and also in mutexes.
+This routine relies on the CMPXCHG machine instruction which
+is not available on i386 CPUs. This library (from snapshot
+20010712 onwards) is therefore no longer supported on i386
+processor platforms.
+
+
+New standard routines
+---------------------
+For source code portability only - rwlocks cannot be process shared yet.
+
+ pthread_rwlockattr_init()
+ pthread_rwlockattr_destroy()
+ pthread_rwlockattr_setpshared()
+ pthread_rwlockattr_getpshared()
+
+As defined in the new POSIX standard, and the Single Unix Spec version 3:
+
+ sem_timedwait()
+ pthread_mutex_timedlock() - Alexander Terekhov and Thomas Pfaff
+ pthread_rwlock_timedrdlock() - adapted from pthread_rwlock_rdlock()
+ pthread_rwlock_timedwrlock() - adapted from pthread_rwlock_wrlock()
+
+
+pthread.h no longer includes windows.h
+--------------------------------------
+[Not yet for G++]
+
+This was done to prevent conflicts.
+
+HANDLE, DWORD, and NULL are temporarily defined within pthread.h if
+they are not already.
+
+
+pthread.h, sched.h and semaphore.h now use dllexport/dllimport
+--------------------------------------------------------------
+Not only to avoid the need for the pthread.def file, but to
+improve performance. Apparently, declaring functions with dllimport
+generates a direct call to the function and avoids the overhead
+of a stub function call.
+
+Bug fixes
+---------
+* Fixed potential NULL pointer dereferences in pthread_mutexattr_init,
+pthread_mutexattr_getpshared, pthread_barrierattr_init,
+pthread_barrierattr_getpshared, and pthread_condattr_getpshared.
+- Scott McCaskill <scott@magruder.org>
+
+* Removed potential race condition in pthread_mutex_trylock and
+pthread_mutex_lock;
+- Alexander Terekhov <TEREKHOV@de.ibm.com>
+
+* The behaviour of pthread_mutex_trylock in relation to
+recursive mutexes was inconsistent with commercial implementations.
+Trylock would return EBUSY if the lock was owned already by the
+calling thread regardless of mutex type. Trylock now increments the
+recursion count and returns 0 for RECURSIVE mutexes, and will
+return EDEADLK rather than EBUSY for ERRORCHECK mutexes. This is
+consistent with Solaris.
+- Thomas Pfaff <tpfaff@gmx.net>
+
+* Found a fix for the library and workaround for applications for
+the known bug #2, i.e. where __CLEANUP_CXX or __CLEANUP_SEH is defined.
+See the "Known Bugs in this snapshot" section below.
+
+This could be made transparent to applications by replacing the macros that
+define the current C++ and SEH versions of pthread_cleanup_push/pop
+with the C version, but AFAIK cleanup handlers would not then run in the
+correct sequence with destructors and exception cleanup handlers when
+an exception occurs.
+
+* Cancelation once started in a thread cannot now be inadvertantly
+double canceled. That is, once a thread begins it's cancelation run,
+cancelation is disabled and a subsequent cancel request will
+return an error (ESRCH).
+
+* errno: An incorrect compiler directive caused a local version
+of errno to be used instead of the Win32 errno. Both instances are
+thread-safe but applications checking errno after a pthreads-win32
+call would be wrong. Fixing this also fixed a bad compiler
+option in the testsuite (/MT should have been /MD) which is
+needed to link with the correct library MSVCRT.LIB.
+
+
+SNAPSHOT 2001-07-12
+-------------------
+
+To be added
+
+
+SNAPSHOT 2001-07-03
+-------------------
+
+To be added
+
+
+SNAPSHOT 2000-08-13
+-------------------
+
+New:
+- Renamed DLL and LIB files:
+ pthreadVSE.dll (MS VC++/Structured EH)
+ pthreadVSE.lib
+ pthreadVCE.dll (MS VC++/C++ EH)
+ pthreadVCE.lib
+ pthreadGCE.dll (GNU G++/C++ EH)
+ libpthreadw32.a
+
+ Both your application and the pthread dll should use the
+ same exception handling scheme.
+
+Bugs fixed:
+- MSVC++ C++ exception handling.
+
+Some new tests have been added.
+
+
+SNAPSHOT 2000-08-10
+-------------------
+
+New:
+- asynchronous cancelation on X86 (Jason Nye)
+- Makefile compatible with MS nmake to replace
+ buildlib.bat
+- GNUmakefile for Mingw32
+- tests/Makefile for MS nmake replaces runall.bat
+- tests/GNUmakefile for Mingw32
+
+Bugs fixed:
+- kernel32 load/free problem
+- attempt to hide internel exceptions from application
+ exception handlers (__try/__except and try/catch blocks)
+- Win32 thread handle leakage bug
+ (David Baggett/Paul Redondo/Eyal Lebedinsky)
+
+Some new tests have been added.
+
+
+SNAPSHOT 1999-11-02
+-------------------
+
+Bugs fixed:
+- ctime_r macro had an incorrect argument (Erik Hensema),
+- threads were not being created
+ PTHREAD_CANCEL_DEFERRED. This should have
+ had little effect as deferred is the only
+ supported type. (Ross Johnson).
+
+Some compatibility improvements added, eg.
+- pthread_setcancelstate accepts NULL pointer
+ for the previous value argument. Ditto for
+ pthread_setcanceltype. This is compatible
+ with Solaris but should not affect
+ standard applications (Erik Hensema)
+
+Some new tests have been added.
+
+
+SNAPSHOT 1999-10-17
+-------------------
+
+Bug fix - Cancelation of threads waiting on condition variables
+now works properly (Lorin Hochstein and Peter Slacik)
+
+
+SNAPSHOT 1999-08-12
+-------------------
+
+Fixed exception stack cleanup if calling pthread_exit()
+- (Lorin Hochstein and John Bossom).
+
+Fixed bugs in condition variables - (Peter Slacik):
+ - additional contention checks
+ - properly adjust number of waiting threads after timed
+ condvar timeout.
+
+
+SNAPSHOT 1999-05-30
+-------------------
+
+Some minor bugs have been fixed. See the ChangeLog file for details.
+
+Some more POSIX 1b functions are now included but ony return an
+error (ENOSYS) if called. They are:
+
+ sem_open
+ sem_close
+ sem_unlink
+ sem_getvalue
+
+
+SNAPSHOT 1999-04-07
+-------------------
+
+Some POSIX 1b functions which were internally supported are now
+available as exported functions:
+
+ sem_init
+ sem_destroy
+ sem_wait
+ sem_trywait
+ sem_post
+ sched_yield
+ sched_get_priority_min
+ sched_get_priority_max
+
+Some minor bugs have been fixed. See the ChangeLog file for details.
+
+
+SNAPSHOT 1999-03-16
+-------------------
+
+Initial release.
+
diff --git a/libs/pthreads/docs/Nmakefile b/libs/pthreads/docs/Nmakefile
new file mode 100644
index 0000000000..d9e5bf1bc7
--- /dev/null
+++ b/libs/pthreads/docs/Nmakefile
@@ -0,0 +1,24 @@
+/*
+ * nmake file for uwin pthread library
+ */
+
+VERSION = -
+CCFLAGS = -V -g $(CC.DLL)
+HAVE_PTW32_CONFIG_H == 1
+_MT == 1
+_timeb == timeb
+_ftime == ftime
+_errno == _ast_errno
+
+$(INCLUDEDIR) :INSTALLDIR: pthread.h sched.h
+
+pthread $(VERSION) :LIBRARY: attr.c barrier.c cancel.c cleanup.c condvar.c \
+ create.c dll.c exit.c fork.c global.c misc.c mutex.c private.c \
+ rwlock.c sched.c semaphore.c spin.c sync.c tsd.c nonportable.c
+
+:: ANNOUNCE CONTRIBUTORS COPYING.LIB ChangeLog FAQ GNUmakefile MAINTAINERS \
+ Makefile Makefile.in Makefile.vc NEWS PROGRESS README README.WinCE \
+ TODO WinCE-PORT install-sh errno.c tests tests.mk acconfig.h \
+ config.guess config.h.in config.sub configure configure.in signal.c \
+ README.CV README.NONPORTABLE pthread.dsp pthread.dsw
+
diff --git a/libs/pthreads/docs/PROGRESS b/libs/pthreads/docs/PROGRESS
new file mode 100644
index 0000000000..9abf0bca47
--- /dev/null
+++ b/libs/pthreads/docs/PROGRESS
@@ -0,0 +1,4 @@
+Please see the ANNOUNCE file "Level of Standards Conformance"
+or the web page:
+
+http://sources.redhat.com/pthreads-win32/conformance.html
diff --git a/libs/pthreads/docs/README b/libs/pthreads/docs/README
new file mode 100644
index 0000000000..545360bfa7
--- /dev/null
+++ b/libs/pthreads/docs/README
@@ -0,0 +1,601 @@
+PTHREADS-WIN32
+==============
+
+Pthreads-win32 is free software, distributed under the GNU Lesser
+General Public License (LGPL). See the file 'COPYING.LIB' for terms
+and conditions. Also see the file 'COPYING' for information
+specific to pthreads-win32, copyrights and the LGPL.
+
+
+What is it?
+-----------
+
+Pthreads-win32 is an Open Source Software implementation of the
+Threads component of the POSIX 1003.1c 1995 Standard (or later)
+for Microsoft's Win32 environment. Some functions from POSIX
+1003.1b are also supported including semaphores. Other related
+functions include the set of read-write lock functions. The
+library also supports some of the functionality of the Open
+Group's Single Unix specification, version 2, namely mutex types,
+plus some common and pthreads-win32 specific non-portable
+routines (see README.NONPORTABLE).
+
+See the file "ANNOUNCE" for more information including standards
+conformance details and the list of supported and unsupported
+routines.
+
+
+Prerequisites
+-------------
+MSVC or GNU C (MinGW32 MSys development kit)
+ To build from source.
+
+QueueUserAPCEx by Panagiotis E. Hadjidoukas
+ To support any thread cancelation in C++ library builds or
+ to support cancelation of blocked threads in any build.
+ This library is not required otherwise.
+
+ For true async cancelation of threads (including blocked threads).
+ This is a DLL and Windows driver that provides pre-emptive APC
+ by forcing threads into an alertable state when the APC is queued.
+ Both the DLL and driver are provided with the pthreads-win32.exe
+ self-unpacking ZIP, and on the pthreads-win32 FTP site (in source
+ and pre-built forms). Currently this is a separate LGPL package to
+ pthreads-win32. See the README in the QueueUserAPCEx folder for
+ installation instructions.
+
+ Pthreads-win32 will automatically detect if the QueueUserAPCEx DLL
+ QuserEx.DLL is available and whether the driver AlertDrv.sys is
+ loaded. If it is not available, pthreads-win32 will simulate async
+ cancelation, which means that it can async cancel only threads that
+ are runnable. The simulated async cancellation cannot cancel blocked
+ threads.
+
+ [FOR SECURITY] To be found Quserex.dll MUST be installed in the
+ Windows System Folder. This is not an unreasonable constraint given a
+ driver must also be installed and loaded at system startup.
+
+
+Library naming
+--------------
+
+Because the library is being built using various exception
+handling schemes and compilers - and because the library
+may not work reliably if these are mixed in an application,
+each different version of the library has it's own name.
+
+Note 1: the incompatibility is really between EH implementations
+of the different compilers. It should be possible to use the
+standard C version from either compiler with C++ applications
+built with a different compiler. If you use an EH version of
+the library, then you must use the same compiler for the
+application. This is another complication and dependency that
+can be avoided by using only the standard C library version.
+
+Note 2: if you use a standard C pthread*.dll with a C++
+application, then any functions that you define that are
+intended to be called via pthread_cleanup_push() must be
+__cdecl.
+
+Note 3: the intention was to also name either the VC or GC
+version (it should be arbitrary) as pthread.dll, including
+pthread.lib and libpthread.a as appropriate. This is no longer
+likely to happen.
+
+Note 4: the compatibility number was added so that applications
+can differentiate between binary incompatible versions of the
+libs and dlls.
+
+In general:
+ pthread[VG]{SE,CE,C}[c].dll
+ pthread[VG]{SE,CE,C}[c].lib
+
+where:
+ [VG] indicates the compiler
+ V - MS VC, or
+ G - GNU C
+
+ {SE,CE,C} indicates the exception handling scheme
+ SE - Structured EH, or
+ CE - C++ EH, or
+ C - no exceptions - uses setjmp/longjmp
+
+ c - DLL compatibility number indicating ABI and API
+ compatibility with applications built against
+ a snapshot with the same compatibility number.
+ See 'Version numbering' below.
+
+The name may also be suffixed by a 'd' to indicate a debugging version
+of the library. E.g. pthreadVC2d.lib. Debugging versions contain
+additional information for debugging (symbols etc) and are often not
+optimised in any way (compiled with optimisation turned off).
+
+Examples:
+ pthreadVSE.dll (MSVC/SEH)
+ pthreadGCE.dll (GNUC/C++ EH)
+ pthreadGC.dll (GNUC/not dependent on exceptions)
+ pthreadVC1.dll (MSVC/not dependent on exceptions - not binary
+ compatible with pthreadVC.dll)
+ pthreadVC2.dll (MSVC/not dependent on exceptions - not binary
+ compatible with pthreadVC1.dll or pthreadVC.dll)
+
+The GNU library archive file names have correspondingly changed to:
+
+ libpthreadGCEc.a
+ libpthreadGCc.a
+
+
+Versioning numbering
+--------------------
+
+Version numbering is separate from the snapshot dating system, and
+is the canonical version identification system embedded within the
+DLL using the Microsoft version resource system. The versioning
+system chosen follows the GNU Libtool system. See
+http://www.gnu.org/software/libtool/manual.html section 6.2.
+
+See the resource file 'version.rc'.
+
+Microsoft version numbers use 4 integers:
+
+ 0.0.0.0
+
+Pthreads-win32 uses the first 3 following the Libtool convention.
+The fourth is commonly used for the build number, but will be reserved
+for future use.
+
+ current.revision.age.0
+
+The numbers are changed as follows:
+
+1. If the library source code has changed at all since the last update,
+ then increment revision (`c:r:a' becomes `c:r+1:a').
+2. If any interfaces have been added, removed, or changed since the last
+ update, increment current, and set revision to 0.
+3. If any interfaces have been added since the last public release, then
+ increment age.
+4. If any interfaces have been removed or changed since the last public
+ release, then set age to 0.
+
+
+DLL compatibility numbering is an attempt to ensure that applications
+always load a compatible pthreads-win32 DLL by using a DLL naming system
+that is consistent with the version numbering system. It also allows
+older and newer DLLs to coexist in the same filesystem so that older
+applications can continue to be used. For pre .NET Windows systems,
+this inevitably requires incompatible versions of the same DLLs to have
+different names.
+
+Pthreads-win32 has adopted the Cygwin convention of appending a single
+integer number to the DLL name. The number used is based on the library
+version number and is computed as 'current' - 'age'.
+
+(See http://home.att.net/~perlspinr/libversioning.html for a nicely
+detailed explanation.)
+
+Using this method, DLL name/s will only change when the DLL's
+backwards compatibility changes. Note that the addition of new
+'interfaces' will not of itself change the DLL's compatibility for older
+applications.
+
+
+Which of the several dll versions to use?
+-----------------------------------------
+or,
+---
+What are all these pthread*.dll and pthread*.lib files?
+-------------------------------------------------------
+
+Simple, use either pthreadGCv.* if you use GCC, or pthreadVCv.* if you
+use MSVC - where 'v' is the DLL versioning (compatibility) number.
+
+Otherwise, you need to choose carefully and know WHY.
+
+The most important choice you need to make is whether to use a
+version that uses exceptions internally, or not. There are versions
+of the library that use exceptions as part of the thread
+cancelation and exit implementation. The default version uses
+setjmp/longjmp.
+
+There is some contension amongst POSIX threads experts as
+to how POSIX threads cancelation and exit should work
+with languages that use exceptions, e.g. C++ and even C
+(Microsoft's Structured Exceptions).
+
+The issue is: should cancelation of a thread in, say,
+a C++ application cause object destructors and C++ exception
+handlers to be invoked as the stack unwinds during thread
+exit, or not?
+
+There seems to be more opinion in favour of using the
+standard C version of the library (no EH) with C++ applications
+for the reason that this appears to be the assumption commercial
+pthreads implementations make. Therefore, if you use an EH version
+of pthreads-win32 then you may be under the illusion that
+your application will be portable, when in fact it is likely to
+behave differently when linked with other pthreads libraries.
+
+Now you may be asking: then why have you kept the EH versions of
+the library?
+
+There are a couple of reasons:
+- there is division amongst the experts and so the code may
+ be needed in the future. Yes, it's in the repository and we
+ can get it out anytime in the future, but it would be difficult
+ to find.
+- pthreads-win32 is one of the few implementations, and possibly
+ the only freely available one, that has EH versions. It may be
+ useful to people who want to play with or study application
+ behaviour under these conditions.
+
+Notes:
+
+[If you use either pthreadVCE or pthreadGCE]
+
+1. [See also the discussion in the FAQ file - Q2, Q4, and Q5]
+
+If your application contains catch(...) blocks in your POSIX
+threads then you will need to replace the "catch(...)" with the macro
+"PtW32Catch", eg.
+
+ #ifdef PtW32Catch
+ PtW32Catch {
+ ...
+ }
+ #else
+ catch(...) {
+ ...
+ }
+ #endif
+
+Otherwise neither pthreads cancelation nor pthread_exit() will work
+reliably when using versions of the library that use C++ exceptions
+for cancelation and thread exit.
+
+This is due to what is believed to be a C++ compliance error in VC++
+whereby you may not have multiple handlers for the same exception in
+the same try/catch block. GNU G++ doesn't have this restriction.
+
+
+Other name changes
+------------------
+
+All snapshots prior to and including snapshot 2000-08-13
+used "_pthread_" as the prefix to library internal
+functions, and "_PTHREAD_" to many library internal
+macros. These have now been changed to "ptw32_" and "PTW32_"
+respectively so as to not conflict with the ANSI standard's
+reservation of identifiers beginning with "_" and "__" for
+use by compiler implementations only.
+
+If you have written any applications and you are linking
+statically with the pthreads-win32 library then you may have
+included a call to _pthread_processInitialize. You will
+now have to change that to ptw32_processInitialize.
+
+
+Cleanup code default style
+--------------------------
+
+Previously, if not defined, the cleanup style was determined automatically
+from the compiler used, and one of the following was defined accordingly:
+
+ __CLEANUP_SEH MSVC only
+ __CLEANUP_CXX C++, including MSVC++, GNU G++
+ __CLEANUP_C C, including GNU GCC, not MSVC
+
+These defines determine the style of cleanup (see pthread.h) and,
+most importantly, the way that cancelation and thread exit (via
+pthread_exit) is performed (see the routine ptw32_throw()).
+
+In short, the exceptions versions of the library throw an exception
+when a thread is canceled, or exits via pthread_exit(). This exception is
+caught by a handler in the thread startup routine, so that the
+the correct stack unwinding occurs regardless of where the thread
+is when it's canceled or exits via pthread_exit().
+
+In this snapshot, unless the build explicitly defines (e.g. via a
+compiler option) __CLEANUP_SEH, __CLEANUP_CXX, or __CLEANUP_C, then
+the build NOW always defaults to __CLEANUP_C style cleanup. This style
+uses setjmp/longjmp in the cancelation and pthread_exit implementations,
+and therefore won't do stack unwinding even when linked to applications
+that have it (e.g. C++ apps). This is for consistency with most/all
+commercial Unix POSIX threads implementations.
+
+Although it was not clearly documented before, it is still necessary to
+build your application using the same __CLEANUP_* define as was
+used for the version of the library that you link with, so that the
+correct parts of pthread.h are included. That is, the possible
+defines require the following library versions:
+
+ __CLEANUP_SEH pthreadVSE.dll
+ __CLEANUP_CXX pthreadVCE.dll or pthreadGCE.dll
+ __CLEANUP_C pthreadVC.dll or pthreadGC.dll
+
+It is recommended that you let pthread.h use it's default __CLEANUP_C
+for both library and application builds. That is, don't define any of
+the above, and then link with pthreadVC.lib (MSVC or MSVC++) and
+libpthreadGC.a (MinGW GCC or G++). The reason is explained below, but
+another reason is that the prebuilt pthreadVCE.dll is currently broken.
+Versions built with MSVC++ later than version 6 may not be broken, but I
+can't verify this yet.
+
+WHY ARE WE MAKING THE DEFAULT STYLE LESS EXCEPTION-FRIENDLY?
+Because no commercial Unix POSIX threads implementation allows you to
+choose to have stack unwinding. Therefore, providing it in pthread-win32
+as a default is dangerous. We still provide the choice but unless
+you consciously choose to do otherwise, your pthreads applications will
+now run or crash in similar ways irrespective of the pthreads platform
+you use. Or at least this is the hope.
+
+
+Building under VC++ using C++ EH, Structured EH, or just C
+----------------------------------------------------------
+
+From the source directory run nmake without any arguments to list
+help information. E.g.
+
+$ nmake
+
+Microsoft (R) Program Maintenance Utility Version 6.00.8168.0
+Copyright (C) Microsoft Corp 1988-1998. All rights reserved.
+
+Run one of the following command lines:
+nmake clean VCE (to build the MSVC dll with C++ exception handling)
+nmake clean VSE (to build the MSVC dll with structured exception handling)
+nmake clean VC (to build the MSVC dll with C cleanup code)
+nmake clean VCE-inlined (to build the MSVC inlined dll with C++ exception handling)
+nmake clean VSE-inlined (to build the MSVC inlined dll with structured exception handling)
+nmake clean VC-inlined (to build the MSVC inlined dll with C cleanup code)
+nmake clean VC-static (to build the MSVC static lib with C cleanup code)
+nmake clean VCE-debug (to build the debug MSVC dll with C++ exception handling)
+nmake clean VSE-debug (to build the debug MSVC dll with structured exception handling)
+nmake clean VC-debug (to build the debug MSVC dll with C cleanup code)
+nmake clean VCE-inlined-debug (to build the debug MSVC inlined dll with C++ exception handling)
+nmake clean VSE-inlined-debug (to build the debug MSVC inlined dll with structured exception handling)
+nmake clean VC-inlined-debug (to build the debug MSVC inlined dll with C cleanup code)
+nmake clean VC-static-debug (to build the debug MSVC static lib with C cleanup code)
+
+
+The pre-built dlls are normally built using the *-inlined targets.
+
+You can run the testsuite by changing to the "tests" directory and
+running nmake. E.g.:
+
+$ cd tests
+$ nmake
+
+Microsoft (R) Program Maintenance Utility Version 6.00.8168.0
+Copyright (C) Microsoft Corp 1988-1998. All rights reserved.
+
+Run one of the following command lines:
+nmake clean VC (to test using VC dll with VC (no EH) applications)
+nmake clean VCX (to test using VC dll with VC++ (EH) applications)
+nmake clean VCE (to test using the VCE dll with VC++ EH applications)
+nmake clean VSE (to test using VSE dll with VC (SEH) applications)
+nmake clean VC-bench (to benchtest using VC dll with C bench app)
+nmake clean VCX-bench (to benchtest using VC dll with C++ bench app)
+nmake clean VCE-bench (to benchtest using VCE dll with C++ bench app)
+nmake clean VSE-bench (to benchtest using VSE dll with SEH bench app)
+nmake clean VC-static (to test using VC static lib with VC (no EH) applications)
+
+
+Building under Mingw32
+----------------------
+
+The dll can be built easily with recent versions of Mingw32.
+(The distributed versions are built using Mingw32 and MsysDTK
+from www.mingw32.org.)
+
+From the source directory, run make for help information. E.g.:
+
+$ make
+Run one of the following command lines:
+make clean GC (to build the GNU C dll with C cleanup code)
+make clean GCE (to build the GNU C dll with C++ exception handling)
+make clean GC-inlined (to build the GNU C inlined dll with C cleanup code)
+make clean GCE-inlined (to build the GNU C inlined dll with C++ exception handling)
+make clean GC-static (to build the GNU C inlined static lib with C cleanup code)
+make clean GC-debug (to build the GNU C debug dll with C cleanup code)
+make clean GCE-debug (to build the GNU C debug dll with C++ exception handling)
+make clean GC-inlined-debug (to build the GNU C inlined debug dll with C cleanup code)
+make clean GCE-inlined-debug (to build the GNU C inlined debug dll with C++ exception handling)
+make clean GC-static-debug (to build the GNU C inlined static debug lib with C cleanup code)
+
+
+The pre-built dlls are normally built using the *-inlined targets.
+
+You can run the testsuite by changing to the "tests" directory and
+running make for help information. E.g.:
+
+$ cd tests
+$ make
+Run one of the following command lines:
+make clean GC (to test using GC dll with C (no EH) applications)
+make clean GCX (to test using GC dll with C++ (EH) applications)
+make clean GCE (to test using GCE dll with C++ (EH) applications)
+make clean GC-bench (to benchtest using GNU C dll with C cleanup code)
+make clean GCE-bench (to benchtest using GNU C dll with C++ exception handling)
+make clean GC-static (to test using GC static lib with C (no EH) applications)
+
+
+Building under Linux using the Mingw32 cross development tools
+--------------------------------------------------------------
+
+You can build the library without leaving Linux by using the Mingw32 cross
+development toolchain. See http://www.libsdl.org/extras/win32/cross/ for
+tools and info. The GNUmakefile contains some support for this, for example:
+
+make CROSS=i386-mingw32msvc- clean GC-inlined
+
+will build pthreadGCn.dll and libpthreadGCn.a (n=version#), provided your
+cross-tools/bin directory is in your PATH (or use the cross-make.sh script
+at the URL above).
+
+
+Building the library as a statically linkable library
+-----------------------------------------------------
+
+General: PTW32_STATIC_LIB must be defined for both the library build and the
+application build. The makefiles supplied and used by the following 'make'
+command lines will define this for you.
+
+MSVC (creates pthreadVCn.lib as a static link lib):
+
+nmake clean VC-static
+
+
+MinGW32 (creates libpthreadGCn.a as a static link lib):
+
+make clean GC-static
+
+
+Define PTW32_STATIC_LIB when building your application. Also, your
+application must call a two non-portable routines to initialise the
+some state on startup and cleanup before exit. One other routine needs
+to be called to cleanup after any Win32 threads have called POSIX API
+routines. See README.NONPORTABLE or the html reference manual pages for
+details on these routines:
+
+BOOL pthread_win32_process_attach_np (void);
+BOOL pthread_win32_process_detach_np (void);
+BOOL pthread_win32_thread_attach_np (void); // Currently a no-op
+BOOL pthread_win32_thread_detach_np (void);
+
+
+The tests makefiles have the same targets but only check that the
+static library is statically linkable. They don't run the full
+testsuite. To run the full testsuite, build the dlls and run the
+dll test targets.
+
+
+Building the library under Cygwin
+---------------------------------
+
+Cygwin is implementing it's own POSIX threads routines and these
+will be the ones to use if you develop using Cygwin.
+
+
+Ready to run binaries
+---------------------
+
+For convenience, the following ready-to-run files can be downloaded
+from the FTP site (see under "Availability" below):
+
+ pthread.h
+ semaphore.h
+ sched.h
+ pthreadVC.dll - built with MSVC compiler using C setjmp/longjmp
+ pthreadVC.lib
+ pthreadVCE.dll - built with MSVC++ compiler using C++ EH
+ pthreadVCE.lib
+ pthreadVSE.dll - built with MSVC compiler using SEH
+ pthreadVSE.lib
+ pthreadGC.dll - built with Mingw32 GCC
+ libpthreadGC.a - derived from pthreadGC.dll
+ pthreadGCE.dll - built with Mingw32 G++
+ libpthreadGCE.a - derived from pthreadGCE.dll
+
+As of August 2003 pthreads-win32 pthreadG* versions are built and tested
+using the MinGW + MsysDTK environment current as of that date or later.
+The following file MAY be needed for older MinGW environments.
+
+ gcc.dll - needed to build and run applications that use
+ pthreadGCE.dll.
+
+
+Building applications with GNU compilers
+----------------------------------------
+
+If you're using pthreadGC.dll:
+
+With the three header files, pthreadGC.dll and libpthreadGC.a in the
+same directory as your application myapp.c, you could compile, link
+and run myapp.c under Mingw32 as follows:
+
+ gcc -o myapp.exe myapp.c -I. -L. -lpthreadGC
+ myapp
+
+Or put pthreadGC.dll in an appropriate directory in your PATH,
+put libpthreadGC.a in your system lib directory, and
+put the three header files in your system include directory,
+then use:
+
+ gcc -o myapp.exe myapp.c -lpthreadGC
+ myapp
+
+
+If you're using pthreadGCE.dll:
+
+With the three header files, pthreadGCE.dll, gcc.dll and libpthreadGCE.a
+in the same directory as your application myapp.c, you could compile,
+link and run myapp.c under Mingw32 as follows:
+
+ gcc -x c++ -o myapp.exe myapp.c -I. -L. -lpthreadGCE
+ myapp
+
+Or put pthreadGCE.dll and gcc.dll in an appropriate directory in
+your PATH, put libpthreadGCE.a in your system lib directory, and
+put the three header files in your system include directory,
+then use:
+
+ gcc -x c++ -o myapp.exe myapp.c -lpthreadGCE
+ myapp
+
+
+Availability
+------------
+
+The complete source code in either unbundled, self-extracting
+Zip file, or tar/gzipped format can be found at:
+
+ ftp://sources.redhat.com/pub/pthreads-win32
+
+The pre-built DLL, export libraries and matching pthread.h can
+be found at:
+
+ ftp://sources.redhat.com/pub/pthreads-win32/dll-latest
+
+Home page:
+
+ http://sources.redhat.com/pthreads-win32/
+
+
+Mailing list
+------------
+
+There is a mailing list for discussing pthreads on Win32.
+To join, send email to:
+
+ pthreads-win32-subscribe@sources.redhat.com
+
+Unsubscribe by sending mail to:
+
+ pthreads-win32-unsubscribe@sources.redhat.com
+
+
+Acknowledgements
+----------------
+
+See the ANNOUNCE file for acknowledgements.
+See the 'CONTRIBUTORS' file for the list of contributors.
+
+As much as possible, the ChangeLog file attributes
+contributions and patches that have been incorporated
+in the library to the individuals responsible.
+
+Finally, thanks to all those who work on and contribute to the
+POSIX and Single Unix Specification standards. The maturity of an
+industry can be measured by it's open standards.
+
+----
+Ross Johnson
+<rpj@callisto.canberra.edu.au>
+
+
+
+
+
+
+
+
diff --git a/libs/pthreads/docs/TODO b/libs/pthreads/docs/TODO
new file mode 100644
index 0000000000..fa9efc46e7
--- /dev/null
+++ b/libs/pthreads/docs/TODO
@@ -0,0 +1,7 @@
+ Things that aren't done yet
+ ---------------------------
+
+1. Implement PTHREAD_PROCESS_SHARED for semaphores, mutexes,
+ condition variables, read/write locks, barriers.
+
+
diff --git a/libs/pthreads/docs/WinCE-PORT b/libs/pthreads/docs/WinCE-PORT
new file mode 100644
index 0000000000..7bcfdea6cc
--- /dev/null
+++ b/libs/pthreads/docs/WinCE-PORT
@@ -0,0 +1,222 @@
+NOTE: The comments in this file relate to the original WinCE port
+done by Tristan Savatier. The semaphore routines have been
+completely rewritten since (2005-04-25), having been progressively
+broken more and more by changes to the library. All of the semaphore
+routines implemented for W9x/WNT/2000 and up should now also work for
+WinCE. Also, pthread_mutex_timedlock should now work.
+
+Additional WinCE updates have been applied since this as well. Check the
+ChangeLog file and search for WINCE for example. (2007-01-07)
+
+[RPJ]
+
+----
+
+Some interesting news:
+
+I have been able to port pthread-win32 to Windows-CE,
+which uses a subset of the WIN32 API.
+
+Since we intend to keep using pthread-win32 for our
+Commercial WinCE developments, I would be very interested
+if WinCE support could be added to the main source tree
+of pthread-win32. Also, I would like to be credited
+for this port :-)
+
+Now, here is the story...
+
+The port was performed and tested on a Casio "Cassiopeia"
+PalmSize PC, which runs a MIP processor. The OS in the
+Casio is WinCE version 2.11, but I used VC++ 6.0 with
+the WinCE SDK for version 2.01.
+
+I used pthread-win32 to port a heavily multithreaded
+commercial application (real-time MPEG video player)
+from Linux to WinCE. I consider the changes that
+I have done to be quite well tested.
+
+Overall the modifications that we had to do are minor.
+
+The WinCE port were based on pthread-win32-snap-1999-05-30,
+but I am certain that they can be integrated very easiely
+to more recent versions of the source.
+
+I have attached the modified source code:
+pthread-win32-snap-1999-05-30-WinCE.
+
+All the changes do not affect the code compiled on non-WinCE
+environment, provided that the macros used for WinCE compilation
+are not used, of course!
+
+Overall description of the WinCE port:
+-------------------------------------
+
+Most of the changes had to be made in areas where
+pthread-win32 was relying on some standard-C librairies
+(e.g. _ftime, calloc, errno), which are not available
+on WinCE. We have changed the code to use native Win32
+API instead (or in some cases we made wrappers).
+
+The Win32 Semaphores are not available,
+so we had to re-implement Semaphores using mutexes
+and events.
+
+Limitations / known problems of the WinCE port:
+----------------------------------------------
+
+Not all the semaphore routines have been ported
+(semaphores are defined by Posix but are not part
+pf pthread). I have just done enough to make
+pthread routines (that rely internally on semaphores)
+work, like signal conditions.
+
+I noticed that the Win32 threads work slightly
+differently on WinCE. This may have some impact
+on some tricky parts of pthread-win32, but I have
+not really investigated. For example, on WinCE,
+the process is killed if the main thread falls off
+the bottom (or calls pthread_exit), regardless
+of the existence of any other detached thread.
+Microsoft manual indicates that this behavior is
+deffirent from that of Windows Threads for other
+Win32 platforms.
+
+
+Detailed descriptions of the changes and rationals:
+
+------------------------------------
+- use a new macro NEED_ERRNO.
+
+If defined, the code in errno.c that defines a reentrant errno
+is compiled, regardless of _MT and _REENTRANT.
+
+Rational: On WinCE, there is no support for <stdio.h>, <errno.h> or
+any other standard C library, i.e. even if _MT or _REENTRANT
+is defined, errno is not provided by any library. NEED_ERRNO
+must be set to compile for WinCE.
+
+------------------------------------
+- In implement.h, change #include <semaphore.h> to #include "semaphore.h".
+
+Rational: semaphore.h is provided in pthread-win32 and should not
+be searched in the systems standard include. would not compile.
+This change does not seem to create problems on "classic" win32
+(e.g. win95).
+
+------------------------------------
+- use a new macro NEED_CALLOC.
+
+If defined, some code in misc.c will provide a replacement
+for calloc, which is not available on Win32.
+
+
+------------------------------------
+- use a new macro NEED_CREATETHREAD.
+
+If defined, implement.h defines the macro _beginthreadex
+and _endthreadex.
+
+Rational: On WinCE, the wrappers _beginthreadex and _endthreadex
+do not exist. The native Win32 routines must be used.
+
+------------------------------------
+- in misc.c:
+
+#ifdef NEED_DUPLICATEHANDLE
+ /* DuplicateHandle does not exist on WinCE */
+ self->threadH = GetCurrentThread();
+#else
+ if( !DuplicateHandle(
+ GetCurrentProcess(),
+ GetCurrentThread(),
+ GetCurrentProcess(),
+ &self->threadH,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS ) )
+ {
+ free( self );
+ return (NULL);
+ }
+#endif
+
+Rational: On WinCE, DuplicateHandle does not exist. I could not understand
+why DuplicateHandle must be used. It seems to me that getting the current
+thread handle with GetCurrentThread() is sufficient, and it seems to work
+perfectly fine, so maybe DuplicateHandle was just plain useless to begin with ?
+
+------------------------------------
+- In private.c, added some code at the beginning of ptw32_processInitialize
+to detect the case of multiple calls to ptw32_processInitialize.
+
+Rational: In order to debug pthread-win32, it is easier to compile
+it as a regular library (it is not possible to debug DLL's on winCE).
+In that case, the application must call ptw32_rocessInitialize()
+explicitely, to initialize pthread-win32. It is safer in this circumstance
+to handle the case where ptw32_processInitialize() is called on
+an already initialized library:
+
+int
+ptw32_processInitialize (void)
+{
+ if (ptw32_processInitialized) {
+ /*
+ * ignore if already initialized. this is useful for
+ * programs that uses a non-dll pthread
+ * library. such programs must call ptw32_processInitialize() explicitely,
+ * since this initialization routine is automatically called only when
+ * the dll is loaded.
+ */
+ return TRUE;
+ }
+ ptw32_processInitialized = TRUE;
+ [...]
+}
+
+------------------------------------
+- in private.c, if macro NEED_FTIME is defined, add routines to
+convert timespec_to_filetime and filetime_to_timespec, and modified
+code that was using _ftime() to use Win32 API instead.
+
+Rational: _ftime is not available on WinCE. It is necessary to use
+the native Win32 time API instead.
+
+Note: the routine timespec_to_filetime is provided as a convenience and a mean
+to test that filetime_to_timespec works, but it is not used by the library.
+
+------------------------------------
+- in semaphore.c, if macro NEED_SEM is defined, add code for the routines
+_increase_semaphore and _decrease_semaphore, and modify significantly
+the implementation of the semaphores so that it does not use CreateSemaphore.
+
+Rational: CreateSemaphore is not available on WinCE. I had to re-implement
+semaphores using mutexes and Events.
+
+Note: Only the semaphore routines that are used by pthread are implemented
+(i.e. signal conditions rely on a subset of the semaphores routines, and
+this subset works). Some other semaphore routines (e.g. sem_trywait) are
+not yet supported on my WinCE port (and since I don't need them, I am not
+planning to do anything about them).
+
+------------------------------------
+- in tsd.c, changed the code that defines TLS_OUT_OF_INDEXES
+
+/* TLS_OUT_OF_INDEXES not defined on WinCE */
+#ifndef TLS_OUT_OF_INDEXES
+#define TLS_OUT_OF_INDEXES 0xffffffff
+#endif
+
+Rational: TLS_OUT_OF_INDEXES is not defined in any standard include file
+on WinCE.
+
+------------------------------------
+- added file need_errno.h
+
+Rational: On WinCE, there is no errno.h file. need_errno.h is just a
+copy of windows version of errno.h, with minor modifications due to the fact
+that some of the error codes are defined by the WinCE socket library.
+In pthread.h, if NEED_ERRNO is defined, the file need_errno.h is
+included (instead of <errno.h>).
+
+
+-- eof
diff --git a/libs/pthreads/pthreads.vcxproj b/libs/pthreads/pthreads.vcxproj
new file mode 100644
index 0000000000..d1ddccbe03
--- /dev/null
+++ b/libs/pthreads/pthreads.vcxproj
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{E0EBB8A5-B577-414C-A5F9-9B4E2A0A66E9}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <ProjectName>pthreads</ProjectName>
+ <CharacterSet>Unicode</CharacterSet>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <GenerateManifest>false</GenerateManifest>
+ <EmbedManifest>false</EmbedManifest>
+ <PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141_xp</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir Condition="'$(Platform)'=='Win32'">$(SolutionDir)$(Configuration)\Libs\</OutDir>
+ <IntDir Condition="'$(Platform)'=='Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Platform)'=='x64'">$(SolutionDir)$(Configuration)64\Libs\</OutDir>
+ <IntDir Condition="'$(Platform)'=='x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
+ <LinkIncremental Condition="'$(Configuration)'=='Release'">false</LinkIncremental>
+ <TargetName>pthreads</TargetName>
+ <TargetExt>.mir</TargetExt>
+ </PropertyGroup>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <PrecompiledHeader></PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>$(ProjectDir)\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <IntrinsicFunctions>false</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <PreprocessorDefinitions Condition="'$(Platform)'=='Win32'">WIN32;HAVE_PTW32_CONFIG_H;PTW32_RC_MSC;PTW32_ARCHx86;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Platform)'=='x64'">WIN32;HAVE_PTW32_CONFIG_H;PTW32_RC_MSC;PTW32_ARCHx64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions Condition="'$(Platform)'=='Win32'">WIN32;HAVE_PTW32_CONFIG_H;PTW32_RC_MSC;PTW32_ARCHx86;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Platform)'=='x64'">WIN32;HAVE_PTW32_CONFIG_H;PTW32_RC_MSC;PTW32_ARCHx64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="src\config.h" />
+ <ClInclude Include="src\context.h" />
+ <ClInclude Include="src\implement.h" />
+ <ClInclude Include="src\need_errno.h" />
+ <ClInclude Include="src\sched.h" />
+ <ClInclude Include="src\semaphore.h" />
+ <ClInclude Include="src\pthread.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\pthread.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/libs/pthreads/pthreads.vcxproj.filters b/libs/pthreads/pthreads.vcxproj.filters
new file mode 100644
index 0000000000..49f1229401
--- /dev/null
+++ b/libs/pthreads/pthreads.vcxproj.filters
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(ProjectDir)..\..\build\vc.common\common.filters" />
+ <ItemGroup>
+ <ClCompile Include="src\stdafx.cxx">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\*.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\*.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\*.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/libs/pthreads/src/attr.c b/libs/pthreads/src/attr.c
new file mode 100644
index 0000000000..a9d55f4a4b
--- /dev/null
+++ b/libs/pthreads/src/attr.c
@@ -0,0 +1,53 @@
+/*
+ * attr.c
+ *
+ * Description:
+ * This translation unit agregates operations on thread attribute objects.
+ * It is used for inline optimisation.
+ *
+ * The included modules are used separately when static executable sizes
+ * must be minimised.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+#include "pthread_attr_init.c"
+#include "pthread_attr_destroy.c"
+#include "pthread_attr_getdetachstate.c"
+#include "pthread_attr_setdetachstate.c"
+#include "pthread_attr_getstackaddr.c"
+#include "pthread_attr_setstackaddr.c"
+#include "pthread_attr_getstacksize.c"
+#include "pthread_attr_setstacksize.c"
+#include "pthread_attr_getscope.c"
+#include "pthread_attr_setscope.c"
diff --git a/libs/pthreads/src/autostatic.c b/libs/pthreads/src/autostatic.c
new file mode 100644
index 0000000000..092aff2aee
--- /dev/null
+++ b/libs/pthreads/src/autostatic.c
@@ -0,0 +1,69 @@
+/*
+ * autostatic.c
+ *
+ * Description:
+ * This translation unit implements static auto-init and auto-exit logic.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#if defined(PTW32_STATIC_LIB)
+
+#if defined(__MINGW64__) || defined(__MINGW32__) || defined(_MSC_VER)
+
+#include "pthread.h"
+#include "implement.h"
+
+static void on_process_init(void)
+{
+ pthread_win32_process_attach_np ();
+}
+
+static void on_process_exit(void)
+{
+ pthread_win32_thread_detach_np ();
+ pthread_win32_process_detach_np ();
+}
+
+#if defined(__MINGW64__) || defined(__MINGW32__)
+# define attribute_section(a) __attribute__((section(a)))
+#elif defined(_MSC_VER)
+# define attribute_section(a) __pragma(section(a,long,read)); __declspec(allocate(a))
+#endif
+
+attribute_section(".ctors") void *gcc_ctor = on_process_init;
+attribute_section(".dtors") void *gcc_dtor = on_process_exit;
+
+attribute_section(".CRT$XCU") void *msc_ctor = on_process_init;
+attribute_section(".CRT$XPU") void *msc_dtor = on_process_exit;
+
+#endif /* defined(__MINGW64__) || defined(__MINGW32__) || defined(_MSC_VER) */
+
+#endif /* PTW32_STATIC_LIB */
diff --git a/libs/pthreads/src/barrier.c b/libs/pthreads/src/barrier.c
new file mode 100644
index 0000000000..41b950cd12
--- /dev/null
+++ b/libs/pthreads/src/barrier.c
@@ -0,0 +1,47 @@
+/*
+ * barrier.c
+ *
+ * Description:
+ * This translation unit implements barrier primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#include "pthread_barrier_init.c"
+#include "pthread_barrier_destroy.c"
+#include "pthread_barrier_wait.c"
+#include "pthread_barrierattr_init.c"
+#include "pthread_barrierattr_destroy.c"
+#include "pthread_barrierattr_getpshared.c"
+#include "pthread_barrierattr_setpshared.c"
diff --git a/libs/pthreads/src/cancel.c b/libs/pthreads/src/cancel.c
new file mode 100644
index 0000000000..1bd14ebe65
--- /dev/null
+++ b/libs/pthreads/src/cancel.c
@@ -0,0 +1,44 @@
+/*
+ * cancel.c
+ *
+ * Description:
+ * POSIX thread functions related to thread cancellation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#include "pthread_setcancelstate.c"
+#include "pthread_setcanceltype.c"
+#include "pthread_testcancel.c"
+#include "pthread_cancel.c"
diff --git a/libs/pthreads/src/cleanup.c b/libs/pthreads/src/cleanup.c
new file mode 100644
index 0000000000..381d1e87c8
--- /dev/null
+++ b/libs/pthreads/src/cleanup.c
@@ -0,0 +1,148 @@
+/*
+ * cleanup.c
+ *
+ * Description:
+ * This translation unit implements routines associated
+ * with cleaning up threads.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+/*
+ * The functions ptw32_pop_cleanup and ptw32_push_cleanup
+ * are implemented here for applications written in C with no
+ * SEH or C++ destructor support.
+ */
+
+ptw32_cleanup_t *
+ptw32_pop_cleanup (int execute)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function pops the most recently pushed cleanup
+ * handler. If execute is nonzero, then the cleanup handler
+ * is executed if non-null.
+ *
+ * PARAMETERS
+ * execute
+ * if nonzero, execute the cleanup handler
+ *
+ *
+ * DESCRIPTION
+ * This function pops the most recently pushed cleanup
+ * handler. If execute is nonzero, then the cleanup handler
+ * is executed if non-null.
+ * NOTE: specify 'execute' as nonzero to avoid duplication
+ * of common cleanup code.
+ *
+ * RESULTS
+ * N/A
+ *
+ * ------------------------------------------------------
+ */
+{
+ ptw32_cleanup_t *cleanup;
+
+ cleanup = (ptw32_cleanup_t *) pthread_getspecific (ptw32_cleanupKey);
+
+ if (cleanup != NULL)
+ {
+ if (execute && (cleanup->routine != NULL))
+ {
+
+ (*cleanup->routine) (cleanup->arg);
+
+ }
+
+ pthread_setspecific (ptw32_cleanupKey, (void *) cleanup->prev);
+
+ }
+
+ return (cleanup);
+
+} /* ptw32_pop_cleanup */
+
+
+void
+ptw32_push_cleanup (ptw32_cleanup_t * cleanup,
+ ptw32_cleanup_callback_t routine, void *arg)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function pushes a new cleanup handler onto the thread's stack
+ * of cleanup handlers. Each cleanup handler pushed onto the stack is
+ * popped and invoked with the argument 'arg' when
+ * a) the thread exits by calling 'pthread_exit',
+ * b) when the thread acts on a cancellation request,
+ * c) or when the thread calls pthread_cleanup_pop with a nonzero
+ * 'execute' argument
+ *
+ * PARAMETERS
+ * cleanup
+ * a pointer to an instance of pthread_cleanup_t,
+ *
+ * routine
+ * pointer to a cleanup handler,
+ *
+ * arg
+ * parameter to be passed to the cleanup handler
+ *
+ *
+ * DESCRIPTION
+ * This function pushes a new cleanup handler onto the thread's stack
+ * of cleanup handlers. Each cleanup handler pushed onto the stack is
+ * popped and invoked with the argument 'arg' when
+ * a) the thread exits by calling 'pthread_exit',
+ * b) when the thread acts on a cancellation request,
+ * c) or when the thrad calls pthread_cleanup_pop with a nonzero
+ * 'execute' argument
+ * NOTE: pthread_push_cleanup, ptw32_pop_cleanup must be paired
+ * in the same lexical scope.
+ *
+ * RESULTS
+ * pthread_cleanup_t *
+ * pointer to the previous cleanup
+ *
+ * ------------------------------------------------------
+ */
+{
+ cleanup->routine = routine;
+ cleanup->arg = arg;
+
+ cleanup->prev = (ptw32_cleanup_t *) pthread_getspecific (ptw32_cleanupKey);
+
+ pthread_setspecific (ptw32_cleanupKey, (void *) cleanup);
+
+} /* ptw32_push_cleanup */
diff --git a/libs/pthreads/src/condvar.c b/libs/pthreads/src/condvar.c
new file mode 100644
index 0000000000..704f4d7931
--- /dev/null
+++ b/libs/pthreads/src/condvar.c
@@ -0,0 +1,50 @@
+/*
+ * condvar.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+#include "ptw32_cond_check_need_init.c"
+#include "pthread_condattr_init.c"
+#include "pthread_condattr_destroy.c"
+#include "pthread_condattr_getpshared.c"
+#include "pthread_condattr_setpshared.c"
+#include "pthread_cond_init.c"
+#include "pthread_cond_destroy.c"
+#include "pthread_cond_wait.c"
+#include "pthread_cond_signal.c"
diff --git a/libs/pthreads/src/config.h b/libs/pthreads/src/config.h
new file mode 100644
index 0000000000..e63ce2da46
--- /dev/null
+++ b/libs/pthreads/src/config.h
@@ -0,0 +1,153 @@
+/* config.h */
+
+#ifndef PTW32_CONFIG_H
+#define PTW32_CONFIG_H
+
+/*********************************************************************
+ * Defaults: see target specific redefinitions below.
+ *********************************************************************/
+
+/* We're building the pthreads-win32 library */
+#define PTW32_BUILD
+
+/* Do we know about the C type sigset_t? */
+#undef HAVE_SIGSET_T
+
+/* Define if you have the <signal.h> header file. */
+#undef HAVE_SIGNAL_H
+
+/* Define if you have the Borland TASM32 or compatible assembler. */
+#undef HAVE_TASM32
+
+/* Define if you don't have Win32 DuplicateHandle. (eg. WinCE) */
+#undef NEED_DUPLICATEHANDLE
+
+/* Define if you don't have Win32 _beginthreadex. (eg. WinCE) */
+#undef NEED_CREATETHREAD
+
+/* Define if you don't have Win32 errno. (eg. WinCE) */
+#undef NEED_ERRNO
+
+/* Define if you don't have Win32 calloc. (eg. WinCE) */
+#undef NEED_CALLOC
+
+/* Define if you don't have Win32 ftime. (eg. WinCE) */
+#undef NEED_FTIME
+
+/* Define if you don't have Win32 semaphores. (eg. WinCE 2.1 or earlier) */
+#undef NEED_SEM
+
+/* Define if you need to convert string parameters to unicode. (eg. WinCE) */
+#undef NEED_UNICODE_CONSTS
+
+/* Define if your C (not C++) compiler supports "inline" functions. */
+#undef HAVE_C_INLINE
+
+/* Do we know about type mode_t? */
+#undef HAVE_MODE_T
+
+/*
+ * Define if GCC has atomic builtins, i.e. __sync_* intrinsics
+ * __sync_lock_* is implemented in mingw32 gcc 4.5.2 at least
+ * so this define does not turn those on or off. If you get an
+ * error from __sync_lock* then consider upgrading your gcc.
+ */
+#undef HAVE_GCC_ATOMIC_BUILTINS
+
+/* Define if you have the timespec struct */
+#define HAVE_STRUCT_TIMESPEC 1
+
+/* Define if you don't have the GetProcessAffinityMask() */
+#undef NEED_PROCESS_AFFINITY_MASK
+
+/* Define if your version of Windows TLSGetValue() clears WSALastError
+ * and calling SetLastError() isn't enough restore it. You'll also need to
+ * link against wsock32.lib (or libwsock32.a for MinGW).
+ */
+#undef RETAIN_WSALASTERROR
+
+/*
+# ----------------------------------------------------------------------
+# The library can be built with some alternative behaviour to better
+# facilitate development of applications on Win32 that will be ported
+# to other POSIX systems.
+#
+# Nothing described here will make the library non-compliant and strictly
+# compliant applications will not be affected in any way, but
+# applications that make assumptions that POSIX does not guarantee are
+# not strictly compliant and may fail or misbehave with some settings.
+#
+# PTW32_THREAD_ID_REUSE_INCREMENT
+# Purpose:
+# POSIX says that applications should assume that thread IDs can be
+# recycled. However, Solaris (and some other systems) use a [very large]
+# sequence number as the thread ID, which provides virtual uniqueness.
+# This provides a very high but finite level of safety for applications
+# that are not meticulous in tracking thread lifecycles e.g. applications
+# that call functions which target detached threads without some form of
+# thread exit synchronisation.
+#
+# Usage:
+# Set to any value in the range: 0 <= value < 2^wordsize.
+# Set to 0 to emulate reusable thread ID behaviour like Linux or *BSD.
+# Set to 1 for unique thread IDs like Solaris (this is the default).
+# Set to some factor of 2^wordsize to emulate smaller word size types
+# (i.e. will wrap sooner). This might be useful to emulate some embedded
+# systems.
+#
+# define PTW32_THREAD_ID_REUSE_INCREMENT 0
+#
+# ----------------------------------------------------------------------
+ */
+#undef PTW32_THREAD_ID_REUSE_INCREMENT
+
+
+/*********************************************************************
+ * Target specific groups
+ *
+ * If you find that these are incorrect or incomplete please report it
+ * to the pthreads-win32 maintainer. Thanks.
+ *********************************************************************/
+#if defined(WINCE)
+#define NEED_DUPLICATEHANDLE
+#define NEED_CREATETHREAD
+#define NEED_ERRNO
+#define NEED_CALLOC
+#define NEED_FTIME
+/* #define NEED_SEM */
+#define NEED_UNICODE_CONSTS
+#define NEED_PROCESS_AFFINITY_MASK
+/* This may not be needed */
+#define RETAIN_WSALASTERROR
+#endif
+
+#if defined(_UWIN)
+#define HAVE_MODE_T
+#define HAVE_STRUCT_TIMESPEC
+#endif
+
+#if defined(__GNUC__)
+#define HAVE_C_INLINE
+#endif
+
+#if defined(__MINGW64__)
+#define HAVE_MODE_T
+#define HAVE_STRUCT_TIMESPEC
+#elif defined(__MINGW32__)
+#define HAVE_MODE_T
+#endif
+
+#if defined(__BORLANDC__)
+#endif
+
+#if defined(__WATCOMC__)
+#endif
+
+#if defined(__DMC__)
+#define HAVE_SIGNAL_H
+#define HAVE_C_INLINE
+#endif
+
+
+
+#endif
diff --git a/libs/pthreads/src/context.h b/libs/pthreads/src/context.h
new file mode 100644
index 0000000000..3d4511f5b3
--- /dev/null
+++ b/libs/pthreads/src/context.h
@@ -0,0 +1,74 @@
+/*
+ * context.h
+ *
+ * Description:
+ * POSIX thread macros related to thread cancellation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef PTW32_CONTEXT_H
+#define PTW32_CONTEXT_H
+
+#undef PTW32_PROGCTR
+
+#if defined(_M_IX86) || (defined(_X86_) && !defined(__amd64__))
+#define PTW32_PROGCTR(Context) ((Context).Eip)
+#endif
+
+#if defined (_M_IA64) || defined(_IA64)
+#define PTW32_PROGCTR(Context) ((Context).StIIP)
+#endif
+
+#if defined(_MIPS_) || defined(MIPS)
+#define PTW32_PROGCTR(Context) ((Context).Fir)
+#endif
+
+#if defined(_ALPHA_)
+#define PTW32_PROGCTR(Context) ((Context).Fir)
+#endif
+
+#if defined(_PPC_)
+#define PTW32_PROGCTR(Context) ((Context).Iar)
+#endif
+
+#if defined(_AMD64_) || defined(__amd64__)
+#define PTW32_PROGCTR(Context) ((Context).Rip)
+#endif
+
+#if defined(_ARM_) || defined(ARM)
+#define PTW32_PROGCTR(Context) ((Context).Pc)
+#endif
+
+#if !defined(PTW32_PROGCTR)
+#error Module contains CPU-specific code; modify and recompile.
+#endif
+
+#endif
diff --git a/libs/pthreads/src/create.c b/libs/pthreads/src/create.c
new file mode 100644
index 0000000000..8b036cc2e9
--- /dev/null
+++ b/libs/pthreads/src/create.c
@@ -0,0 +1,308 @@
+/*
+ * create.c
+ *
+ * Description:
+ * This translation unit implements routines associated with spawning a new
+ * thread.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#if ! defined(_UWIN) && ! defined(WINCE)
+#include <process.h>
+#endif
+
+int
+pthread_create (pthread_t * tid,
+ const pthread_attr_t * attr,
+ void *(PTW32_CDECL *start) (void *), void *arg)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function creates a thread running the start function,
+ * passing it the parameter value, 'arg'. The 'attr'
+ * argument specifies optional creation attributes.
+ * The identity of the new thread is returned
+ * via 'tid', which should not be NULL.
+ *
+ * PARAMETERS
+ * tid
+ * pointer to an instance of pthread_t
+ *
+ * attr
+ * optional pointer to an instance of pthread_attr_t
+ *
+ * start
+ * pointer to the starting routine for the new thread
+ *
+ * arg
+ * optional parameter passed to 'start'
+ *
+ *
+ * DESCRIPTION
+ * This function creates a thread running the start function,
+ * passing it the parameter value, 'arg'. The 'attr'
+ * argument specifies optional creation attributes.
+ * The identity of the new thread is returned
+ * via 'tid', which should not be the NULL pointer.
+ *
+ * RESULTS
+ * 0 successfully created thread,
+ * EINVAL attr invalid,
+ * EAGAIN insufficient resources.
+ *
+ * ------------------------------------------------------
+ */
+{
+ pthread_t thread;
+ ptw32_thread_t * tp;
+ register pthread_attr_t a;
+ HANDLE threadH = 0;
+ int result = EAGAIN;
+ int run = PTW32_TRUE;
+ ThreadParms *parms = NULL;
+ unsigned int stackSize;
+ int priority;
+ pthread_t self;
+
+ /*
+ * Before doing anything, check that tid can be stored through
+ * without invoking a memory protection error (segfault).
+ * Make sure that the assignment below can't be optimised out by the compiler.
+ * This is assured by conditionally assigning *tid again at the end.
+ */
+ tid->x = 0;
+
+ if (attr != NULL)
+ {
+ a = *attr;
+ }
+ else
+ {
+ a = NULL;
+ }
+
+ if ((thread = ptw32_new ()).p == NULL)
+ {
+ goto FAIL0;
+ }
+
+ tp = (ptw32_thread_t *) thread.p;
+
+ priority = tp->sched_priority;
+
+ if ((parms = (ThreadParms *) malloc (sizeof (*parms))) == NULL)
+ {
+ goto FAIL0;
+ }
+
+ parms->tid = thread;
+ parms->start = start;
+ parms->arg = arg;
+
+#if defined(HAVE_SIGSET_T)
+
+ /*
+ * Threads inherit their initial sigmask from their creator thread.
+ */
+ self = pthread_self();
+ tp->sigmask = ((ptw32_thread_t *)self.p)->sigmask;
+
+#endif /* HAVE_SIGSET_T */
+
+
+ if (a != NULL)
+ {
+ stackSize = (unsigned int)a->stacksize;
+ tp->detachState = a->detachstate;
+ priority = a->param.sched_priority;
+
+#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL)
+ /* WinCE */
+#else
+ /* Everything else */
+
+ /*
+ * Thread priority must be set to a valid system level
+ * without altering the value set by pthread_attr_setschedparam().
+ */
+
+ /*
+ * PTHREAD_EXPLICIT_SCHED is the default because Win32 threads
+ * don't inherit their creator's priority. They are started with
+ * THREAD_PRIORITY_NORMAL (win32 value). The result of not supplying
+ * an 'attr' arg to pthread_create() is equivalent to defaulting to
+ * PTHREAD_EXPLICIT_SCHED and priority THREAD_PRIORITY_NORMAL.
+ */
+ if (PTHREAD_INHERIT_SCHED == a->inheritsched)
+ {
+ /*
+ * If the thread that called pthread_create() is a Win32 thread
+ * then the inherited priority could be the result of a temporary
+ * system adjustment. This is not the case for POSIX threads.
+ */
+#if ! defined(HAVE_SIGSET_T)
+ self = pthread_self ();
+#endif
+ priority = ((ptw32_thread_t *) self.p)->sched_priority;
+ }
+
+#endif
+
+ }
+ else
+ {
+ /*
+ * Default stackSize
+ */
+ stackSize = PTHREAD_STACK_MIN;
+ }
+
+ tp->state = run ? PThreadStateInitial : PThreadStateSuspended;
+
+ tp->keys = NULL;
+
+ /*
+ * Threads must be started in suspended mode and resumed if necessary
+ * after _beginthreadex returns us the handle. Otherwise we set up a
+ * race condition between the creating and the created threads.
+ * Note that we also retain a local copy of the handle for use
+ * by us in case thread.p->threadH gets NULLed later but before we've
+ * finished with it here.
+ */
+
+#if ! (defined (__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
+
+ tp->threadH =
+ threadH =
+ (HANDLE) _beginthreadex ((void *) NULL, /* No security info */
+ stackSize, /* default stack size */
+ ptw32_threadStart,
+ parms,
+ (unsigned)
+ CREATE_SUSPENDED,
+ (unsigned *) &(tp->thread));
+
+ if (threadH != 0)
+ {
+ if (a != NULL)
+ {
+ (void) ptw32_setthreadpriority (thread, SCHED_OTHER, priority);
+ }
+
+ if (run)
+ {
+ ResumeThread (threadH);
+ }
+ }
+
+#else
+
+ {
+ ptw32_mcs_local_node_t stateLock;
+
+ /*
+ * This lock will force pthread_threadStart() to wait until we have
+ * the thread handle and have set the priority.
+ */
+ ptw32_mcs_lock_acquire(&tp->stateLock, &stateLock);
+
+ tp->threadH =
+ threadH =
+ (HANDLE) _beginthread (ptw32_threadStart, stackSize, /* default stack size */
+ parms);
+
+ /*
+ * Make the return code match _beginthreadex's.
+ */
+ if (threadH == (HANDLE) - 1L)
+ {
+ tp->threadH = threadH = 0;
+ }
+ else
+ {
+ if (!run)
+ {
+ /*
+ * beginthread does not allow for create flags, so we do it now.
+ * Note that beginthread itself creates the thread in SUSPENDED
+ * mode, and then calls ResumeThread to start it.
+ */
+ SuspendThread (threadH);
+ }
+
+ if (a != NULL)
+ {
+ (void) ptw32_setthreadpriority (thread, SCHED_OTHER, priority);
+ }
+ }
+
+ ptw32_mcs_lock_release (&stateLock);
+ }
+#endif
+
+ result = (threadH != 0) ? 0 : EAGAIN;
+
+ /*
+ * Fall Through Intentionally
+ */
+
+ /*
+ * ------------
+ * Failure Code
+ * ------------
+ */
+
+FAIL0:
+ if (result != 0)
+ {
+
+ ptw32_threadDestroy (thread);
+ tp = NULL;
+
+ if (parms != NULL)
+ {
+ free (parms);
+ }
+ }
+ else
+ {
+ *tid = thread;
+ }
+
+#if defined(_UWIN)
+ if (result == 0)
+ pthread_count++;
+#endif
+ return (result);
+
+} /* pthread_create */
diff --git a/libs/pthreads/src/dll.c b/libs/pthreads/src/dll.c
new file mode 100644
index 0000000000..05e01bee76
--- /dev/null
+++ b/libs/pthreads/src/dll.c
@@ -0,0 +1,92 @@
+/*
+ * dll.c
+ *
+ * Description:
+ * This translation unit implements DLL initialisation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#if !defined(PTW32_STATIC_LIB)
+
+#include "pthread.h"
+#include "implement.h"
+
+#if defined(_MSC_VER)
+/*
+ * lpvReserved yields an unreferenced formal parameter;
+ * ignore it
+ */
+#pragma warning( disable : 4100 )
+#endif
+
+#if defined(__cplusplus)
+/*
+ * Dear c++: Please don't mangle this name. -thanks
+ */
+extern "C"
+#endif /* __cplusplus */
+ BOOL WINAPI
+DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
+{
+ BOOL result = PTW32_TRUE;
+
+ switch (fdwReason)
+ {
+
+ case DLL_PROCESS_ATTACH:
+ result = pthread_win32_process_attach_np ();
+ break;
+
+ case DLL_THREAD_ATTACH:
+ /*
+ * A thread is being created
+ */
+ result = pthread_win32_thread_attach_np ();
+ break;
+
+ case DLL_THREAD_DETACH:
+ /*
+ * A thread is exiting cleanly
+ */
+ result = pthread_win32_thread_detach_np ();
+ break;
+
+ case DLL_PROCESS_DETACH:
+ (void) pthread_win32_thread_detach_np ();
+ result = pthread_win32_process_detach_np ();
+ break;
+ }
+
+ return (result);
+
+} /* DllMain */
+
+#endif /* PTW32_STATIC_LIB */
diff --git a/libs/pthreads/src/errno.c b/libs/pthreads/src/errno.c
new file mode 100644
index 0000000000..78aa920a5b
--- /dev/null
+++ b/libs/pthreads/src/errno.c
@@ -0,0 +1,94 @@
+/*
+ * errno.c
+ *
+ * Description:
+ * This translation unit implements routines associated with spawning a new
+ * thread.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#if defined(NEED_ERRNO)
+
+#include "pthread.h"
+#include "implement.h"
+
+static int reallyBad = ENOMEM;
+
+/*
+ * Re-entrant errno.
+ *
+ * Each thread has it's own errno variable in pthread_t.
+ *
+ * The benefit of using the pthread_t structure
+ * instead of another TSD key is TSD keys are limited
+ * on Win32 to 64 per process. Secondly, to implement
+ * it properly without using pthread_t you'd need
+ * to dynamically allocate an int on starting the thread
+ * and store it manually into TLS and then ensure that you free
+ * it on thread termination. We get all that for free
+ * by simply storing the errno on the pthread_t structure.
+ *
+ * MSVC and Mingw32 already have their own thread-safe errno.
+ *
+ * #if defined( _REENTRANT ) || defined( _MT )
+ * #define errno *_errno()
+ *
+ * int *_errno( void );
+ * #else
+ * extern int errno;
+ * #endif
+ *
+ */
+
+int *
+_errno (void)
+{
+ pthread_t self;
+ int *result;
+
+ if ((self = pthread_self ()).p == NULL)
+ {
+ /*
+ * Yikes! unable to allocate a thread!
+ * Throw an exception? return an error?
+ */
+ result = &reallyBad;
+ }
+ else
+ {
+ result = (int *)(&self.p->exitStatus);
+ }
+
+ return (result);
+
+} /* _errno */
+
+#endif /* (NEED_ERRNO) */
diff --git a/libs/pthreads/src/exit.c b/libs/pthreads/src/exit.c
new file mode 100644
index 0000000000..94369d007c
--- /dev/null
+++ b/libs/pthreads/src/exit.c
@@ -0,0 +1,44 @@
+/*
+ * exit.c
+ *
+ * Description:
+ * This translation unit implements routines associated with exiting from
+ * a thread.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#if ! defined(_UWIN) && ! defined(WINCE)
+# include <process.h>
+#endif
+
+#include "pthread_exit.c"
diff --git a/libs/pthreads/src/fork.c b/libs/pthreads/src/fork.c
new file mode 100644
index 0000000000..8a29550caf
--- /dev/null
+++ b/libs/pthreads/src/fork.c
@@ -0,0 +1,39 @@
+/*
+ * fork.c
+ *
+ * Description:
+ * Implementation of fork() for POSIX threads.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#include "pthread.h"
+#include "implement.h"
diff --git a/libs/pthreads/src/global.c b/libs/pthreads/src/global.c
new file mode 100644
index 0000000000..f1e9b3f669
--- /dev/null
+++ b/libs/pthreads/src/global.c
@@ -0,0 +1,107 @@
+/*
+ * global.c
+ *
+ * Description:
+ * This translation unit instantiates data associated with the implementation
+ * as a whole.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int ptw32_processInitialized = PTW32_FALSE;
+ptw32_thread_t * ptw32_threadReuseTop = PTW32_THREAD_REUSE_EMPTY;
+ptw32_thread_t * ptw32_threadReuseBottom = PTW32_THREAD_REUSE_EMPTY;
+pthread_key_t ptw32_selfThreadKey = NULL;
+pthread_key_t ptw32_cleanupKey = NULL;
+pthread_cond_t ptw32_cond_list_head = NULL;
+pthread_cond_t ptw32_cond_list_tail = NULL;
+
+int ptw32_concurrency = 0;
+
+/* What features have been auto-detected */
+int ptw32_features = 0;
+
+/*
+ * Global [process wide] thread sequence Number
+ */
+unsigned __int64 ptw32_threadSeqNumber = 0;
+
+/*
+ * Function pointer to QueueUserAPCEx if it exists, otherwise
+ * it will be set at runtime to a substitute routine which cannot unblock
+ * blocked threads.
+ */
+DWORD (*ptw32_register_cancelation) (PAPCFUNC, HANDLE, DWORD) = NULL;
+
+/*
+ * Global lock for managing pthread_t struct reuse.
+ */
+ptw32_mcs_lock_t ptw32_thread_reuse_lock = 0;
+
+/*
+ * Global lock for testing internal state of statically declared mutexes.
+ */
+ptw32_mcs_lock_t ptw32_mutex_test_init_lock = 0;
+
+/*
+ * Global lock for testing internal state of PTHREAD_COND_INITIALIZER
+ * created condition variables.
+ */
+ptw32_mcs_lock_t ptw32_cond_test_init_lock = 0;
+
+/*
+ * Global lock for testing internal state of PTHREAD_RWLOCK_INITIALIZER
+ * created read/write locks.
+ */
+ptw32_mcs_lock_t ptw32_rwlock_test_init_lock = 0;
+
+/*
+ * Global lock for testing internal state of PTHREAD_SPINLOCK_INITIALIZER
+ * created spin locks.
+ */
+ptw32_mcs_lock_t ptw32_spinlock_test_init_lock = 0;
+
+/*
+ * Global lock for condition variable linked list. The list exists
+ * to wake up CVs when a WM_TIMECHANGE message arrives. See
+ * w32_TimeChangeHandler.c.
+ */
+ptw32_mcs_lock_t ptw32_cond_list_lock = 0;
+
+#if defined(_UWIN)
+/*
+ * Keep a count of the number of threads.
+ */
+int pthread_count = 0;
+#endif
diff --git a/libs/pthreads/src/implement.h b/libs/pthreads/src/implement.h
new file mode 100644
index 0000000000..693be26a24
--- /dev/null
+++ b/libs/pthreads/src/implement.h
@@ -0,0 +1,943 @@
+/*
+ * implement.h
+ *
+ * Definitions that don't need to be public.
+ *
+ * Keeps all the internals out of pthread.h
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: Ross.Johnson@homemail.com.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#if !defined(_IMPLEMENT_H)
+#define _IMPLEMENT_H
+
+#if !defined(_WIN32_WINNT)
+#define _WIN32_WINNT 0x0400
+#endif
+
+#include <windows.h>
+
+/*
+ * In case windows.h doesn't define it (e.g. WinCE perhaps)
+ */
+#if defined(WINCE)
+typedef VOID (APIENTRY *PAPCFUNC)(DWORD dwParam);
+#endif
+
+/*
+ * note: ETIMEDOUT is correctly defined in winsock.h
+ */
+#include <winsock.h>
+
+/*
+ * In case ETIMEDOUT hasn't been defined above somehow.
+ */
+#if !defined(ETIMEDOUT)
+# define ETIMEDOUT 10060 /* This is the value in winsock.h. */
+#endif
+
+#if !defined(malloc)
+#include <malloc.h>
+#endif
+
+#if defined(__CLEANUP_C)
+# include <setjmp.h>
+#endif
+
+#if !defined(INT_MAX)
+#include <limits.h>
+#endif
+
+/* use local include files during development */
+#include "semaphore.h"
+#include "sched.h"
+
+#if defined(HAVE_C_INLINE) || defined(__cplusplus)
+#define INLINE inline
+#else
+#define INLINE
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1300
+/*
+ * MSVC 6 does not use the "volatile" qualifier
+ */
+#define PTW32_INTERLOCKED_VOLATILE
+#else
+#define PTW32_INTERLOCKED_VOLATILE volatile
+#endif
+#define PTW32_INTERLOCKED_LONG long
+#define PTW32_INTERLOCKED_SIZE size_t
+#define PTW32_INTERLOCKED_PVOID PVOID
+#define PTW32_INTERLOCKED_LONGPTR PTW32_INTERLOCKED_VOLATILE long*
+#define PTW32_INTERLOCKED_SIZEPTR PTW32_INTERLOCKED_VOLATILE size_t*
+#define PTW32_INTERLOCKED_PVOID_PTR PTW32_INTERLOCKED_VOLATILE PVOID*
+
+#if defined(__MINGW64__) || defined(__MINGW32__)
+# include <stdint.h>
+#elif defined(__BORLANDC__)
+# define int64_t ULONGLONG
+#else
+# define int64_t _int64
+# if defined(_MSC_VER) && _MSC_VER < 1300
+ typedef long intptr_t;
+# endif
+#endif
+
+typedef enum
+{
+ /*
+ * This enumeration represents the state of the thread;
+ * The thread is still "alive" if the numeric value of the
+ * state is greater or equal "PThreadStateRunning".
+ */
+ PThreadStateInitial = 0, /* Thread not running */
+ PThreadStateRunning, /* Thread alive & kicking */
+ PThreadStateSuspended, /* Thread alive but suspended */
+ PThreadStateCancelPending, /* Thread alive but */
+ /* has cancelation pending. */
+ PThreadStateCanceling, /* Thread alive but is */
+ /* in the process of terminating */
+ /* due to a cancellation request */
+ PThreadStateExiting, /* Thread alive but exiting */
+ /* due to an exception */
+ PThreadStateLast, /* All handlers have been run and now */
+ /* final cleanup can be done. */
+ PThreadStateReuse /* In reuse pool. */
+}
+PThreadState;
+
+typedef struct ptw32_mcs_node_t_ ptw32_mcs_local_node_t;
+typedef struct ptw32_mcs_node_t_* ptw32_mcs_lock_t;
+typedef struct ptw32_robust_node_t_ ptw32_robust_node_t;
+typedef struct ptw32_thread_t_ ptw32_thread_t;
+
+
+struct ptw32_thread_t_
+{
+ unsigned __int64 seqNumber; /* Process-unique thread sequence number */
+ HANDLE threadH; /* Win32 thread handle - POSIX thread is invalid if threadH == 0 */
+ pthread_t ptHandle; /* This thread's permanent pthread_t handle */
+ ptw32_thread_t * prevReuse; /* Links threads on reuse stack */
+ volatile PThreadState state;
+ ptw32_mcs_lock_t threadLock; /* Used for serialised access to public thread state */
+ ptw32_mcs_lock_t stateLock; /* Used for async-cancel safety */
+ HANDLE cancelEvent;
+ void *exitStatus;
+ void *parms;
+ void *keys;
+ void *nextAssoc;
+#if defined(__CLEANUP_C)
+ jmp_buf start_mark; /* Jump buffer follows void* so should be aligned */
+#endif /* __CLEANUP_C */
+#if defined(HAVE_SIGSET_T)
+ sigset_t sigmask;
+#endif /* HAVE_SIGSET_T */
+ ptw32_mcs_lock_t
+ robustMxListLock; /* robustMxList lock */
+ ptw32_robust_node_t*
+ robustMxList; /* List of currenty held robust mutexes */
+ int ptErrno;
+ int detachState;
+ int sched_priority; /* As set, not as currently is */
+ int cancelState;
+ int cancelType;
+ int implicit:1;
+ DWORD thread; /* Win32 thread ID */
+#if defined(_UWIN)
+ DWORD dummy[5];
+#endif
+ size_t align; /* Force alignment if this struct is packed */
+};
+
+
+/*
+ * Special value to mark attribute objects as valid.
+ */
+#define PTW32_ATTR_VALID ((unsigned long) 0xC4C0FFEE)
+
+struct pthread_attr_t_
+{
+ unsigned long valid;
+ void *stackaddr;
+ size_t stacksize;
+ int detachstate;
+ struct sched_param param;
+ int inheritsched;
+ int contentionscope;
+#if defined(HAVE_SIGSET_T)
+ sigset_t sigmask;
+#endif /* HAVE_SIGSET_T */
+};
+
+
+/*
+ * ====================
+ * ====================
+ * Semaphores, Mutexes and Condition Variables
+ * ====================
+ * ====================
+ */
+
+struct sem_t_
+{
+ int value;
+ pthread_mutex_t lock;
+ HANDLE sem;
+#if defined(NEED_SEM)
+ int leftToUnblock;
+#endif
+};
+
+#define PTW32_OBJECT_AUTO_INIT ((void *)(size_t) -1)
+#define PTW32_OBJECT_INVALID NULL
+
+struct pthread_mutex_t_
+{
+ LONG lock_idx; /* Provides exclusive access to mutex state
+ via the Interlocked* mechanism.
+ 0: unlocked/free.
+ 1: locked - no other waiters.
+ -1: locked - with possible other waiters.
+ */
+ int recursive_count; /* Number of unlocks a thread needs to perform
+ before the lock is released (recursive
+ mutexes only). */
+ int kind; /* Mutex type. */
+ pthread_t ownerThread;
+ HANDLE event; /* Mutex release notification to waiting
+ threads. */
+ ptw32_robust_node_t*
+ robustNode; /* Extra state for robust mutexes */
+};
+
+enum ptw32_robust_state_t_
+{
+ PTW32_ROBUST_CONSISTENT,
+ PTW32_ROBUST_INCONSISTENT,
+ PTW32_ROBUST_NOTRECOVERABLE
+};
+
+typedef enum ptw32_robust_state_t_ ptw32_robust_state_t;
+
+/*
+ * Node used to manage per-thread lists of currently-held robust mutexes.
+ */
+struct ptw32_robust_node_t_
+{
+ pthread_mutex_t mx;
+ ptw32_robust_state_t stateInconsistent;
+ ptw32_robust_node_t* prev;
+ ptw32_robust_node_t* next;
+};
+
+struct pthread_mutexattr_t_
+{
+ int pshared;
+ int kind;
+ int robustness;
+};
+
+/*
+ * Possible values, other than PTW32_OBJECT_INVALID,
+ * for the "interlock" element in a spinlock.
+ *
+ * In this implementation, when a spinlock is initialised,
+ * the number of cpus available to the process is checked.
+ * If there is only one cpu then "interlock" is set equal to
+ * PTW32_SPIN_USE_MUTEX and u.mutex is an initialised mutex.
+ * If the number of cpus is greater than 1 then "interlock"
+ * is set equal to PTW32_SPIN_UNLOCKED and the number is
+ * stored in u.cpus. This arrangement allows the spinlock
+ * routines to attempt an InterlockedCompareExchange on "interlock"
+ * immediately and, if that fails, to try the inferior mutex.
+ *
+ * "u.cpus" isn't used for anything yet, but could be used at
+ * some point to optimise spinlock behaviour.
+ */
+#define PTW32_SPIN_INVALID (0)
+#define PTW32_SPIN_UNLOCKED (1)
+#define PTW32_SPIN_LOCKED (2)
+#define PTW32_SPIN_USE_MUTEX (3)
+
+struct pthread_spinlock_t_
+{
+ long interlock; /* Locking element for multi-cpus. */
+ union
+ {
+ int cpus; /* No. of cpus if multi cpus, or */
+ pthread_mutex_t mutex; /* mutex if single cpu. */
+ } u;
+};
+
+/*
+ * MCS lock queue node - see ptw32_MCS_lock.c
+ */
+struct ptw32_mcs_node_t_
+{
+ struct ptw32_mcs_node_t_ **lock; /* ptr to tail of queue */
+ struct ptw32_mcs_node_t_ *next; /* ptr to successor in queue */
+ HANDLE readyFlag; /* set after lock is released by
+ predecessor */
+ HANDLE nextFlag; /* set after 'next' ptr is set by
+ successor */
+};
+
+
+struct pthread_barrier_t_
+{
+ unsigned int nCurrentBarrierHeight;
+ unsigned int nInitialBarrierHeight;
+ int pshared;
+ sem_t semBarrierBreeched;
+ ptw32_mcs_lock_t lock;
+ ptw32_mcs_local_node_t proxynode;
+};
+
+struct pthread_barrierattr_t_
+{
+ int pshared;
+};
+
+struct pthread_key_t_
+{
+ DWORD key;
+ void (PTW32_CDECL *destructor) (void *);
+ ptw32_mcs_lock_t keyLock;
+ void *threads;
+};
+
+
+typedef struct ThreadParms ThreadParms;
+
+struct ThreadParms
+{
+ pthread_t tid;
+ void *(PTW32_CDECL *start) (void *);
+ void *arg;
+};
+
+
+struct pthread_cond_t_
+{
+ long nWaitersBlocked; /* Number of threads blocked */
+ long nWaitersGone; /* Number of threads timed out */
+ long nWaitersToUnblock; /* Number of threads to unblock */
+ sem_t semBlockQueue; /* Queue up threads waiting for the */
+ /* condition to become signalled */
+ sem_t semBlockLock; /* Semaphore that guards access to */
+ /* | waiters blocked count/block queue */
+ /* +-> Mandatory Sync.LEVEL-1 */
+ pthread_mutex_t mtxUnblockLock; /* Mutex that guards access to */
+ /* | waiters (to)unblock(ed) counts */
+ /* +-> Optional* Sync.LEVEL-2 */
+ pthread_cond_t next; /* Doubly linked list */
+ pthread_cond_t prev;
+};
+
+
+struct pthread_condattr_t_
+{
+ int pshared;
+};
+
+#define PTW32_RWLOCK_MAGIC 0xfacade2
+
+struct pthread_rwlock_t_
+{
+ pthread_mutex_t mtxExclusiveAccess;
+ pthread_mutex_t mtxSharedAccessCompleted;
+ pthread_cond_t cndSharedAccessCompleted;
+ int nSharedAccessCount;
+ int nExclusiveAccessCount;
+ int nCompletedSharedAccessCount;
+ int nMagic;
+};
+
+struct pthread_rwlockattr_t_
+{
+ int pshared;
+};
+
+typedef struct ThreadKeyAssoc ThreadKeyAssoc;
+
+struct ThreadKeyAssoc
+{
+ /*
+ * Purpose:
+ * This structure creates an association between a thread and a key.
+ * It is used to implement the implicit invocation of a user defined
+ * destroy routine for thread specific data registered by a user upon
+ * exiting a thread.
+ *
+ * Graphically, the arrangement is as follows, where:
+ *
+ * K - Key with destructor
+ * (head of chain is key->threads)
+ * T - Thread that has called pthread_setspecific(Kn)
+ * (head of chain is thread->keys)
+ * A - Association. Each association is a node at the
+ * intersection of two doubly-linked lists.
+ *
+ * T1 T2 T3
+ * | | |
+ * | | |
+ * K1 -----+-----A-----A----->
+ * | | |
+ * | | |
+ * K2 -----A-----A-----+----->
+ * | | |
+ * | | |
+ * K3 -----A-----+-----A----->
+ * | | |
+ * | | |
+ * V V V
+ *
+ * Access to the association is guarded by two locks: the key's
+ * general lock (guarding the row) and the thread's general
+ * lock (guarding the column). This avoids the need for a
+ * dedicated lock for each association, which not only consumes
+ * more handles but requires that the lock resources persist
+ * until both the key is deleted and the thread has called the
+ * destructor. The two-lock arrangement allows those resources
+ * to be freed as soon as either thread or key is concluded.
+ *
+ * To avoid deadlock, whenever both locks are required both the
+ * key and thread locks are acquired consistently in the order
+ * "key lock then thread lock". An exception to this exists
+ * when a thread calls the destructors, however, this is done
+ * carefully (but inelegantly) to avoid deadlock.
+ *
+ * An association is created when a thread first calls
+ * pthread_setspecific() on a key that has a specified
+ * destructor.
+ *
+ * An association is destroyed either immediately after the
+ * thread calls the key destructor function on thread exit, or
+ * when the key is deleted.
+ *
+ * Attributes:
+ * thread
+ * reference to the thread that owns the
+ * association. This is actually the pointer to the
+ * thread struct itself. Since the association is
+ * destroyed before the thread exits, this can never
+ * point to a different logical thread to the one that
+ * created the assoc, i.e. after thread struct reuse.
+ *
+ * key
+ * reference to the key that owns the association.
+ *
+ * nextKey
+ * The pthread_t->keys attribute is the head of a
+ * chain of associations that runs through the nextKey
+ * link. This chain provides the 1 to many relationship
+ * between a pthread_t and all pthread_key_t on which
+ * it called pthread_setspecific.
+ *
+ * prevKey
+ * Similarly.
+ *
+ * nextThread
+ * The pthread_key_t->threads attribute is the head of
+ * a chain of associations that runs through the
+ * nextThreads link. This chain provides the 1 to many
+ * relationship between a pthread_key_t and all the
+ * PThreads that have called pthread_setspecific for
+ * this pthread_key_t.
+ *
+ * prevThread
+ * Similarly.
+ *
+ * Notes:
+ * 1) As soon as either the key or the thread is no longer
+ * referencing the association, it can be destroyed. The
+ * association will be removed from both chains.
+ *
+ * 2) Under WIN32, an association is only created by
+ * pthread_setspecific if the user provided a
+ * destroyRoutine when they created the key.
+ *
+ *
+ */
+ ptw32_thread_t * thread;
+ pthread_key_t key;
+ ThreadKeyAssoc *nextKey;
+ ThreadKeyAssoc *nextThread;
+ ThreadKeyAssoc *prevKey;
+ ThreadKeyAssoc *prevThread;
+};
+
+
+#if defined(__CLEANUP_SEH)
+/*
+ * --------------------------------------------------------------
+ * MAKE_SOFTWARE_EXCEPTION
+ * This macro constructs a software exception code following
+ * the same format as the standard Win32 error codes as defined
+ * in WINERROR.H
+ * Values are 32 bit values laid out as follows:
+ *
+ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +---+-+-+-----------------------+-------------------------------+
+ * |Sev|C|R| Facility | Code |
+ * +---+-+-+-----------------------+-------------------------------+
+ *
+ * Severity Values:
+ */
+#define SE_SUCCESS 0x00
+#define SE_INFORMATION 0x01
+#define SE_WARNING 0x02
+#define SE_ERROR 0x03
+
+#define MAKE_SOFTWARE_EXCEPTION( _severity, _facility, _exception ) \
+( (DWORD) ( ( (_severity) << 30 ) | /* Severity code */ \
+ ( 1 << 29 ) | /* MS=0, User=1 */ \
+ ( 0 << 28 ) | /* Reserved */ \
+ ( (_facility) << 16 ) | /* Facility Code */ \
+ ( (_exception) << 0 ) /* Exception Code */ \
+ ) )
+
+/*
+ * We choose one specific Facility/Error code combination to
+ * identify our software exceptions vs. WIN32 exceptions.
+ * We store our actual component and error code within
+ * the optional information array.
+ */
+#define EXCEPTION_PTW32_SERVICES \
+ MAKE_SOFTWARE_EXCEPTION( SE_ERROR, \
+ PTW32_SERVICES_FACILITY, \
+ PTW32_SERVICES_ERROR )
+
+#define PTW32_SERVICES_FACILITY 0xBAD
+#define PTW32_SERVICES_ERROR 0xDEED
+
+#endif /* __CLEANUP_SEH */
+
+/*
+ * Services available through EXCEPTION_PTW32_SERVICES
+ * and also used [as parameters to ptw32_throw()] as
+ * generic exception selectors.
+ */
+
+#define PTW32_EPS_EXIT (1)
+#define PTW32_EPS_CANCEL (2)
+
+
+/* Useful macros */
+#define PTW32_MAX(a,b) ((a)<(b)?(b):(a))
+#define PTW32_MIN(a,b) ((a)>(b)?(b):(a))
+
+
+/* Declared in pthread_cancel.c */
+extern DWORD (*ptw32_register_cancelation) (PAPCFUNC, HANDLE, DWORD);
+
+/* Thread Reuse stack bottom marker. Must not be NULL or any valid pointer to memory. */
+#define PTW32_THREAD_REUSE_EMPTY ((ptw32_thread_t *)(size_t) 1)
+
+extern int ptw32_processInitialized;
+extern ptw32_thread_t * ptw32_threadReuseTop;
+extern ptw32_thread_t * ptw32_threadReuseBottom;
+extern pthread_key_t ptw32_selfThreadKey;
+extern pthread_key_t ptw32_cleanupKey;
+extern pthread_cond_t ptw32_cond_list_head;
+extern pthread_cond_t ptw32_cond_list_tail;
+
+extern int ptw32_mutex_default_kind;
+
+extern unsigned __int64 ptw32_threadSeqNumber;
+
+extern int ptw32_concurrency;
+
+extern int ptw32_features;
+
+extern ptw32_mcs_lock_t ptw32_thread_reuse_lock;
+extern ptw32_mcs_lock_t ptw32_mutex_test_init_lock;
+extern ptw32_mcs_lock_t ptw32_cond_list_lock;
+extern ptw32_mcs_lock_t ptw32_cond_test_init_lock;
+extern ptw32_mcs_lock_t ptw32_rwlock_test_init_lock;
+extern ptw32_mcs_lock_t ptw32_spinlock_test_init_lock;
+
+#if defined(_UWIN)
+extern int pthread_count;
+#endif
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif /* __cplusplus */
+
+/*
+ * =====================
+ * =====================
+ * Forward Declarations
+ * =====================
+ * =====================
+ */
+
+ int ptw32_is_attr (const pthread_attr_t * attr);
+
+ int ptw32_cond_check_need_init (pthread_cond_t * cond);
+ int ptw32_mutex_check_need_init (pthread_mutex_t * mutex);
+ int ptw32_rwlock_check_need_init (pthread_rwlock_t * rwlock);
+
+ int ptw32_robust_mutex_inherit(pthread_mutex_t * mutex);
+ void ptw32_robust_mutex_add(pthread_mutex_t* mutex, pthread_t self);
+ void ptw32_robust_mutex_remove(pthread_mutex_t* mutex, ptw32_thread_t* otp);
+
+ DWORD
+ ptw32_RegisterCancelation (PAPCFUNC callback,
+ HANDLE threadH, DWORD callback_arg);
+
+ int ptw32_processInitialize (void);
+
+ void ptw32_processTerminate (void);
+
+ void ptw32_threadDestroy (pthread_t tid);
+
+ void ptw32_pop_cleanup_all (int execute);
+
+ pthread_t ptw32_new (void);
+
+ pthread_t ptw32_threadReusePop (void);
+
+ void ptw32_threadReusePush (pthread_t thread);
+
+ int ptw32_getprocessors (int *count);
+
+ int ptw32_setthreadpriority (pthread_t thread, int policy, int priority);
+
+ void ptw32_rwlock_cancelwrwait (void *arg);
+
+#if ! (defined (__MINGW64__) || defined(__MINGW32__)) || (defined(__MSVCRT__) && ! defined(__DMC__))
+ unsigned __stdcall
+#else
+ void
+#endif
+ ptw32_threadStart (void *vthreadParms);
+
+ void ptw32_callUserDestroyRoutines (pthread_t thread);
+
+ int ptw32_tkAssocCreate (ptw32_thread_t * thread, pthread_key_t key);
+
+ void ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc);
+
+ int ptw32_semwait (sem_t * sem);
+
+ DWORD ptw32_relmillisecs (const struct timespec * abstime);
+
+ void ptw32_mcs_lock_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node);
+
+ int ptw32_mcs_lock_try_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node);
+
+ void ptw32_mcs_lock_release (ptw32_mcs_local_node_t * node);
+
+ void ptw32_mcs_node_transfer (ptw32_mcs_local_node_t * new_node, ptw32_mcs_local_node_t * old_node);
+
+#if defined(NEED_FTIME)
+ void ptw32_timespec_to_filetime (const struct timespec *ts, FILETIME * ft);
+ void ptw32_filetime_to_timespec (const FILETIME * ft, struct timespec *ts);
+#endif
+
+/* Declared in misc.c */
+#if defined(NEED_CALLOC)
+#define calloc(n, s) ptw32_calloc(n, s)
+ void *ptw32_calloc (size_t n, size_t s);
+#endif
+
+/* Declared in private.c */
+#if defined(_MSC_VER)
+/*
+ * Ignore the warning:
+ * "C++ exception specification ignored except to indicate that
+ * the function is not __declspec(nothrow)."
+ */
+#pragma warning(disable:4290)
+#endif
+ void ptw32_throw (DWORD exception)
+#if defined(__CLEANUP_CXX)
+ throw(ptw32_exception_cancel,ptw32_exception_exit)
+#endif
+;
+
+#if defined(__cplusplus)
+}
+#endif /* __cplusplus */
+
+
+#if defined(_UWIN_)
+# if defined(_MT)
+# if defined(__cplusplus)
+extern "C"
+{
+# endif
+ _CRTIMP unsigned long __cdecl _beginthread (void (__cdecl *) (void *),
+ unsigned, void *);
+ _CRTIMP void __cdecl _endthread (void);
+ _CRTIMP unsigned long __cdecl _beginthreadex (void *, unsigned,
+ unsigned (__stdcall *) (void *),
+ void *, unsigned, unsigned *);
+ _CRTIMP void __cdecl _endthreadex (unsigned);
+# if defined(__cplusplus)
+}
+# endif
+# endif
+#else
+# include <process.h>
+# endif
+
+
+/*
+ * Use intrinsic versions wherever possible. VC will do this
+ * automatically where possible and GCC define these if available:
+ * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
+ * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
+ * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
+ * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
+ * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
+ *
+ * The full set of Interlocked intrinsics in GCC are (check versions):
+ * type __sync_fetch_and_add (type *ptr, type value, ...)
+ * type __sync_fetch_and_sub (type *ptr, type value, ...)
+ * type __sync_fetch_and_or (type *ptr, type value, ...)
+ * type __sync_fetch_and_and (type *ptr, type value, ...)
+ * type __sync_fetch_and_xor (type *ptr, type value, ...)
+ * type __sync_fetch_and_nand (type *ptr, type value, ...)
+ * type __sync_add_and_fetch (type *ptr, type value, ...)
+ * type __sync_sub_and_fetch (type *ptr, type value, ...)
+ * type __sync_or_and_fetch (type *ptr, type value, ...)
+ * type __sync_and_and_fetch (type *ptr, type value, ...)
+ * type __sync_xor_and_fetch (type *ptr, type value, ...)
+ * type __sync_nand_and_fetch (type *ptr, type value, ...)
+ * bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)
+ * type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)
+ * __sync_synchronize (...) // Full memory barrier
+ * type __sync_lock_test_and_set (type *ptr, type value, ...) // Acquire barrier
+ * void __sync_lock_release (type *ptr, ...) // Release barrier
+ *
+ * These are all overloaded and take 1,2,4,8 byte scalar or pointer types.
+ *
+ * The above aren't available in Mingw32 as of gcc 4.5.2 so define our own.
+ */
+#if defined(__GNUC__)
+# if defined(_WIN64)
+# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_64(location, value, comparand) \
+ ({ \
+ __typeof (value) _result; \
+ __asm__ __volatile__ \
+ ( \
+ "lock\n\t" \
+ "cmpxchgq %2,(%1)" \
+ :"=a" (_result) \
+ :"r" (location), "r" (value), "a" (comparand) \
+ :"memory", "cc"); \
+ _result; \
+ })
+# define PTW32_INTERLOCKED_EXCHANGE_64(location, value) \
+ ({ \
+ __typeof (value) _result; \
+ __asm__ __volatile__ \
+ ( \
+ "xchgq %0,(%1)" \
+ :"=r" (_result) \
+ :"r" (location), "0" (value) \
+ :"memory", "cc"); \
+ _result; \
+ })
+# define PTW32_INTERLOCKED_EXCHANGE_ADD_64(location, value) \
+ ({ \
+ __typeof (value) _result; \
+ __asm__ __volatile__ \
+ ( \
+ "lock\n\t" \
+ "xaddq %0,(%1)" \
+ :"=r" (_result) \
+ :"r" (location), "0" (value) \
+ :"memory", "cc"); \
+ _result; \
+ })
+# define PTW32_INTERLOCKED_INCREMENT_64(location) \
+ ({ \
+ PTW32_INTERLOCKED_LONG _temp = 1; \
+ __asm__ __volatile__ \
+ ( \
+ "lock\n\t" \
+ "xaddq %0,(%1)" \
+ :"+r" (_temp) \
+ :"r" (location) \
+ :"memory", "cc"); \
+ ++_temp; \
+ })
+# define PTW32_INTERLOCKED_DECREMENT_64(location) \
+ ({ \
+ PTW32_INTERLOCKED_LONG _temp = -1; \
+ __asm__ __volatile__ \
+ ( \
+ "lock\n\t" \
+ "xaddq %2,(%1)" \
+ :"+r" (_temp) \
+ :"r" (location) \
+ :"memory", "cc"); \
+ --_temp; \
+ })
+#endif
+# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(location, value, comparand) \
+ ({ \
+ __typeof (value) _result; \
+ __asm__ __volatile__ \
+ ( \
+ "lock\n\t" \
+ "cmpxchgl %2,(%1)" \
+ :"=a" (_result) \
+ :"r" (location), "r" (value), "a" (comparand) \
+ :"memory", "cc"); \
+ _result; \
+ })
+# define PTW32_INTERLOCKED_EXCHANGE_LONG(location, value) \
+ ({ \
+ __typeof (value) _result; \
+ __asm__ __volatile__ \
+ ( \
+ "xchgl %0,(%1)" \
+ :"=r" (_result) \
+ :"r" (location), "0" (value) \
+ :"memory", "cc"); \
+ _result; \
+ })
+# define PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(location, value) \
+ ({ \
+ __typeof (value) _result; \
+ __asm__ __volatile__ \
+ ( \
+ "lock\n\t" \
+ "xaddl %0,(%1)" \
+ :"=r" (_result) \
+ :"r" (location), "0" (value) \
+ :"memory", "cc"); \
+ _result; \
+ })
+# define PTW32_INTERLOCKED_INCREMENT_LONG(location) \
+ ({ \
+ PTW32_INTERLOCKED_LONG _temp = 1; \
+ __asm__ __volatile__ \
+ ( \
+ "lock\n\t" \
+ "xaddl %0,(%1)" \
+ :"+r" (_temp) \
+ :"r" (location) \
+ :"memory", "cc"); \
+ ++_temp; \
+ })
+# define PTW32_INTERLOCKED_DECREMENT_LONG(location) \
+ ({ \
+ PTW32_INTERLOCKED_LONG _temp = -1; \
+ __asm__ __volatile__ \
+ ( \
+ "lock\n\t" \
+ "xaddl %0,(%1)" \
+ :"+r" (_temp) \
+ :"r" (location) \
+ :"memory", "cc"); \
+ --_temp; \
+ })
+# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR(location, value, comparand) \
+ PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE((PTW32_INTERLOCKED_SIZEPTR)location, \
+ (PTW32_INTERLOCKED_SIZE)value, \
+ (PTW32_INTERLOCKED_SIZE)comparand)
+# define PTW32_INTERLOCKED_EXCHANGE_PTR(location, value) \
+ PTW32_INTERLOCKED_EXCHANGE_SIZE((PTW32_INTERLOCKED_SIZEPTR)location, \
+ (PTW32_INTERLOCKED_SIZE)value)
+#else
+# if defined(_WIN64)
+# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_64 InterlockedCompareExchange64
+# define PTW32_INTERLOCKED_EXCHANGE_64 InterlockedExchange64
+# define PTW32_INTERLOCKED_EXCHANGE_ADD_64 InterlockedExchangeAdd64
+# define PTW32_INTERLOCKED_INCREMENT_64 InterlockedIncrement64
+# define PTW32_INTERLOCKED_DECREMENT_64 InterlockedDecrement64
+# endif
+# if defined(_MSC_VER) && _MSC_VER < 1300 && !defined(_WIN64) /* MSVC 6 */
+# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(location, value, comparand) \
+ ((LONG)InterlockedCompareExchange((PVOID *)(location), (PVOID)(value), (PVOID)(comparand)))
+# else
+# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG InterlockedCompareExchange
+# endif
+# define PTW32_INTERLOCKED_EXCHANGE_LONG InterlockedExchange
+# define PTW32_INTERLOCKED_EXCHANGE_ADD_LONG InterlockedExchangeAdd
+# define PTW32_INTERLOCKED_INCREMENT_LONG InterlockedIncrement
+# define PTW32_INTERLOCKED_DECREMENT_LONG InterlockedDecrement
+# if defined(_MSC_VER) && _MSC_VER < 1300 && !defined(_WIN64) /* MSVC 6 */
+# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR InterlockedCompareExchange
+# define PTW32_INTERLOCKED_EXCHANGE_PTR(location, value) \
+ ((PVOID)InterlockedExchange((LPLONG)(location), (LONG)(value)))
+# else
+# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR InterlockedCompareExchangePointer
+# define PTW32_INTERLOCKED_EXCHANGE_PTR InterlockedExchangePointer
+# endif
+#endif
+#if defined(_WIN64)
+# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE PTW32_INTERLOCKED_COMPARE_EXCHANGE_64
+# define PTW32_INTERLOCKED_EXCHANGE_SIZE PTW32_INTERLOCKED_EXCHANGE_64
+# define PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE PTW32_INTERLOCKED_EXCHANGE_ADD_64
+# define PTW32_INTERLOCKED_INCREMENT_SIZE PTW32_INTERLOCKED_INCREMENT_64
+# define PTW32_INTERLOCKED_DECREMENT_SIZE PTW32_INTERLOCKED_DECREMENT_64
+#else
+# define PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG
+# define PTW32_INTERLOCKED_EXCHANGE_SIZE PTW32_INTERLOCKED_EXCHANGE_LONG
+# define PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE PTW32_INTERLOCKED_EXCHANGE_ADD_LONG
+# define PTW32_INTERLOCKED_INCREMENT_SIZE PTW32_INTERLOCKED_INCREMENT_LONG
+# define PTW32_INTERLOCKED_DECREMENT_SIZE PTW32_INTERLOCKED_DECREMENT_LONG
+#endif
+
+#if defined(NEED_CREATETHREAD)
+
+/*
+ * Macro uses args so we can cast start_proc to LPTHREAD_START_ROUTINE
+ * in order to avoid warnings because of return type
+ */
+
+#define _beginthreadex(security, \
+ stack_size, \
+ start_proc, \
+ arg, \
+ flags, \
+ pid) \
+ CreateThread(security, \
+ stack_size, \
+ (LPTHREAD_START_ROUTINE) start_proc, \
+ arg, \
+ flags, \
+ pid)
+
+#define _endthreadex ExitThread
+
+#endif /* NEED_CREATETHREAD */
+
+
+#endif /* _IMPLEMENT_H */
diff --git a/libs/pthreads/src/misc.c b/libs/pthreads/src/misc.c
new file mode 100644
index 0000000000..06d1d21374
--- /dev/null
+++ b/libs/pthreads/src/misc.c
@@ -0,0 +1,50 @@
+/*
+ * misc.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#include "pthread_kill.c"
+#include "pthread_once.c"
+#include "pthread_self.c"
+#include "pthread_equal.c"
+#include "pthread_setconcurrency.c"
+#include "pthread_getconcurrency.c"
+#include "ptw32_new.c"
+#include "ptw32_calloc.c"
+#include "ptw32_reuse.c"
+#include "w32_CancelableWait.c"
diff --git a/libs/pthreads/src/mutex.c b/libs/pthreads/src/mutex.c
new file mode 100644
index 0000000000..c2b3607ca2
--- /dev/null
+++ b/libs/pthreads/src/mutex.c
@@ -0,0 +1,62 @@
+/*
+ * mutex.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#if ! defined(_UWIN) && ! defined(WINCE)
+# include <process.h>
+#endif
+#if !defined(NEED_FTIME)
+#include <sys/timeb.h>
+#endif
+#include "pthread.h"
+#include "implement.h"
+
+
+#include "ptw32_mutex_check_need_init.c"
+#include "pthread_mutex_init.c"
+#include "pthread_mutex_destroy.c"
+#include "pthread_mutexattr_init.c"
+#include "pthread_mutexattr_destroy.c"
+#include "pthread_mutexattr_getpshared.c"
+#include "pthread_mutexattr_setpshared.c"
+#include "pthread_mutexattr_settype.c"
+#include "pthread_mutexattr_gettype.c"
+#include "pthread_mutexattr_setrobust.c"
+#include "pthread_mutexattr_getrobust.c"
+#include "pthread_mutex_lock.c"
+#include "pthread_mutex_timedlock.c"
+#include "pthread_mutex_unlock.c"
+#include "pthread_mutex_trylock.c"
+#include "pthread_mutex_consistent.c"
diff --git a/libs/pthreads/src/need_errno.h b/libs/pthreads/src/need_errno.h
new file mode 100644
index 0000000000..abf1c95574
--- /dev/null
+++ b/libs/pthreads/src/need_errno.h
@@ -0,0 +1,145 @@
+/***
+* errno.h - system wide error numbers (set by system calls)
+*
+* Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
+*
+* Purpose:
+* This file defines the system-wide error numbers (set by
+* system calls). Conforms to the XENIX standard. Extended
+* for compatibility with Uniforum standard.
+* [System V]
+*
+* [Public]
+*
+****/
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#if !defined(_INC_ERRNO)
+#define _INC_ERRNO
+
+#if !defined(_WIN32)
+#error ERROR: Only Win32 targets supported!
+#endif
+
+#include <winsock.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+
+/* Define _CRTIMP */
+
+#ifndef _CRTIMP
+#if defined(_DLL)
+#define _CRTIMP __declspec(dllimport)
+#else /* ndef _DLL */
+#define _CRTIMP
+#endif /* _DLL */
+#endif /* _CRTIMP */
+
+
+/* Define __cdecl for non-Microsoft compilers */
+
+#if ( !defined(_MSC_VER) && !defined(__cdecl) )
+#define __cdecl
+#endif
+
+/* Define _CRTAPI1 (for compatibility with the NT SDK) */
+
+#if !defined(_CRTAPI1)
+#if _MSC_VER >= 800 && _M_IX86 >= 300
+#define _CRTAPI1 __cdecl
+#else
+#define _CRTAPI1
+#endif
+#endif
+
+#if !defined(PTW32_STATIC_LIB)
+# if defined(PTW32_BUILD)
+# define PTW32_DLLPORT __declspec (dllexport)
+# else
+# define PTW32_DLLPORT __declspec (dllimport)
+# endif
+#else
+# define PTW32_DLLPORT
+#endif
+
+/* declare reference to errno */
+
+#if (defined(_MT) || defined(_MD) || defined(_DLL)) && !defined(_MAC)
+PTW32_DLLPORT int * __cdecl _errno(void);
+#define errno (*_errno())
+#else /* ndef _MT && ndef _MD && ndef _DLL */
+_CRTIMP extern int errno;
+#endif /* _MT || _MD || _DLL */
+
+/* Error Codes */
+
+#define EPERM 1
+#define ENOENT 2
+#define ESRCH 3
+#define EINTR 4
+#define EIO 5
+#define ENXIO 6
+#define E2BIG 7
+#define ENOEXEC 8
+#define EBADF 9
+#define ECHILD 10
+#define EAGAIN 11
+#define ENOMEM 12
+#define EACCES 13
+#define EFAULT 14
+#define EBUSY 16
+#define EEXIST 17
+#define EXDEV 18
+#define ENODEV 19
+#define ENOTDIR 20
+#define EISDIR 21
+#define EINVAL 22
+#define ENFILE 23
+#define EMFILE 24
+#define ENOTTY 25
+#define EFBIG 27
+#define ENOSPC 28
+#define ESPIPE 29
+#define EROFS 30
+#define EMLINK 31
+#define EPIPE 32
+#define EDOM 33
+#define ERANGE 34
+#define EDEADLK 36
+
+/* defined differently in winsock.h on WinCE */
+#if !defined(ENAMETOOLONG)
+#define ENAMETOOLONG 38
+#endif
+
+#define ENOLCK 39
+#define ENOSYS 40
+
+/* defined differently in winsock.h on WinCE */
+#if !defined(ENOTEMPTY)
+#define ENOTEMPTY 41
+#endif
+
+#define EILSEQ 42
+
+/* POSIX 2008 - robust mutexes */
+#define EOWNERDEAD 43
+#define ENOTRECOVERABLE 44
+
+/*
+ * Support EDEADLOCK for compatibiity with older MS-C versions.
+ */
+#define EDEADLOCK EDEADLK
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* _INC_ERRNO */
diff --git a/libs/pthreads/src/nonportable.c b/libs/pthreads/src/nonportable.c
new file mode 100644
index 0000000000..742cb969b4
--- /dev/null
+++ b/libs/pthreads/src/nonportable.c
@@ -0,0 +1,47 @@
+/*
+ * nonportable.c
+ *
+ * Description:
+ * This translation unit implements non-portable thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+#include "pthread_mutexattr_setkind_np.c"
+#include "pthread_mutexattr_getkind_np.c"
+#include "pthread_getw32threadhandle_np.c"
+#include "pthread_getunique_np.c"
+#include "pthread_delay_np.c"
+#include "pthread_num_processors_np.c"
+#include "pthread_win32_attach_detach_np.c"
+#include "pthread_timechange_handler_np.c"
diff --git a/libs/pthreads/src/private.c b/libs/pthreads/src/private.c
new file mode 100644
index 0000000000..1b1ccb7c52
--- /dev/null
+++ b/libs/pthreads/src/private.c
@@ -0,0 +1,54 @@
+/*
+ * private.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+#include "ptw32_MCS_lock.c"
+#include "ptw32_is_attr.c"
+#include "ptw32_processInitialize.c"
+#include "ptw32_processTerminate.c"
+#include "ptw32_threadStart.c"
+#include "ptw32_threadDestroy.c"
+#include "ptw32_tkAssocCreate.c"
+#include "ptw32_tkAssocDestroy.c"
+#include "ptw32_callUserDestroyRoutines.c"
+#include "ptw32_semwait.c"
+#include "ptw32_timespec.c"
+#include "ptw32_relmillisecs.c"
+#include "ptw32_throw.c"
+#include "ptw32_getprocessors.c"
diff --git a/libs/pthreads/src/pthread.c b/libs/pthreads/src/pthread.c
new file mode 100644
index 0000000000..60b53412be
--- /dev/null
+++ b/libs/pthreads/src/pthread.c
@@ -0,0 +1,66 @@
+/*
+ * pthread.c
+ *
+ * Description:
+ * This translation unit agregates pthreads-win32 translation units.
+ * It is used for inline optimisation of the library,
+ * maximising for speed at the expense of size.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/* The following are ordered for inlining */
+
+#include "private.c"
+#include "attr.c"
+#include "barrier.c"
+#include "cancel.c"
+#include "cleanup.c"
+#include "condvar.c"
+#include "create.c"
+#include "dll.c"
+#include "autostatic.c"
+#include "errno.c"
+#include "exit.c"
+#include "fork.c"
+#include "global.c"
+#include "misc.c"
+#include "mutex.c"
+#include "nonportable.c"
+#include "rwlock.c"
+#include "sched.c"
+#include "semaphore.c"
+#include "signal.c"
+#include "spin.c"
+#include "sync.c"
+#include "tsd.c"
diff --git a/libs/pthreads/src/pthread.h b/libs/pthreads/src/pthread.h
new file mode 100644
index 0000000000..32ff72bb54
--- /dev/null
+++ b/libs/pthreads/src/pthread.h
@@ -0,0 +1,1368 @@
+/* This is an implementation of the threads API of POSIX 1003.1-2001.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#if !defined( PTHREAD_H )
+#define PTHREAD_H
+
+/*
+ * See the README file for an explanation of the pthreads-win32 version
+ * numbering scheme and how the DLL is named etc.
+ */
+#define PTW32_VERSION 2,9,1,0
+#define PTW32_VERSION_STRING "2, 9, 1, 0\0"
+
+/* There are three implementations of cancel cleanup.
+ * Note that pthread.h is included in both application
+ * compilation units and also internally for the library.
+ * The code here and within the library aims to work
+ * for all reasonable combinations of environments.
+ *
+ * The three implementations are:
+ *
+ * WIN32 SEH
+ * C
+ * C++
+ *
+ * Please note that exiting a push/pop block via
+ * "return", "exit", "break", or "continue" will
+ * lead to different behaviour amongst applications
+ * depending upon whether the library was built
+ * using SEH, C++, or C. For example, a library built
+ * with SEH will call the cleanup routine, while both
+ * C++ and C built versions will not.
+ */
+
+/*
+ * Define defaults for cleanup code.
+ * Note: Unless the build explicitly defines one of the following, then
+ * we default to standard C style cleanup. This style uses setjmp/longjmp
+ * in the cancelation and thread exit implementations and therefore won't
+ * do stack unwinding if linked to applications that have it (e.g.
+ * C++ apps). This is currently consistent with most/all commercial Unix
+ * POSIX threads implementations.
+ */
+#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C )
+# define __CLEANUP_C
+#endif
+
+#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC))
+#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler.
+#endif
+
+/*
+ * Stop here if we are being included by the resource compiler.
+ */
+#if !defined(RC_INVOKED)
+
+#undef PTW32_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_LEVEL_MAX 3
+
+#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_LEVEL)
+#define PTW32_LEVEL PTW32_LEVEL_MAX
+/* Include everything */
+#endif
+
+#if defined(_UWIN)
+# define HAVE_STRUCT_TIMESPEC 1
+# define HAVE_SIGNAL_H 1
+# undef HAVE_PTW32_CONFIG_H
+# pragma comment(lib, "pthread")
+#endif
+
+/*
+ * -------------------------------------------------------------
+ *
+ *
+ * Module: pthread.h
+ *
+ * Purpose:
+ * Provides an implementation of PThreads based upon the
+ * standard:
+ *
+ * POSIX 1003.1-2001
+ * and
+ * The Single Unix Specification version 3
+ *
+ * (these two are equivalent)
+ *
+ * in order to enhance code portability between Windows,
+ * various commercial Unix implementations, and Linux.
+ *
+ * See the ANNOUNCE file for a full list of conforming
+ * routines and defined constants, and a list of missing
+ * routines and constants not defined in this implementation.
+ *
+ * Authors:
+ * There have been many contributors to this library.
+ * The initial implementation was contributed by
+ * John Bossom, and several others have provided major
+ * sections or revisions of parts of the implementation.
+ * Often significant effort has been contributed to
+ * find and fix important bugs and other problems to
+ * improve the reliability of the library, which sometimes
+ * is not reflected in the amount of code which changed as
+ * result.
+ * As much as possible, the contributors are acknowledged
+ * in the ChangeLog file in the source code distribution
+ * where their changes are noted in detail.
+ *
+ * Contributors are listed in the CONTRIBUTORS file.
+ *
+ * As usual, all bouquets go to the contributors, and all
+ * brickbats go to the project maintainer.
+ *
+ * Maintainer:
+ * The code base for this project is coordinated and
+ * eventually pre-tested, packaged, and made available by
+ *
+ * Ross Johnson <rpj@callisto.canberra.edu.au>
+ *
+ * QA Testers:
+ * Ultimately, the library is tested in the real world by
+ * a host of competent and demanding scientists and
+ * engineers who report bugs and/or provide solutions
+ * which are then fixed or incorporated into subsequent
+ * versions of the library. Each time a bug is fixed, a
+ * test case is written to prove the fix and ensure
+ * that later changes to the code don't reintroduce the
+ * same error. The number of test cases is slowly growing
+ * and therefore so is the code reliability.
+ *
+ * Compliance:
+ * See the file ANNOUNCE for the list of implemented
+ * and not-implemented routines and defined options.
+ * Of course, these are all defined is this file as well.
+ *
+ * Web site:
+ * The source code and other information about this library
+ * are available from
+ *
+ * http://sources.redhat.com/pthreads-win32/
+ *
+ * -------------------------------------------------------------
+ */
+
+/* Try to avoid including windows.h */
+#if (defined(__MINGW64__) || defined(__MINGW32__)) && defined(__cplusplus)
+#define PTW32_INCLUDE_WINDOWS_H
+#endif
+
+#if defined(PTW32_INCLUDE_WINDOWS_H)
+#include <windows.h>
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__)
+/*
+ * VC++6.0 or early compiler's header has no DWORD_PTR type.
+ */
+typedef unsigned long DWORD_PTR;
+typedef unsigned long ULONG_PTR;
+#endif
+/*
+ * -----------------
+ * autoconf switches
+ * -----------------
+ */
+
+#if defined(HAVE_PTW32_CONFIG_H)
+#include "config.h"
+#endif /* HAVE_PTW32_CONFIG_H */
+
+#if !defined(NEED_FTIME)
+#include <time.h>
+#else /* NEED_FTIME */
+/* use native WIN32 time API */
+#endif /* NEED_FTIME */
+
+#if defined(HAVE_SIGNAL_H)
+#include <signal.h>
+#endif /* HAVE_SIGNAL_H */
+
+#include <limits.h>
+
+/*
+ * Boolean values to make us independent of system includes.
+ */
+enum {
+ PTW32_FALSE = 0,
+ PTW32_TRUE = (! PTW32_FALSE)
+};
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#if !defined(PTW32_CONFIG_H)
+# if defined(WINCE)
+# define NEED_ERRNO
+# define NEED_SEM
+# endif
+# if defined(_MSC_VER) || defined(__MINGW64__)
+# define HAVE_STRUCT_TIMESPEC
+# define HAVE_MODE_T
+# elif defined(_UWIN) || defined(__MINGW32__)
+# define HAVE_MODE_T
+# endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+#if defined(NEED_ERRNO)
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Several systems don't define some error numbers.
+ */
+#if !defined(ENOTSUP)
+# define ENOTSUP 48 /* This is the value in Solaris. */
+#endif
+
+#if !defined(ETIMEDOUT)
+# define ETIMEDOUT 10060 /* Same as WSAETIMEDOUT */
+#endif
+
+#if !defined(ENOSYS)
+# define ENOSYS 140 /* Semi-arbitrary value */
+#endif
+
+#if !defined(EDEADLK)
+# if defined(EDEADLOCK)
+# define EDEADLK EDEADLOCK
+# else
+# define EDEADLK 36 /* This is the value in MSVC. */
+# endif
+#endif
+
+/* POSIX 2008 - related to robust mutexes */
+#if !defined(EOWNERDEAD)
+# define EOWNERDEAD 43
+#endif
+#if !defined(ENOTRECOVERABLE)
+# define ENOTRECOVERABLE 44
+#endif
+
+#include <sched.h>
+
+/*
+ * To avoid including windows.h we define only those things that we
+ * actually need from it.
+ */
+#if !defined(PTW32_INCLUDE_WINDOWS_H)
+#if !defined(HANDLE)
+# define PTW32__HANDLE_DEF
+# define HANDLE void *
+#endif
+#if !defined(DWORD)
+# define PTW32__DWORD_DEF
+# define DWORD unsigned long
+#endif
+#endif
+
+#if !defined(HAVE_STRUCT_TIMESPEC)
+#define HAVE_STRUCT_TIMESPEC
+#if !defined(_TIMESPEC_DEFINED)
+#define _TIMESPEC_DEFINED
+struct timespec {
+ time_t tv_sec;
+ long tv_nsec;
+};
+#endif /* _TIMESPEC_DEFINED */
+#endif /* HAVE_STRUCT_TIMESPEC */
+
+#if !defined(SIG_BLOCK)
+#define SIG_BLOCK 0
+#endif /* SIG_BLOCK */
+
+#if !defined(SIG_UNBLOCK)
+#define SIG_UNBLOCK 1
+#endif /* SIG_UNBLOCK */
+
+#if !defined(SIG_SETMASK)
+#define SIG_SETMASK 2
+#endif /* SIG_SETMASK */
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif /* __cplusplus */
+
+/*
+ * -------------------------------------------------------------
+ *
+ * POSIX 1003.1-2001 Options
+ * =========================
+ *
+ * Options are normally set in <unistd.h>, which is not provided
+ * with pthreads-win32.
+ *
+ * For conformance with the Single Unix Specification (version 3), all of the
+ * options below are defined, and have a value of either -1 (not supported)
+ * or 200112L (supported).
+ *
+ * These options can neither be left undefined nor have a value of 0, because
+ * either indicates that sysconf(), which is not implemented, may be used at
+ * runtime to check the status of the option.
+ *
+ * _POSIX_THREADS (== 200112L)
+ * If == 200112L, you can use threads
+ *
+ * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L)
+ * If == 200112L, you can control the size of a thread's
+ * stack
+ * pthread_attr_getstacksize
+ * pthread_attr_setstacksize
+ *
+ * _POSIX_THREAD_ATTR_STACKADDR (== -1)
+ * If == 200112L, you can allocate and control a thread's
+ * stack. If not supported, the following functions
+ * will return ENOSYS, indicating they are not
+ * supported:
+ * pthread_attr_getstackaddr
+ * pthread_attr_setstackaddr
+ *
+ * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1)
+ * If == 200112L, you can use realtime scheduling.
+ * This option indicates that the behaviour of some
+ * implemented functions conforms to the additional TPS
+ * requirements in the standard. E.g. rwlocks favour
+ * writers over readers when threads have equal priority.
+ *
+ * _POSIX_THREAD_PRIO_INHERIT (== -1)
+ * If == 200112L, you can create priority inheritance
+ * mutexes.
+ * pthread_mutexattr_getprotocol +
+ * pthread_mutexattr_setprotocol +
+ *
+ * _POSIX_THREAD_PRIO_PROTECT (== -1)
+ * If == 200112L, you can create priority ceiling mutexes
+ * Indicates the availability of:
+ * pthread_mutex_getprioceiling
+ * pthread_mutex_setprioceiling
+ * pthread_mutexattr_getprioceiling
+ * pthread_mutexattr_getprotocol +
+ * pthread_mutexattr_setprioceiling
+ * pthread_mutexattr_setprotocol +
+ *
+ * _POSIX_THREAD_PROCESS_SHARED (== -1)
+ * If set, you can create mutexes and condition
+ * variables that can be shared with another
+ * process.If set, indicates the availability
+ * of:
+ * pthread_mutexattr_getpshared
+ * pthread_mutexattr_setpshared
+ * pthread_condattr_getpshared
+ * pthread_condattr_setpshared
+ *
+ * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L)
+ * If == 200112L you can use the special *_r library
+ * functions that provide thread-safe behaviour
+ *
+ * _POSIX_READER_WRITER_LOCKS (== 200112L)
+ * If == 200112L, you can use read/write locks
+ *
+ * _POSIX_SPIN_LOCKS (== 200112L)
+ * If == 200112L, you can use spin locks
+ *
+ * _POSIX_BARRIERS (== 200112L)
+ * If == 200112L, you can use barriers
+ *
+ * + These functions provide both 'inherit' and/or
+ * 'protect' protocol, based upon these macro
+ * settings.
+ *
+ * -------------------------------------------------------------
+ */
+
+/*
+ * POSIX Options
+ */
+#undef _POSIX_THREADS
+#define _POSIX_THREADS 200809L
+
+#undef _POSIX_READER_WRITER_LOCKS
+#define _POSIX_READER_WRITER_LOCKS 200809L
+
+#undef _POSIX_SPIN_LOCKS
+#define _POSIX_SPIN_LOCKS 200809L
+
+#undef _POSIX_BARRIERS
+#define _POSIX_BARRIERS 200809L
+
+#undef _POSIX_THREAD_SAFE_FUNCTIONS
+#define _POSIX_THREAD_SAFE_FUNCTIONS 200809L
+
+#undef _POSIX_THREAD_ATTR_STACKSIZE
+#define _POSIX_THREAD_ATTR_STACKSIZE 200809L
+
+/*
+ * The following options are not supported
+ */
+#undef _POSIX_THREAD_ATTR_STACKADDR
+#define _POSIX_THREAD_ATTR_STACKADDR -1
+
+#undef _POSIX_THREAD_PRIO_INHERIT
+#define _POSIX_THREAD_PRIO_INHERIT -1
+
+#undef _POSIX_THREAD_PRIO_PROTECT
+#define _POSIX_THREAD_PRIO_PROTECT -1
+
+/* TPS is not fully supported. */
+#undef _POSIX_THREAD_PRIORITY_SCHEDULING
+#define _POSIX_THREAD_PRIORITY_SCHEDULING -1
+
+#undef _POSIX_THREAD_PROCESS_SHARED
+#define _POSIX_THREAD_PROCESS_SHARED -1
+
+
+/*
+ * POSIX 1003.1-2001 Limits
+ * ===========================
+ *
+ * These limits are normally set in <limits.h>, which is not provided with
+ * pthreads-win32.
+ *
+ * PTHREAD_DESTRUCTOR_ITERATIONS
+ * Maximum number of attempts to destroy
+ * a thread's thread-specific data on
+ * termination (must be at least 4)
+ *
+ * PTHREAD_KEYS_MAX
+ * Maximum number of thread-specific data keys
+ * available per process (must be at least 128)
+ *
+ * PTHREAD_STACK_MIN
+ * Minimum supported stack size for a thread
+ *
+ * PTHREAD_THREADS_MAX
+ * Maximum number of threads supported per
+ * process (must be at least 64).
+ *
+ * SEM_NSEMS_MAX
+ * The maximum number of semaphores a process can have.
+ * (must be at least 256)
+ *
+ * SEM_VALUE_MAX
+ * The maximum value a semaphore can have.
+ * (must be at least 32767)
+ *
+ */
+#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS
+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
+
+#undef PTHREAD_DESTRUCTOR_ITERATIONS
+#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
+
+#undef _POSIX_THREAD_KEYS_MAX
+#define _POSIX_THREAD_KEYS_MAX 128
+
+#undef PTHREAD_KEYS_MAX
+#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX
+
+#undef PTHREAD_STACK_MIN
+#define PTHREAD_STACK_MIN 0
+
+#undef _POSIX_THREAD_THREADS_MAX
+#define _POSIX_THREAD_THREADS_MAX 64
+
+ /* Arbitrary value */
+#undef PTHREAD_THREADS_MAX
+#define PTHREAD_THREADS_MAX 2019
+
+#undef _POSIX_SEM_NSEMS_MAX
+#define _POSIX_SEM_NSEMS_MAX 256
+
+ /* Arbitrary value */
+#undef SEM_NSEMS_MAX
+#define SEM_NSEMS_MAX 1024
+
+#undef _POSIX_SEM_VALUE_MAX
+#define _POSIX_SEM_VALUE_MAX 32767
+
+#undef SEM_VALUE_MAX
+#define SEM_VALUE_MAX INT_MAX
+
+
+#if defined(__GNUC__) && !defined(__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the library, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the library,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#if !defined(PTW32_STATIC_LIB)
+# if defined(PTW32_BUILD)
+# define PTW32_DLLPORT __declspec (dllexport)
+# else
+# define PTW32_DLLPORT __declspec (dllimport)
+# endif
+#else
+# define PTW32_DLLPORT
+#endif
+
+/*
+ * The Open Watcom C/C++ compiler uses a non-standard calling convention
+ * that passes function args in registers unless __cdecl is explicitly specified
+ * in exposed function prototypes.
+ *
+ * We force all calls to cdecl even though this could slow Watcom code down
+ * slightly. If you know that the Watcom compiler will be used to build both
+ * the DLL and application, then you can probably define this as a null string.
+ * Remember that pthread.h (this file) is used for both the DLL and application builds.
+ */
+#define PTW32_CDECL __cdecl
+
+#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX
+# include <sys/types.h>
+#else
+/*
+ * Generic handle type - intended to extend uniqueness beyond
+ * that available with a simple pointer. It should scale for either
+ * IA-32 or IA-64.
+ */
+typedef struct {
+ void * p; /* Pointer to actual object */
+ unsigned int x; /* Extra information - reuse count etc */
+} ptw32_handle_t;
+
+typedef ptw32_handle_t pthread_t;
+typedef struct pthread_attr_t_ * pthread_attr_t;
+typedef struct pthread_once_t_ pthread_once_t;
+typedef struct pthread_key_t_ * pthread_key_t;
+typedef struct pthread_mutex_t_ * pthread_mutex_t;
+typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t;
+typedef struct pthread_cond_t_ * pthread_cond_t;
+typedef struct pthread_condattr_t_ * pthread_condattr_t;
+#endif
+typedef struct pthread_rwlock_t_ * pthread_rwlock_t;
+typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t;
+typedef struct pthread_spinlock_t_ * pthread_spinlock_t;
+typedef struct pthread_barrier_t_ * pthread_barrier_t;
+typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t;
+
+/*
+ * ====================
+ * ====================
+ * POSIX Threads
+ * ====================
+ * ====================
+ */
+
+enum {
+/*
+ * pthread_attr_{get,set}detachstate
+ */
+ PTHREAD_CREATE_JOINABLE = 0, /* Default */
+ PTHREAD_CREATE_DETACHED = 1,
+
+/*
+ * pthread_attr_{get,set}inheritsched
+ */
+ PTHREAD_INHERIT_SCHED = 0,
+ PTHREAD_EXPLICIT_SCHED = 1, /* Default */
+
+/*
+ * pthread_{get,set}scope
+ */
+ PTHREAD_SCOPE_PROCESS = 0,
+ PTHREAD_SCOPE_SYSTEM = 1, /* Default */
+
+/*
+ * pthread_setcancelstate paramters
+ */
+ PTHREAD_CANCEL_ENABLE = 0, /* Default */
+ PTHREAD_CANCEL_DISABLE = 1,
+
+/*
+ * pthread_setcanceltype parameters
+ */
+ PTHREAD_CANCEL_ASYNCHRONOUS = 0,
+ PTHREAD_CANCEL_DEFERRED = 1, /* Default */
+
+/*
+ * pthread_mutexattr_{get,set}pshared
+ * pthread_condattr_{get,set}pshared
+ */
+ PTHREAD_PROCESS_PRIVATE = 0,
+ PTHREAD_PROCESS_SHARED = 1,
+
+/*
+ * pthread_mutexattr_{get,set}robust
+ */
+ PTHREAD_MUTEX_STALLED = 0, /* Default */
+ PTHREAD_MUTEX_ROBUST = 1,
+
+/*
+ * pthread_barrier_wait
+ */
+ PTHREAD_BARRIER_SERIAL_THREAD = -1
+};
+
+/*
+ * ====================
+ * ====================
+ * Cancelation
+ * ====================
+ * ====================
+ */
+#define PTHREAD_CANCELED ((void *)(size_t) -1)
+
+
+/*
+ * ====================
+ * ====================
+ * Once Key
+ * ====================
+ * ====================
+ */
+#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0}
+
+struct pthread_once_t_
+{
+ int done; /* indicates if user function has been executed */
+ void * lock;
+ int reserved1;
+ int reserved2;
+};
+
+
+/*
+ * ====================
+ * ====================
+ * Object initialisers
+ * ====================
+ * ====================
+ */
+#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -1)
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -2)
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -3)
+
+/*
+ * Compatibility with LinuxThreads
+ */
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
+
+#define PTHREAD_COND_INITIALIZER ((pthread_cond_t)(size_t) -1)
+
+#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t)(size_t) -1)
+
+#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t)(size_t) -1)
+
+
+/*
+ * Mutex types.
+ */
+enum
+{
+ /* Compatibility with LinuxThreads */
+ PTHREAD_MUTEX_FAST_NP,
+ PTHREAD_MUTEX_RECURSIVE_NP,
+ PTHREAD_MUTEX_ERRORCHECK_NP,
+ PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP,
+ PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP,
+ /* For compatibility with POSIX */
+ PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP,
+ PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
+ PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
+ PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
+};
+
+
+typedef struct ptw32_cleanup_t ptw32_cleanup_t;
+
+#if defined(_MSC_VER)
+/* Disable MSVC 'anachronism used' warning */
+#pragma warning( disable : 4229 )
+#endif
+
+typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *);
+
+#if defined(_MSC_VER)
+#pragma warning( default : 4229 )
+#endif
+
+struct ptw32_cleanup_t
+{
+ ptw32_cleanup_callback_t routine;
+ void *arg;
+ struct ptw32_cleanup_t *prev;
+};
+
+#if defined(__CLEANUP_SEH)
+ /*
+ * WIN32 SEH version of cancel cleanup.
+ */
+
+#define pthread_cleanup_push( _rout, _arg ) \
+ { \
+ ptw32_cleanup_t _cleanup; \
+ \
+ _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \
+ _cleanup.arg = (_arg); \
+ __try \
+ { \
+
+#define pthread_cleanup_pop( _execute ) \
+ } \
+ __finally \
+ { \
+ if( _execute || AbnormalTermination()) \
+ { \
+ (*(_cleanup.routine))( _cleanup.arg ); \
+ } \
+ } \
+ }
+
+#else /* __CLEANUP_SEH */
+
+#if defined(__CLEANUP_C)
+
+ /*
+ * C implementation of PThreads cancel cleanup
+ */
+
+#define pthread_cleanup_push( _rout, _arg ) \
+ { \
+ ptw32_cleanup_t _cleanup; \
+ \
+ ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \
+
+#define pthread_cleanup_pop( _execute ) \
+ (void) ptw32_pop_cleanup( _execute ); \
+ }
+
+#else /* __CLEANUP_C */
+
+#if defined(__CLEANUP_CXX)
+
+ /*
+ * C++ version of cancel cleanup.
+ * - John E. Bossom.
+ */
+
+ class PThreadCleanup {
+ /*
+ * PThreadCleanup
+ *
+ * Purpose
+ * This class is a C++ helper class that is
+ * used to implement pthread_cleanup_push/
+ * pthread_cleanup_pop.
+ * The destructor of this class automatically
+ * pops the pushed cleanup routine regardless
+ * of how the code exits the scope
+ * (i.e. such as by an exception)
+ */
+ ptw32_cleanup_callback_t cleanUpRout;
+ void * obj;
+ int executeIt;
+
+ public:
+ PThreadCleanup() :
+ cleanUpRout( 0 ),
+ obj( 0 ),
+ executeIt( 0 )
+ /*
+ * No cleanup performed
+ */
+ {
+ }
+
+ PThreadCleanup(
+ ptw32_cleanup_callback_t routine,
+ void * arg ) :
+ cleanUpRout( routine ),
+ obj( arg ),
+ executeIt( 1 )
+ /*
+ * Registers a cleanup routine for 'arg'
+ */
+ {
+ }
+
+ ~PThreadCleanup()
+ {
+ if ( executeIt && ((void *) cleanUpRout != (void *) 0) )
+ {
+ (void) (*cleanUpRout)( obj );
+ }
+ }
+
+ void execute( int exec )
+ {
+ executeIt = exec;
+ }
+ };
+
+ /*
+ * C++ implementation of PThreads cancel cleanup;
+ * This implementation takes advantage of a helper
+ * class who's destructor automatically calls the
+ * cleanup routine if we exit our scope weirdly
+ */
+#define pthread_cleanup_push( _rout, _arg ) \
+ { \
+ PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \
+ (void *) (_arg) );
+
+#define pthread_cleanup_pop( _execute ) \
+ cleanup.execute( _execute ); \
+ }
+
+#else
+
+#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* __CLEANUP_C */
+
+#endif /* __CLEANUP_SEH */
+
+/*
+ * ===============
+ * ===============
+ * Methods
+ * ===============
+ * ===============
+ */
+
+/*
+ * PThread Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr,
+ int *detachstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr,
+ void **stackaddr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr,
+ size_t * stacksize);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr,
+ int detachstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr,
+ void *stackaddr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr,
+ size_t stacksize);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr,
+ struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr,
+ const struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *,
+ int);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (const pthread_attr_t *,
+ int *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr,
+ int inheritsched);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(const pthread_attr_t * attr,
+ int * inheritsched);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *,
+ int);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *,
+ int *);
+
+/*
+ * PThread Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid,
+ const pthread_attr_t * attr,
+ void *(PTW32_CDECL *start) (void *),
+ void *arg);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1,
+ pthread_t t2);
+
+PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread,
+ void **value_ptr);
+
+PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state,
+ int *oldstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type,
+ int *oldtype);
+
+PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control,
+ void (PTW32_CDECL *init_routine) (void));
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute);
+
+PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup,
+ ptw32_cleanup_callback_t routine,
+ void *arg);
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Thread Specific Data Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key,
+ void (PTW32_CDECL *destructor) (void *));
+
+PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key,
+ const void *value);
+
+PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key);
+
+
+/*
+ * Mutex Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t
+ * attr,
+ int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr,
+ int pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind);
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (const pthread_mutexattr_t * attr, int *kind);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setrobust(
+ pthread_mutexattr_t *attr,
+ int robust);
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getrobust(
+ const pthread_mutexattr_t * attr,
+ int * robust);
+
+/*
+ * Barrier Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t
+ * attr,
+ int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr,
+ int pshared);
+
+/*
+ * Mutex Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex,
+ const pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t * mutex,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_consistent (pthread_mutex_t * mutex);
+
+/*
+ * Spinlock Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock);
+
+/*
+ * Barrier Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier,
+ const pthread_barrierattr_t * attr,
+ unsigned int count);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier);
+
+/*
+ * Condition Variable Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr,
+ int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr,
+ int pshared);
+
+/*
+ * Condition Variable Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond,
+ const pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond,
+ pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond,
+ pthread_mutex_t * mutex,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond);
+
+/*
+ * Scheduling
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread,
+ int policy,
+ const struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread,
+ int *policy,
+ struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void);
+
+/*
+ * Read-Write Lock Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock,
+ const pthread_rwlockattr_t *attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr,
+ int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr,
+ int pshared);
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1
+
+/*
+ * Signal Functions. Should be defined in <signal.h> but MSVC and MinGW32
+ * already have signal.h that don't define these.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig);
+
+/*
+ * Non-portable functions
+ */
+
+/*
+ * Compatibility with Linux.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr,
+ int kind);
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr,
+ int *kind);
+
+/*
+ * Possibly supported by other POSIX threads implementations
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval);
+PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void);
+PTW32_DLLPORT unsigned __int64 PTW32_CDECL pthread_getunique_np(pthread_t thread);
+
+/*
+ * Useful if an application wants to statically link
+ * the lib rather than load the DLL at run-time.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void);
+
+/*
+ * Features that are auto-detected at load/run time.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int);
+enum ptw32_features {
+ PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */
+ PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */
+};
+
+/*
+ * Register a system time change with the library.
+ * Causes the library to perform various functions
+ * in response to the change. Should be called whenever
+ * the application's top level window receives a
+ * WM_TIMECHANGE message. It can be passed directly to
+ * pthread_create() as a new thread if desired.
+ */
+PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *);
+
+#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+
+/*
+ * Returns the Win32 HANDLE for the POSIX thread.
+ */
+PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread);
+/*
+ * Returns the win32 thread ID for POSIX thread.
+ */
+PTW32_DLLPORT DWORD PTW32_CDECL pthread_getw32threadid_np (pthread_t thread);
+
+
+/*
+ * Protected Methods
+ *
+ * This function blocks until the given WIN32 handle
+ * is signaled or pthread_cancel had been called.
+ * This function allows the caller to hook into the
+ * PThreads cancel mechanism. It is implemented using
+ *
+ * WaitForMultipleObjects
+ *
+ * on 'waitHandle' and a manually reset WIN32 Event
+ * used to implement pthread_cancel. The 'timeout'
+ * argument to TimedWait is simply passed to
+ * WaitForMultipleObjects.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle);
+PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle,
+ DWORD timeout);
+
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Thread-Safe C Runtime Library Mappings.
+ */
+#if !defined(_UWIN)
+# if defined(NEED_ERRNO)
+ PTW32_DLLPORT int * PTW32_CDECL _errno( void );
+# else
+# if !defined(errno)
+# if (defined(_MT) || defined(_DLL))
+ __declspec(dllimport) extern int * __cdecl _errno(void);
+# define errno (*_errno())
+# endif
+# endif
+# endif
+#endif
+
+/*
+ * Some compiler environments don't define some things.
+ */
+#if defined(__BORLANDC__)
+# define _ftime ftime
+# define _timeb timeb
+#endif
+
+#if defined(__cplusplus)
+
+/*
+ * Internal exceptions
+ */
+class ptw32_exception {};
+class ptw32_exception_cancel : public ptw32_exception {};
+class ptw32_exception_exit : public ptw32_exception {};
+
+#endif
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+
+/* FIXME: This is only required if the library was built using SEH */
+/*
+ * Get internal SEH tag
+ */
+PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void);
+
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#if !defined(PTW32_BUILD)
+
+#if defined(__CLEANUP_SEH)
+
+/*
+ * Redefine the SEH __except keyword to ensure that applications
+ * propagate our internal exceptions up to the library's internal handlers.
+ */
+#define __except( E ) \
+ __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \
+ ? EXCEPTION_CONTINUE_SEARCH : ( E ) )
+
+#endif /* __CLEANUP_SEH */
+
+#if defined(__CLEANUP_CXX)
+
+/*
+ * Redefine the C++ catch keyword to ensure that applications
+ * propagate our internal exceptions up to the library's internal handlers.
+ */
+#if defined(_MSC_VER)
+ /*
+ * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll'
+ * if you want Pthread-Win32 cancelation and pthread_exit to work.
+ */
+
+#if !defined(PtW32NoCatchWarn)
+
+#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.")
+#pragma message("------------------------------------------------------------------")
+#pragma message("When compiling applications with MSVC++ and C++ exception handling:")
+#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads")
+#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread")
+#pragma message(" cancelation and pthread_exit to work. For example:")
+#pragma message("")
+#pragma message(" #if defined(PtW32CatchAll)")
+#pragma message(" PtW32CatchAll")
+#pragma message(" #else")
+#pragma message(" catch(...)")
+#pragma message(" #endif")
+#pragma message(" {")
+#pragma message(" /* Catchall block processing */")
+#pragma message(" }")
+#pragma message("------------------------------------------------------------------")
+
+#endif
+
+#define PtW32CatchAll \
+ catch( ptw32_exception & ) { throw; } \
+ catch( ... )
+
+#else /* _MSC_VER */
+
+#define catch( E ) \
+ catch( ptw32_exception & ) { throw; } \
+ catch( E )
+
+#endif /* _MSC_VER */
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* ! PTW32_BUILD */
+
+#if defined(__cplusplus)
+} /* End of extern "C" */
+#endif /* __cplusplus */
+
+#if defined(PTW32__HANDLE_DEF)
+# undef HANDLE
+#endif
+#if defined(PTW32__DWORD_DEF)
+# undef DWORD
+#endif
+
+#undef PTW32_LEVEL
+#undef PTW32_LEVEL_MAX
+
+#endif /* ! RC_INVOKED */
+
+#endif /* PTHREAD_H */
diff --git a/libs/pthreads/src/pthread_attr_destroy.c b/libs/pthreads/src/pthread_attr_destroy.c
new file mode 100644
index 0000000000..8b3e04c536
--- /dev/null
+++ b/libs/pthreads/src/pthread_attr_destroy.c
@@ -0,0 +1,79 @@
+/*
+ * pthread_attr_destroy.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_attr_destroy (pthread_attr_t * attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Destroys a thread attributes object.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_attr_t
+ *
+ *
+ * DESCRIPTION
+ * Destroys a thread attributes object.
+ *
+ * NOTES:
+ * 1) Does not affect threads created with 'attr'.
+ *
+ * RESULTS
+ * 0 successfully destroyed attr,
+ * EINVAL 'attr' is invalid.
+ *
+ * ------------------------------------------------------
+ */
+{
+ if (ptw32_is_attr (attr) != 0)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * Set the attribute object to a specific invalid value.
+ */
+ (*attr)->valid = 0;
+ free (*attr);
+ *attr = NULL;
+
+ return 0;
+}
diff --git a/libs/pthreads/src/pthread_attr_getdetachstate.c b/libs/pthreads/src/pthread_attr_getdetachstate.c
new file mode 100644
index 0000000000..188533b13c
--- /dev/null
+++ b/libs/pthreads/src/pthread_attr_getdetachstate.c
@@ -0,0 +1,86 @@
+/*
+ * pthread_attr_getdetachstate.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_attr_getdetachstate (const pthread_attr_t * attr, int *detachstate)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function determines whether threads created with
+ * 'attr' will run detached.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_attr_t
+ *
+ * detachstate
+ * pointer to an integer into which is returned one
+ * of:
+ *
+ * PTHREAD_CREATE_JOINABLE
+ * Thread ID is valid, must be joined
+ *
+ * PTHREAD_CREATE_DETACHED
+ * Thread ID is invalid, cannot be joined,
+ * canceled, or modified
+ *
+ *
+ * DESCRIPTION
+ * This function determines whether threads created with
+ * 'attr' will run detached.
+ *
+ * NOTES:
+ * 1) You cannot join or cancel detached threads.
+ *
+ * RESULTS
+ * 0 successfully retrieved detach state,
+ * EINVAL 'attr' is invalid
+ *
+ * ------------------------------------------------------
+ */
+{
+ if (ptw32_is_attr (attr) != 0 || detachstate == NULL)
+ {
+ return EINVAL;
+ }
+
+ *detachstate = (*attr)->detachstate;
+ return 0;
+}
diff --git a/libs/pthreads/src/pthread_attr_getinheritsched.c b/libs/pthreads/src/pthread_attr_getinheritsched.c
new file mode 100644
index 0000000000..9c6885ed92
--- /dev/null
+++ b/libs/pthreads/src/pthread_attr_getinheritsched.c
@@ -0,0 +1,51 @@
+/*
+ * pthread_attr_getinheritsched.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_getinheritsched (const pthread_attr_t * attr, int *inheritsched)
+{
+ if (ptw32_is_attr (attr) != 0 || inheritsched == NULL)
+ {
+ return EINVAL;
+ }
+
+ *inheritsched = (*attr)->inheritsched;
+ return 0;
+}
diff --git a/libs/pthreads/src/pthread_attr_getschedparam.c b/libs/pthreads/src/pthread_attr_getschedparam.c
new file mode 100644
index 0000000000..ab89b2241a
--- /dev/null
+++ b/libs/pthreads/src/pthread_attr_getschedparam.c
@@ -0,0 +1,52 @@
+/*
+ * pthread_attr_getschedparam.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_getschedparam (const pthread_attr_t * attr,
+ struct sched_param *param)
+{
+ if (ptw32_is_attr (attr) != 0 || param == NULL)
+ {
+ return EINVAL;
+ }
+
+ memcpy (param, &(*attr)->param, sizeof (*param));
+ return 0;
+}
diff --git a/libs/pthreads/src/pthread_attr_getschedpolicy.c b/libs/pthreads/src/pthread_attr_getschedpolicy.c
new file mode 100644
index 0000000000..94a257d609
--- /dev/null
+++ b/libs/pthreads/src/pthread_attr_getschedpolicy.c
@@ -0,0 +1,61 @@
+/*
+ * pthread_attr_getschedpolicy.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_getschedpolicy (const pthread_attr_t * attr, int *policy)
+{
+ if (ptw32_is_attr (attr) != 0 || policy == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * Validate the policy arg.
+ * Check that a policy constant wasn't passed rather than &policy.
+ */
+ if (policy <= (int *) SCHED_MAX)
+ {
+ return EINVAL;
+ }
+
+ *policy = SCHED_OTHER;
+
+ return 0;
+}
diff --git a/libs/pthreads/src/pthread_attr_getscope.c b/libs/pthreads/src/pthread_attr_getscope.c
new file mode 100644
index 0000000000..2efdb2fe6d
--- /dev/null
+++ b/libs/pthreads/src/pthread_attr_getscope.c
@@ -0,0 +1,54 @@
+/*
+ * pthread_attr_getscope.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/* ignore warning "unreferenced formal parameter" */
+#if defined(_MSC_VER)
+#pragma warning( disable : 4100 )
+#endif
+
+int
+pthread_attr_getscope (const pthread_attr_t * attr, int *contentionscope)
+{
+#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
+ *contentionscope = (*attr)->contentionscope;
+ return 0;
+#else
+ return ENOSYS;
+#endif
+}
diff --git a/libs/pthreads/src/pthread_attr_getstackaddr.c b/libs/pthreads/src/pthread_attr_getstackaddr.c
new file mode 100644
index 0000000000..1a2da01c78
--- /dev/null
+++ b/libs/pthreads/src/pthread_attr_getstackaddr.c
@@ -0,0 +1,97 @@
+/*
+ * pthread_attr_getstackaddr.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/* ignore warning "unreferenced formal parameter" */
+#if defined(_MSC_VER)
+#pragma warning( disable : 4100 )
+#endif
+
+int
+pthread_attr_getstackaddr (const pthread_attr_t * attr, void **stackaddr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function determines the address of the stack
+ * on which threads created with 'attr' will run.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_attr_t
+ *
+ * stackaddr
+ * pointer into which is returned the stack address.
+ *
+ *
+ * DESCRIPTION
+ * This function determines the address of the stack
+ * on which threads created with 'attr' will run.
+ *
+ * NOTES:
+ * 1) Function supported only if this macro is
+ * defined:
+ *
+ * _POSIX_THREAD_ATTR_STACKADDR
+ *
+ * 2) Create only one thread for each stack
+ * address..
+ *
+ * RESULTS
+ * 0 successfully retreived stack address,
+ * EINVAL 'attr' is invalid
+ * ENOSYS function not supported
+ *
+ * ------------------------------------------------------
+ */
+{
+#if defined( _POSIX_THREAD_ATTR_STACKADDR )
+
+ if (ptw32_is_attr (attr) != 0)
+ {
+ return EINVAL;
+ }
+
+ *stackaddr = (*attr)->stackaddr;
+ return 0;
+
+#else
+
+ return ENOSYS;
+
+#endif /* _POSIX_THREAD_ATTR_STACKADDR */
+}
diff --git a/libs/pthreads/src/pthread_attr_getstacksize.c b/libs/pthreads/src/pthread_attr_getstacksize.c
new file mode 100644
index 0000000000..dff9230f28
--- /dev/null
+++ b/libs/pthreads/src/pthread_attr_getstacksize.c
@@ -0,0 +1,100 @@
+/*
+ * pthread_attr_getstacksize.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/* ignore warning "unreferenced formal parameter" */
+#if defined(_MSC_VER)
+#pragma warning( disable : 4100 )
+#endif
+
+int
+pthread_attr_getstacksize (const pthread_attr_t * attr, size_t * stacksize)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function determines the size of the stack on
+ * which threads created with 'attr' will run.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_attr_t
+ *
+ * stacksize
+ * pointer to size_t into which is returned the
+ * stack size, in bytes.
+ *
+ *
+ * DESCRIPTION
+ * This function determines the size of the stack on
+ * which threads created with 'attr' will run.
+ *
+ * NOTES:
+ * 1) Function supported only if this macro is
+ * defined:
+ *
+ * _POSIX_THREAD_ATTR_STACKSIZE
+ *
+ * 2) Use on newly created attributes object to
+ * find the default stack size.
+ *
+ * RESULTS
+ * 0 successfully retrieved stack size,
+ * EINVAL 'attr' is invalid
+ * ENOSYS function not supported
+ *
+ * ------------------------------------------------------
+ */
+{
+#if defined(_POSIX_THREAD_ATTR_STACKSIZE)
+
+ if (ptw32_is_attr (attr) != 0)
+ {
+ return EINVAL;
+ }
+
+ /* Everything is okay. */
+ *stacksize = (*attr)->stacksize;
+ return 0;
+
+#else
+
+ return ENOSYS;
+
+#endif /* _POSIX_THREAD_ATTR_STACKSIZE */
+
+}
diff --git a/libs/pthreads/src/pthread_attr_init.c b/libs/pthreads/src/pthread_attr_init.c
new file mode 100644
index 0000000000..ae9d3eb5f4
--- /dev/null
+++ b/libs/pthreads/src/pthread_attr_init.c
@@ -0,0 +1,117 @@
+/*
+ * pthread_attr_init.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_attr_init (pthread_attr_t * attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Initializes a thread attributes object with default
+ * attributes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_attr_t
+ *
+ *
+ * DESCRIPTION
+ * Initializes a thread attributes object with default
+ * attributes.
+ *
+ * NOTES:
+ * 1) Used to define thread attributes
+ *
+ * RESULTS
+ * 0 successfully initialized attr,
+ * ENOMEM insufficient memory for attr.
+ *
+ * ------------------------------------------------------
+ */
+{
+ pthread_attr_t attr_result;
+
+ if (attr == NULL)
+ {
+ /* This is disallowed. */
+ return EINVAL;
+ }
+
+ attr_result = (pthread_attr_t) malloc (sizeof (*attr_result));
+
+ if (attr_result == NULL)
+ {
+ return ENOMEM;
+ }
+
+#if defined(_POSIX_THREAD_ATTR_STACKSIZE)
+ /*
+ * Default to zero size. Unless changed explicitly this
+ * will allow Win32 to set the size to that of the
+ * main thread.
+ */
+ attr_result->stacksize = 0;
+#endif
+
+#if defined(_POSIX_THREAD_ATTR_STACKADDR)
+ /* FIXME: Set this to something sensible when we support it. */
+ attr_result->stackaddr = NULL;
+#endif
+
+ attr_result->detachstate = PTHREAD_CREATE_JOINABLE;
+
+#if defined(HAVE_SIGSET_T)
+ memset (&(attr_result->sigmask), 0, sizeof (sigset_t));
+#endif /* HAVE_SIGSET_T */
+
+ /*
+ * Win32 sets new threads to THREAD_PRIORITY_NORMAL and
+ * not to that of the parent thread. We choose to default to
+ * this arrangement.
+ */
+ attr_result->param.sched_priority = THREAD_PRIORITY_NORMAL;
+ attr_result->inheritsched = PTHREAD_EXPLICIT_SCHED;
+ attr_result->contentionscope = PTHREAD_SCOPE_SYSTEM;
+
+ attr_result->valid = PTW32_ATTR_VALID;
+
+ *attr = attr_result;
+
+ return 0;
+}
diff --git a/libs/pthreads/src/pthread_attr_setdetachstate.c b/libs/pthreads/src/pthread_attr_setdetachstate.c
new file mode 100644
index 0000000000..784642a807
--- /dev/null
+++ b/libs/pthreads/src/pthread_attr_setdetachstate.c
@@ -0,0 +1,91 @@
+/*
+ * pthread_attr_setdetachstate.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_attr_setdetachstate (pthread_attr_t * attr, int detachstate)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function specifies whether threads created with
+ * 'attr' will run detached.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_attr_t
+ *
+ * detachstate
+ * an integer containing one of:
+ *
+ * PTHREAD_CREATE_JOINABLE
+ * Thread ID is valid, must be joined
+ *
+ * PTHREAD_CREATE_DETACHED
+ * Thread ID is invalid, cannot be joined,
+ * canceled, or modified
+ *
+ *
+ * DESCRIPTION
+ * This function specifies whether threads created with
+ * 'attr' will run detached.
+ *
+ * NOTES:
+ * 1) You cannot join or cancel detached threads.
+ *
+ * RESULTS
+ * 0 successfully set detach state,
+ * EINVAL 'attr' or 'detachstate' is invalid
+ *
+ * ------------------------------------------------------
+ */
+{
+ if (ptw32_is_attr (attr) != 0)
+ {
+ return EINVAL;
+ }
+
+ if (detachstate != PTHREAD_CREATE_JOINABLE &&
+ detachstate != PTHREAD_CREATE_DETACHED)
+ {
+ return EINVAL;
+ }
+
+ (*attr)->detachstate = detachstate;
+ return 0;
+}
diff --git a/libs/pthreads/src/pthread_attr_setinheritsched.c b/libs/pthreads/src/pthread_attr_setinheritsched.c
new file mode 100644
index 0000000000..e0a407a3b7
--- /dev/null
+++ b/libs/pthreads/src/pthread_attr_setinheritsched.c
@@ -0,0 +1,57 @@
+/*
+ * pthread_attr_setinheritsched.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_setinheritsched (pthread_attr_t * attr, int inheritsched)
+{
+ if (ptw32_is_attr (attr) != 0)
+ {
+ return EINVAL;
+ }
+
+ if (PTHREAD_INHERIT_SCHED != inheritsched
+ && PTHREAD_EXPLICIT_SCHED != inheritsched)
+ {
+ return EINVAL;
+ }
+
+ (*attr)->inheritsched = inheritsched;
+ return 0;
+}
diff --git a/libs/pthreads/src/pthread_attr_setschedparam.c b/libs/pthreads/src/pthread_attr_setschedparam.c
new file mode 100644
index 0000000000..f246bfae7a
--- /dev/null
+++ b/libs/pthreads/src/pthread_attr_setschedparam.c
@@ -0,0 +1,63 @@
+/*
+ * pthread_attr_setschedparam.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_setschedparam (pthread_attr_t * attr,
+ const struct sched_param *param)
+{
+ int priority;
+
+ if (ptw32_is_attr (attr) != 0 || param == NULL)
+ {
+ return EINVAL;
+ }
+
+ priority = param->sched_priority;
+
+ /* Validate priority level. */
+ if (priority < sched_get_priority_min (SCHED_OTHER) ||
+ priority > sched_get_priority_max (SCHED_OTHER))
+ {
+ return EINVAL;
+ }
+
+ memcpy (&(*attr)->param, param, sizeof (*param));
+ return 0;
+}
diff --git a/libs/pthreads/src/pthread_attr_setschedpolicy.c b/libs/pthreads/src/pthread_attr_setschedpolicy.c
new file mode 100644
index 0000000000..45ff165973
--- /dev/null
+++ b/libs/pthreads/src/pthread_attr_setschedpolicy.c
@@ -0,0 +1,55 @@
+/*
+ * pthread_attr_setschedpolicy.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_setschedpolicy (pthread_attr_t * attr, int policy)
+{
+ if (ptw32_is_attr (attr) != 0)
+ {
+ return EINVAL;
+ }
+
+ if (policy != SCHED_OTHER)
+ {
+ return ENOTSUP;
+ }
+
+ return 0;
+}
diff --git a/libs/pthreads/src/pthread_attr_setscope.c b/libs/pthreads/src/pthread_attr_setscope.c
new file mode 100644
index 0000000000..39a51df887
--- /dev/null
+++ b/libs/pthreads/src/pthread_attr_setscope.c
@@ -0,0 +1,62 @@
+/*
+ * pthread_attr_setscope.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/* ignore warning "unreferenced formal parameter" */
+#if defined(_MSC_VER)
+#pragma warning( disable : 4100 )
+#endif
+
+int
+pthread_attr_setscope (pthread_attr_t * attr, int contentionscope)
+{
+#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
+ switch (contentionscope)
+ {
+ case PTHREAD_SCOPE_SYSTEM:
+ (*attr)->contentionscope = contentionscope;
+ return 0;
+ case PTHREAD_SCOPE_PROCESS:
+ return ENOTSUP;
+ default:
+ return EINVAL;
+ }
+#else
+ return ENOSYS;
+#endif
+}
diff --git a/libs/pthreads/src/pthread_attr_setstackaddr.c b/libs/pthreads/src/pthread_attr_setstackaddr.c
new file mode 100644
index 0000000000..1316c06592
--- /dev/null
+++ b/libs/pthreads/src/pthread_attr_setstackaddr.c
@@ -0,0 +1,97 @@
+/*
+ * pthread_attr_setstackaddr.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_attr_setstackaddr (pthread_attr_t * attr, void *stackaddr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Threads created with 'attr' will run on the stack
+ * starting at 'stackaddr'.
+ * Stack must be at least PTHREAD_STACK_MIN bytes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_attr_t
+ *
+ * stackaddr
+ * the address of the stack to use
+ *
+ *
+ * DESCRIPTION
+ * Threads created with 'attr' will run on the stack
+ * starting at 'stackaddr'.
+ * Stack must be at least PTHREAD_STACK_MIN bytes.
+ *
+ * NOTES:
+ * 1) Function supported only if this macro is
+ * defined:
+ *
+ * _POSIX_THREAD_ATTR_STACKADDR
+ *
+ * 2) Create only one thread for each stack
+ * address..
+ *
+ * 3) Ensure that stackaddr is aligned.
+ *
+ * RESULTS
+ * 0 successfully set stack address,
+ * EINVAL 'attr' is invalid
+ * ENOSYS function not supported
+ *
+ * ------------------------------------------------------
+ */
+{
+#if defined( _POSIX_THREAD_ATTR_STACKADDR )
+
+ if (ptw32_is_attr (attr) != 0)
+ {
+ return EINVAL;
+ }
+
+ (*attr)->stackaddr = stackaddr;
+ return 0;
+
+#else
+
+ return ENOSYS;
+
+#endif /* _POSIX_THREAD_ATTR_STACKADDR */
+}
diff --git a/libs/pthreads/src/pthread_attr_setstacksize.c b/libs/pthreads/src/pthread_attr_setstacksize.c
new file mode 100644
index 0000000000..eb13589a00
--- /dev/null
+++ b/libs/pthreads/src/pthread_attr_setstacksize.c
@@ -0,0 +1,110 @@
+/*
+ * pthread_attr_setstacksize.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_attr_setstacksize (pthread_attr_t * attr, size_t stacksize)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function specifies the size of the stack on
+ * which threads created with 'attr' will run.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_attr_t
+ *
+ * stacksize
+ * stack size, in bytes.
+ *
+ *
+ * DESCRIPTION
+ * This function specifies the size of the stack on
+ * which threads created with 'attr' will run.
+ *
+ * NOTES:
+ * 1) Function supported only if this macro is
+ * defined:
+ *
+ * _POSIX_THREAD_ATTR_STACKSIZE
+ *
+ * 2) Find the default first (using
+ * pthread_attr_getstacksize), then increase
+ * by multiplying.
+ *
+ * 3) Only use if thread needs more than the
+ * default.
+ *
+ * RESULTS
+ * 0 successfully set stack size,
+ * EINVAL 'attr' is invalid or stacksize too
+ * small or too big.
+ * ENOSYS function not supported
+ *
+ * ------------------------------------------------------
+ */
+{
+#if defined(_POSIX_THREAD_ATTR_STACKSIZE)
+
+#if PTHREAD_STACK_MIN > 0
+
+ /* Verify that the stack size is within range. */
+ if (stacksize < PTHREAD_STACK_MIN)
+ {
+ return EINVAL;
+ }
+
+#endif
+
+ if (ptw32_is_attr (attr) != 0)
+ {
+ return EINVAL;
+ }
+
+ /* Everything is okay. */
+ (*attr)->stacksize = stacksize;
+ return 0;
+
+#else
+
+ return ENOSYS;
+
+#endif /* _POSIX_THREAD_ATTR_STACKSIZE */
+
+}
diff --git a/libs/pthreads/src/pthread_barrier_destroy.c b/libs/pthreads/src/pthread_barrier_destroy.c
new file mode 100644
index 0000000000..55163cc858
--- /dev/null
+++ b/libs/pthreads/src/pthread_barrier_destroy.c
@@ -0,0 +1,103 @@
+/*
+ * pthread_barrier_destroy.c
+ *
+ * Description:
+ * This translation unit implements barrier primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_barrier_destroy (pthread_barrier_t * barrier)
+{
+ int result = 0;
+ pthread_barrier_t b;
+ ptw32_mcs_local_node_t node;
+
+ if (barrier == NULL || *barrier == (pthread_barrier_t) PTW32_OBJECT_INVALID)
+ {
+ return EINVAL;
+ }
+
+ if (0 != ptw32_mcs_lock_try_acquire(&(*barrier)->lock, &node))
+ {
+ return EBUSY;
+ }
+
+ b = *barrier;
+
+ if (b->nCurrentBarrierHeight < b->nInitialBarrierHeight)
+ {
+ result = EBUSY;
+ }
+ else
+ {
+ if (0 == (result = sem_destroy (&(b->semBarrierBreeched))))
+ {
+ *barrier = (pthread_barrier_t) PTW32_OBJECT_INVALID;
+ /*
+ * Release the lock before freeing b.
+ *
+ * FIXME: There may be successors which, when we release the lock,
+ * will be linked into b->lock, which will be corrupted at some
+ * point with undefined results for the application. To fix this
+ * will require changing pthread_barrier_t from a pointer to
+ * pthread_barrier_t_ to an instance. This is a change to the ABI
+ * and will require a major version number increment.
+ */
+ ptw32_mcs_lock_release(&node);
+ (void) free (b);
+ return 0;
+ }
+ else
+ {
+ /*
+ * This should not ever be reached.
+ * Restore the barrier to working condition before returning.
+ */
+ (void) sem_init (&(b->semBarrierBreeched), b->pshared, 0);
+ }
+
+ if (result != 0)
+ {
+ /*
+ * The barrier still exists and is valid
+ * in the event of any error above.
+ */
+ result = EBUSY;
+ }
+ }
+
+ ptw32_mcs_lock_release(&node);
+ return (result);
+}
diff --git a/libs/pthreads/src/pthread_barrier_init.c b/libs/pthreads/src/pthread_barrier_init.c
new file mode 100644
index 0000000000..618bfae264
--- /dev/null
+++ b/libs/pthreads/src/pthread_barrier_init.c
@@ -0,0 +1,69 @@
+/*
+ * pthread_barrier_init.c
+ *
+ * Description:
+ * This translation unit implements barrier primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_barrier_init (pthread_barrier_t * barrier,
+ const pthread_barrierattr_t * attr, unsigned int count)
+{
+ pthread_barrier_t b;
+
+ if (barrier == NULL || count == 0)
+ {
+ return EINVAL;
+ }
+
+ if (NULL != (b = (pthread_barrier_t) calloc (1, sizeof (*b))))
+ {
+ b->pshared = (attr != NULL && *attr != NULL
+ ? (*attr)->pshared : PTHREAD_PROCESS_PRIVATE);
+
+ b->nCurrentBarrierHeight = b->nInitialBarrierHeight = count;
+ b->lock = 0;
+
+ if (0 == sem_init (&(b->semBarrierBreeched), b->pshared, 0))
+ {
+ *barrier = b;
+ return 0;
+ }
+ (void) free (b);
+ }
+
+ return ENOMEM;
+}
diff --git a/libs/pthreads/src/pthread_barrier_wait.c b/libs/pthreads/src/pthread_barrier_wait.c
new file mode 100644
index 0000000000..e0e97e6c78
--- /dev/null
+++ b/libs/pthreads/src/pthread_barrier_wait.c
@@ -0,0 +1,104 @@
+/*
+ * pthread_barrier_wait.c
+ *
+ * Description:
+ * This translation unit implements barrier primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_barrier_wait (pthread_barrier_t * barrier)
+{
+ int result;
+ pthread_barrier_t b;
+
+ ptw32_mcs_local_node_t node;
+
+ if (barrier == NULL || *barrier == (pthread_barrier_t) PTW32_OBJECT_INVALID)
+ {
+ return EINVAL;
+ }
+
+ ptw32_mcs_lock_acquire(&(*barrier)->lock, &node);
+
+ b = *barrier;
+ if (--b->nCurrentBarrierHeight == 0)
+ {
+ /*
+ * We are the last thread to arrive at the barrier before it releases us.
+ * Move our MCS local node to the global scope barrier handle so that the
+ * last thread out (not necessarily us) can release the lock.
+ */
+ ptw32_mcs_node_transfer(&b->proxynode, &node);
+
+ /*
+ * Any threads that have not quite entered sem_wait below when the
+ * multiple_post has completed will nevertheless continue through
+ * the semaphore (barrier).
+ */
+ result = (b->nInitialBarrierHeight > 1
+ ? sem_post_multiple (&(b->semBarrierBreeched),
+ b->nInitialBarrierHeight - 1) : 0);
+ }
+ else
+ {
+ ptw32_mcs_lock_release(&node);
+ /*
+ * Use the non-cancelable version of sem_wait().
+ *
+ * It is possible that all nInitialBarrierHeight-1 threads are
+ * at this point when the last thread enters the barrier, resets
+ * nCurrentBarrierHeight = nInitialBarrierHeight and leaves.
+ * If pthread_barrier_destroy is called at that moment then the
+ * barrier will be destroyed along with the semas.
+ */
+ result = ptw32_semwait (&(b->semBarrierBreeched));
+ }
+
+ if ((PTW32_INTERLOCKED_LONG)PTW32_INTERLOCKED_INCREMENT_LONG((PTW32_INTERLOCKED_LONGPTR)&b->nCurrentBarrierHeight)
+ == (PTW32_INTERLOCKED_LONG)b->nInitialBarrierHeight)
+ {
+ /*
+ * We are the last thread to cross this barrier
+ */
+ ptw32_mcs_lock_release(&b->proxynode);
+ if (0 == result)
+ {
+ result = PTHREAD_BARRIER_SERIAL_THREAD;
+ }
+ }
+
+ return (result);
+}
diff --git a/libs/pthreads/src/pthread_barrierattr_destroy.c b/libs/pthreads/src/pthread_barrierattr_destroy.c
new file mode 100644
index 0000000000..5ab662e3f4
--- /dev/null
+++ b/libs/pthreads/src/pthread_barrierattr_destroy.c
@@ -0,0 +1,83 @@
+/*
+ * pthread_barrier_attr_destroy.c
+ *
+ * Description:
+ * This translation unit implements barrier primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_barrierattr_destroy (pthread_barrierattr_t * attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Destroys a barrier attributes object. The object can
+ * no longer be used.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_barrierattr_t
+ *
+ *
+ * DESCRIPTION
+ * Destroys a barrier attributes object. The object can
+ * no longer be used.
+ *
+ * NOTES:
+ * 1) Does not affect barrieres created using 'attr'
+ *
+ * RESULTS
+ * 0 successfully released attr,
+ * EINVAL 'attr' is invalid.
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+
+ if (attr == NULL || *attr == NULL)
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ pthread_barrierattr_t ba = *attr;
+
+ *attr = NULL;
+ free (ba);
+ }
+
+ return (result);
+} /* pthread_barrierattr_destroy */
diff --git a/libs/pthreads/src/pthread_barrierattr_getpshared.c b/libs/pthreads/src/pthread_barrierattr_getpshared.c
new file mode 100644
index 0000000000..44c467e2bf
--- /dev/null
+++ b/libs/pthreads/src/pthread_barrierattr_getpshared.c
@@ -0,0 +1,95 @@
+/*
+ * pthread_barrier_attr_getpshared.c
+ *
+ * Description:
+ * This translation unit implements barrier primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_barrierattr_getpshared (const pthread_barrierattr_t * attr,
+ int *pshared)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Determine whether barriers created with 'attr' can be
+ * shared between processes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_barrierattr_t
+ *
+ * pshared
+ * will be set to one of:
+ *
+ * PTHREAD_PROCESS_SHARED
+ * May be shared if in shared memory
+ *
+ * PTHREAD_PROCESS_PRIVATE
+ * Cannot be shared.
+ *
+ *
+ * DESCRIPTION
+ * Mutexes creatd with 'attr' can be shared between
+ * processes if pthread_barrier_t variable is allocated
+ * in memory shared by these processes.
+ * NOTES:
+ * 1) pshared barriers MUST be allocated in shared
+ * memory.
+ * 2) The following macro is defined if shared barriers
+ * are supported:
+ * _POSIX_THREAD_PROCESS_SHARED
+ *
+ * RESULTS
+ * 0 successfully retrieved attribute,
+ * EINVAL 'attr' is invalid,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+
+ if ((attr != NULL && *attr != NULL) && (pshared != NULL))
+ {
+ *pshared = (*attr)->pshared;
+ result = 0;
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return (result);
+} /* pthread_barrierattr_getpshared */
diff --git a/libs/pthreads/src/pthread_barrierattr_init.c b/libs/pthreads/src/pthread_barrierattr_init.c
new file mode 100644
index 0000000000..342f8b0c69
--- /dev/null
+++ b/libs/pthreads/src/pthread_barrierattr_init.c
@@ -0,0 +1,85 @@
+/*
+ * pthread_barrier_attr_init.c
+ *
+ * Description:
+ * This translation unit implements barrier primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_barrierattr_init (pthread_barrierattr_t * attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Initializes a barrier attributes object with default
+ * attributes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_barrierattr_t
+ *
+ *
+ * DESCRIPTION
+ * Initializes a barrier attributes object with default
+ * attributes.
+ *
+ * NOTES:
+ * 1) Used to define barrier types
+ *
+ * RESULTS
+ * 0 successfully initialized attr,
+ * ENOMEM insufficient memory for attr.
+ *
+ * ------------------------------------------------------
+ */
+{
+ pthread_barrierattr_t ba;
+ int result = 0;
+
+ ba = (pthread_barrierattr_t) calloc (1, sizeof (*ba));
+
+ if (ba == NULL)
+ {
+ result = ENOMEM;
+ }
+ else
+ {
+ ba->pshared = PTHREAD_PROCESS_PRIVATE;
+ }
+
+ *attr = ba;
+
+ return (result);
+} /* pthread_barrierattr_init */
diff --git a/libs/pthreads/src/pthread_barrierattr_setpshared.c b/libs/pthreads/src/pthread_barrierattr_setpshared.c
new file mode 100644
index 0000000000..08c6fde30b
--- /dev/null
+++ b/libs/pthreads/src/pthread_barrierattr_setpshared.c
@@ -0,0 +1,119 @@
+/*
+ * pthread_barrier_attr_setpshared.c
+ *
+ * Description:
+ * This translation unit implements barrier primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, int pshared)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Barriers created with 'attr' can be shared between
+ * processes if pthread_barrier_t variable is allocated
+ * in memory shared by these processes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_barrierattr_t
+ *
+ * pshared
+ * must be one of:
+ *
+ * PTHREAD_PROCESS_SHARED
+ * May be shared if in shared memory
+ *
+ * PTHREAD_PROCESS_PRIVATE
+ * Cannot be shared.
+ *
+ * DESCRIPTION
+ * Mutexes creatd with 'attr' can be shared between
+ * processes if pthread_barrier_t variable is allocated
+ * in memory shared by these processes.
+ *
+ * NOTES:
+ * 1) pshared barriers MUST be allocated in shared
+ * memory.
+ *
+ * 2) The following macro is defined if shared barriers
+ * are supported:
+ * _POSIX_THREAD_PROCESS_SHARED
+ *
+ * RESULTS
+ * 0 successfully set attribute,
+ * EINVAL 'attr' or pshared is invalid,
+ * ENOSYS PTHREAD_PROCESS_SHARED not supported,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+
+ if ((attr != NULL && *attr != NULL) &&
+ ((pshared == PTHREAD_PROCESS_SHARED) ||
+ (pshared == PTHREAD_PROCESS_PRIVATE)))
+ {
+ if (pshared == PTHREAD_PROCESS_SHARED)
+ {
+
+#if !defined( _POSIX_THREAD_PROCESS_SHARED )
+
+ result = ENOSYS;
+ pshared = PTHREAD_PROCESS_PRIVATE;
+
+#else
+
+ result = 0;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+ }
+ else
+ {
+ result = 0;
+ }
+
+ (*attr)->pshared = pshared;
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return (result);
+
+} /* pthread_barrierattr_setpshared */
diff --git a/libs/pthreads/src/pthread_cancel.c b/libs/pthreads/src/pthread_cancel.c
new file mode 100644
index 0000000000..ae60b72936
--- /dev/null
+++ b/libs/pthreads/src/pthread_cancel.c
@@ -0,0 +1,189 @@
+/*
+ * pthread_cancel.c
+ *
+ * Description:
+ * POSIX thread functions related to thread cancellation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "context.h"
+
+static void
+ptw32_cancel_self (void)
+{
+ ptw32_throw (PTW32_EPS_CANCEL);
+
+ /* Never reached */
+}
+
+static void CALLBACK
+ptw32_cancel_callback (ULONG_PTR unused)
+{
+ ptw32_throw (PTW32_EPS_CANCEL);
+
+ /* Never reached */
+}
+
+/*
+ * ptw32_RegisterCancelation() -
+ * Must have args of same type as QueueUserAPCEx because this function
+ * is a substitute for QueueUserAPCEx if it's not available.
+ */
+DWORD
+ptw32_RegisterCancelation (PAPCFUNC unused1, HANDLE threadH, DWORD unused2)
+{
+ CONTEXT context;
+
+ context.ContextFlags = CONTEXT_CONTROL;
+ GetThreadContext (threadH, &context);
+ PTW32_PROGCTR (context) = (DWORD_PTR) ptw32_cancel_self;
+ SetThreadContext (threadH, &context);
+ return 0;
+}
+
+int
+pthread_cancel (pthread_t thread)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function requests cancellation of 'thread'.
+ *
+ * PARAMETERS
+ * thread
+ * reference to an instance of pthread_t
+ *
+ *
+ * DESCRIPTION
+ * This function requests cancellation of 'thread'.
+ * NOTE: cancellation is asynchronous; use pthread_join to
+ * wait for termination of 'thread' if necessary.
+ *
+ * RESULTS
+ * 0 successfully requested cancellation,
+ * ESRCH no thread found corresponding to 'thread',
+ * ENOMEM implicit self thread create failed.
+ * ------------------------------------------------------
+ */
+{
+ int result;
+ int cancel_self;
+ pthread_t self;
+ ptw32_thread_t * tp;
+ ptw32_mcs_local_node_t stateLock;
+
+ result = pthread_kill (thread, 0);
+
+ if (0 != result)
+ {
+ return result;
+ }
+
+ if ((self = pthread_self ()).p == NULL)
+ {
+ return ENOMEM;
+ };
+
+ /*
+ * For self cancellation we need to ensure that a thread can't
+ * deadlock itself trying to cancel itself asynchronously
+ * (pthread_cancel is required to be an async-cancel
+ * safe function).
+ */
+ cancel_self = pthread_equal (thread, self);
+
+ tp = (ptw32_thread_t *) thread.p;
+
+ /*
+ * Lock for async-cancel safety.
+ */
+ ptw32_mcs_lock_acquire (&tp->stateLock, &stateLock);
+
+ if (tp->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS
+ && tp->cancelState == PTHREAD_CANCEL_ENABLE
+ && tp->state < PThreadStateCanceling)
+ {
+ if (cancel_self)
+ {
+ tp->state = PThreadStateCanceling;
+ tp->cancelState = PTHREAD_CANCEL_DISABLE;
+
+ ptw32_mcs_lock_release (&stateLock);
+ ptw32_throw (PTW32_EPS_CANCEL);
+
+ /* Never reached */
+ }
+ else
+ {
+ HANDLE threadH = tp->threadH;
+
+ SuspendThread (threadH);
+
+ if (WaitForSingleObject (threadH, 0) == WAIT_TIMEOUT)
+ {
+ tp->state = PThreadStateCanceling;
+ tp->cancelState = PTHREAD_CANCEL_DISABLE;
+ /*
+ * If alertdrv and QueueUserAPCEx is available then the following
+ * will result in a call to QueueUserAPCEx with the args given, otherwise
+ * this will result in a call to ptw32_RegisterCancelation and only
+ * the threadH arg will be used.
+ */
+ ptw32_register_cancelation ((PAPCFUNC)ptw32_cancel_callback, threadH, 0);
+ ptw32_mcs_lock_release (&stateLock);
+ ResumeThread (threadH);
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Set for deferred cancellation.
+ */
+ if (tp->state < PThreadStateCancelPending)
+ {
+ tp->state = PThreadStateCancelPending;
+ if (!SetEvent (tp->cancelEvent))
+ {
+ result = ESRCH;
+ }
+ }
+ else if (tp->state >= PThreadStateCanceling)
+ {
+ result = ESRCH;
+ }
+
+ ptw32_mcs_lock_release (&stateLock);
+ }
+
+ return (result);
+}
diff --git a/libs/pthreads/src/pthread_cond_destroy.c b/libs/pthreads/src/pthread_cond_destroy.c
new file mode 100644
index 0000000000..40d4a0896c
--- /dev/null
+++ b/libs/pthreads/src/pthread_cond_destroy.c
@@ -0,0 +1,253 @@
+/*
+ * pthread_cond_destroy.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_cond_destroy (pthread_cond_t * cond)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function destroys a condition variable
+ *
+ *
+ * PARAMETERS
+ * cond
+ * pointer to an instance of pthread_cond_t
+ *
+ *
+ * DESCRIPTION
+ * This function destroys a condition variable.
+ *
+ * NOTES:
+ * 1) A condition variable can be destroyed
+ * immediately after all the threads that
+ * are blocked on it are awakened. e.g.
+ *
+ * struct list {
+ * pthread_mutex_t lm;
+ * ...
+ * }
+ *
+ * struct elt {
+ * key k;
+ * int busy;
+ * pthread_cond_t notbusy;
+ * ...
+ * }
+ *
+ *
+ * struct elt *
+ * list_find(struct list *lp, key k)
+ * {
+ * struct elt *ep;
+ *
+ * pthread_mutex_lock(&lp->lm);
+ * while ((ep = find_elt(l,k) != NULL) && ep->busy)
+ * pthread_cond_wait(&ep->notbusy, &lp->lm);
+ * if (ep != NULL)
+ * ep->busy = 1;
+ * pthread_mutex_unlock(&lp->lm);
+ * return(ep);
+ * }
+ *
+ * delete_elt(struct list *lp, struct elt *ep)
+ * {
+ * pthread_mutex_lock(&lp->lm);
+ * assert(ep->busy);
+ * ... remove ep from list ...
+ * ep->busy = 0;
+ * (A) pthread_cond_broadcast(&ep->notbusy);
+ * pthread_mutex_unlock(&lp->lm);
+ * (B) pthread_cond_destroy(&rp->notbusy);
+ * free(ep);
+ * }
+ *
+ * In this example, the condition variable
+ * and its list element may be freed (line B)
+ * immediately after all threads waiting for
+ * it are awakened (line A), since the mutex
+ * and the code ensure that no other thread
+ * can touch the element to be deleted.
+ *
+ * RESULTS
+ * 0 successfully released condition variable,
+ * EINVAL 'cond' is invalid,
+ * EBUSY 'cond' is in use,
+ *
+ * ------------------------------------------------------
+ */
+{
+ pthread_cond_t cv;
+ int result = 0, result1 = 0, result2 = 0;
+
+ /*
+ * Assuming any race condition here is harmless.
+ */
+ if (cond == NULL || *cond == NULL)
+ {
+ return EINVAL;
+ }
+
+ if (*cond != PTHREAD_COND_INITIALIZER)
+ {
+ ptw32_mcs_local_node_t node;
+ ptw32_mcs_lock_acquire(&ptw32_cond_list_lock, &node);
+
+ cv = *cond;
+
+ /*
+ * Close the gate; this will synchronize this thread with
+ * all already signaled waiters to let them retract their
+ * waiter status - SEE NOTE 1 ABOVE!!!
+ */
+ if (ptw32_semwait (&(cv->semBlockLock)) != 0) /* Non-cancelable */
+ {
+ result = errno;
+ }
+ else
+ {
+ /*
+ * !TRY! lock mtxUnblockLock; try will detect busy condition
+ * and will not cause a deadlock with respect to concurrent
+ * signal/broadcast.
+ */
+ if ((result = pthread_mutex_trylock (&(cv->mtxUnblockLock))) != 0)
+ {
+ (void) sem_post (&(cv->semBlockLock));
+ }
+ }
+
+ if (result != 0)
+ {
+ ptw32_mcs_lock_release(&node);
+ return result;
+ }
+
+ /*
+ * Check whether cv is still busy (still has waiters)
+ */
+ if (cv->nWaitersBlocked > cv->nWaitersGone)
+ {
+ if (sem_post (&(cv->semBlockLock)) != 0)
+ {
+ result = errno;
+ }
+ result1 = pthread_mutex_unlock (&(cv->mtxUnblockLock));
+ result2 = EBUSY;
+ }
+ else
+ {
+ /*
+ * Now it is safe to destroy
+ */
+ *cond = NULL;
+
+ if (sem_destroy (&(cv->semBlockLock)) != 0)
+ {
+ result = errno;
+ }
+ if (sem_destroy (&(cv->semBlockQueue)) != 0)
+ {
+ result1 = errno;
+ }
+ if ((result2 = pthread_mutex_unlock (&(cv->mtxUnblockLock))) == 0)
+ {
+ result2 = pthread_mutex_destroy (&(cv->mtxUnblockLock));
+ }
+
+ /* Unlink the CV from the list */
+
+ if (ptw32_cond_list_head == cv)
+ {
+ ptw32_cond_list_head = cv->next;
+ }
+ else
+ {
+ cv->prev->next = cv->next;
+ }
+
+ if (ptw32_cond_list_tail == cv)
+ {
+ ptw32_cond_list_tail = cv->prev;
+ }
+ else
+ {
+ cv->next->prev = cv->prev;
+ }
+
+ (void) free (cv);
+ }
+
+ ptw32_mcs_lock_release(&node);
+ }
+ else
+ {
+ ptw32_mcs_local_node_t node;
+ /*
+ * See notes in ptw32_cond_check_need_init() above also.
+ */
+ ptw32_mcs_lock_acquire(&ptw32_cond_test_init_lock, &node);
+
+ /*
+ * Check again.
+ */
+ if (*cond == PTHREAD_COND_INITIALIZER)
+ {
+ /*
+ * This is all we need to do to destroy a statically
+ * initialised cond that has not yet been used (initialised).
+ * If we get to here, another thread waiting to initialise
+ * this cond will get an EINVAL. That's OK.
+ */
+ *cond = NULL;
+ }
+ else
+ {
+ /*
+ * The cv has been initialised while we were waiting
+ * so assume it's in use.
+ */
+ result = EBUSY;
+ }
+
+ ptw32_mcs_lock_release(&node);
+ }
+
+ return ((result != 0) ? result : ((result1 != 0) ? result1 : result2));
+}
diff --git a/libs/pthreads/src/pthread_cond_init.c b/libs/pthreads/src/pthread_cond_init.c
new file mode 100644
index 0000000000..f28fd67b43
--- /dev/null
+++ b/libs/pthreads/src/pthread_cond_init.c
@@ -0,0 +1,167 @@
+/*
+ * pthread_cond_init.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_cond_init (pthread_cond_t * cond, const pthread_condattr_t * attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function initializes a condition variable.
+ *
+ * PARAMETERS
+ * cond
+ * pointer to an instance of pthread_cond_t
+ *
+ * attr
+ * specifies optional creation attributes.
+ *
+ *
+ * DESCRIPTION
+ * This function initializes a condition variable.
+ *
+ * RESULTS
+ * 0 successfully created condition variable,
+ * EINVAL 'attr' is invalid,
+ * EAGAIN insufficient resources (other than
+ * memory,
+ * ENOMEM insufficient memory,
+ * EBUSY 'cond' is already initialized,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+ pthread_cond_t cv = NULL;
+
+ if (cond == NULL)
+ {
+ return EINVAL;
+ }
+
+ if ((attr != NULL && *attr != NULL) &&
+ ((*attr)->pshared == PTHREAD_PROCESS_SHARED))
+ {
+ /*
+ * Creating condition variable that can be shared between
+ * processes.
+ */
+ result = ENOSYS;
+ goto DONE;
+ }
+
+ cv = (pthread_cond_t) calloc (1, sizeof (*cv));
+
+ if (cv == NULL)
+ {
+ result = ENOMEM;
+ goto DONE;
+ }
+
+ cv->nWaitersBlocked = 0;
+ cv->nWaitersToUnblock = 0;
+ cv->nWaitersGone = 0;
+
+ if (sem_init (&(cv->semBlockLock), 0, 1) != 0)
+ {
+ result = errno;
+ goto FAIL0;
+ }
+
+ if (sem_init (&(cv->semBlockQueue), 0, 0) != 0)
+ {
+ result = errno;
+ goto FAIL1;
+ }
+
+ if ((result = pthread_mutex_init (&(cv->mtxUnblockLock), 0)) != 0)
+ {
+ goto FAIL2;
+ }
+
+ result = 0;
+
+ goto DONE;
+
+ /*
+ * -------------
+ * Failed...
+ * -------------
+ */
+FAIL2:
+ (void) sem_destroy (&(cv->semBlockQueue));
+
+FAIL1:
+ (void) sem_destroy (&(cv->semBlockLock));
+
+FAIL0:
+ (void) free (cv);
+ cv = NULL;
+
+DONE:
+ if (0 == result)
+ {
+ ptw32_mcs_local_node_t node;
+
+ ptw32_mcs_lock_acquire(&ptw32_cond_list_lock, &node);
+
+ cv->next = NULL;
+ cv->prev = ptw32_cond_list_tail;
+
+ if (ptw32_cond_list_tail != NULL)
+ {
+ ptw32_cond_list_tail->next = cv;
+ }
+
+ ptw32_cond_list_tail = cv;
+
+ if (ptw32_cond_list_head == NULL)
+ {
+ ptw32_cond_list_head = cv;
+ }
+
+ ptw32_mcs_lock_release(&node);
+ }
+
+ *cond = cv;
+
+ return result;
+
+} /* pthread_cond_init */
diff --git a/libs/pthreads/src/pthread_cond_signal.c b/libs/pthreads/src/pthread_cond_signal.c
new file mode 100644
index 0000000000..2b4f6d4d44
--- /dev/null
+++ b/libs/pthreads/src/pthread_cond_signal.c
@@ -0,0 +1,231 @@
+/*
+ * pthread_cond_signal.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * -------------------------------------------------------------
+ * Algorithm:
+ * See the comments at the top of pthread_cond_wait.c.
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+static INLINE int
+ptw32_cond_unblock (pthread_cond_t * cond, int unblockAll)
+ /*
+ * Notes.
+ *
+ * Does not use the external mutex for synchronisation,
+ * therefore semBlockLock is needed.
+ * mtxUnblockLock is for LEVEL-2 synch. LEVEL-2 is the
+ * state where the external mutex is not necessarily locked by
+ * any thread, ie. between cond_wait unlocking and re-acquiring
+ * the lock after having been signaled or a timeout or
+ * cancellation.
+ *
+ * Uses the following CV elements:
+ * nWaitersBlocked
+ * nWaitersToUnblock
+ * nWaitersGone
+ * mtxUnblockLock
+ * semBlockLock
+ * semBlockQueue
+ */
+{
+ int result;
+ pthread_cond_t cv;
+ int nSignalsToIssue;
+
+ if (cond == NULL || *cond == NULL)
+ {
+ return EINVAL;
+ }
+
+ cv = *cond;
+
+ /*
+ * No-op if the CV is static and hasn't been initialised yet.
+ * Assuming that any race condition is harmless.
+ */
+ if (cv == PTHREAD_COND_INITIALIZER)
+ {
+ return 0;
+ }
+
+ if ((result = pthread_mutex_lock (&(cv->mtxUnblockLock))) != 0)
+ {
+ return result;
+ }
+
+ if (0 != cv->nWaitersToUnblock)
+ {
+ if (0 == cv->nWaitersBlocked)
+ {
+ return pthread_mutex_unlock (&(cv->mtxUnblockLock));
+ }
+ if (unblockAll)
+ {
+ cv->nWaitersToUnblock += (nSignalsToIssue = cv->nWaitersBlocked);
+ cv->nWaitersBlocked = 0;
+ }
+ else
+ {
+ nSignalsToIssue = 1;
+ cv->nWaitersToUnblock++;
+ cv->nWaitersBlocked--;
+ }
+ }
+ else if (cv->nWaitersBlocked > cv->nWaitersGone)
+ {
+ /* Use the non-cancellable version of sem_wait() */
+ if (ptw32_semwait (&(cv->semBlockLock)) != 0)
+ {
+ result = errno;
+ (void) pthread_mutex_unlock (&(cv->mtxUnblockLock));
+ return result;
+ }
+ if (0 != cv->nWaitersGone)
+ {
+ cv->nWaitersBlocked -= cv->nWaitersGone;
+ cv->nWaitersGone = 0;
+ }
+ if (unblockAll)
+ {
+ nSignalsToIssue = cv->nWaitersToUnblock = cv->nWaitersBlocked;
+ cv->nWaitersBlocked = 0;
+ }
+ else
+ {
+ nSignalsToIssue = cv->nWaitersToUnblock = 1;
+ cv->nWaitersBlocked--;
+ }
+ }
+ else
+ {
+ return pthread_mutex_unlock (&(cv->mtxUnblockLock));
+ }
+
+ if ((result = pthread_mutex_unlock (&(cv->mtxUnblockLock))) == 0)
+ {
+ if (sem_post_multiple (&(cv->semBlockQueue), nSignalsToIssue) != 0)
+ {
+ result = errno;
+ }
+ }
+
+ return result;
+
+} /* ptw32_cond_unblock */
+
+int
+pthread_cond_signal (pthread_cond_t * cond)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function signals a condition variable, waking
+ * one waiting thread.
+ * If SCHED_FIFO or SCHED_RR policy threads are waiting
+ * the highest priority waiter is awakened; otherwise,
+ * an unspecified waiter is awakened.
+ *
+ * PARAMETERS
+ * cond
+ * pointer to an instance of pthread_cond_t
+ *
+ *
+ * DESCRIPTION
+ * This function signals a condition variable, waking
+ * one waiting thread.
+ * If SCHED_FIFO or SCHED_RR policy threads are waiting
+ * the highest priority waiter is awakened; otherwise,
+ * an unspecified waiter is awakened.
+ *
+ * NOTES:
+ *
+ * 1) Use when any waiter can respond and only one need
+ * respond (all waiters being equal).
+ *
+ * RESULTS
+ * 0 successfully signaled condition,
+ * EINVAL 'cond' is invalid,
+ *
+ * ------------------------------------------------------
+ */
+{
+ /*
+ * The '0'(FALSE) unblockAll arg means unblock ONE waiter.
+ */
+ return (ptw32_cond_unblock (cond, 0));
+
+} /* pthread_cond_signal */
+
+int
+pthread_cond_broadcast (pthread_cond_t * cond)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function broadcasts the condition variable,
+ * waking all current waiters.
+ *
+ * PARAMETERS
+ * cond
+ * pointer to an instance of pthread_cond_t
+ *
+ *
+ * DESCRIPTION
+ * This function signals a condition variable, waking
+ * all waiting threads.
+ *
+ * NOTES:
+ *
+ * 1) Use when more than one waiter may respond to
+ * predicate change or if any waiting thread may
+ * not be able to respond
+ *
+ * RESULTS
+ * 0 successfully signalled condition to all
+ * waiting threads,
+ * EINVAL 'cond' is invalid
+ * ENOSPC a required resource has been exhausted,
+ *
+ * ------------------------------------------------------
+ */
+{
+ /*
+ * The TRUE unblockAll arg means unblock ALL waiters.
+ */
+ return (ptw32_cond_unblock (cond, PTW32_TRUE));
+
+} /* pthread_cond_broadcast */
diff --git a/libs/pthreads/src/pthread_cond_wait.c b/libs/pthreads/src/pthread_cond_wait.c
new file mode 100644
index 0000000000..359219ae9b
--- /dev/null
+++ b/libs/pthreads/src/pthread_cond_wait.c
@@ -0,0 +1,567 @@
+/*
+ * pthread_cond_wait.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * -------------------------------------------------------------
+ * Algorithm:
+ * The algorithm used in this implementation is that developed by
+ * Alexander Terekhov in colaboration with Louis Thomas. The bulk
+ * of the discussion is recorded in the file README.CV, which contains
+ * several generations of both colaborators original algorithms. The final
+ * algorithm used here is the one referred to as
+ *
+ * Algorithm 8a / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL
+ *
+ * presented below in pseudo-code as it appeared:
+ *
+ *
+ * given:
+ * semBlockLock - bin.semaphore
+ * semBlockQueue - semaphore
+ * mtxExternal - mutex or CS
+ * mtxUnblockLock - mutex or CS
+ * nWaitersGone - int
+ * nWaitersBlocked - int
+ * nWaitersToUnblock - int
+ *
+ * wait( timeout ) {
+ *
+ * [auto: register int result ] // error checking omitted
+ * [auto: register int nSignalsWasLeft ]
+ * [auto: register int nWaitersWasGone ]
+ *
+ * sem_wait( semBlockLock );
+ * nWaitersBlocked++;
+ * sem_post( semBlockLock );
+ *
+ * unlock( mtxExternal );
+ * bTimedOut = sem_wait( semBlockQueue,timeout );
+ *
+ * lock( mtxUnblockLock );
+ * if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) {
+ * if ( bTimeout ) { // timeout (or canceled)
+ * if ( 0 != nWaitersBlocked ) {
+ * nWaitersBlocked--;
+ * }
+ * else {
+ * nWaitersGone++; // count spurious wakeups.
+ * }
+ * }
+ * if ( 0 == --nWaitersToUnblock ) {
+ * if ( 0 != nWaitersBlocked ) {
+ * sem_post( semBlockLock ); // open the gate.
+ * nSignalsWasLeft = 0; // do not open the gate
+ * // below again.
+ * }
+ * else if ( 0 != (nWaitersWasGone = nWaitersGone) ) {
+ * nWaitersGone = 0;
+ * }
+ * }
+ * }
+ * else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or
+ * // spurious semaphore :-)
+ * sem_wait( semBlockLock );
+ * nWaitersBlocked -= nWaitersGone; // something is going on here
+ * // - test of timeouts? :-)
+ * sem_post( semBlockLock );
+ * nWaitersGone = 0;
+ * }
+ * unlock( mtxUnblockLock );
+ *
+ * if ( 1 == nSignalsWasLeft ) {
+ * if ( 0 != nWaitersWasGone ) {
+ * // sem_adjust( semBlockQueue,-nWaitersWasGone );
+ * while ( nWaitersWasGone-- ) {
+ * sem_wait( semBlockQueue ); // better now than spurious later
+ * }
+ * } sem_post( semBlockLock ); // open the gate
+ * }
+ *
+ * lock( mtxExternal );
+ *
+ * return ( bTimedOut ) ? ETIMEOUT : 0;
+ * }
+ *
+ * signal(bAll) {
+ *
+ * [auto: register int result ]
+ * [auto: register int nSignalsToIssue]
+ *
+ * lock( mtxUnblockLock );
+ *
+ * if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
+ * if ( 0 == nWaitersBlocked ) { // NO-OP
+ * return unlock( mtxUnblockLock );
+ * }
+ * if (bAll) {
+ * nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked;
+ * nWaitersBlocked = 0;
+ * }
+ * else {
+ * nSignalsToIssue = 1;
+ * nWaitersToUnblock++;
+ * nWaitersBlocked--;
+ * }
+ * }
+ * else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
+ * sem_wait( semBlockLock ); // close the gate
+ * if ( 0 != nWaitersGone ) {
+ * nWaitersBlocked -= nWaitersGone;
+ * nWaitersGone = 0;
+ * }
+ * if (bAll) {
+ * nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked;
+ * nWaitersBlocked = 0;
+ * }
+ * else {
+ * nSignalsToIssue = nWaitersToUnblock = 1;
+ * nWaitersBlocked--;
+ * }
+ * }
+ * else { // NO-OP
+ * return unlock( mtxUnblockLock );
+ * }
+ *
+ * unlock( mtxUnblockLock );
+ * sem_post( semBlockQueue,nSignalsToIssue );
+ * return result;
+ * }
+ * -------------------------------------------------------------
+ *
+ * Algorithm 9 / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL
+ *
+ * presented below in pseudo-code; basically 8a...
+ * ...BUT W/O "spurious wakes" prevention:
+ *
+ *
+ * given:
+ * semBlockLock - bin.semaphore
+ * semBlockQueue - semaphore
+ * mtxExternal - mutex or CS
+ * mtxUnblockLock - mutex or CS
+ * nWaitersGone - int
+ * nWaitersBlocked - int
+ * nWaitersToUnblock - int
+ *
+ * wait( timeout ) {
+ *
+ * [auto: register int result ] // error checking omitted
+ * [auto: register int nSignalsWasLeft ]
+ *
+ * sem_wait( semBlockLock );
+ * ++nWaitersBlocked;
+ * sem_post( semBlockLock );
+ *
+ * unlock( mtxExternal );
+ * bTimedOut = sem_wait( semBlockQueue,timeout );
+ *
+ * lock( mtxUnblockLock );
+ * if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) {
+ * --nWaitersToUnblock;
+ * }
+ * else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or
+ * // spurious semaphore :-)
+ * sem_wait( semBlockLock );
+ * nWaitersBlocked -= nWaitersGone; // something is going on here
+ * // - test of timeouts? :-)
+ * sem_post( semBlockLock );
+ * nWaitersGone = 0;
+ * }
+ * unlock( mtxUnblockLock );
+ *
+ * if ( 1 == nSignalsWasLeft ) {
+ * sem_post( semBlockLock ); // open the gate
+ * }
+ *
+ * lock( mtxExternal );
+ *
+ * return ( bTimedOut ) ? ETIMEOUT : 0;
+ * }
+ *
+ * signal(bAll) {
+ *
+ * [auto: register int result ]
+ * [auto: register int nSignalsToIssue]
+ *
+ * lock( mtxUnblockLock );
+ *
+ * if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
+ * if ( 0 == nWaitersBlocked ) { // NO-OP
+ * return unlock( mtxUnblockLock );
+ * }
+ * if (bAll) {
+ * nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked;
+ * nWaitersBlocked = 0;
+ * }
+ * else {
+ * nSignalsToIssue = 1;
+ * ++nWaitersToUnblock;
+ * --nWaitersBlocked;
+ * }
+ * }
+ * else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
+ * sem_wait( semBlockLock ); // close the gate
+ * if ( 0 != nWaitersGone ) {
+ * nWaitersBlocked -= nWaitersGone;
+ * nWaitersGone = 0;
+ * }
+ * if (bAll) {
+ * nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked;
+ * nWaitersBlocked = 0;
+ * }
+ * else {
+ * nSignalsToIssue = nWaitersToUnblock = 1;
+ * --nWaitersBlocked;
+ * }
+ * }
+ * else { // NO-OP
+ * return unlock( mtxUnblockLock );
+ * }
+ *
+ * unlock( mtxUnblockLock );
+ * sem_post( semBlockQueue,nSignalsToIssue );
+ * return result;
+ * }
+ * -------------------------------------------------------------
+ *
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * Arguments for cond_wait_cleanup, since we can only pass a
+ * single void * to it.
+ */
+typedef struct
+{
+ pthread_mutex_t *mutexPtr;
+ pthread_cond_t cv;
+ int *resultPtr;
+} ptw32_cond_wait_cleanup_args_t;
+
+static void PTW32_CDECL
+ptw32_cond_wait_cleanup (void *args)
+{
+ ptw32_cond_wait_cleanup_args_t *cleanup_args =
+ (ptw32_cond_wait_cleanup_args_t *) args;
+ pthread_cond_t cv = cleanup_args->cv;
+ int *resultPtr = cleanup_args->resultPtr;
+ int nSignalsWasLeft;
+ int result;
+
+ /*
+ * Whether we got here as a result of signal/broadcast or because of
+ * timeout on wait or thread cancellation we indicate that we are no
+ * longer waiting. The waiter is responsible for adjusting waiters
+ * (to)unblock(ed) counts (protected by unblock lock).
+ */
+ if ((result = pthread_mutex_lock (&(cv->mtxUnblockLock))) != 0)
+ {
+ *resultPtr = result;
+ return;
+ }
+
+ if (0 != (nSignalsWasLeft = cv->nWaitersToUnblock))
+ {
+ --(cv->nWaitersToUnblock);
+ }
+ else if (INT_MAX / 2 == ++(cv->nWaitersGone))
+ {
+ /* Use the non-cancellable version of sem_wait() */
+ if (ptw32_semwait (&(cv->semBlockLock)) != 0)
+ {
+ *resultPtr = errno;
+ /*
+ * This is a fatal error for this CV,
+ * so we deliberately don't unlock
+ * cv->mtxUnblockLock before returning.
+ */
+ return;
+ }
+ cv->nWaitersBlocked -= cv->nWaitersGone;
+ if (sem_post (&(cv->semBlockLock)) != 0)
+ {
+ *resultPtr = errno;
+ /*
+ * This is a fatal error for this CV,
+ * so we deliberately don't unlock
+ * cv->mtxUnblockLock before returning.
+ */
+ return;
+ }
+ cv->nWaitersGone = 0;
+ }
+
+ if ((result = pthread_mutex_unlock (&(cv->mtxUnblockLock))) != 0)
+ {
+ *resultPtr = result;
+ return;
+ }
+
+ if (1 == nSignalsWasLeft)
+ {
+ if (sem_post (&(cv->semBlockLock)) != 0)
+ {
+ *resultPtr = errno;
+ return;
+ }
+ }
+
+ /*
+ * XSH: Upon successful return, the mutex has been locked and is owned
+ * by the calling thread.
+ */
+ if ((result = pthread_mutex_lock (cleanup_args->mutexPtr)) != 0)
+ {
+ *resultPtr = result;
+ }
+} /* ptw32_cond_wait_cleanup */
+
+static INLINE int
+ptw32_cond_timedwait (pthread_cond_t * cond,
+ pthread_mutex_t * mutex, const struct timespec *abstime)
+{
+ int result = 0;
+ pthread_cond_t cv;
+ ptw32_cond_wait_cleanup_args_t cleanup_args;
+
+ if (cond == NULL || *cond == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static condition variable. We check
+ * again inside the guarded section of ptw32_cond_check_need_init()
+ * to avoid race conditions.
+ */
+ if (*cond == PTHREAD_COND_INITIALIZER)
+ {
+ result = ptw32_cond_check_need_init (cond);
+ }
+
+ if (result != 0 && result != EBUSY)
+ {
+ return result;
+ }
+
+ cv = *cond;
+
+ /* Thread can be cancelled in sem_wait() but this is OK */
+ if (sem_wait (&(cv->semBlockLock)) != 0)
+ {
+ return errno;
+ }
+
+ ++(cv->nWaitersBlocked);
+
+ if (sem_post (&(cv->semBlockLock)) != 0)
+ {
+ return errno;
+ }
+
+ /*
+ * Setup this waiter cleanup handler
+ */
+ cleanup_args.mutexPtr = mutex;
+ cleanup_args.cv = cv;
+ cleanup_args.resultPtr = &result;
+
+#if defined(_MSC_VER) && _MSC_VER < 1400
+#pragma inline_depth(0)
+#endif
+ pthread_cleanup_push (ptw32_cond_wait_cleanup, (void *) &cleanup_args);
+
+ /*
+ * Now we can release 'mutex' and...
+ */
+ if ((result = pthread_mutex_unlock (mutex)) == 0)
+ {
+
+ /*
+ * ...wait to be awakened by
+ * pthread_cond_signal, or
+ * pthread_cond_broadcast, or
+ * timeout, or
+ * thread cancellation
+ *
+ * Note:
+ *
+ * sem_timedwait is a cancellation point,
+ * hence providing the mechanism for making
+ * pthread_cond_wait a cancellation point.
+ * We use the cleanup mechanism to ensure we
+ * re-lock the mutex and adjust (to)unblock(ed) waiters
+ * counts if we are cancelled, timed out or signalled.
+ */
+ if (sem_timedwait (&(cv->semBlockQueue), abstime) != 0)
+ {
+ result = errno;
+ }
+ }
+
+ /*
+ * Always cleanup
+ */
+ pthread_cleanup_pop (1);
+#if defined(_MSC_VER) && _MSC_VER < 1400
+#pragma inline_depth()
+#endif
+
+ /*
+ * "result" can be modified by the cleanup handler.
+ */
+ return result;
+
+} /* ptw32_cond_timedwait */
+
+
+int
+pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function waits on a condition variable until
+ * awakened by a signal or broadcast.
+ *
+ * Caller MUST be holding the mutex lock; the
+ * lock is released and the caller is blocked waiting
+ * on 'cond'. When 'cond' is signaled, the mutex
+ * is re-acquired before returning to the caller.
+ *
+ * PARAMETERS
+ * cond
+ * pointer to an instance of pthread_cond_t
+ *
+ * mutex
+ * pointer to an instance of pthread_mutex_t
+ *
+ *
+ * DESCRIPTION
+ * This function waits on a condition variable until
+ * awakened by a signal or broadcast.
+ *
+ * NOTES:
+ *
+ * 1) The function must be called with 'mutex' LOCKED
+ * by the calling thread, or undefined behaviour
+ * will result.
+ *
+ * 2) This routine atomically releases 'mutex' and causes
+ * the calling thread to block on the condition variable.
+ * The blocked thread may be awakened by
+ * pthread_cond_signal or
+ * pthread_cond_broadcast.
+ *
+ * Upon successful completion, the 'mutex' has been locked and
+ * is owned by the calling thread.
+ *
+ *
+ * RESULTS
+ * 0 caught condition; mutex released,
+ * EINVAL 'cond' or 'mutex' is invalid,
+ * EINVAL different mutexes for concurrent waits,
+ * EINVAL mutex is not held by the calling thread,
+ *
+ * ------------------------------------------------------
+ */
+{
+ /*
+ * The NULL abstime arg means INFINITE waiting.
+ */
+ return (ptw32_cond_timedwait (cond, mutex, NULL));
+
+} /* pthread_cond_wait */
+
+
+int
+pthread_cond_timedwait (pthread_cond_t * cond,
+ pthread_mutex_t * mutex,
+ const struct timespec *abstime)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function waits on a condition variable either until
+ * awakened by a signal or broadcast; or until the time
+ * specified by abstime passes.
+ *
+ * PARAMETERS
+ * cond
+ * pointer to an instance of pthread_cond_t
+ *
+ * mutex
+ * pointer to an instance of pthread_mutex_t
+ *
+ * abstime
+ * pointer to an instance of (const struct timespec)
+ *
+ *
+ * DESCRIPTION
+ * This function waits on a condition variable either until
+ * awakened by a signal or broadcast; or until the time
+ * specified by abstime passes.
+ *
+ * NOTES:
+ * 1) The function must be called with 'mutex' LOCKED
+ * by the calling thread, or undefined behaviour
+ * will result.
+ *
+ * 2) This routine atomically releases 'mutex' and causes
+ * the calling thread to block on the condition variable.
+ * The blocked thread may be awakened by
+ * pthread_cond_signal or
+ * pthread_cond_broadcast.
+ *
+ *
+ * RESULTS
+ * 0 caught condition; mutex released,
+ * EINVAL 'cond', 'mutex', or abstime is invalid,
+ * EINVAL different mutexes for concurrent waits,
+ * EINVAL mutex is not held by the calling thread,
+ * ETIMEDOUT abstime ellapsed before cond was signaled.
+ *
+ * ------------------------------------------------------
+ */
+{
+ if (abstime == NULL)
+ {
+ return EINVAL;
+ }
+
+ return (ptw32_cond_timedwait (cond, mutex, abstime));
+
+} /* pthread_cond_timedwait */
diff --git a/libs/pthreads/src/pthread_condattr_destroy.c b/libs/pthreads/src/pthread_condattr_destroy.c
new file mode 100644
index 0000000000..58a14828fd
--- /dev/null
+++ b/libs/pthreads/src/pthread_condattr_destroy.c
@@ -0,0 +1,86 @@
+/*
+ * condvar_attr_destroy.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_condattr_destroy (pthread_condattr_t * attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Destroys a condition variable attributes object.
+ * The object can no longer be used.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_condattr_t
+ *
+ *
+ * DESCRIPTION
+ * Destroys a condition variable attributes object.
+ * The object can no longer be used.
+ *
+ * NOTES:
+ * 1) Does not affect condition variables created
+ * using 'attr'
+ *
+ * RESULTS
+ * 0 successfully released attr,
+ * EINVAL 'attr' is invalid.
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+
+ if (attr == NULL || *attr == NULL)
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ (void) free (*attr);
+
+ *attr = NULL;
+ result = 0;
+ }
+
+ return result;
+
+} /* pthread_condattr_destroy */
diff --git a/libs/pthreads/src/pthread_condattr_getpshared.c b/libs/pthreads/src/pthread_condattr_getpshared.c
new file mode 100644
index 0000000000..a0ac6d8829
--- /dev/null
+++ b/libs/pthreads/src/pthread_condattr_getpshared.c
@@ -0,0 +1,97 @@
+/*
+ * pthread_condattr_getpshared.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_condattr_getpshared (const pthread_condattr_t * attr, int *pshared)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Determine whether condition variables created with 'attr'
+ * can be shared between processes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_condattr_t
+ *
+ * pshared
+ * will be set to one of:
+ *
+ * PTHREAD_PROCESS_SHARED
+ * May be shared if in shared memory
+ *
+ * PTHREAD_PROCESS_PRIVATE
+ * Cannot be shared.
+ *
+ *
+ * DESCRIPTION
+ * Condition Variables created with 'attr' can be shared
+ * between processes if pthread_cond_t variable is allocated
+ * in memory shared by these processes.
+ * NOTES:
+ * 1) pshared condition variables MUST be allocated in
+ * shared memory.
+ *
+ * 2) The following macro is defined if shared mutexes
+ * are supported:
+ * _POSIX_THREAD_PROCESS_SHARED
+ *
+ * RESULTS
+ * 0 successfully retrieved attribute,
+ * EINVAL 'attr' or 'pshared' is invalid,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+
+ if ((attr != NULL && *attr != NULL) && (pshared != NULL))
+ {
+ *pshared = (*attr)->pshared;
+ result = 0;
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return result;
+
+} /* pthread_condattr_getpshared */
diff --git a/libs/pthreads/src/pthread_condattr_init.c b/libs/pthreads/src/pthread_condattr_init.c
new file mode 100644
index 0000000000..5987878e0c
--- /dev/null
+++ b/libs/pthreads/src/pthread_condattr_init.c
@@ -0,0 +1,87 @@
+/*
+ * pthread_condattr_init.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_condattr_init (pthread_condattr_t * attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Initializes a condition variable attributes object
+ * with default attributes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_condattr_t
+ *
+ *
+ * DESCRIPTION
+ * Initializes a condition variable attributes object
+ * with default attributes.
+ *
+ * NOTES:
+ * 1) Use to define condition variable types
+ * 2) It is up to the application to ensure
+ * that it doesn't re-init an attribute
+ * without destroying it first. Otherwise
+ * a memory leak is created.
+ *
+ * RESULTS
+ * 0 successfully initialized attr,
+ * ENOMEM insufficient memory for attr.
+ *
+ * ------------------------------------------------------
+ */
+{
+ pthread_condattr_t attr_result;
+ int result = 0;
+
+ attr_result = (pthread_condattr_t) calloc (1, sizeof (*attr_result));
+
+ if (attr_result == NULL)
+ {
+ result = ENOMEM;
+ }
+
+ *attr = attr_result;
+
+ return result;
+
+} /* pthread_condattr_init */
diff --git a/libs/pthreads/src/pthread_condattr_setpshared.c b/libs/pthreads/src/pthread_condattr_setpshared.c
new file mode 100644
index 0000000000..954fb38299
--- /dev/null
+++ b/libs/pthreads/src/pthread_condattr_setpshared.c
@@ -0,0 +1,117 @@
+/*
+ * pthread_condattr_setpshared.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_condattr_setpshared (pthread_condattr_t * attr, int pshared)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Mutexes created with 'attr' can be shared between
+ * processes if pthread_mutex_t variable is allocated
+ * in memory shared by these processes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_mutexattr_t
+ *
+ * pshared
+ * must be one of:
+ *
+ * PTHREAD_PROCESS_SHARED
+ * May be shared if in shared memory
+ *
+ * PTHREAD_PROCESS_PRIVATE
+ * Cannot be shared.
+ *
+ * DESCRIPTION
+ * Mutexes creatd with 'attr' can be shared between
+ * processes if pthread_mutex_t variable is allocated
+ * in memory shared by these processes.
+ *
+ * NOTES:
+ * 1) pshared mutexes MUST be allocated in shared
+ * memory.
+ *
+ * 2) The following macro is defined if shared mutexes
+ * are supported:
+ * _POSIX_THREAD_PROCESS_SHARED
+ *
+ * RESULTS
+ * 0 successfully set attribute,
+ * EINVAL 'attr' or pshared is invalid,
+ * ENOSYS PTHREAD_PROCESS_SHARED not supported,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+
+ if ((attr != NULL && *attr != NULL)
+ && ((pshared == PTHREAD_PROCESS_SHARED)
+ || (pshared == PTHREAD_PROCESS_PRIVATE)))
+ {
+ if (pshared == PTHREAD_PROCESS_SHARED)
+ {
+
+#if !defined( _POSIX_THREAD_PROCESS_SHARED )
+ result = ENOSYS;
+ pshared = PTHREAD_PROCESS_PRIVATE;
+#else
+ result = 0;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+ }
+ else
+ {
+ result = 0;
+ }
+
+ (*attr)->pshared = pshared;
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return result;
+
+} /* pthread_condattr_setpshared */
diff --git a/libs/pthreads/src/pthread_delay_np.c b/libs/pthreads/src/pthread_delay_np.c
new file mode 100644
index 0000000000..e6c96d8070
--- /dev/null
+++ b/libs/pthreads/src/pthread_delay_np.c
@@ -0,0 +1,172 @@
+/*
+ * pthreads_delay_np.c
+ *
+ * Description:
+ * This translation unit implements non-portable thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * pthread_delay_np
+ *
+ * DESCRIPTION
+ *
+ * This routine causes a thread to delay execution for a specific period of time.
+ * This period ends at the current time plus the specified interval. The routine
+ * will not return before the end of the period is reached, but may return an
+ * arbitrary amount of time after the period has gone by. This can be due to
+ * system load, thread priorities, and system timer granularity.
+ *
+ * Specifying an interval of zero (0) seconds and zero (0) nanoseconds is
+ * allowed and can be used to force the thread to give up the processor or to
+ * deliver a pending cancelation request.
+ *
+ * The timespec structure contains the following two fields:
+ *
+ * tv_sec is an integer number of seconds.
+ * tv_nsec is an integer number of nanoseconds.
+ *
+ * Return Values
+ *
+ * If an error condition occurs, this routine returns an integer value indicating
+ * the type of error. Possible return values are as follows:
+ *
+ * 0
+ * Successful completion.
+ * [EINVAL]
+ * The value specified by interval is invalid.
+ *
+ * Example
+ *
+ * The following code segment would wait for 5 and 1/2 seconds
+ *
+ * struct timespec tsWait;
+ * int intRC;
+ *
+ * tsWait.tv_sec = 5;
+ * tsWait.tv_nsec = 500000000L;
+ * intRC = pthread_delay_np(&tsWait);
+ */
+int
+pthread_delay_np (struct timespec *interval)
+{
+ DWORD wait_time;
+ DWORD secs_in_millisecs;
+ DWORD millisecs;
+ DWORD status;
+ pthread_t self;
+ ptw32_thread_t * sp;
+
+ if (interval == NULL)
+ {
+ return EINVAL;
+ }
+
+ if (interval->tv_sec == 0L && interval->tv_nsec == 0L)
+ {
+ pthread_testcancel ();
+ Sleep (0);
+ pthread_testcancel ();
+ return (0);
+ }
+
+ /* convert secs to millisecs */
+ secs_in_millisecs = (DWORD)interval->tv_sec * 1000L;
+
+ /* convert nanosecs to millisecs (rounding up) */
+ millisecs = (interval->tv_nsec + 999999L) / 1000000L;
+
+#if defined(__WATCOMC__)
+#pragma disable_message (124)
+#endif
+
+ /*
+ * Most compilers will issue a warning 'comparison always 0'
+ * because the variable type is unsigned, but we need to keep this
+ * for some reason I can't recall now.
+ */
+ if (0 > (wait_time = secs_in_millisecs + millisecs))
+ {
+ return EINVAL;
+ }
+
+#if defined(__WATCOMC__)
+#pragma enable_message (124)
+#endif
+
+ if (NULL == (self = pthread_self ()).p)
+ {
+ return ENOMEM;
+ }
+
+ sp = (ptw32_thread_t *) self.p;
+
+ if (sp->cancelState == PTHREAD_CANCEL_ENABLE)
+ {
+ /*
+ * Async cancelation won't catch us until wait_time is up.
+ * Deferred cancelation will cancel us immediately.
+ */
+ if (WAIT_OBJECT_0 ==
+ (status = WaitForSingleObject (sp->cancelEvent, wait_time)))
+ {
+ ptw32_mcs_local_node_t stateLock;
+ /*
+ * Canceling!
+ */
+ ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
+ if (sp->state < PThreadStateCanceling)
+ {
+ sp->state = PThreadStateCanceling;
+ sp->cancelState = PTHREAD_CANCEL_DISABLE;
+ ptw32_mcs_lock_release (&stateLock);
+
+ ptw32_throw (PTW32_EPS_CANCEL);
+ }
+
+ ptw32_mcs_lock_release (&stateLock);
+ return ESRCH;
+ }
+ else if (status != WAIT_TIMEOUT)
+ {
+ return EINVAL;
+ }
+ }
+ else
+ {
+ Sleep (wait_time);
+ }
+
+ return (0);
+}
diff --git a/libs/pthreads/src/pthread_detach.c b/libs/pthreads/src/pthread_detach.c
new file mode 100644
index 0000000000..9ff6587f3c
--- /dev/null
+++ b/libs/pthreads/src/pthread_detach.c
@@ -0,0 +1,136 @@
+/*
+ * pthread_detach.c
+ *
+ * Description:
+ * This translation unit implements functions related to thread
+ * synchronisation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * Not needed yet, but defining it should indicate clashes with build target
+ * environment that should be fixed.
+ */
+#if !defined(WINCE)
+# include <signal.h>
+#endif
+
+
+int
+pthread_detach (pthread_t thread)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function detaches the given thread.
+ *
+ * PARAMETERS
+ * thread
+ * an instance of a pthread_t
+ *
+ *
+ * DESCRIPTION
+ * This function detaches the given thread. You may use it to
+ * detach the main thread or to detach a joinable thread.
+ * NOTE: detached threads cannot be joined;
+ * storage is freed immediately on termination.
+ *
+ * RESULTS
+ * 0 successfully detached the thread,
+ * EINVAL thread is not a joinable thread,
+ * ENOSPC a required resource has been exhausted,
+ * ESRCH no thread could be found for 'thread',
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+ BOOL destroyIt = PTW32_FALSE;
+ ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
+ ptw32_mcs_local_node_t node;
+
+ ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node);
+
+ if (NULL == tp
+ || thread.x != tp->ptHandle.x)
+ {
+ result = ESRCH;
+ }
+ else if (PTHREAD_CREATE_DETACHED == tp->detachState)
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ ptw32_mcs_local_node_t stateLock;
+ /*
+ * Joinable ptw32_thread_t structs are not scavenged until
+ * a join or detach is done. The thread may have exited already,
+ * but all of the state and locks etc are still there.
+ */
+ result = 0;
+
+ ptw32_mcs_lock_acquire (&tp->stateLock, &stateLock);
+ if (tp->state != PThreadStateLast)
+ {
+ tp->detachState = PTHREAD_CREATE_DETACHED;
+ }
+ else if (tp->detachState != PTHREAD_CREATE_DETACHED)
+ {
+ /*
+ * Thread is joinable and has exited or is exiting.
+ */
+ destroyIt = PTW32_TRUE;
+ }
+ ptw32_mcs_lock_release (&stateLock);
+ }
+
+ ptw32_mcs_lock_release(&node);
+
+ if (result == 0)
+ {
+ /* Thread is joinable */
+
+ if (destroyIt)
+ {
+ /* The thread has exited or is exiting but has not been joined or
+ * detached. Need to wait in case it's still exiting.
+ */
+ (void) WaitForSingleObject(tp->threadH, INFINITE);
+ ptw32_threadDestroy (thread);
+ }
+ }
+
+ return (result);
+
+} /* pthread_detach */
diff --git a/libs/pthreads/src/pthread_equal.c b/libs/pthreads/src/pthread_equal.c
new file mode 100644
index 0000000000..5ddd82acba
--- /dev/null
+++ b/libs/pthreads/src/pthread_equal.c
@@ -0,0 +1,76 @@
+/*
+ * pthread_equal.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_equal (pthread_t t1, pthread_t t2)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function returns nonzero if t1 and t2 are equal, else
+ * returns zero
+ *
+ * PARAMETERS
+ * t1,
+ * t2
+ * thread IDs
+ *
+ *
+ * DESCRIPTION
+ * This function returns nonzero if t1 and t2 are equal, else
+ * returns zero.
+ *
+ * RESULTS
+ * non-zero if t1 and t2 refer to the same thread,
+ * 0 t1 and t2 do not refer to the same thread
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+
+ /*
+ * We also accept NULL == NULL - treating NULL as a thread
+ * for this special case, because there is no error that we can return.
+ */
+ result = ( t1.p == t2.p && t1.x == t2.x );
+
+ return (result);
+
+} /* pthread_equal */
diff --git a/libs/pthreads/src/pthread_exit.c b/libs/pthreads/src/pthread_exit.c
new file mode 100644
index 0000000000..37b3c09902
--- /dev/null
+++ b/libs/pthreads/src/pthread_exit.c
@@ -0,0 +1,106 @@
+/*
+ * pthread_exit.c
+ *
+ * Description:
+ * This translation unit implements routines associated with exiting from
+ * a thread.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#if !defined(_UWIN)
+/*# include <process.h> */
+#endif
+
+void
+pthread_exit (void *value_ptr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function terminates the calling thread, returning
+ * the value 'value_ptr' to any joining thread.
+ *
+ * PARAMETERS
+ * value_ptr
+ * a generic data value (i.e. not the address of a value)
+ *
+ *
+ * DESCRIPTION
+ * This function terminates the calling thread, returning
+ * the value 'value_ptr' to any joining thread.
+ * NOTE: thread should be joinable.
+ *
+ * RESULTS
+ * N/A
+ *
+ * ------------------------------------------------------
+ */
+{
+ ptw32_thread_t * sp;
+
+ /*
+ * Don't use pthread_self() to avoid creating an implicit POSIX thread handle
+ * unnecessarily.
+ */
+ sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
+
+#if defined(_UWIN)
+ if (--pthread_count <= 0)
+ exit ((int) value_ptr);
+#endif
+
+ if (NULL == sp)
+ {
+ /*
+ * A POSIX thread handle was never created. I.e. this is a
+ * Win32 thread that has never called a pthreads-win32 routine that
+ * required a POSIX handle.
+ *
+ * Implicit POSIX handles are cleaned up in ptw32_throw() now.
+ */
+
+#if ! (defined (__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
+ _endthreadex ((unsigned) (size_t) value_ptr);
+#else
+ _endthread ();
+#endif
+
+ /* Never reached */
+ }
+
+ sp->exitStatus = value_ptr;
+
+ ptw32_throw (PTW32_EPS_EXIT);
+
+ /* Never reached. */
+
+}
diff --git a/libs/pthreads/src/pthread_getconcurrency.c b/libs/pthreads/src/pthread_getconcurrency.c
new file mode 100644
index 0000000000..cf9e9c85c2
--- /dev/null
+++ b/libs/pthreads/src/pthread_getconcurrency.c
@@ -0,0 +1,45 @@
+/*
+ * pthread_getconcurrency.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_getconcurrency (void)
+{
+ return ptw32_concurrency;
+}
diff --git a/libs/pthreads/src/pthread_getschedparam.c b/libs/pthreads/src/pthread_getschedparam.c
new file mode 100644
index 0000000000..0afcfb74a9
--- /dev/null
+++ b/libs/pthreads/src/pthread_getschedparam.c
@@ -0,0 +1,75 @@
+/*
+ * sched_getschedparam.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_getschedparam (pthread_t thread, int *policy,
+ struct sched_param *param)
+{
+ int result;
+
+ /* Validate the thread id. */
+ result = pthread_kill (thread, 0);
+ if (0 != result)
+ {
+ return result;
+ }
+
+ /*
+ * Validate the policy and param args.
+ * Check that a policy constant wasn't passed rather than &policy.
+ */
+ if (policy <= (int *) SCHED_MAX || param == NULL)
+ {
+ return EINVAL;
+ }
+
+ /* Fill out the policy. */
+ *policy = SCHED_OTHER;
+
+ /*
+ * This function must return the priority value set by
+ * the most recent pthread_setschedparam() or pthread_create()
+ * for the target thread. It must not return the actual thread
+ * priority as altered by any system priority adjustments etc.
+ */
+ param->sched_priority = ((ptw32_thread_t *)thread.p)->sched_priority;
+
+ return 0;
+}
diff --git a/libs/pthreads/src/pthread_getspecific.c b/libs/pthreads/src/pthread_getspecific.c
new file mode 100644
index 0000000000..5ee1641dc1
--- /dev/null
+++ b/libs/pthreads/src/pthread_getspecific.c
@@ -0,0 +1,87 @@
+/*
+ * pthread_getspecific.c
+ *
+ * Description:
+ * POSIX thread functions which implement thread-specific data (TSD).
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+void *
+pthread_getspecific (pthread_key_t key)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function returns the current value of key in the
+ * calling thread. If no value has been set for 'key' in
+ * the thread, NULL is returned.
+ *
+ * PARAMETERS
+ * key
+ * an instance of pthread_key_t
+ *
+ *
+ * DESCRIPTION
+ * This function returns the current value of key in the
+ * calling thread. If no value has been set for 'key' in
+ * the thread, NULL is returned.
+ *
+ * RESULTS
+ * key value or NULL on failure
+ *
+ * ------------------------------------------------------
+ */
+{
+ void * ptr;
+
+ if (key == NULL)
+ {
+ ptr = NULL;
+ }
+ else
+ {
+ int lasterror = GetLastError ();
+#if defined(RETAIN_WSALASTERROR)
+ int lastWSAerror = WSAGetLastError ();
+#endif
+ ptr = TlsGetValue (key->key);
+
+ SetLastError (lasterror);
+#if defined(RETAIN_WSALASTERROR)
+ WSASetLastError (lastWSAerror);
+#endif
+ }
+
+ return ptr;
+}
diff --git a/libs/pthreads/src/pthread_getunique_np.c b/libs/pthreads/src/pthread_getunique_np.c
new file mode 100644
index 0000000000..4496c68bf5
--- /dev/null
+++ b/libs/pthreads/src/pthread_getunique_np.c
@@ -0,0 +1,47 @@
+/*
+ * pthread_getunique_np.c
+ *
+ * Description:
+ * This translation unit implements non-portable thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ *
+ */
+unsigned __int64
+pthread_getunique_np (pthread_t thread)
+{
+ return ((ptw32_thread_t*)thread.p)->seqNumber;
+}
diff --git a/libs/pthreads/src/pthread_getw32threadhandle_np.c b/libs/pthreads/src/pthread_getw32threadhandle_np.c
new file mode 100644
index 0000000000..309a8f281f
--- /dev/null
+++ b/libs/pthreads/src/pthread_getw32threadhandle_np.c
@@ -0,0 +1,65 @@
+/*
+ * pthread_getw32threadhandle_np.c
+ *
+ * Description:
+ * This translation unit implements non-portable thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * pthread_getw32threadhandle_np()
+ *
+ * Returns the win32 thread handle that the POSIX
+ * thread "thread" is running as.
+ *
+ * Applications can use the win32 handle to set
+ * win32 specific attributes of the thread.
+ */
+HANDLE
+pthread_getw32threadhandle_np (pthread_t thread)
+{
+ return ((ptw32_thread_t *)thread.p)->threadH;
+}
+
+/*
+ * pthread_getw32threadid_np()
+ *
+ * Returns the win32 thread id that the POSIX
+ * thread "thread" is running as.
+ */
+DWORD
+pthread_getw32threadid_np (pthread_t thread)
+{
+ return ((ptw32_thread_t *)thread.p)->thread;
+}
diff --git a/libs/pthreads/src/pthread_join.c b/libs/pthreads/src/pthread_join.c
new file mode 100644
index 0000000000..c2b7c1e757
--- /dev/null
+++ b/libs/pthreads/src/pthread_join.c
@@ -0,0 +1,157 @@
+/*
+ * pthread_join.c
+ *
+ * Description:
+ * This translation unit implements functions related to thread
+ * synchronisation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * Not needed yet, but defining it should indicate clashes with build target
+ * environment that should be fixed.
+ */
+#if !defined(WINCE)
+# include <signal.h>
+#endif
+
+
+int
+pthread_join (pthread_t thread, void **value_ptr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function waits for 'thread' to terminate and
+ * returns the thread's exit value if 'value_ptr' is not
+ * NULL. This also detaches the thread on successful
+ * completion.
+ *
+ * PARAMETERS
+ * thread
+ * an instance of pthread_t
+ *
+ * value_ptr
+ * pointer to an instance of pointer to void
+ *
+ *
+ * DESCRIPTION
+ * This function waits for 'thread' to terminate and
+ * returns the thread's exit value if 'value_ptr' is not
+ * NULL. This also detaches the thread on successful
+ * completion.
+ * NOTE: detached threads cannot be joined or canceled
+ *
+ * RESULTS
+ * 0 'thread' has completed
+ * EINVAL thread is not a joinable thread,
+ * ESRCH no thread could be found with ID 'thread',
+ * ENOENT thread couldn't find it's own valid handle,
+ * EDEADLK attempt to join thread with self
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+ pthread_t self;
+ ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
+ ptw32_mcs_local_node_t node;
+
+ ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node);
+
+ if (NULL == tp
+ || thread.x != tp->ptHandle.x)
+ {
+ result = ESRCH;
+ }
+ else if (PTHREAD_CREATE_DETACHED == tp->detachState)
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ result = 0;
+ }
+
+ ptw32_mcs_lock_release(&node);
+
+ if (result == 0)
+ {
+ /*
+ * The target thread is joinable and can't be reused before we join it.
+ */
+ self = pthread_self();
+
+ if (NULL == self.p)
+ {
+ result = ENOENT;
+ }
+ else if (pthread_equal (self, thread))
+ {
+ result = EDEADLK;
+ }
+ else
+ {
+ /*
+ * Pthread_join is a cancelation point.
+ * If we are canceled then our target thread must not be
+ * detached (destroyed). This is guarranteed because
+ * pthreadCancelableWait will not return if we
+ * are canceled.
+ */
+ result = pthreadCancelableWait (tp->threadH);
+
+ if (0 == result)
+ {
+ if (value_ptr != NULL)
+ {
+ *value_ptr = tp->exitStatus;
+ }
+
+ /*
+ * The result of making multiple simultaneous calls to
+ * pthread_join() or pthread_detach() specifying the same
+ * target is undefined.
+ */
+ result = pthread_detach (thread);
+ }
+ else
+ {
+ result = ESRCH;
+ }
+ }
+ }
+
+ return (result);
+
+} /* pthread_join */
diff --git a/libs/pthreads/src/pthread_key_create.c b/libs/pthreads/src/pthread_key_create.c
new file mode 100644
index 0000000000..65c6f95081
--- /dev/null
+++ b/libs/pthreads/src/pthread_key_create.c
@@ -0,0 +1,108 @@
+/*
+ * pthread_key_create.c
+ *
+ * Description:
+ * POSIX thread functions which implement thread-specific data (TSD).
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+/* TLS_OUT_OF_INDEXES not defined on WinCE */
+#if !defined(TLS_OUT_OF_INDEXES)
+#define TLS_OUT_OF_INDEXES 0xffffffff
+#endif
+
+int
+pthread_key_create (pthread_key_t * key, void (PTW32_CDECL *destructor) (void *))
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function creates a thread-specific data key visible
+ * to all threads. All existing and new threads have a value
+ * NULL for key until set using pthread_setspecific. When any
+ * thread with a non-NULL value for key terminates, 'destructor'
+ * is called with key's current value for that thread.
+ *
+ * PARAMETERS
+ * key
+ * pointer to an instance of pthread_key_t
+ *
+ *
+ * DESCRIPTION
+ * This function creates a thread-specific data key visible
+ * to all threads. All existing and new threads have a value
+ * NULL for key until set using pthread_setspecific. When any
+ * thread with a non-NULL value for key terminates, 'destructor'
+ * is called with key's current value for that thread.
+ *
+ * RESULTS
+ * 0 successfully created semaphore,
+ * EAGAIN insufficient resources or PTHREAD_KEYS_MAX
+ * exceeded,
+ * ENOMEM insufficient memory to create the key,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ pthread_key_t newkey;
+
+ if ((newkey = (pthread_key_t) calloc (1, sizeof (*newkey))) == NULL)
+ {
+ result = ENOMEM;
+ }
+ else if ((newkey->key = TlsAlloc ()) == TLS_OUT_OF_INDEXES)
+ {
+ result = EAGAIN;
+
+ free (newkey);
+ newkey = NULL;
+ }
+ else if (destructor != NULL)
+ {
+ /*
+ * Have to manage associations between thread and key;
+ * Therefore, need a lock that allows competing threads
+ * to gain exclusive access to the key->threads list.
+ *
+ * The mutex will only be created when it is first locked.
+ */
+ newkey->keyLock = 0;
+ newkey->destructor = destructor;
+ }
+
+ *key = newkey;
+
+ return (result);
+}
diff --git a/libs/pthreads/src/pthread_key_delete.c b/libs/pthreads/src/pthread_key_delete.c
new file mode 100644
index 0000000000..09d70c63f5
--- /dev/null
+++ b/libs/pthreads/src/pthread_key_delete.c
@@ -0,0 +1,125 @@
+/*
+ * pthread_key_delete.c
+ *
+ * Description:
+ * POSIX thread functions which implement thread-specific data (TSD).
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_key_delete (pthread_key_t key)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function deletes a thread-specific data key. This
+ * does not change the value of the thread specific data key
+ * for any thread and does not run the key's destructor
+ * in any thread so it should be used with caution.
+ *
+ * PARAMETERS
+ * key
+ * pointer to an instance of pthread_key_t
+ *
+ *
+ * DESCRIPTION
+ * This function deletes a thread-specific data key. This
+ * does not change the value of the thread specific data key
+ * for any thread and does not run the key's destructor
+ * in any thread so it should be used with caution.
+ *
+ * RESULTS
+ * 0 successfully deleted the key,
+ * EINVAL key is invalid,
+ *
+ * ------------------------------------------------------
+ */
+{
+ ptw32_mcs_local_node_t keyLock;
+ int result = 0;
+
+ if (key != NULL)
+ {
+ if (key->threads != NULL && key->destructor != NULL)
+ {
+ ThreadKeyAssoc *assoc;
+ ptw32_mcs_lock_acquire (&(key->keyLock), &keyLock);
+ /*
+ * Run through all Thread<-->Key associations
+ * for this key.
+ *
+ * While we hold at least one of the locks guarding
+ * the assoc, we know that the assoc pointed to by
+ * key->threads is valid.
+ */
+ while ((assoc = (ThreadKeyAssoc *) key->threads) != NULL)
+ {
+ ptw32_mcs_local_node_t threadLock;
+ ptw32_thread_t * thread = assoc->thread;
+
+ if (assoc == NULL)
+ {
+ /* Finished */
+ break;
+ }
+
+ ptw32_mcs_lock_acquire (&(thread->threadLock), &threadLock);
+ /*
+ * Since we are starting at the head of the key's threads
+ * chain, this will also point key->threads at the next assoc.
+ * While we hold key->keyLock, no other thread can insert
+ * a new assoc via pthread_setspecific.
+ */
+ ptw32_tkAssocDestroy (assoc);
+ ptw32_mcs_lock_release (&threadLock);
+ ptw32_mcs_lock_release (&keyLock);
+ }
+ }
+
+ TlsFree (key->key);
+ if (key->destructor != NULL)
+ {
+ /* A thread could be holding the keyLock */
+ ptw32_mcs_lock_acquire (&(key->keyLock), &keyLock);
+ ptw32_mcs_lock_release (&keyLock);
+ }
+
+#if defined( _DEBUG )
+ memset ((char *) key, 0, sizeof (*key));
+#endif
+ free (key);
+ }
+
+ return (result);
+}
diff --git a/libs/pthreads/src/pthread_kill.c b/libs/pthreads/src/pthread_kill.c
new file mode 100644
index 0000000000..5473b43cd4
--- /dev/null
+++ b/libs/pthreads/src/pthread_kill.c
@@ -0,0 +1,105 @@
+/*
+ * pthread_kill.c
+ *
+ * Description:
+ * This translation unit implements the pthread_kill routine.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * Not needed yet, but defining it should indicate clashes with build target
+ * environment that should be fixed.
+ */
+#if !defined(WINCE)
+# include <signal.h>
+#endif
+
+int
+pthread_kill (pthread_t thread, int sig)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function requests that a signal be delivered to the
+ * specified thread. If sig is zero, error checking is
+ * performed but no signal is actually sent such that this
+ * function can be used to check for a valid thread ID.
+ *
+ * PARAMETERS
+ * thread reference to an instances of pthread_t
+ * sig signal. Currently only a value of 0 is supported.
+ *
+ *
+ * DESCRIPTION
+ * This function requests that a signal be delivered to the
+ * specified thread. If sig is zero, error checking is
+ * performed but no signal is actually sent such that this
+ * function can be used to check for a valid thread ID.
+ *
+ * RESULTS
+ * ESRCH the thread is not a valid thread ID,
+ * EINVAL the value of the signal is invalid
+ * or unsupported.
+ * 0 the signal was successfully sent.
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ ptw32_thread_t * tp;
+ ptw32_mcs_local_node_t node;
+
+ ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node);
+
+ tp = (ptw32_thread_t *) thread.p;
+
+ if (NULL == tp
+ || thread.x != tp->ptHandle.x
+ || NULL == tp->threadH)
+ {
+ result = ESRCH;
+ }
+
+ ptw32_mcs_lock_release(&node);
+
+ if (0 == result && 0 != sig)
+ {
+ /*
+ * Currently does not support any signals.
+ */
+ result = EINVAL;
+ }
+
+ return result;
+
+} /* pthread_kill */
diff --git a/libs/pthreads/src/pthread_mutex_consistent.c b/libs/pthreads/src/pthread_mutex_consistent.c
new file mode 100644
index 0000000000..b7805e7b19
--- /dev/null
+++ b/libs/pthreads/src/pthread_mutex_consistent.c
@@ -0,0 +1,190 @@
+/*
+ * pthread_mutex_consistent.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/*
+ * From the Sun Multi-threaded Programming Guide
+ *
+ * robustness defines the behavior when the owner of the mutex terminates without unlocking the
+ * mutex, usually because its process terminated abnormally. The value of robustness that is
+ * defined in pthread.h is PTHREAD_MUTEX_ROBUST or PTHREAD_MUTEX_STALLED. The
+ * default value is PTHREAD_MUTEX_STALLED .
+ * â–  PTHREAD_MUTEX_STALLED
+ * When the owner of the mutex terminates without unlocking the mutex, all subsequent calls
+ * to pthread_mutex_lock() are blocked from progress in an unspecified manner.
+ * â–  PTHREAD_MUTEX_ROBUST
+ * When the owner of the mutex terminates without unlocking the mutex, the mutex is
+ * unlocked. The next owner of this mutex acquires the mutex with an error return of
+ * EOWNERDEAD.
+ * Note – Your application must always check the return code from pthread_mutex_lock() for
+ * a mutex initialized with the PTHREAD_MUTEX_ROBUST attribute.
+ * â–  The new owner of this mutex should make the state protected by the mutex consistent.
+ * This state might have been left inconsistent when the previous owner terminated.
+ * â–  If the new owner is able to make the state consistent, call
+ * pthread_mutex_consistent() for the mutex before unlocking the mutex. This
+ * marks the mutex as consistent and subsequent calls to pthread_mutex_lock() and
+ * pthread_mutex_unlock() will behave in the normal manner.
+ * â–  If the new owner is not able to make the state consistent, do not call
+ * pthread_mutex_consistent() for the mutex, but unlock the mutex.
+ * All waiters are woken up and all subsequent calls to pthread_mutex_lock() fail to
+ * acquire the mutex. The return code is ENOTRECOVERABLE. The mutex can be made
+ * consistent by calling pthread_mutex_destroy() to uninitialize the mutex, and calling
+ * pthread_mutex_int() to reinitialize the mutex.However, the state that was protected
+ * by the mutex remains inconsistent and some form of application recovery is required.
+ * â–  If the thread that acquires the lock with EOWNERDEAD terminates without unlocking the
+ * mutex, the next owner acquires the lock with an EOWNERDEAD return code.
+ */
+#if !defined(_UWIN)
+/*# include <process.h> */
+#endif
+#include "pthread.h"
+#include "implement.h"
+
+INLINE
+int
+ptw32_robust_mutex_inherit(pthread_mutex_t * mutex)
+{
+ int result;
+ pthread_mutex_t mx = *mutex;
+ ptw32_robust_node_t* robust = mx->robustNode;
+
+ switch ((LONG)PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR)&robust->stateInconsistent,
+ (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_INCONSISTENT,
+ (PTW32_INTERLOCKED_LONG)-1 /* The terminating thread sets this */))
+ {
+ case -1L:
+ result = EOWNERDEAD;
+ break;
+ case (LONG)PTW32_ROBUST_NOTRECOVERABLE:
+ result = ENOTRECOVERABLE;
+ break;
+ default:
+ result = 0;
+ break;
+ }
+
+ return result;
+}
+
+/*
+ * The next two internal support functions depend on only being
+ * called by the thread that owns the robust mutex. This enables
+ * us to avoid additional locks.
+ * Any mutex currently in the thread's robust mutex list is held
+ * by the thread, again eliminating the need for locks.
+ * The forward/backward links allow the thread to unlock mutexes
+ * in any order, not necessarily the reverse locking order.
+ * This is all possible because it is an error if a thread that
+ * does not own the [robust] mutex attempts to unlock it.
+ */
+
+INLINE
+void
+ptw32_robust_mutex_add(pthread_mutex_t* mutex, pthread_t self)
+{
+ ptw32_robust_node_t** list;
+ pthread_mutex_t mx = *mutex;
+ ptw32_thread_t* tp = (ptw32_thread_t*)self.p;
+ ptw32_robust_node_t* robust = mx->robustNode;
+
+ list = &tp->robustMxList;
+ mx->ownerThread = self;
+ if (NULL == *list)
+ {
+ robust->prev = NULL;
+ robust->next = NULL;
+ *list = robust;
+ }
+ else
+ {
+ robust->prev = NULL;
+ robust->next = *list;
+ (*list)->prev = robust;
+ *list = robust;
+ }
+}
+
+INLINE
+void
+ptw32_robust_mutex_remove(pthread_mutex_t* mutex, ptw32_thread_t* otp)
+{
+ ptw32_robust_node_t** list;
+ pthread_mutex_t mx = *mutex;
+ ptw32_robust_node_t* robust = mx->robustNode;
+
+ list = &(((ptw32_thread_t*)mx->ownerThread.p)->robustMxList);
+ mx->ownerThread.p = otp;
+ if (robust->next != NULL)
+ {
+ robust->next->prev = robust->prev;
+ }
+ if (robust->prev != NULL)
+ {
+ robust->prev->next = robust->next;
+ }
+ if (*list == robust)
+ {
+ *list = robust->next;
+ }
+}
+
+
+int
+pthread_mutex_consistent (pthread_mutex_t* mutex)
+{
+ pthread_mutex_t mx = *mutex;
+ int result = 0;
+
+ /*
+ * Let the system deal with invalid pointers.
+ */
+ if (mx == NULL)
+ {
+ return EINVAL;
+ }
+
+ if (mx->kind >= 0
+ || (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_INCONSISTENT != PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR)&mx->robustNode->stateInconsistent,
+ (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_CONSISTENT,
+ (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_INCONSISTENT))
+ {
+ result = EINVAL;
+ }
+
+ return (result);
+}
+
diff --git a/libs/pthreads/src/pthread_mutex_destroy.c b/libs/pthreads/src/pthread_mutex_destroy.c
new file mode 100644
index 0000000000..7b8c9cd65b
--- /dev/null
+++ b/libs/pthreads/src/pthread_mutex_destroy.c
@@ -0,0 +1,148 @@
+/*
+ * pthread_mutex_destroy.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutex_destroy (pthread_mutex_t * mutex)
+{
+ int result = 0;
+ pthread_mutex_t mx;
+
+ /*
+ * Let the system deal with invalid pointers.
+ */
+
+ /*
+ * Check to see if we have something to delete.
+ */
+ if (*mutex < PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
+ {
+ mx = *mutex;
+
+ result = pthread_mutex_trylock (&mx);
+
+ /*
+ * If trylock succeeded and the mutex is not recursively locked it
+ * can be destroyed.
+ */
+ if (0 == result || ENOTRECOVERABLE == result)
+ {
+ if (mx->kind != PTHREAD_MUTEX_RECURSIVE || 1 == mx->recursive_count)
+ {
+ /*
+ * FIXME!!!
+ * The mutex isn't held by another thread but we could still
+ * be too late invalidating the mutex below since another thread
+ * may already have entered mutex_lock and the check for a valid
+ * *mutex != NULL.
+ */
+ *mutex = NULL;
+
+ result = (0 == result)?pthread_mutex_unlock(&mx):0;
+
+ if (0 == result)
+ {
+ if (mx->robustNode != NULL)
+ {
+ free(mx->robustNode);
+ }
+ if (!CloseHandle (mx->event))
+ {
+ *mutex = mx;
+ result = EINVAL;
+ }
+ else
+ {
+ free (mx);
+ }
+ }
+ else
+ {
+ /*
+ * Restore the mutex before we return the error.
+ */
+ *mutex = mx;
+ }
+ }
+ else /* mx->recursive_count > 1 */
+ {
+ /*
+ * The mutex must be recursive and already locked by us (this thread).
+ */
+ mx->recursive_count--; /* Undo effect of pthread_mutex_trylock() above */
+ result = EBUSY;
+ }
+ }
+ }
+ else
+ {
+ ptw32_mcs_local_node_t node;
+
+ /*
+ * See notes in ptw32_mutex_check_need_init() above also.
+ */
+
+ ptw32_mcs_lock_acquire(&ptw32_mutex_test_init_lock, &node);
+
+ /*
+ * Check again.
+ */
+ if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
+ {
+ /*
+ * This is all we need to do to destroy a statically
+ * initialised mutex that has not yet been used (initialised).
+ * If we get to here, another thread
+ * waiting to initialise this mutex will get an EINVAL.
+ */
+ *mutex = NULL;
+ }
+ else
+ {
+ /*
+ * The mutex has been initialised while we were waiting
+ * so assume it's in use.
+ */
+ result = EBUSY;
+ }
+ ptw32_mcs_lock_release(&node);
+ }
+
+ return (result);
+}
diff --git a/libs/pthreads/src/pthread_mutex_init.c b/libs/pthreads/src/pthread_mutex_init.c
new file mode 100644
index 0000000000..daf805e5bc
--- /dev/null
+++ b/libs/pthreads/src/pthread_mutex_init.c
@@ -0,0 +1,130 @@
+/*
+ * pthread_mutex_init.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t * attr)
+{
+ int result = 0;
+ pthread_mutex_t mx;
+
+ if (mutex == NULL)
+ {
+ return EINVAL;
+ }
+
+ if (attr != NULL && *attr != NULL)
+ {
+ if ((*attr)->pshared == PTHREAD_PROCESS_SHARED)
+ {
+ /*
+ * Creating mutex that can be shared between
+ * processes.
+ */
+#if _POSIX_THREAD_PROCESS_SHARED >= 0
+
+ /*
+ * Not implemented yet.
+ */
+
+#error ERROR [__FILE__, line __LINE__]: Process shared mutexes are not supported yet.
+
+#else
+
+ return ENOSYS;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+ }
+ }
+
+ mx = (pthread_mutex_t) calloc (1, sizeof (*mx));
+
+ if (mx == NULL)
+ {
+ result = ENOMEM;
+ }
+ else
+ {
+ mx->lock_idx = 0;
+ mx->recursive_count = 0;
+ mx->robustNode = NULL;
+ if (attr == NULL || *attr == NULL)
+ {
+ mx->kind = PTHREAD_MUTEX_DEFAULT;
+ }
+ else
+ {
+ mx->kind = (*attr)->kind;
+ if ((*attr)->robustness == PTHREAD_MUTEX_ROBUST)
+ {
+ /*
+ * Use the negative range to represent robust types.
+ * Replaces a memory fetch with a register negate and incr
+ * in pthread_mutex_lock etc.
+ *
+ * Map 0,1,..,n to -1,-2,..,(-n)-1
+ */
+ mx->kind = -mx->kind - 1;
+
+ mx->robustNode = (ptw32_robust_node_t*) malloc(sizeof(ptw32_robust_node_t));
+ mx->robustNode->stateInconsistent = PTW32_ROBUST_CONSISTENT;
+ mx->robustNode->mx = mx;
+ mx->robustNode->next = NULL;
+ mx->robustNode->prev = NULL;
+ }
+ }
+
+ mx->ownerThread.p = NULL;
+
+ mx->event = CreateEvent (NULL, PTW32_FALSE, /* manual reset = No */
+ PTW32_FALSE, /* initial state = not signaled */
+ NULL); /* event name */
+
+ if (0 == mx->event)
+ {
+ result = ENOSPC;
+ free (mx);
+ mx = NULL;
+ }
+ }
+
+ *mutex = mx;
+
+ return (result);
+}
diff --git a/libs/pthreads/src/pthread_mutex_lock.c b/libs/pthreads/src/pthread_mutex_lock.c
new file mode 100644
index 0000000000..eee9abe8c7
--- /dev/null
+++ b/libs/pthreads/src/pthread_mutex_lock.c
@@ -0,0 +1,269 @@
+/*
+ * pthread_mutex_lock.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#if !defined(_UWIN)
+/*# include <process.h> */
+#endif
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_mutex_lock (pthread_mutex_t * mutex)
+{
+ int kind;
+ pthread_mutex_t mx;
+ int result = 0;
+
+ /*
+ * Let the system deal with invalid pointers.
+ */
+ if (*mutex == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static mutex. We check
+ * again inside the guarded section of ptw32_mutex_check_need_init()
+ * to avoid race conditions.
+ */
+ if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
+ {
+ if ((result = ptw32_mutex_check_need_init (mutex)) != 0)
+ {
+ return (result);
+ }
+ }
+
+ mx = *mutex;
+ kind = mx->kind;
+
+ if (kind >= 0)
+ {
+ /* Non-robust */
+ if (PTHREAD_MUTEX_NORMAL == kind)
+ {
+ if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) 1) != 0)
+ {
+ while ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) -1) != 0)
+ {
+ if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE))
+ {
+ result = EINVAL;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ pthread_t self = pthread_self();
+
+ if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) 1,
+ (PTW32_INTERLOCKED_LONG) 0) == 0)
+ {
+ mx->recursive_count = 1;
+ mx->ownerThread = self;
+ }
+ else
+ {
+ if (pthread_equal (mx->ownerThread, self))
+ {
+ if (kind == PTHREAD_MUTEX_RECURSIVE)
+ {
+ mx->recursive_count++;
+ }
+ else
+ {
+ result = EDEADLK;
+ }
+ }
+ else
+ {
+ while ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) -1) != 0)
+ {
+ if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE))
+ {
+ result = EINVAL;
+ break;
+ }
+ }
+
+ if (0 == result)
+ {
+ mx->recursive_count = 1;
+ mx->ownerThread = self;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Robust types
+ * All types record the current owner thread.
+ * The mutex is added to a per thread list when ownership is acquired.
+ */
+ ptw32_robust_state_t* statePtr = &mx->robustNode->stateInconsistent;
+
+ if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE == PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
+ (PTW32_INTERLOCKED_LONGPTR)statePtr,
+ (PTW32_INTERLOCKED_LONG)0))
+ {
+ result = ENOTRECOVERABLE;
+ }
+ else
+ {
+ pthread_t self = pthread_self();
+
+ kind = -kind - 1; /* Convert to non-robust range */
+
+ if (PTHREAD_MUTEX_NORMAL == kind)
+ {
+ if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) 1) != 0)
+ {
+ while (0 == (result = ptw32_robust_mutex_inherit(mutex))
+ && (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) -1) != 0)
+ {
+ if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE))
+ {
+ result = EINVAL;
+ break;
+ }
+ if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE ==
+ PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
+ (PTW32_INTERLOCKED_LONGPTR)statePtr,
+ (PTW32_INTERLOCKED_LONG)0))
+ {
+ /* Unblock the next thread */
+ SetEvent(mx->event);
+ result = ENOTRECOVERABLE;
+ break;
+ }
+ }
+ }
+ if (0 == result || EOWNERDEAD == result)
+ {
+ /*
+ * Add mutex to the per-thread robust mutex currently-held list.
+ * If the thread terminates, all mutexes in this list will be unlocked.
+ */
+ ptw32_robust_mutex_add(mutex, self);
+ }
+ }
+ else
+ {
+ if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) 1,
+ (PTW32_INTERLOCKED_LONG) 0) == 0)
+ {
+ mx->recursive_count = 1;
+ /*
+ * Add mutex to the per-thread robust mutex currently-held list.
+ * If the thread terminates, all mutexes in this list will be unlocked.
+ */
+ ptw32_robust_mutex_add(mutex, self);
+ }
+ else
+ {
+ if (pthread_equal (mx->ownerThread, self))
+ {
+ if (PTHREAD_MUTEX_RECURSIVE == kind)
+ {
+ mx->recursive_count++;
+ }
+ else
+ {
+ result = EDEADLK;
+ }
+ }
+ else
+ {
+ while (0 == (result = ptw32_robust_mutex_inherit(mutex))
+ && (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) -1) != 0)
+ {
+ if (WAIT_OBJECT_0 != WaitForSingleObject (mx->event, INFINITE))
+ {
+ result = EINVAL;
+ break;
+ }
+ if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE ==
+ PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
+ (PTW32_INTERLOCKED_LONGPTR)statePtr,
+ (PTW32_INTERLOCKED_LONG)0))
+ {
+ /* Unblock the next thread */
+ SetEvent(mx->event);
+ result = ENOTRECOVERABLE;
+ break;
+ }
+ }
+
+ if (0 == result || EOWNERDEAD == result)
+ {
+ mx->recursive_count = 1;
+ /*
+ * Add mutex to the per-thread robust mutex currently-held list.
+ * If the thread terminates, all mutexes in this list will be unlocked.
+ */
+ ptw32_robust_mutex_add(mutex, self);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return (result);
+}
+
diff --git a/libs/pthreads/src/pthread_mutex_timedlock.c b/libs/pthreads/src/pthread_mutex_timedlock.c
new file mode 100644
index 0000000000..1745316795
--- /dev/null
+++ b/libs/pthreads/src/pthread_mutex_timedlock.c
@@ -0,0 +1,324 @@
+/*
+ * pthread_mutex_timedlock.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+static INLINE int
+ptw32_timed_eventwait (HANDLE event, const struct timespec *abstime)
+ /*
+ * ------------------------------------------------------
+ * DESCRIPTION
+ * This function waits on an event until signaled or until
+ * abstime passes.
+ * If abstime has passed when this routine is called then
+ * it returns a result to indicate this.
+ *
+ * If 'abstime' is a NULL pointer then this function will
+ * block until it can successfully decrease the value or
+ * until interrupted by a signal.
+ *
+ * This routine is not a cancelation point.
+ *
+ * RESULTS
+ * 0 successfully signaled,
+ * ETIMEDOUT abstime passed
+ * EINVAL 'event' is not a valid event,
+ *
+ * ------------------------------------------------------
+ */
+{
+
+ DWORD milliseconds;
+ DWORD status;
+
+ if (event == NULL)
+ {
+ return EINVAL;
+ }
+ else
+ {
+ if (abstime == NULL)
+ {
+ milliseconds = INFINITE;
+ }
+ else
+ {
+ /*
+ * Calculate timeout as milliseconds from current system time.
+ */
+ milliseconds = ptw32_relmillisecs (abstime);
+ }
+
+ status = WaitForSingleObject (event, milliseconds);
+
+ if (status == WAIT_OBJECT_0)
+ {
+ return 0;
+ }
+ else if (status == WAIT_TIMEOUT)
+ {
+ return ETIMEDOUT;
+ }
+ else
+ {
+ return EINVAL;
+ }
+ }
+
+ return 0;
+
+} /* ptw32_timed_semwait */
+
+
+int
+pthread_mutex_timedlock (pthread_mutex_t * mutex,
+ const struct timespec *abstime)
+{
+ pthread_mutex_t mx;
+ int kind;
+ int result = 0;
+
+ /*
+ * Let the system deal with invalid pointers.
+ */
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static mutex. We check
+ * again inside the guarded section of ptw32_mutex_check_need_init()
+ * to avoid race conditions.
+ */
+ if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
+ {
+ if ((result = ptw32_mutex_check_need_init (mutex)) != 0)
+ {
+ return (result);
+ }
+ }
+
+ mx = *mutex;
+ kind = mx->kind;
+
+ if (kind >= 0)
+ {
+ if (mx->kind == PTHREAD_MUTEX_NORMAL)
+ {
+ if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) 1) != 0)
+ {
+ while ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) -1) != 0)
+ {
+ if (0 != (result = ptw32_timed_eventwait (mx->event, abstime)))
+ {
+ return result;
+ }
+ }
+ }
+ }
+ else
+ {
+ pthread_t self = pthread_self();
+
+ if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) 1,
+ (PTW32_INTERLOCKED_LONG) 0) == 0)
+ {
+ mx->recursive_count = 1;
+ mx->ownerThread = self;
+ }
+ else
+ {
+ if (pthread_equal (mx->ownerThread, self))
+ {
+ if (mx->kind == PTHREAD_MUTEX_RECURSIVE)
+ {
+ mx->recursive_count++;
+ }
+ else
+ {
+ return EDEADLK;
+ }
+ }
+ else
+ {
+ while ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) -1) != 0)
+ {
+ if (0 != (result = ptw32_timed_eventwait (mx->event, abstime)))
+ {
+ return result;
+ }
+ }
+
+ mx->recursive_count = 1;
+ mx->ownerThread = self;
+ }
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Robust types
+ * All types record the current owner thread.
+ * The mutex is added to a per thread list when ownership is acquired.
+ */
+ ptw32_robust_state_t* statePtr = &mx->robustNode->stateInconsistent;
+
+ if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE == PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
+ (PTW32_INTERLOCKED_LONGPTR)statePtr,
+ (PTW32_INTERLOCKED_LONG)0))
+ {
+ result = ENOTRECOVERABLE;
+ }
+ else
+ {
+ pthread_t self = pthread_self();
+
+ kind = -kind - 1; /* Convert to non-robust range */
+
+ if (PTHREAD_MUTEX_NORMAL == kind)
+ {
+ if ((PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) 1) != 0)
+ {
+ while (0 == (result = ptw32_robust_mutex_inherit(mutex))
+ && (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) -1) != 0)
+ {
+ if (0 != (result = ptw32_timed_eventwait (mx->event, abstime)))
+ {
+ return result;
+ }
+ if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE ==
+ PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
+ (PTW32_INTERLOCKED_LONGPTR)statePtr,
+ (PTW32_INTERLOCKED_LONG)0))
+ {
+ /* Unblock the next thread */
+ SetEvent(mx->event);
+ result = ENOTRECOVERABLE;
+ break;
+ }
+ }
+
+ if (0 == result || EOWNERDEAD == result)
+ {
+ /*
+ * Add mutex to the per-thread robust mutex currently-held list.
+ * If the thread terminates, all mutexes in this list will be unlocked.
+ */
+ ptw32_robust_mutex_add(mutex, self);
+ }
+ }
+ }
+ else
+ {
+ pthread_t self = pthread_self();
+
+ if (0 == (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) 1,
+ (PTW32_INTERLOCKED_LONG) 0))
+ {
+ mx->recursive_count = 1;
+ /*
+ * Add mutex to the per-thread robust mutex currently-held list.
+ * If the thread terminates, all mutexes in this list will be unlocked.
+ */
+ ptw32_robust_mutex_add(mutex, self);
+ }
+ else
+ {
+ if (pthread_equal (mx->ownerThread, self))
+ {
+ if (PTHREAD_MUTEX_RECURSIVE == kind)
+ {
+ mx->recursive_count++;
+ }
+ else
+ {
+ return EDEADLK;
+ }
+ }
+ else
+ {
+ while (0 == (result = ptw32_robust_mutex_inherit(mutex))
+ && (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) -1) != 0)
+ {
+ if (0 != (result = ptw32_timed_eventwait (mx->event, abstime)))
+ {
+ return result;
+ }
+ }
+
+ if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE ==
+ PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
+ (PTW32_INTERLOCKED_LONGPTR)statePtr,
+ (PTW32_INTERLOCKED_LONG)0))
+ {
+ /* Unblock the next thread */
+ SetEvent(mx->event);
+ result = ENOTRECOVERABLE;
+ }
+ else if (0 == result || EOWNERDEAD == result)
+ {
+ mx->recursive_count = 1;
+ /*
+ * Add mutex to the per-thread robust mutex currently-held list.
+ * If the thread terminates, all mutexes in this list will be unlocked.
+ */
+ ptw32_robust_mutex_add(mutex, self);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return result;
+}
diff --git a/libs/pthreads/src/pthread_mutex_trylock.c b/libs/pthreads/src/pthread_mutex_trylock.c
new file mode 100644
index 0000000000..5728728b62
--- /dev/null
+++ b/libs/pthreads/src/pthread_mutex_trylock.c
@@ -0,0 +1,158 @@
+/*
+ * pthread_mutex_trylock.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutex_trylock (pthread_mutex_t * mutex)
+{
+ pthread_mutex_t mx;
+ int kind;
+ int result = 0;
+
+ /*
+ * Let the system deal with invalid pointers.
+ */
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static mutex. We check
+ * again inside the guarded section of ptw32_mutex_check_need_init()
+ * to avoid race conditions.
+ */
+ if (*mutex >= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
+ {
+ if ((result = ptw32_mutex_check_need_init (mutex)) != 0)
+ {
+ return (result);
+ }
+ }
+
+ mx = *mutex;
+ if (mx == NULL) {
+ return EINVAL;
+ }
+
+ kind = mx->kind;
+
+ if (kind >= 0)
+ {
+ /* Non-robust */
+ if (0 == (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG (
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) 1,
+ (PTW32_INTERLOCKED_LONG) 0))
+ {
+ if (kind != PTHREAD_MUTEX_NORMAL)
+ {
+ mx->recursive_count = 1;
+ mx->ownerThread = pthread_self ();
+ }
+ }
+ else
+ {
+ if (kind == PTHREAD_MUTEX_RECURSIVE &&
+ pthread_equal (mx->ownerThread, pthread_self ()))
+ {
+ mx->recursive_count++;
+ }
+ else
+ {
+ result = EBUSY;
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Robust types
+ * All types record the current owner thread.
+ * The mutex is added to a per thread list when ownership is acquired.
+ */
+ pthread_t self;
+ ptw32_robust_state_t* statePtr = &mx->robustNode->stateInconsistent;
+
+ if ((PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE ==
+ PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(
+ (PTW32_INTERLOCKED_LONGPTR)statePtr,
+ (PTW32_INTERLOCKED_LONG)0))
+ {
+ return ENOTRECOVERABLE;
+ }
+
+ self = pthread_self();
+ kind = -kind - 1; /* Convert to non-robust range */
+
+ if (0 == (PTW32_INTERLOCKED_LONG) PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG (
+ (PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) 1,
+ (PTW32_INTERLOCKED_LONG) 0))
+ {
+ if (kind != PTHREAD_MUTEX_NORMAL)
+ {
+ mx->recursive_count = 1;
+ }
+ ptw32_robust_mutex_add(mutex, self);
+ }
+ else
+ {
+ if (PTHREAD_MUTEX_RECURSIVE == kind &&
+ pthread_equal (mx->ownerThread, pthread_self ()))
+ {
+ mx->recursive_count++;
+ }
+ else
+ {
+ if (EOWNERDEAD == (result = ptw32_robust_mutex_inherit(mutex)))
+ {
+ mx->recursive_count = 1;
+ ptw32_robust_mutex_add(mutex, self);
+ }
+ else
+ {
+ if (0 == result)
+ {
+ result = EBUSY;
+ }
+ }
+ }
+ }
+ }
+
+ return (result);
+}
diff --git a/libs/pthreads/src/pthread_mutex_unlock.c b/libs/pthreads/src/pthread_mutex_unlock.c
new file mode 100644
index 0000000000..77175bb5da
--- /dev/null
+++ b/libs/pthreads/src/pthread_mutex_unlock.c
@@ -0,0 +1,178 @@
+/*
+ * pthread_mutex_unlock.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutex_unlock (pthread_mutex_t * mutex)
+{
+ int result = 0;
+ int kind;
+ pthread_mutex_t mx;
+
+ /*
+ * Let the system deal with invalid pointers.
+ */
+
+ mx = *mutex;
+ if (mx == NULL) {
+ return EINVAL;
+ }
+
+ /*
+ * If the thread calling us holds the mutex then there is no
+ * race condition. If another thread holds the
+ * lock then we shouldn't be in here.
+ */
+ if (mx < PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
+ {
+ kind = mx->kind;
+
+ if (kind >= 0)
+ {
+ if (kind == PTHREAD_MUTEX_NORMAL)
+ {
+ LONG idx;
+
+ idx = (LONG) PTW32_INTERLOCKED_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR)&mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG)0);
+ if (idx != 0)
+ {
+ if (idx < 0)
+ {
+ /*
+ * Someone may be waiting on that mutex.
+ */
+ if (SetEvent (mx->event) == 0)
+ {
+ result = EINVAL;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (pthread_equal (mx->ownerThread, pthread_self()))
+ {
+ if (kind != PTHREAD_MUTEX_RECURSIVE
+ || 0 == --mx->recursive_count)
+ {
+ mx->ownerThread.p = NULL;
+
+ if ((LONG) PTW32_INTERLOCKED_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR)&mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG)0) < 0L)
+ {
+ /* Someone may be waiting on that mutex */
+ if (SetEvent (mx->event) == 0)
+ {
+ result = EINVAL;
+ }
+ }
+ }
+ }
+ else
+ {
+ result = EPERM;
+ }
+ }
+ }
+ else
+ {
+ /* Robust types */
+ pthread_t self = pthread_self();
+ kind = -kind - 1; /* Convert to non-robust range */
+
+ /*
+ * The thread must own the lock regardless of type if the mutex
+ * is robust.
+ */
+ if (pthread_equal (mx->ownerThread, self))
+ {
+ PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG((PTW32_INTERLOCKED_LONGPTR) &mx->robustNode->stateInconsistent,
+ (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_NOTRECOVERABLE,
+ (PTW32_INTERLOCKED_LONG)PTW32_ROBUST_INCONSISTENT);
+ if (PTHREAD_MUTEX_NORMAL == kind)
+ {
+ ptw32_robust_mutex_remove(mutex, NULL);
+
+ if ((LONG) PTW32_INTERLOCKED_EXCHANGE_LONG((PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) 0) < 0)
+ {
+ /*
+ * Someone may be waiting on that mutex.
+ */
+ if (SetEvent (mx->event) == 0)
+ {
+ result = EINVAL;
+ }
+ }
+ }
+ else
+ {
+ if (kind != PTHREAD_MUTEX_RECURSIVE
+ || 0 == --mx->recursive_count)
+ {
+ ptw32_robust_mutex_remove(mutex, NULL);
+
+ if ((LONG) PTW32_INTERLOCKED_EXCHANGE_LONG((PTW32_INTERLOCKED_LONGPTR) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) 0) < 0)
+ {
+ /*
+ * Someone may be waiting on that mutex.
+ */
+ if (SetEvent (mx->event) == 0)
+ {
+ result = EINVAL;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ result = EPERM;
+ }
+ }
+ }
+ else if (mx != PTHREAD_MUTEX_INITIALIZER)
+ {
+ result = EINVAL;
+ }
+
+ return (result);
+}
diff --git a/libs/pthreads/src/pthread_mutexattr_destroy.c b/libs/pthreads/src/pthread_mutexattr_destroy.c
new file mode 100644
index 0000000000..9d424bfa28
--- /dev/null
+++ b/libs/pthreads/src/pthread_mutexattr_destroy.c
@@ -0,0 +1,83 @@
+/*
+ * pthread_mutexattr_destroy.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_destroy (pthread_mutexattr_t * attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Destroys a mutex attributes object. The object can
+ * no longer be used.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_mutexattr_t
+ *
+ *
+ * DESCRIPTION
+ * Destroys a mutex attributes object. The object can
+ * no longer be used.
+ *
+ * NOTES:
+ * 1) Does not affect mutexes created using 'attr'
+ *
+ * RESULTS
+ * 0 successfully released attr,
+ * EINVAL 'attr' is invalid.
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+
+ if (attr == NULL || *attr == NULL)
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ pthread_mutexattr_t ma = *attr;
+
+ *attr = NULL;
+ free (ma);
+ }
+
+ return (result);
+} /* pthread_mutexattr_destroy */
diff --git a/libs/pthreads/src/pthread_mutexattr_getkind_np.c b/libs/pthreads/src/pthread_mutexattr_getkind_np.c
new file mode 100644
index 0000000000..2d82ec6bc7
--- /dev/null
+++ b/libs/pthreads/src/pthread_mutexattr_getkind_np.c
@@ -0,0 +1,44 @@
+/*
+ * pthread_mutexattr_getkind_np.c
+ *
+ * Description:
+ * This translation unit implements non-portable thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_mutexattr_getkind_np (pthread_mutexattr_t * attr, int *kind)
+{
+ return pthread_mutexattr_gettype (attr, kind);
+}
diff --git a/libs/pthreads/src/pthread_mutexattr_getpshared.c b/libs/pthreads/src/pthread_mutexattr_getpshared.c
new file mode 100644
index 0000000000..42f9589c51
--- /dev/null
+++ b/libs/pthreads/src/pthread_mutexattr_getpshared.c
@@ -0,0 +1,95 @@
+/*
+ * pthread_mutexattr_getpshared.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_getpshared (const pthread_mutexattr_t * attr, int *pshared)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Determine whether mutexes created with 'attr' can be
+ * shared between processes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_mutexattr_t
+ *
+ * pshared
+ * will be set to one of:
+ *
+ * PTHREAD_PROCESS_SHARED
+ * May be shared if in shared memory
+ *
+ * PTHREAD_PROCESS_PRIVATE
+ * Cannot be shared.
+ *
+ *
+ * DESCRIPTION
+ * Mutexes creatd with 'attr' can be shared between
+ * processes if pthread_mutex_t variable is allocated
+ * in memory shared by these processes.
+ * NOTES:
+ * 1) pshared mutexes MUST be allocated in shared
+ * memory.
+ * 2) The following macro is defined if shared mutexes
+ * are supported:
+ * _POSIX_THREAD_PROCESS_SHARED
+ *
+ * RESULTS
+ * 0 successfully retrieved attribute,
+ * EINVAL 'attr' is invalid,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+
+ if ((attr != NULL && *attr != NULL) && (pshared != NULL))
+ {
+ *pshared = (*attr)->pshared;
+ result = 0;
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return (result);
+
+} /* pthread_mutexattr_getpshared */
diff --git a/libs/pthreads/src/pthread_mutexattr_getrobust.c b/libs/pthreads/src/pthread_mutexattr_getrobust.c
new file mode 100644
index 0000000000..be004837bc
--- /dev/null
+++ b/libs/pthreads/src/pthread_mutexattr_getrobust.c
@@ -0,0 +1,113 @@
+/*
+ * pthread_mutexattr_getrobust.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_getrobust (const pthread_mutexattr_t * attr, int * robust)
+ /*
+ * ------------------------------------------------------
+ *
+ * DOCPUBLIC
+ * The pthread_mutexattr_setrobust() and
+ * pthread_mutexattr_getrobust() functions respectively set and
+ * get the mutex robust attribute. This attribute is set in the
+ * robust parameter to these functions.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_mutexattr_t
+ *
+ * robust
+ * must be one of:
+ *
+ * PTHREAD_MUTEX_STALLED
+ *
+ * PTHREAD_MUTEX_ROBUST
+ *
+ * DESCRIPTION
+ * The pthread_mutexattr_setrobust() and
+ * pthread_mutexattr_getrobust() functions respectively set and
+ * get the mutex robust attribute. This attribute is set in the
+ * robust parameter to these functions. The default value of the
+ * robust attribute is PTHREAD_MUTEX_STALLED.
+ *
+ * The robustness of mutex is contained in the robustness attribute
+ * of the mutex attributes. Valid mutex robustness values are:
+ *
+ * PTHREAD_MUTEX_STALLED
+ * No special actions are taken if the owner of the mutex is
+ * terminated while holding the mutex lock. This can lead to
+ * deadlocks if no other thread can unlock the mutex.
+ * This is the default value.
+ *
+ * PTHREAD_MUTEX_ROBUST
+ * If the process containing the owning thread of a robust mutex
+ * terminates while holding the mutex lock, the next thread that
+ * acquires the mutex shall be notified about the termination by
+ * the return value [EOWNERDEAD] from the locking function. If the
+ * owning thread of a robust mutex terminates while holding the mutex
+ * lock, the next thread that acquires the mutex may be notified
+ * about the termination by the return value [EOWNERDEAD]. The
+ * notified thread can then attempt to mark the state protected by
+ * the mutex as consistent again by a call to
+ * pthread_mutex_consistent(). After a subsequent successful call to
+ * pthread_mutex_unlock(), the mutex lock shall be released and can
+ * be used normally by other threads. If the mutex is unlocked without
+ * a call to pthread_mutex_consistent(), it shall be in a permanently
+ * unusable state and all attempts to lock the mutex shall fail with
+ * the error [ENOTRECOVERABLE]. The only permissible operation on such
+ * a mutex is pthread_mutex_destroy().
+ *
+ * RESULTS
+ * 0 successfully set attribute,
+ * EINVAL 'attr' or 'robust' is invalid,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = EINVAL;
+
+ if ((attr != NULL && *attr != NULL && robust != NULL))
+ {
+ *robust = (*attr)->robustness;
+ result = 0;
+ }
+
+ return (result);
+} /* pthread_mutexattr_getrobust */
diff --git a/libs/pthreads/src/pthread_mutexattr_gettype.c b/libs/pthreads/src/pthread_mutexattr_gettype.c
new file mode 100644
index 0000000000..c63fcfa03a
--- /dev/null
+++ b/libs/pthreads/src/pthread_mutexattr_gettype.c
@@ -0,0 +1,56 @@
+/*
+ * pthread_mutexattr_gettype.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_gettype (const pthread_mutexattr_t * attr, int *kind)
+{
+ int result = 0;
+
+ if (attr != NULL && *attr != NULL && kind != NULL)
+ {
+ *kind = (*attr)->kind;
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return (result);
+}
diff --git a/libs/pthreads/src/pthread_mutexattr_init.c b/libs/pthreads/src/pthread_mutexattr_init.c
new file mode 100644
index 0000000000..d2797ff248
--- /dev/null
+++ b/libs/pthreads/src/pthread_mutexattr_init.c
@@ -0,0 +1,86 @@
+/*
+ * pthread_mutexattr_init.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_init (pthread_mutexattr_t * attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Initializes a mutex attributes object with default
+ * attributes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_mutexattr_t
+ *
+ *
+ * DESCRIPTION
+ * Initializes a mutex attributes object with default
+ * attributes.
+ *
+ * NOTES:
+ * 1) Used to define mutex types
+ *
+ * RESULTS
+ * 0 successfully initialized attr,
+ * ENOMEM insufficient memory for attr.
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ pthread_mutexattr_t ma;
+
+ ma = (pthread_mutexattr_t) calloc (1, sizeof (*ma));
+
+ if (ma == NULL)
+ {
+ result = ENOMEM;
+ }
+ else
+ {
+ ma->pshared = PTHREAD_PROCESS_PRIVATE;
+ ma->kind = PTHREAD_MUTEX_DEFAULT;
+ }
+
+ *attr = ma;
+
+ return (result);
+} /* pthread_mutexattr_init */
diff --git a/libs/pthreads/src/pthread_mutexattr_setkind_np.c b/libs/pthreads/src/pthread_mutexattr_setkind_np.c
new file mode 100644
index 0000000000..faa936658f
--- /dev/null
+++ b/libs/pthreads/src/pthread_mutexattr_setkind_np.c
@@ -0,0 +1,44 @@
+/*
+ * pthread_mutexattr_setkind_np.c
+ *
+ * Description:
+ * This translation unit implements non-portable thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_mutexattr_setkind_np (pthread_mutexattr_t * attr, int kind)
+{
+ return pthread_mutexattr_settype (attr, kind);
+}
diff --git a/libs/pthreads/src/pthread_mutexattr_setpshared.c b/libs/pthreads/src/pthread_mutexattr_setpshared.c
new file mode 100644
index 0000000000..cfa6f71994
--- /dev/null
+++ b/libs/pthreads/src/pthread_mutexattr_setpshared.c
@@ -0,0 +1,119 @@
+/*
+ * pthread_mutexattr_setpshared.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, int pshared)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Mutexes created with 'attr' can be shared between
+ * processes if pthread_mutex_t variable is allocated
+ * in memory shared by these processes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_mutexattr_t
+ *
+ * pshared
+ * must be one of:
+ *
+ * PTHREAD_PROCESS_SHARED
+ * May be shared if in shared memory
+ *
+ * PTHREAD_PROCESS_PRIVATE
+ * Cannot be shared.
+ *
+ * DESCRIPTION
+ * Mutexes creatd with 'attr' can be shared between
+ * processes if pthread_mutex_t variable is allocated
+ * in memory shared by these processes.
+ *
+ * NOTES:
+ * 1) pshared mutexes MUST be allocated in shared
+ * memory.
+ *
+ * 2) The following macro is defined if shared mutexes
+ * are supported:
+ * _POSIX_THREAD_PROCESS_SHARED
+ *
+ * RESULTS
+ * 0 successfully set attribute,
+ * EINVAL 'attr' or pshared is invalid,
+ * ENOSYS PTHREAD_PROCESS_SHARED not supported,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+
+ if ((attr != NULL && *attr != NULL) &&
+ ((pshared == PTHREAD_PROCESS_SHARED) ||
+ (pshared == PTHREAD_PROCESS_PRIVATE)))
+ {
+ if (pshared == PTHREAD_PROCESS_SHARED)
+ {
+
+#if !defined( _POSIX_THREAD_PROCESS_SHARED )
+
+ result = ENOSYS;
+ pshared = PTHREAD_PROCESS_PRIVATE;
+
+#else
+
+ result = 0;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+ }
+ else
+ {
+ result = 0;
+ }
+
+ (*attr)->pshared = pshared;
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return (result);
+
+} /* pthread_mutexattr_setpshared */
diff --git a/libs/pthreads/src/pthread_mutexattr_setrobust.c b/libs/pthreads/src/pthread_mutexattr_setrobust.c
new file mode 100644
index 0000000000..b1acef7572
--- /dev/null
+++ b/libs/pthreads/src/pthread_mutexattr_setrobust.c
@@ -0,0 +1,119 @@
+/*
+ * pthread_mutexattr_setrobust.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_setrobust (pthread_mutexattr_t * attr, int robust)
+ /*
+ * ------------------------------------------------------
+ *
+ * DOCPUBLIC
+ * The pthread_mutexattr_setrobust() and
+ * pthread_mutexattr_getrobust() functions respectively set and
+ * get the mutex robust attribute. This attribute is set in the
+ * robust parameter to these functions.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_mutexattr_t
+ *
+ * robust
+ * must be one of:
+ *
+ * PTHREAD_MUTEX_STALLED
+ *
+ * PTHREAD_MUTEX_ROBUST
+ *
+ * DESCRIPTION
+ * The pthread_mutexattr_setrobust() and
+ * pthread_mutexattr_getrobust() functions respectively set and
+ * get the mutex robust attribute. This attribute is set in the
+ * robust parameter to these functions. The default value of the
+ * robust attribute is PTHREAD_MUTEX_STALLED.
+ *
+ * The robustness of mutex is contained in the robustness attribute
+ * of the mutex attributes. Valid mutex robustness values are:
+ *
+ * PTHREAD_MUTEX_STALLED
+ * No special actions are taken if the owner of the mutex is
+ * terminated while holding the mutex lock. This can lead to
+ * deadlocks if no other thread can unlock the mutex.
+ * This is the default value.
+ *
+ * PTHREAD_MUTEX_ROBUST
+ * If the process containing the owning thread of a robust mutex
+ * terminates while holding the mutex lock, the next thread that
+ * acquires the mutex shall be notified about the termination by
+ * the return value [EOWNERDEAD] from the locking function. If the
+ * owning thread of a robust mutex terminates while holding the mutex
+ * lock, the next thread that acquires the mutex may be notified
+ * about the termination by the return value [EOWNERDEAD]. The
+ * notified thread can then attempt to mark the state protected by
+ * the mutex as consistent again by a call to
+ * pthread_mutex_consistent(). After a subsequent successful call to
+ * pthread_mutex_unlock(), the mutex lock shall be released and can
+ * be used normally by other threads. If the mutex is unlocked without
+ * a call to pthread_mutex_consistent(), it shall be in a permanently
+ * unusable state and all attempts to lock the mutex shall fail with
+ * the error [ENOTRECOVERABLE]. The only permissible operation on such
+ * a mutex is pthread_mutex_destroy().
+ *
+ * RESULTS
+ * 0 successfully set attribute,
+ * EINVAL 'attr' or 'robust' is invalid,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = EINVAL;
+
+ if ((attr != NULL && *attr != NULL))
+ {
+ switch (robust)
+ {
+ case PTHREAD_MUTEX_STALLED:
+ case PTHREAD_MUTEX_ROBUST:
+ (*attr)->robustness = robust;
+ result = 0;
+ break;
+ }
+ }
+
+ return (result);
+} /* pthread_mutexattr_setrobust */
diff --git a/libs/pthreads/src/pthread_mutexattr_settype.c b/libs/pthreads/src/pthread_mutexattr_settype.c
new file mode 100644
index 0000000000..8365daf65d
--- /dev/null
+++ b/libs/pthreads/src/pthread_mutexattr_settype.c
@@ -0,0 +1,143 @@
+/*
+ * pthread_mutexattr_settype.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind)
+ /*
+ * ------------------------------------------------------
+ *
+ * DOCPUBLIC
+ * The pthread_mutexattr_settype() and
+ * pthread_mutexattr_gettype() functions respectively set and
+ * get the mutex type attribute. This attribute is set in the
+ * type parameter to these functions.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_mutexattr_t
+ *
+ * type
+ * must be one of:
+ *
+ * PTHREAD_MUTEX_DEFAULT
+ *
+ * PTHREAD_MUTEX_NORMAL
+ *
+ * PTHREAD_MUTEX_ERRORCHECK
+ *
+ * PTHREAD_MUTEX_RECURSIVE
+ *
+ * DESCRIPTION
+ * The pthread_mutexattr_settype() and
+ * pthread_mutexattr_gettype() functions respectively set and
+ * get the mutex type attribute. This attribute is set in the
+ * type parameter to these functions. The default value of the
+ * type attribute is PTHREAD_MUTEX_DEFAULT.
+ *
+ * The type of mutex is contained in the type attribute of the
+ * mutex attributes. Valid mutex types include:
+ *
+ * PTHREAD_MUTEX_NORMAL
+ * This type of mutex does not detect deadlock. A
+ * thread attempting to relock this mutex without
+ * first unlocking it will deadlock. Attempting to
+ * unlock a mutex locked by a different thread
+ * results in undefined behavior. Attempting to
+ * unlock an unlocked mutex results in undefined
+ * behavior.
+ *
+ * PTHREAD_MUTEX_ERRORCHECK
+ * This type of mutex provides error checking. A
+ * thread attempting to relock this mutex without
+ * first unlocking it will return with an error. A
+ * thread attempting to unlock a mutex which another
+ * thread has locked will return with an error. A
+ * thread attempting to unlock an unlocked mutex will
+ * return with an error.
+ *
+ * PTHREAD_MUTEX_DEFAULT
+ * Same as PTHREAD_MUTEX_NORMAL.
+ *
+ * PTHREAD_MUTEX_RECURSIVE
+ * A thread attempting to relock this mutex without
+ * first unlocking it will succeed in locking the
+ * mutex. The relocking deadlock which can occur with
+ * mutexes of type PTHREAD_MUTEX_NORMAL cannot occur
+ * with this type of mutex. Multiple locks of this
+ * mutex require the same number of unlocks to
+ * release the mutex before another thread can
+ * acquire the mutex. A thread attempting to unlock a
+ * mutex which another thread has locked will return
+ * with an error. A thread attempting to unlock an
+ * unlocked mutex will return with an error. This
+ * type of mutex is only supported for mutexes whose
+ * process shared attribute is
+ * PTHREAD_PROCESS_PRIVATE.
+ *
+ * RESULTS
+ * 0 successfully set attribute,
+ * EINVAL 'attr' or 'type' is invalid,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+
+ if ((attr != NULL && *attr != NULL))
+ {
+ switch (kind)
+ {
+ case PTHREAD_MUTEX_FAST_NP:
+ case PTHREAD_MUTEX_RECURSIVE_NP:
+ case PTHREAD_MUTEX_ERRORCHECK_NP:
+ (*attr)->kind = kind;
+ break;
+ default:
+ result = EINVAL;
+ break;
+ }
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return (result);
+} /* pthread_mutexattr_settype */
diff --git a/libs/pthreads/src/pthread_num_processors_np.c b/libs/pthreads/src/pthread_num_processors_np.c
new file mode 100644
index 0000000000..3067d117d3
--- /dev/null
+++ b/libs/pthreads/src/pthread_num_processors_np.c
@@ -0,0 +1,56 @@
+/*
+ * pthread_num_processors_np.c
+ *
+ * Description:
+ * This translation unit implements non-portable thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * pthread_num_processors_np()
+ *
+ * Get the number of CPUs available to the process.
+ */
+int
+pthread_num_processors_np (void)
+{
+ int count;
+
+ if (ptw32_getprocessors (&count) != 0)
+ {
+ count = 1;
+ }
+
+ return (count);
+}
diff --git a/libs/pthreads/src/pthread_once.c b/libs/pthreads/src/pthread_once.c
new file mode 100644
index 0000000000..3bfeb9f0bf
--- /dev/null
+++ b/libs/pthreads/src/pthread_once.c
@@ -0,0 +1,79 @@
+/*
+ * pthread_once.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_once (pthread_once_t * once_control, void (PTW32_CDECL *init_routine) (void))
+{
+ if (once_control == NULL || init_routine == NULL)
+ {
+ return EINVAL;
+ }
+
+ if ((PTW32_INTERLOCKED_LONG)PTW32_FALSE ==
+ (PTW32_INTERLOCKED_LONG)PTW32_INTERLOCKED_EXCHANGE_ADD_LONG((PTW32_INTERLOCKED_LONGPTR)&once_control->done,
+ (PTW32_INTERLOCKED_LONG)0)) /* MBR fence */
+ {
+ ptw32_mcs_local_node_t node;
+
+ ptw32_mcs_lock_acquire((ptw32_mcs_lock_t *)&once_control->lock, &node);
+
+ if (!once_control->done)
+ {
+
+#if defined(_MSC_VER) && _MSC_VER < 1400
+#pragma inline_depth(0)
+#endif
+
+ pthread_cleanup_push(ptw32_mcs_lock_release, &node);
+ (*init_routine)();
+ pthread_cleanup_pop(0);
+
+#if defined(_MSC_VER) && _MSC_VER < 1400
+#pragma inline_depth()
+#endif
+
+ once_control->done = PTW32_TRUE;
+ }
+
+ ptw32_mcs_lock_release(&node);
+ }
+
+ return 0;
+
+} /* pthread_once */
diff --git a/libs/pthreads/src/pthread_rwlock_destroy.c b/libs/pthreads/src/pthread_rwlock_destroy.c
new file mode 100644
index 0000000000..245a892410
--- /dev/null
+++ b/libs/pthreads/src/pthread_rwlock_destroy.c
@@ -0,0 +1,143 @@
+/*
+ * pthread_rwlock_destroy.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_destroy (pthread_rwlock_t * rwlock)
+{
+ pthread_rwlock_t rwl;
+ int result = 0, result1 = 0, result2 = 0;
+
+ if (rwlock == NULL || *rwlock == NULL)
+ {
+ return EINVAL;
+ }
+
+ if (*rwlock != PTHREAD_RWLOCK_INITIALIZER)
+ {
+ rwl = *rwlock;
+
+ if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+ {
+ return EINVAL;
+ }
+
+ if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0)
+ {
+ return result;
+ }
+
+ if ((result =
+ pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+ return result;
+ }
+
+ /*
+ * Check whether any threads own/wait for the lock (wait for ex.access);
+ * report "BUSY" if so.
+ */
+ if (rwl->nExclusiveAccessCount > 0
+ || rwl->nSharedAccessCount > rwl->nCompletedSharedAccessCount)
+ {
+ result = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted));
+ result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+ result2 = EBUSY;
+ }
+ else
+ {
+ rwl->nMagic = 0;
+
+ if ((result =
+ pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ pthread_mutex_unlock (&rwl->mtxExclusiveAccess);
+ return result;
+ }
+
+ if ((result =
+ pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))) != 0)
+ {
+ return result;
+ }
+
+ *rwlock = NULL; /* Invalidate rwlock before anything else */
+ result = pthread_cond_destroy (&(rwl->cndSharedAccessCompleted));
+ result1 = pthread_mutex_destroy (&(rwl->mtxSharedAccessCompleted));
+ result2 = pthread_mutex_destroy (&(rwl->mtxExclusiveAccess));
+ (void) free (rwl);
+ }
+ }
+ else
+ {
+ ptw32_mcs_local_node_t node;
+ /*
+ * See notes in ptw32_rwlock_check_need_init() above also.
+ */
+ ptw32_mcs_lock_acquire(&ptw32_rwlock_test_init_lock, &node);
+
+ /*
+ * Check again.
+ */
+ if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+ {
+ /*
+ * This is all we need to do to destroy a statically
+ * initialised rwlock that has not yet been used (initialised).
+ * If we get to here, another thread
+ * waiting to initialise this rwlock will get an EINVAL.
+ */
+ *rwlock = NULL;
+ }
+ else
+ {
+ /*
+ * The rwlock has been initialised while we were waiting
+ * so assume it's in use.
+ */
+ result = EBUSY;
+ }
+
+ ptw32_mcs_lock_release(&node);
+ }
+
+ return ((result != 0) ? result : ((result1 != 0) ? result1 : result2));
+}
diff --git a/libs/pthreads/src/pthread_rwlock_init.c b/libs/pthreads/src/pthread_rwlock_init.c
new file mode 100644
index 0000000000..597c1ff266
--- /dev/null
+++ b/libs/pthreads/src/pthread_rwlock_init.c
@@ -0,0 +1,109 @@
+/*
+ * pthread_rwlock_init.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_init (pthread_rwlock_t * rwlock,
+ const pthread_rwlockattr_t * attr)
+{
+ int result;
+ pthread_rwlock_t rwl = 0;
+
+ if (rwlock == NULL)
+ {
+ return EINVAL;
+ }
+
+ if (attr != NULL && *attr != NULL)
+ {
+ result = EINVAL; /* Not supported */
+ goto DONE;
+ }
+
+ rwl = (pthread_rwlock_t) calloc (1, sizeof (*rwl));
+
+ if (rwl == NULL)
+ {
+ result = ENOMEM;
+ goto DONE;
+ }
+
+ rwl->nSharedAccessCount = 0;
+ rwl->nExclusiveAccessCount = 0;
+ rwl->nCompletedSharedAccessCount = 0;
+
+ result = pthread_mutex_init (&rwl->mtxExclusiveAccess, NULL);
+ if (result != 0)
+ {
+ goto FAIL0;
+ }
+
+ result = pthread_mutex_init (&rwl->mtxSharedAccessCompleted, NULL);
+ if (result != 0)
+ {
+ goto FAIL1;
+ }
+
+ result = pthread_cond_init (&rwl->cndSharedAccessCompleted, NULL);
+ if (result != 0)
+ {
+ goto FAIL2;
+ }
+
+ rwl->nMagic = PTW32_RWLOCK_MAGIC;
+
+ result = 0;
+ goto DONE;
+
+FAIL2:
+ (void) pthread_mutex_destroy (&(rwl->mtxSharedAccessCompleted));
+
+FAIL1:
+ (void) pthread_mutex_destroy (&(rwl->mtxExclusiveAccess));
+
+FAIL0:
+ (void) free (rwl);
+ rwl = NULL;
+
+DONE:
+ *rwlock = rwl;
+
+ return result;
+}
diff --git a/libs/pthreads/src/pthread_rwlock_rdlock.c b/libs/pthreads/src/pthread_rwlock_rdlock.c
new file mode 100644
index 0000000000..91e180835e
--- /dev/null
+++ b/libs/pthreads/src/pthread_rwlock_rdlock.c
@@ -0,0 +1,102 @@
+/*
+ * pthread_rwlock_rdlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_rdlock (pthread_rwlock_t * rwlock)
+{
+ int result;
+ pthread_rwlock_t rwl;
+
+ if (rwlock == NULL || *rwlock == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static rwlock. We check
+ * again inside the guarded section of ptw32_rwlock_check_need_init()
+ * to avoid race conditions.
+ */
+ if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+ {
+ result = ptw32_rwlock_check_need_init (rwlock);
+
+ if (result != 0 && result != EBUSY)
+ {
+ return result;
+ }
+ }
+
+ rwl = *rwlock;
+
+ if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+ {
+ return EINVAL;
+ }
+
+ if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0)
+ {
+ return result;
+ }
+
+ if (++rwl->nSharedAccessCount == INT_MAX)
+ {
+ if ((result =
+ pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+ return result;
+ }
+
+ rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
+ rwl->nCompletedSharedAccessCount = 0;
+
+ if ((result =
+ pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+ return result;
+ }
+ }
+
+ return (pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)));
+}
diff --git a/libs/pthreads/src/pthread_rwlock_timedrdlock.c b/libs/pthreads/src/pthread_rwlock_timedrdlock.c
new file mode 100644
index 0000000000..7133778bf1
--- /dev/null
+++ b/libs/pthreads/src/pthread_rwlock_timedrdlock.c
@@ -0,0 +1,109 @@
+/*
+ * pthread_rwlock_timedrdlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_timedrdlock (pthread_rwlock_t * rwlock,
+ const struct timespec *abstime)
+{
+ int result;
+ pthread_rwlock_t rwl;
+
+ if (rwlock == NULL || *rwlock == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static rwlock. We check
+ * again inside the guarded section of ptw32_rwlock_check_need_init()
+ * to avoid race conditions.
+ */
+ if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+ {
+ result = ptw32_rwlock_check_need_init (rwlock);
+
+ if (result != 0 && result != EBUSY)
+ {
+ return result;
+ }
+ }
+
+ rwl = *rwlock;
+
+ if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+ {
+ return EINVAL;
+ }
+
+ if ((result =
+ pthread_mutex_timedlock (&(rwl->mtxExclusiveAccess), abstime)) != 0)
+ {
+ return result;
+ }
+
+ if (++rwl->nSharedAccessCount == INT_MAX)
+ {
+ if ((result =
+ pthread_mutex_timedlock (&(rwl->mtxSharedAccessCompleted),
+ abstime)) != 0)
+ {
+ if (result == ETIMEDOUT)
+ {
+ ++rwl->nCompletedSharedAccessCount;
+ }
+ (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+ return result;
+ }
+
+ rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
+ rwl->nCompletedSharedAccessCount = 0;
+
+ if ((result =
+ pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+ return result;
+ }
+ }
+
+ return (pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)));
+}
diff --git a/libs/pthreads/src/pthread_rwlock_timedwrlock.c b/libs/pthreads/src/pthread_rwlock_timedwrlock.c
new file mode 100644
index 0000000000..8c111bbb1b
--- /dev/null
+++ b/libs/pthreads/src/pthread_rwlock_timedwrlock.c
@@ -0,0 +1,139 @@
+/*
+ * pthread_rwlock_timedwrlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_timedwrlock (pthread_rwlock_t * rwlock,
+ const struct timespec *abstime)
+{
+ int result;
+ pthread_rwlock_t rwl;
+
+ if (rwlock == NULL || *rwlock == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static rwlock. We check
+ * again inside the guarded section of ptw32_rwlock_check_need_init()
+ * to avoid race conditions.
+ */
+ if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+ {
+ result = ptw32_rwlock_check_need_init (rwlock);
+
+ if (result != 0 && result != EBUSY)
+ {
+ return result;
+ }
+ }
+
+ rwl = *rwlock;
+
+ if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+ {
+ return EINVAL;
+ }
+
+ if ((result =
+ pthread_mutex_timedlock (&(rwl->mtxExclusiveAccess), abstime)) != 0)
+ {
+ return result;
+ }
+
+ if ((result =
+ pthread_mutex_timedlock (&(rwl->mtxSharedAccessCompleted),
+ abstime)) != 0)
+ {
+ (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+ return result;
+ }
+
+ if (rwl->nExclusiveAccessCount == 0)
+ {
+ if (rwl->nCompletedSharedAccessCount > 0)
+ {
+ rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
+ rwl->nCompletedSharedAccessCount = 0;
+ }
+
+ if (rwl->nSharedAccessCount > 0)
+ {
+ rwl->nCompletedSharedAccessCount = -rwl->nSharedAccessCount;
+
+ /*
+ * This routine may be a cancelation point
+ * according to POSIX 1003.1j section 18.1.2.
+ */
+#if defined(_MSC_VER) && _MSC_VER < 1400
+#pragma inline_depth(0)
+#endif
+ pthread_cleanup_push (ptw32_rwlock_cancelwrwait, (void *) rwl);
+
+ do
+ {
+ result =
+ pthread_cond_timedwait (&(rwl->cndSharedAccessCompleted),
+ &(rwl->mtxSharedAccessCompleted),
+ abstime);
+ }
+ while (result == 0 && rwl->nCompletedSharedAccessCount < 0);
+
+ pthread_cleanup_pop ((result != 0) ? 1 : 0);
+#if defined(_MSC_VER) && _MSC_VER < 1400
+#pragma inline_depth()
+#endif
+
+ if (result == 0)
+ {
+ rwl->nSharedAccessCount = 0;
+ }
+ }
+ }
+
+ if (result == 0)
+ {
+ rwl->nExclusiveAccessCount++;
+ }
+
+ return result;
+}
diff --git a/libs/pthreads/src/pthread_rwlock_tryrdlock.c b/libs/pthreads/src/pthread_rwlock_tryrdlock.c
new file mode 100644
index 0000000000..0fc5458579
--- /dev/null
+++ b/libs/pthreads/src/pthread_rwlock_tryrdlock.c
@@ -0,0 +1,102 @@
+/*
+ * pthread_rwlock_tryrdlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_tryrdlock (pthread_rwlock_t * rwlock)
+{
+ int result;
+ pthread_rwlock_t rwl;
+
+ if (rwlock == NULL || *rwlock == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static rwlock. We check
+ * again inside the guarded section of ptw32_rwlock_check_need_init()
+ * to avoid race conditions.
+ */
+ if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+ {
+ result = ptw32_rwlock_check_need_init (rwlock);
+
+ if (result != 0 && result != EBUSY)
+ {
+ return result;
+ }
+ }
+
+ rwl = *rwlock;
+
+ if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+ {
+ return EINVAL;
+ }
+
+ if ((result = pthread_mutex_trylock (&(rwl->mtxExclusiveAccess))) != 0)
+ {
+ return result;
+ }
+
+ if (++rwl->nSharedAccessCount == INT_MAX)
+ {
+ if ((result =
+ pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+ return result;
+ }
+
+ rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
+ rwl->nCompletedSharedAccessCount = 0;
+
+ if ((result =
+ pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+ return result;
+ }
+ }
+
+ return (pthread_mutex_unlock (&rwl->mtxExclusiveAccess));
+}
diff --git a/libs/pthreads/src/pthread_rwlock_trywrlock.c b/libs/pthreads/src/pthread_rwlock_trywrlock.c
new file mode 100644
index 0000000000..9997c5d7fb
--- /dev/null
+++ b/libs/pthreads/src/pthread_rwlock_trywrlock.c
@@ -0,0 +1,122 @@
+/*
+ * pthread_rwlock_trywrlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_trywrlock (pthread_rwlock_t * rwlock)
+{
+ int result, result1;
+ pthread_rwlock_t rwl;
+
+ if (rwlock == NULL || *rwlock == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static rwlock. We check
+ * again inside the guarded section of ptw32_rwlock_check_need_init()
+ * to avoid race conditions.
+ */
+ if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+ {
+ result = ptw32_rwlock_check_need_init (rwlock);
+
+ if (result != 0 && result != EBUSY)
+ {
+ return result;
+ }
+ }
+
+ rwl = *rwlock;
+
+ if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+ {
+ return EINVAL;
+ }
+
+ if ((result = pthread_mutex_trylock (&(rwl->mtxExclusiveAccess))) != 0)
+ {
+ return result;
+ }
+
+ if ((result =
+ pthread_mutex_trylock (&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+ return ((result1 != 0) ? result1 : result);
+ }
+
+ if (rwl->nExclusiveAccessCount == 0)
+ {
+ if (rwl->nCompletedSharedAccessCount > 0)
+ {
+ rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
+ rwl->nCompletedSharedAccessCount = 0;
+ }
+
+ if (rwl->nSharedAccessCount > 0)
+ {
+ if ((result =
+ pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+ return result;
+ }
+
+ if ((result =
+ pthread_mutex_unlock (&(rwl->mtxExclusiveAccess))) == 0)
+ {
+ result = EBUSY;
+ }
+ }
+ else
+ {
+ rwl->nExclusiveAccessCount = 1;
+ }
+ }
+ else
+ {
+ result = EBUSY;
+ }
+
+ return result;
+}
diff --git a/libs/pthreads/src/pthread_rwlock_unlock.c b/libs/pthreads/src/pthread_rwlock_unlock.c
new file mode 100644
index 0000000000..d48d18705b
--- /dev/null
+++ b/libs/pthreads/src/pthread_rwlock_unlock.c
@@ -0,0 +1,93 @@
+/*
+ * pthread_rwlock_unlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_unlock (pthread_rwlock_t * rwlock)
+{
+ int result, result1;
+ pthread_rwlock_t rwl;
+
+ if (rwlock == NULL || *rwlock == NULL)
+ {
+ return (EINVAL);
+ }
+
+ if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+ {
+ /*
+ * Assume any race condition here is harmless.
+ */
+ return 0;
+ }
+
+ rwl = *rwlock;
+
+ if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+ {
+ return EINVAL;
+ }
+
+ if (rwl->nExclusiveAccessCount == 0)
+ {
+ if ((result =
+ pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ return result;
+ }
+
+ if (++rwl->nCompletedSharedAccessCount == 0)
+ {
+ result = pthread_cond_signal (&(rwl->cndSharedAccessCompleted));
+ }
+
+ result1 = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted));
+ }
+ else
+ {
+ rwl->nExclusiveAccessCount--;
+
+ result = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted));
+ result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+
+ }
+
+ return ((result != 0) ? result : result1);
+}
diff --git a/libs/pthreads/src/pthread_rwlock_wrlock.c b/libs/pthreads/src/pthread_rwlock_wrlock.c
new file mode 100644
index 0000000000..e8b4fbb303
--- /dev/null
+++ b/libs/pthreads/src/pthread_rwlock_wrlock.c
@@ -0,0 +1,133 @@
+/*
+ * pthread_rwlock_wrlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_wrlock (pthread_rwlock_t * rwlock)
+{
+ int result;
+ pthread_rwlock_t rwl;
+
+ if (rwlock == NULL || *rwlock == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static rwlock. We check
+ * again inside the guarded section of ptw32_rwlock_check_need_init()
+ * to avoid race conditions.
+ */
+ if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+ {
+ result = ptw32_rwlock_check_need_init (rwlock);
+
+ if (result != 0 && result != EBUSY)
+ {
+ return result;
+ }
+ }
+
+ rwl = *rwlock;
+
+ if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+ {
+ return EINVAL;
+ }
+
+ if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0)
+ {
+ return result;
+ }
+
+ if ((result = pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+ return result;
+ }
+
+ if (rwl->nExclusiveAccessCount == 0)
+ {
+ if (rwl->nCompletedSharedAccessCount > 0)
+ {
+ rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
+ rwl->nCompletedSharedAccessCount = 0;
+ }
+
+ if (rwl->nSharedAccessCount > 0)
+ {
+ rwl->nCompletedSharedAccessCount = -rwl->nSharedAccessCount;
+
+ /*
+ * This routine may be a cancelation point
+ * according to POSIX 1003.1j section 18.1.2.
+ */
+#if defined(_MSC_VER) && _MSC_VER < 1400
+#pragma inline_depth(0)
+#endif
+ pthread_cleanup_push (ptw32_rwlock_cancelwrwait, (void *) rwl);
+
+ do
+ {
+ result = pthread_cond_wait (&(rwl->cndSharedAccessCompleted),
+ &(rwl->mtxSharedAccessCompleted));
+ }
+ while (result == 0 && rwl->nCompletedSharedAccessCount < 0);
+
+ pthread_cleanup_pop ((result != 0) ? 1 : 0);
+#if defined(_MSC_VER) && _MSC_VER < 1400
+#pragma inline_depth()
+#endif
+
+ if (result == 0)
+ {
+ rwl->nSharedAccessCount = 0;
+ }
+ }
+ }
+
+ if (result == 0)
+ {
+ rwl->nExclusiveAccessCount++;
+ }
+
+ return result;
+}
diff --git a/libs/pthreads/src/pthread_rwlockattr_destroy.c b/libs/pthreads/src/pthread_rwlockattr_destroy.c
new file mode 100644
index 0000000000..868e727d30
--- /dev/null
+++ b/libs/pthreads/src/pthread_rwlockattr_destroy.c
@@ -0,0 +1,84 @@
+/*
+ * pthread_rwlockattr_destroy.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Destroys a rwlock attributes object. The object can
+ * no longer be used.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_rwlockattr_t
+ *
+ *
+ * DESCRIPTION
+ * Destroys a rwlock attributes object. The object can
+ * no longer be used.
+ *
+ * NOTES:
+ * 1) Does not affect rwlockss created using 'attr'
+ *
+ * RESULTS
+ * 0 successfully released attr,
+ * EINVAL 'attr' is invalid.
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+
+ if (attr == NULL || *attr == NULL)
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ pthread_rwlockattr_t rwa = *attr;
+
+ *attr = NULL;
+ free (rwa);
+ }
+
+ return (result);
+} /* pthread_rwlockattr_destroy */
diff --git a/libs/pthreads/src/pthread_rwlockattr_getpshared.c b/libs/pthreads/src/pthread_rwlockattr_getpshared.c
new file mode 100644
index 0000000000..eeace207f2
--- /dev/null
+++ b/libs/pthreads/src/pthread_rwlockattr_getpshared.c
@@ -0,0 +1,97 @@
+/*
+ * pthread_rwlockattr_getpshared.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr,
+ int *pshared)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Determine whether rwlocks created with 'attr' can be
+ * shared between processes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_rwlockattr_t
+ *
+ * pshared
+ * will be set to one of:
+ *
+ * PTHREAD_PROCESS_SHARED
+ * May be shared if in shared memory
+ *
+ * PTHREAD_PROCESS_PRIVATE
+ * Cannot be shared.
+ *
+ *
+ * DESCRIPTION
+ * Rwlocks creatd with 'attr' can be shared between
+ * processes if pthread_rwlock_t variable is allocated
+ * in memory shared by these processes.
+ * NOTES:
+ * 1) pshared rwlocks MUST be allocated in shared
+ * memory.
+ * 2) The following macro is defined if shared rwlocks
+ * are supported:
+ * _POSIX_THREAD_PROCESS_SHARED
+ *
+ * RESULTS
+ * 0 successfully retrieved attribute,
+ * EINVAL 'attr' is invalid,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+
+ if ((attr != NULL && *attr != NULL) && (pshared != NULL))
+ {
+ *pshared = (*attr)->pshared;
+ result = 0;
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return (result);
+
+} /* pthread_rwlockattr_getpshared */
diff --git a/libs/pthreads/src/pthread_rwlockattr_init.c b/libs/pthreads/src/pthread_rwlockattr_init.c
new file mode 100644
index 0000000000..a2d2b945f4
--- /dev/null
+++ b/libs/pthreads/src/pthread_rwlockattr_init.c
@@ -0,0 +1,83 @@
+/*
+ * pthread_rwlockattr_init.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlockattr_init (pthread_rwlockattr_t * attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Initializes a rwlock attributes object with default
+ * attributes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_rwlockattr_t
+ *
+ *
+ * DESCRIPTION
+ * Initializes a rwlock attributes object with default
+ * attributes.
+ *
+ * RESULTS
+ * 0 successfully initialized attr,
+ * ENOMEM insufficient memory for attr.
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ pthread_rwlockattr_t rwa;
+
+ rwa = (pthread_rwlockattr_t) calloc (1, sizeof (*rwa));
+
+ if (rwa == NULL)
+ {
+ result = ENOMEM;
+ }
+ else
+ {
+ rwa->pshared = PTHREAD_PROCESS_PRIVATE;
+ }
+
+ *attr = rwa;
+
+ return (result);
+} /* pthread_rwlockattr_init */
diff --git a/libs/pthreads/src/pthread_rwlockattr_setpshared.c b/libs/pthreads/src/pthread_rwlockattr_setpshared.c
new file mode 100644
index 0000000000..a83dd70a4b
--- /dev/null
+++ b/libs/pthreads/src/pthread_rwlockattr_setpshared.c
@@ -0,0 +1,120 @@
+/*
+ * pthread_rwlockattr_setpshared.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, int pshared)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Rwlocks created with 'attr' can be shared between
+ * processes if pthread_rwlock_t variable is allocated
+ * in memory shared by these processes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_rwlockattr_t
+ *
+ * pshared
+ * must be one of:
+ *
+ * PTHREAD_PROCESS_SHARED
+ * May be shared if in shared memory
+ *
+ * PTHREAD_PROCESS_PRIVATE
+ * Cannot be shared.
+ *
+ * DESCRIPTION
+ * Rwlocks creatd with 'attr' can be shared between
+ * processes if pthread_rwlock_t variable is allocated
+ * in memory shared by these processes.
+ *
+ * NOTES:
+ * 1) pshared rwlocks MUST be allocated in shared
+ * memory.
+ *
+ * 2) The following macro is defined if shared rwlocks
+ * are supported:
+ * _POSIX_THREAD_PROCESS_SHARED
+ *
+ * RESULTS
+ * 0 successfully set attribute,
+ * EINVAL 'attr' or pshared is invalid,
+ * ENOSYS PTHREAD_PROCESS_SHARED not supported,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+
+ if ((attr != NULL && *attr != NULL) &&
+ ((pshared == PTHREAD_PROCESS_SHARED) ||
+ (pshared == PTHREAD_PROCESS_PRIVATE)))
+ {
+ if (pshared == PTHREAD_PROCESS_SHARED)
+ {
+
+#if !defined( _POSIX_THREAD_PROCESS_SHARED )
+
+ result = ENOSYS;
+ pshared = PTHREAD_PROCESS_PRIVATE;
+
+#else
+
+ result = 0;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+ }
+ else
+ {
+ result = 0;
+ }
+
+ (*attr)->pshared = pshared;
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return (result);
+
+} /* pthread_rwlockattr_setpshared */
diff --git a/libs/pthreads/src/pthread_self.c b/libs/pthreads/src/pthread_self.c
new file mode 100644
index 0000000000..9a1765f82e
--- /dev/null
+++ b/libs/pthreads/src/pthread_self.c
@@ -0,0 +1,141 @@
+/*
+ * pthread_self.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+pthread_t
+pthread_self (void)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function returns a reference to the current running
+ * thread.
+ *
+ * PARAMETERS
+ * N/A
+ *
+ *
+ * DESCRIPTION
+ * This function returns a reference to the current running
+ * thread.
+ *
+ * RESULTS
+ * pthread_t reference to the current thread
+ *
+ * ------------------------------------------------------
+ */
+{
+ pthread_t self;
+ pthread_t nil = {NULL, 0};
+ ptw32_thread_t * sp;
+
+#if defined(_UWIN)
+ if (!ptw32_selfThreadKey)
+ return nil;
+#endif
+
+ sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
+
+ if (sp != NULL)
+ {
+ self = sp->ptHandle;
+ }
+ else
+ {
+ /*
+ * Need to create an implicit 'self' for the currently
+ * executing thread.
+ */
+ self = ptw32_new ();
+ sp = (ptw32_thread_t *) self.p;
+
+ if (sp != NULL)
+ {
+ /*
+ * This is a non-POSIX thread which has chosen to call
+ * a POSIX threads function for some reason. We assume that
+ * it isn't joinable, but we do assume that it's
+ * (deferred) cancelable.
+ */
+ sp->implicit = 1;
+ sp->detachState = PTHREAD_CREATE_DETACHED;
+ sp->thread = GetCurrentThreadId ();
+
+#if defined(NEED_DUPLICATEHANDLE)
+ /*
+ * DuplicateHandle does not exist on WinCE.
+ *
+ * NOTE:
+ * GetCurrentThread only returns a pseudo-handle
+ * which is only valid in the current thread context.
+ * Therefore, you should not pass the handle to
+ * other threads for whatever purpose.
+ */
+ sp->threadH = GetCurrentThread ();
+#else
+ if (!DuplicateHandle (GetCurrentProcess (),
+ GetCurrentThread (),
+ GetCurrentProcess (),
+ &sp->threadH,
+ 0, FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ /*
+ * Should not do this, but we have no alternative if
+ * we can't get a Win32 thread handle.
+ * Thread structs are never freed.
+ */
+ ptw32_threadReusePush (self);
+ /*
+ * As this is a win32 thread calling us and we have failed,
+ * return a value that makes sense to win32.
+ */
+ return nil;
+ }
+#endif
+
+ /*
+ * No need to explicitly serialise access to sched_priority
+ * because the new handle is not yet public.
+ */
+ sp->sched_priority = GetThreadPriority (sp->threadH);
+ pthread_setspecific (ptw32_selfThreadKey, (void *) sp);
+ }
+ }
+
+ return (self);
+
+} /* pthread_self */
diff --git a/libs/pthreads/src/pthread_setcancelstate.c b/libs/pthreads/src/pthread_setcancelstate.c
new file mode 100644
index 0000000000..bbcd624af8
--- /dev/null
+++ b/libs/pthreads/src/pthread_setcancelstate.c
@@ -0,0 +1,125 @@
+/*
+ * pthread_setcancelstate.c
+ *
+ * Description:
+ * POSIX thread functions related to thread cancellation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_setcancelstate (int state, int *oldstate)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function atomically sets the calling thread's
+ * cancelability state to 'state' and returns the previous
+ * cancelability state at the location referenced by
+ * 'oldstate'
+ *
+ * PARAMETERS
+ * state,
+ * oldstate
+ * PTHREAD_CANCEL_ENABLE
+ * cancellation is enabled,
+ *
+ * PTHREAD_CANCEL_DISABLE
+ * cancellation is disabled
+ *
+ *
+ * DESCRIPTION
+ * This function atomically sets the calling thread's
+ * cancelability state to 'state' and returns the previous
+ * cancelability state at the location referenced by
+ * 'oldstate'.
+ *
+ * NOTES:
+ * 1) Use to disable cancellation around 'atomic' code that
+ * includes cancellation points
+ *
+ * COMPATIBILITY ADDITIONS
+ * If 'oldstate' is NULL then the previous state is not returned
+ * but the function still succeeds. (Solaris)
+ *
+ * RESULTS
+ * 0 successfully set cancelability type,
+ * EINVAL 'state' is invalid
+ *
+ * ------------------------------------------------------
+ */
+{
+ ptw32_mcs_local_node_t stateLock;
+ int result = 0;
+ pthread_t self = pthread_self ();
+ ptw32_thread_t * sp = (ptw32_thread_t *) self.p;
+
+ if (sp == NULL
+ || (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE))
+ {
+ return EINVAL;
+ }
+
+ /*
+ * Lock for async-cancel safety.
+ */
+ ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
+
+ if (oldstate != NULL)
+ {
+ *oldstate = sp->cancelState;
+ }
+
+ sp->cancelState = state;
+
+ /*
+ * Check if there is a pending asynchronous cancel
+ */
+ if (state == PTHREAD_CANCEL_ENABLE
+ && sp->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS
+ && WaitForSingleObject (sp->cancelEvent, 0) == WAIT_OBJECT_0)
+ {
+ sp->state = PThreadStateCanceling;
+ sp->cancelState = PTHREAD_CANCEL_DISABLE;
+ ResetEvent (sp->cancelEvent);
+ ptw32_mcs_lock_release (&stateLock);
+ ptw32_throw (PTW32_EPS_CANCEL);
+
+ /* Never reached */
+ }
+
+ ptw32_mcs_lock_release (&stateLock);
+
+ return (result);
+
+} /* pthread_setcancelstate */
diff --git a/libs/pthreads/src/pthread_setcanceltype.c b/libs/pthreads/src/pthread_setcanceltype.c
new file mode 100644
index 0000000000..72b0af5bbc
--- /dev/null
+++ b/libs/pthreads/src/pthread_setcanceltype.c
@@ -0,0 +1,126 @@
+/*
+ * pthread_setcanceltype.c
+ *
+ * Description:
+ * POSIX thread functions related to thread cancellation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_setcanceltype (int type, int *oldtype)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function atomically sets the calling thread's
+ * cancelability type to 'type' and returns the previous
+ * cancelability type at the location referenced by
+ * 'oldtype'
+ *
+ * PARAMETERS
+ * type,
+ * oldtype
+ * PTHREAD_CANCEL_DEFERRED
+ * only deferred cancelation is allowed,
+ *
+ * PTHREAD_CANCEL_ASYNCHRONOUS
+ * Asynchronous cancellation is allowed
+ *
+ *
+ * DESCRIPTION
+ * This function atomically sets the calling thread's
+ * cancelability type to 'type' and returns the previous
+ * cancelability type at the location referenced by
+ * 'oldtype'
+ *
+ * NOTES:
+ * 1) Use with caution; most code is not safe for use
+ * with asynchronous cancelability.
+ *
+ * COMPATIBILITY ADDITIONS
+ * If 'oldtype' is NULL then the previous type is not returned
+ * but the function still succeeds. (Solaris)
+ *
+ * RESULTS
+ * 0 successfully set cancelability type,
+ * EINVAL 'type' is invalid
+ *
+ * ------------------------------------------------------
+ */
+{
+ ptw32_mcs_local_node_t stateLock;
+ int result = 0;
+ pthread_t self = pthread_self ();
+ ptw32_thread_t * sp = (ptw32_thread_t *) self.p;
+
+ if (sp == NULL
+ || (type != PTHREAD_CANCEL_DEFERRED
+ && type != PTHREAD_CANCEL_ASYNCHRONOUS))
+ {
+ return EINVAL;
+ }
+
+ /*
+ * Lock for async-cancel safety.
+ */
+ ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
+
+ if (oldtype != NULL)
+ {
+ *oldtype = sp->cancelType;
+ }
+
+ sp->cancelType = type;
+
+ /*
+ * Check if there is a pending asynchronous cancel
+ */
+ if (sp->cancelState == PTHREAD_CANCEL_ENABLE
+ && type == PTHREAD_CANCEL_ASYNCHRONOUS
+ && WaitForSingleObject (sp->cancelEvent, 0) == WAIT_OBJECT_0)
+ {
+ sp->state = PThreadStateCanceling;
+ sp->cancelState = PTHREAD_CANCEL_DISABLE;
+ ResetEvent (sp->cancelEvent);
+ ptw32_mcs_lock_release (&stateLock);
+ ptw32_throw (PTW32_EPS_CANCEL);
+
+ /* Never reached */
+ }
+
+ ptw32_mcs_lock_release (&stateLock);
+
+ return (result);
+
+} /* pthread_setcanceltype */
diff --git a/libs/pthreads/src/pthread_setconcurrency.c b/libs/pthreads/src/pthread_setconcurrency.c
new file mode 100644
index 0000000000..f62346f8e5
--- /dev/null
+++ b/libs/pthreads/src/pthread_setconcurrency.c
@@ -0,0 +1,53 @@
+/*
+ * pthread_setconcurrency.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_setconcurrency (int level)
+{
+ if (level < 0)
+ {
+ return EINVAL;
+ }
+ else
+ {
+ ptw32_concurrency = level;
+ return 0;
+ }
+}
diff --git a/libs/pthreads/src/pthread_setschedparam.c b/libs/pthreads/src/pthread_setschedparam.c
new file mode 100644
index 0000000000..b762753cdd
--- /dev/null
+++ b/libs/pthreads/src/pthread_setschedparam.c
@@ -0,0 +1,123 @@
+/*
+ * sched_setschedparam.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_setschedparam (pthread_t thread, int policy,
+ const struct sched_param *param)
+{
+ int result;
+
+ /* Validate the thread id. */
+ result = pthread_kill (thread, 0);
+ if (0 != result)
+ {
+ return result;
+ }
+
+ /* Validate the scheduling policy. */
+ if (policy < SCHED_MIN || policy > SCHED_MAX)
+ {
+ return EINVAL;
+ }
+
+ /* Ensure the policy is SCHED_OTHER. */
+ if (policy != SCHED_OTHER)
+ {
+ return ENOTSUP;
+ }
+
+ return (ptw32_setthreadpriority (thread, policy, param->sched_priority));
+}
+
+
+int
+ptw32_setthreadpriority (pthread_t thread, int policy, int priority)
+{
+ int prio;
+ ptw32_mcs_local_node_t threadLock;
+ int result = 0;
+ ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
+
+ prio = priority;
+
+ /* Validate priority level. */
+ if (prio < sched_get_priority_min (policy) ||
+ prio > sched_get_priority_max (policy))
+ {
+ return EINVAL;
+ }
+
+#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL)
+/* WinCE */
+#else
+/* Everything else */
+
+ if (THREAD_PRIORITY_IDLE < prio && THREAD_PRIORITY_LOWEST > prio)
+ {
+ prio = THREAD_PRIORITY_LOWEST;
+ }
+ else if (THREAD_PRIORITY_TIME_CRITICAL > prio
+ && THREAD_PRIORITY_HIGHEST < prio)
+ {
+ prio = THREAD_PRIORITY_HIGHEST;
+ }
+
+#endif
+
+ ptw32_mcs_lock_acquire (&tp->threadLock, &threadLock);
+
+ /* If this fails, the current priority is unchanged. */
+ if (0 == SetThreadPriority (tp->threadH, prio))
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ /*
+ * Must record the thread's sched_priority as given,
+ * not as finally adjusted.
+ */
+ tp->sched_priority = priority;
+ }
+
+ ptw32_mcs_lock_release (&threadLock);
+
+ return result;
+}
diff --git a/libs/pthreads/src/pthread_setspecific.c b/libs/pthreads/src/pthread_setspecific.c
new file mode 100644
index 0000000000..0f29e704ab
--- /dev/null
+++ b/libs/pthreads/src/pthread_setspecific.c
@@ -0,0 +1,167 @@
+/*
+ * pthread_setspecific.c
+ *
+ * Description:
+ * POSIX thread functions which implement thread-specific data (TSD).
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_setspecific (pthread_key_t key, const void *value)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function sets the value of the thread specific
+ * key in the calling thread.
+ *
+ * PARAMETERS
+ * key
+ * an instance of pthread_key_t
+ * value
+ * the value to set key to
+ *
+ *
+ * DESCRIPTION
+ * This function sets the value of the thread specific
+ * key in the calling thread.
+ *
+ * RESULTS
+ * 0 successfully set value
+ * EAGAIN could not set value
+ * ENOENT SERIOUS!!
+ *
+ * ------------------------------------------------------
+ */
+{
+ pthread_t self;
+ int result = 0;
+
+ if (key != ptw32_selfThreadKey)
+ {
+ /*
+ * Using pthread_self will implicitly create
+ * an instance of pthread_t for the current
+ * thread if one wasn't explicitly created
+ */
+ self = pthread_self ();
+ if (self.p == NULL)
+ {
+ return ENOENT;
+ }
+ }
+ else
+ {
+ /*
+ * Resolve catch-22 of registering thread with selfThread
+ * key
+ */
+ ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
+
+ if (sp == NULL)
+ {
+ if (value == NULL)
+ {
+ return ENOENT;
+ }
+ self = *((pthread_t *) value);
+ }
+ else
+ {
+ self = sp->ptHandle;
+ }
+ }
+
+ result = 0;
+
+ if (key != NULL)
+ {
+ if (self.p != NULL && key->destructor != NULL && value != NULL)
+ {
+ ptw32_mcs_local_node_t keyLock;
+ ptw32_mcs_local_node_t threadLock;
+ ptw32_thread_t * sp = (ptw32_thread_t *) self.p;
+ /*
+ * Only require associations if we have to
+ * call user destroy routine.
+ * Don't need to locate an existing association
+ * when setting data to NULL for WIN32 since the
+ * data is stored with the operating system; not
+ * on the association; setting assoc to NULL short
+ * circuits the search.
+ */
+ ThreadKeyAssoc *assoc;
+
+ ptw32_mcs_lock_acquire(&(key->keyLock), &keyLock);
+ ptw32_mcs_lock_acquire(&(sp->threadLock), &threadLock);
+
+ assoc = (ThreadKeyAssoc *) sp->keys;
+ /*
+ * Locate existing association
+ */
+ while (assoc != NULL)
+ {
+ if (assoc->key == key)
+ {
+ /*
+ * Association already exists
+ */
+ break;
+ }
+ assoc = assoc->nextKey;
+ }
+
+ /*
+ * create an association if not found
+ */
+ if (assoc == NULL)
+ {
+ result = ptw32_tkAssocCreate (sp, key);
+ }
+
+ ptw32_mcs_lock_release(&threadLock);
+ ptw32_mcs_lock_release(&keyLock);
+ }
+
+ if (result == 0)
+ {
+ if (!TlsSetValue (key->key, (LPVOID) value))
+ {
+ result = EAGAIN;
+ }
+ }
+ }
+
+ return (result);
+} /* pthread_setspecific */
diff --git a/libs/pthreads/src/pthread_spin_destroy.c b/libs/pthreads/src/pthread_spin_destroy.c
new file mode 100644
index 0000000000..786c4e34cd
--- /dev/null
+++ b/libs/pthreads/src/pthread_spin_destroy.c
@@ -0,0 +1,111 @@
+/*
+ * pthread_spin_destroy.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_spin_destroy (pthread_spinlock_t * lock)
+{
+ register pthread_spinlock_t s;
+ int result = 0;
+
+ if (lock == NULL || *lock == NULL)
+ {
+ return EINVAL;
+ }
+
+ if ((s = *lock) != PTHREAD_SPINLOCK_INITIALIZER)
+ {
+ if (s->interlock == PTW32_SPIN_USE_MUTEX)
+ {
+ result = pthread_mutex_destroy (&(s->u.mutex));
+ }
+ else if ((PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED !=
+ PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR) &s->interlock,
+ (PTW32_INTERLOCKED_LONG) PTW32_SPIN_INVALID,
+ (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED))
+ {
+ result = EINVAL;
+ }
+
+ if (0 == result)
+ {
+ /*
+ * We are relying on the application to ensure that all other threads
+ * have finished with the spinlock before destroying it.
+ */
+ *lock = NULL;
+ (void) free (s);
+ }
+ }
+ else
+ {
+ /*
+ * See notes in ptw32_spinlock_check_need_init() above also.
+ */
+ ptw32_mcs_local_node_t node;
+
+ ptw32_mcs_lock_acquire(&ptw32_spinlock_test_init_lock, &node);
+
+ /*
+ * Check again.
+ */
+ if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
+ {
+ /*
+ * This is all we need to do to destroy a statically
+ * initialised spinlock that has not yet been used (initialised).
+ * If we get to here, another thread
+ * waiting to initialise this mutex will get an EINVAL.
+ */
+ *lock = NULL;
+ }
+ else
+ {
+ /*
+ * The spinlock has been initialised while we were waiting
+ * so assume it's in use.
+ */
+ result = EBUSY;
+ }
+
+ ptw32_mcs_lock_release(&node);
+ }
+
+ return (result);
+}
diff --git a/libs/pthreads/src/pthread_spin_init.c b/libs/pthreads/src/pthread_spin_init.c
new file mode 100644
index 0000000000..553af7eac8
--- /dev/null
+++ b/libs/pthreads/src/pthread_spin_init.c
@@ -0,0 +1,123 @@
+/*
+ * pthread_spin_init.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_spin_init (pthread_spinlock_t * lock, int pshared)
+{
+ pthread_spinlock_t s;
+ int cpus = 0;
+ int result = 0;
+
+ if (lock == NULL)
+ {
+ return EINVAL;
+ }
+
+ if (0 != ptw32_getprocessors (&cpus))
+ {
+ cpus = 1;
+ }
+
+ if (cpus > 1)
+ {
+ if (pshared == PTHREAD_PROCESS_SHARED)
+ {
+ /*
+ * Creating spinlock that can be shared between
+ * processes.
+ */
+#if _POSIX_THREAD_PROCESS_SHARED >= 0
+
+ /*
+ * Not implemented yet.
+ */
+
+#error ERROR [__FILE__, line __LINE__]: Process shared spin locks are not supported yet.
+
+#else
+
+ return ENOSYS;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+ }
+ }
+
+ s = (pthread_spinlock_t) calloc (1, sizeof (*s));
+
+ if (s == NULL)
+ {
+ return ENOMEM;
+ }
+
+ if (cpus > 1)
+ {
+ s->u.cpus = cpus;
+ s->interlock = PTW32_SPIN_UNLOCKED;
+ }
+ else
+ {
+ pthread_mutexattr_t ma;
+ result = pthread_mutexattr_init (&ma);
+
+ if (0 == result)
+ {
+ ma->pshared = pshared;
+ result = pthread_mutex_init (&(s->u.mutex), &ma);
+ if (0 == result)
+ {
+ s->interlock = PTW32_SPIN_USE_MUTEX;
+ }
+ }
+ (void) pthread_mutexattr_destroy (&ma);
+ }
+
+ if (0 == result)
+ {
+ *lock = s;
+ }
+ else
+ {
+ (void) free (s);
+ *lock = NULL;
+ }
+
+ return (result);
+}
diff --git a/libs/pthreads/src/pthread_spin_lock.c b/libs/pthreads/src/pthread_spin_lock.c
new file mode 100644
index 0000000000..b560e14891
--- /dev/null
+++ b/libs/pthreads/src/pthread_spin_lock.c
@@ -0,0 +1,80 @@
+/*
+ * pthread_spin_lock.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_spin_lock (pthread_spinlock_t * lock)
+{
+ register pthread_spinlock_t s;
+
+ if (NULL == lock || NULL == *lock)
+ {
+ return (EINVAL);
+ }
+
+ if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
+ {
+ int result;
+
+ if ((result = ptw32_spinlock_check_need_init (lock)) != 0)
+ {
+ return (result);
+ }
+ }
+
+ s = *lock;
+
+ while ((PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED ==
+ PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR) &s->interlock,
+ (PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED,
+ (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED))
+ {
+ }
+
+ if (s->interlock == PTW32_SPIN_LOCKED)
+ {
+ return 0;
+ }
+ else if (s->interlock == PTW32_SPIN_USE_MUTEX)
+ {
+ return pthread_mutex_lock (&(s->u.mutex));
+ }
+
+ return EINVAL;
+}
diff --git a/libs/pthreads/src/pthread_spin_trylock.c b/libs/pthreads/src/pthread_spin_trylock.c
new file mode 100644
index 0000000000..a6c65aff6a
--- /dev/null
+++ b/libs/pthreads/src/pthread_spin_trylock.c
@@ -0,0 +1,77 @@
+/*
+ * pthread_spin_trylock.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_spin_trylock (pthread_spinlock_t * lock)
+{
+ register pthread_spinlock_t s;
+
+ if (NULL == lock || NULL == *lock)
+ {
+ return (EINVAL);
+ }
+
+ if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
+ {
+ int result;
+
+ if ((result = ptw32_spinlock_check_need_init (lock)) != 0)
+ {
+ return (result);
+ }
+ }
+
+ s = *lock;
+
+ switch ((long)
+ PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR) &s->interlock,
+ (PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED,
+ (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED))
+ {
+ case PTW32_SPIN_UNLOCKED:
+ return 0;
+ case PTW32_SPIN_LOCKED:
+ return EBUSY;
+ case PTW32_SPIN_USE_MUTEX:
+ return pthread_mutex_trylock (&(s->u.mutex));
+ }
+
+ return EINVAL;
+}
diff --git a/libs/pthreads/src/pthread_spin_unlock.c b/libs/pthreads/src/pthread_spin_unlock.c
new file mode 100644
index 0000000000..3a6932aef3
--- /dev/null
+++ b/libs/pthreads/src/pthread_spin_unlock.c
@@ -0,0 +1,71 @@
+/*
+ * pthread_spin_unlock.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_spin_unlock (pthread_spinlock_t * lock)
+{
+ register pthread_spinlock_t s;
+
+ if (NULL == lock || NULL == *lock)
+ {
+ return (EINVAL);
+ }
+
+ s = *lock;
+
+ if (s == PTHREAD_SPINLOCK_INITIALIZER)
+ {
+ return EPERM;
+ }
+
+ switch ((long)
+ PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG ((PTW32_INTERLOCKED_LONGPTR) &s->interlock,
+ (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED,
+ (PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED))
+ {
+ case PTW32_SPIN_LOCKED:
+ case PTW32_SPIN_UNLOCKED:
+ return 0;
+ case PTW32_SPIN_USE_MUTEX:
+ return pthread_mutex_unlock (&(s->u.mutex));
+ }
+
+ return EINVAL;
+}
diff --git a/libs/pthreads/src/pthread_testcancel.c b/libs/pthreads/src/pthread_testcancel.c
new file mode 100644
index 0000000000..6658650000
--- /dev/null
+++ b/libs/pthreads/src/pthread_testcancel.c
@@ -0,0 +1,103 @@
+/*
+ * pthread_testcancel.c
+ *
+ * Description:
+ * POSIX thread functions related to thread cancellation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+void
+pthread_testcancel (void)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function creates a deferred cancellation point
+ * in the calling thread. The call has no effect if the
+ * current cancelability state is
+ * PTHREAD_CANCEL_DISABLE
+ *
+ * PARAMETERS
+ * N/A
+ *
+ *
+ * DESCRIPTION
+ * This function creates a deferred cancellation point
+ * in the calling thread. The call has no effect if the
+ * current cancelability state is
+ * PTHREAD_CANCEL_DISABLE
+ *
+ * NOTES:
+ * 1) Cancellation is asynchronous. Use pthread_join
+ * to wait for termination of thread if necessary
+ *
+ * RESULTS
+ * N/A
+ *
+ * ------------------------------------------------------
+ */
+{
+ ptw32_mcs_local_node_t stateLock;
+ pthread_t self = pthread_self ();
+ ptw32_thread_t * sp = (ptw32_thread_t *) self.p;
+
+ if (sp == NULL)
+ {
+ return;
+ }
+
+ /*
+ * Pthread_cancel() will have set sp->state to PThreadStateCancelPending
+ * and set an event, so no need to enter kernel space if
+ * sp->state != PThreadStateCancelPending - that only slows us down.
+ */
+ if (sp->state != PThreadStateCancelPending)
+ {
+ return;
+ }
+
+ ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
+
+ if (sp->cancelState != PTHREAD_CANCEL_DISABLE)
+ {
+ ResetEvent(sp->cancelEvent);
+ sp->state = PThreadStateCanceling;
+ sp->cancelState = PTHREAD_CANCEL_DISABLE;
+ ptw32_mcs_lock_release (&stateLock);
+ ptw32_throw (PTW32_EPS_CANCEL);
+ /* Never returns here */
+ }
+
+ ptw32_mcs_lock_release (&stateLock);
+} /* pthread_testcancel */
diff --git a/libs/pthreads/src/pthread_timechange_handler_np.c b/libs/pthreads/src/pthread_timechange_handler_np.c
new file mode 100644
index 0000000000..0f97e74f14
--- /dev/null
+++ b/libs/pthreads/src/pthread_timechange_handler_np.c
@@ -0,0 +1,108 @@
+/*
+ * pthread_timechange_handler_np.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * Notes on handling system time adjustments (especially negative ones).
+ * ---------------------------------------------------------------------
+ *
+ * This solution was suggested by Alexander Terekhov, but any errors
+ * in the implementation are mine - [Ross Johnson]
+ *
+ * 1) The problem: threads doing a timedwait on a CV may expect to timeout
+ * at a specific absolute time according to a system timer. If the
+ * system clock is adjusted backwards then those threads sleep longer than
+ * expected. Also, pthreads-win32 converts absolute times to intervals in
+ * order to make use of the underlying Win32, and so waiting threads may
+ * awake before their proper abstimes.
+ *
+ * 2) We aren't able to distinquish between threads on timed or untimed waits,
+ * so we wake them all at the time of the adjustment so that they can
+ * re-evaluate their conditions and re-compute their timeouts.
+ *
+ * 3) We rely on correctly written applications for this to work. Specifically,
+ * they must be able to deal properly with spurious wakeups. That is,
+ * they must re-test their condition upon wakeup and wait again if
+ * the condition is not satisfied.
+ */
+
+void *
+pthread_timechange_handler_np (void *arg)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Broadcasts all CVs to force re-evaluation and
+ * new timeouts if required.
+ *
+ * PARAMETERS
+ * NONE
+ *
+ *
+ * DESCRIPTION
+ * Broadcasts all CVs to force re-evaluation and
+ * new timeouts if required.
+ *
+ * This routine may be passed directly to pthread_create()
+ * as a new thread in order to run asynchronously.
+ *
+ *
+ * RESULTS
+ * 0 successfully broadcast all CVs
+ * EAGAIN Not all CVs were broadcast
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ pthread_cond_t cv;
+ ptw32_mcs_local_node_t node;
+
+ ptw32_mcs_lock_acquire(&ptw32_cond_list_lock, &node);
+
+ cv = ptw32_cond_list_head;
+
+ while (cv != NULL && 0 == result)
+ {
+ result = pthread_cond_broadcast (&cv);
+ cv = cv->next;
+ }
+
+ ptw32_mcs_lock_release(&node);
+
+ return (void *) (size_t) (result != 0 ? EAGAIN : 0);
+}
diff --git a/libs/pthreads/src/pthread_win32_attach_detach_np.c b/libs/pthreads/src/pthread_win32_attach_detach_np.c
new file mode 100644
index 0000000000..bfad450653
--- /dev/null
+++ b/libs/pthreads/src/pthread_win32_attach_detach_np.c
@@ -0,0 +1,256 @@
+/*
+ * pthread_win32_attach_detach_np.c
+ *
+ * Description:
+ * This translation unit implements non-portable thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * Handle to quserex.dll
+ */
+static HINSTANCE ptw32_h_quserex;
+
+BOOL
+pthread_win32_process_attach_np ()
+{
+ TCHAR QuserExDLLPathBuf[1024];
+ BOOL result = TRUE;
+
+ result = ptw32_processInitialize ();
+
+#if defined(_UWIN)
+ pthread_count++;
+#endif
+
+#if defined(__GNUC__)
+ ptw32_features = 0;
+#else
+ /*
+ * This is obsolete now.
+ */
+ ptw32_features = PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE;
+#endif
+
+ /*
+ * Load QUSEREX.DLL and try to get address of QueueUserAPCEx.
+ * Because QUSEREX.DLL requires a driver to be installed we will
+ * assume the DLL is in the system directory.
+ *
+ * This should take care of any security issues.
+ */
+#if defined(__GNUC__) || _MSC_VER < 1400
+ if(GetSystemDirectory(QuserExDLLPathBuf, sizeof(QuserExDLLPathBuf)))
+ {
+ (void) strncat(QuserExDLLPathBuf,
+ "\\QUSEREX.DLL",
+ sizeof(QuserExDLLPathBuf) - strlen(QuserExDLLPathBuf) - 1);
+ ptw32_h_quserex = LoadLibrary(QuserExDLLPathBuf);
+ }
+#else
+ /* strncat is secure - this is just to avoid a warning */
+ if(GetSystemDirectory(QuserExDLLPathBuf, sizeof(QuserExDLLPathBuf)) &&
+ 0 == strncat_s(QuserExDLLPathBuf, sizeof(QuserExDLLPathBuf), "\\QUSEREX.DLL", 12))
+ {
+ ptw32_h_quserex = LoadLibrary(QuserExDLLPathBuf);
+ }
+#endif
+
+ if (ptw32_h_quserex != NULL)
+ {
+ ptw32_register_cancelation = (DWORD (*)(PAPCFUNC, HANDLE, DWORD))
+#if defined(NEED_UNICODE_CONSTS)
+ GetProcAddress (ptw32_h_quserex,
+ (const TCHAR *) TEXT ("QueueUserAPCEx"));
+#else
+ GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx");
+#endif
+ }
+
+ if (NULL == ptw32_register_cancelation)
+ {
+ ptw32_register_cancelation = ptw32_RegisterCancelation;
+
+ if (ptw32_h_quserex != NULL)
+ {
+ (void) FreeLibrary (ptw32_h_quserex);
+ }
+ ptw32_h_quserex = 0;
+ }
+ else
+ {
+ /* Initialise QueueUserAPCEx */
+ BOOL (*queue_user_apc_ex_init) (VOID);
+
+ queue_user_apc_ex_init = (BOOL (*)(VOID))
+#if defined(NEED_UNICODE_CONSTS)
+ GetProcAddress (ptw32_h_quserex,
+ (const TCHAR *) TEXT ("QueueUserAPCEx_Init"));
+#else
+ GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx_Init");
+#endif
+
+ if (queue_user_apc_ex_init == NULL || !queue_user_apc_ex_init ())
+ {
+ ptw32_register_cancelation = ptw32_RegisterCancelation;
+
+ (void) FreeLibrary (ptw32_h_quserex);
+ ptw32_h_quserex = 0;
+ }
+ }
+
+ if (ptw32_h_quserex)
+ {
+ ptw32_features |= PTW32_ALERTABLE_ASYNC_CANCEL;
+ }
+
+ return result;
+}
+
+
+BOOL
+pthread_win32_process_detach_np ()
+{
+ if (ptw32_processInitialized)
+ {
+ ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
+
+ if (sp != NULL)
+ {
+ /*
+ * Detached threads have their resources automatically
+ * cleaned up upon exit (others must be 'joined').
+ */
+ if (sp->detachState == PTHREAD_CREATE_DETACHED)
+ {
+ ptw32_threadDestroy (sp->ptHandle);
+ TlsSetValue (ptw32_selfThreadKey->key, NULL);
+ }
+ }
+
+ /*
+ * The DLL is being unmapped from the process's address space
+ */
+ ptw32_processTerminate ();
+
+ if (ptw32_h_quserex)
+ {
+ /* Close QueueUserAPCEx */
+ BOOL (*queue_user_apc_ex_fini) (VOID);
+
+ queue_user_apc_ex_fini = (BOOL (*)(VOID))
+#if defined(NEED_UNICODE_CONSTS)
+ GetProcAddress (ptw32_h_quserex,
+ (const TCHAR *) TEXT ("QueueUserAPCEx_Fini"));
+#else
+ GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx_Fini");
+#endif
+
+ if (queue_user_apc_ex_fini != NULL)
+ {
+ (void) queue_user_apc_ex_fini ();
+ }
+ (void) FreeLibrary (ptw32_h_quserex);
+ }
+ }
+
+ return TRUE;
+}
+
+BOOL
+pthread_win32_thread_attach_np ()
+{
+ return TRUE;
+}
+
+BOOL
+pthread_win32_thread_detach_np ()
+{
+ if (ptw32_processInitialized)
+ {
+ /*
+ * Don't use pthread_self() - to avoid creating an implicit POSIX thread handle
+ * unnecessarily.
+ */
+ ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
+
+ if (sp != NULL) // otherwise Win32 thread with no implicit POSIX handle.
+ {
+ ptw32_mcs_local_node_t stateLock;
+ ptw32_callUserDestroyRoutines (sp->ptHandle);
+
+ ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
+ sp->state = PThreadStateLast;
+ /*
+ * If the thread is joinable at this point then it MUST be joined
+ * or detached explicitly by the application.
+ */
+ ptw32_mcs_lock_release (&stateLock);
+
+ /*
+ * Robust Mutexes
+ */
+ while (sp->robustMxList != NULL)
+ {
+ pthread_mutex_t mx = sp->robustMxList->mx;
+ ptw32_robust_mutex_remove(&mx, sp);
+ (void) PTW32_INTERLOCKED_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR)&mx->robustNode->stateInconsistent,
+ (PTW32_INTERLOCKED_LONG)-1);
+ /*
+ * If there are no waiters then the next thread to block will
+ * sleep, wakeup immediately and then go back to sleep.
+ * See pthread_mutex_lock.c.
+ */
+ SetEvent(mx->event);
+ }
+
+
+ if (sp->detachState == PTHREAD_CREATE_DETACHED)
+ {
+ ptw32_threadDestroy (sp->ptHandle);
+
+ TlsSetValue (ptw32_selfThreadKey->key, NULL);
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+BOOL
+pthread_win32_test_features_np (int feature_mask)
+{
+ return ((ptw32_features & feature_mask) == feature_mask);
+}
diff --git a/libs/pthreads/src/ptw32_MCS_lock.c b/libs/pthreads/src/ptw32_MCS_lock.c
new file mode 100644
index 0000000000..659cda60de
--- /dev/null
+++ b/libs/pthreads/src/ptw32_MCS_lock.c
@@ -0,0 +1,278 @@
+/*
+ * ptw32_MCS_lock.c
+ *
+ * Description:
+ * This translation unit implements queue-based locks.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/*
+ * About MCS locks:
+ *
+ * MCS locks are queue-based locks, where the queue nodes are local to the
+ * thread. The 'lock' is nothing more than a global pointer that points to
+ * the last node in the queue, or is NULL if the queue is empty.
+ *
+ * Originally designed for use as spin locks requiring no kernel resources
+ * for synchronisation or blocking, the implementation below has adapted
+ * the MCS spin lock for use as a general mutex that will suspend threads
+ * when there is lock contention.
+ *
+ * Because the queue nodes are thread-local, most of the memory read/write
+ * operations required to add or remove nodes from the queue do not trigger
+ * cache-coherence updates.
+ *
+ * Like 'named' mutexes, MCS locks consume system resources transiently -
+ * they are able to acquire and free resources automatically - but MCS
+ * locks do not require any unique 'name' to identify the lock to all
+ * threads using it.
+ *
+ * Usage of MCS locks:
+ *
+ * - you need a global ptw32_mcs_lock_t instance initialised to 0 or NULL.
+ * - you need a local thread-scope ptw32_mcs_local_node_t instance, which
+ * may serve several different locks but you need at least one node for
+ * every lock held concurrently by a thread.
+ *
+ * E.g.:
+ *
+ * ptw32_mcs_lock_t lock1 = 0;
+ * ptw32_mcs_lock_t lock2 = 0;
+ *
+ * void *mythread(void *arg)
+ * {
+ * ptw32_mcs_local_node_t node;
+ *
+ * ptw32_mcs_acquire (&lock1, &node);
+ * ptw32_mcs_lock_release (&node);
+ *
+ * ptw32_mcs_lock_acquire (&lock2, &node);
+ * ptw32_mcs_lock_release (&node);
+ * {
+ * ptw32_mcs_local_node_t nodex;
+ *
+ * ptw32_mcs_lock_acquire (&lock1, &node);
+ * ptw32_mcs_lock_acquire (&lock2, &nodex);
+ *
+ * ptw32_mcs_lock_release (&nodex);
+ * ptw32_mcs_lock_release (&node);
+ * }
+ * return (void *)0;
+ * }
+ */
+
+#include "pthread.h"
+#include "sched.h"
+#include "implement.h"
+
+/*
+ * ptw32_mcs_flag_set -- notify another thread about an event.
+ *
+ * Set event if an event handle has been stored in the flag, and
+ * set flag to -1 otherwise. Note that -1 cannot be a valid handle value.
+ */
+INLINE void
+ptw32_mcs_flag_set (HANDLE * flag)
+{
+ HANDLE e = (HANDLE)(PTW32_INTERLOCKED_SIZE)PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE(
+ (PTW32_INTERLOCKED_SIZEPTR)flag,
+ (PTW32_INTERLOCKED_SIZE)-1,
+ (PTW32_INTERLOCKED_SIZE)0);
+ if ((HANDLE)0 != e)
+ {
+ /* another thread has already stored an event handle in the flag */
+ SetEvent(e);
+ }
+}
+
+/*
+ * ptw32_mcs_flag_set -- wait for notification from another.
+ *
+ * Store an event handle in the flag and wait on it if the flag has not been
+ * set, and proceed without creating an event otherwise.
+ */
+INLINE void
+ptw32_mcs_flag_wait (HANDLE * flag)
+{
+ if ((PTW32_INTERLOCKED_LONG)0 ==
+ PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE((PTW32_INTERLOCKED_SIZEPTR)flag,
+ (PTW32_INTERLOCKED_SIZE)0)) /* MBR fence */
+ {
+ /* the flag is not set. create event. */
+
+ HANDLE e = CreateEvent(NULL, PTW32_FALSE, PTW32_FALSE, NULL);
+
+ if ((PTW32_INTERLOCKED_SIZE)0 == PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE(
+ (PTW32_INTERLOCKED_SIZEPTR)flag,
+ (PTW32_INTERLOCKED_SIZE)e,
+ (PTW32_INTERLOCKED_SIZE)0))
+ {
+ /* stored handle in the flag. wait on it now. */
+ WaitForSingleObject(e, INFINITE);
+ }
+
+ CloseHandle(e);
+ }
+}
+
+/*
+ * ptw32_mcs_lock_acquire -- acquire an MCS lock.
+ *
+ * See:
+ * J. M. Mellor-Crummey and M. L. Scott.
+ * Algorithms for Scalable Synchronization on Shared-Memory Multiprocessors.
+ * ACM Transactions on Computer Systems, 9(1):21-65, Feb. 1991.
+ */
+#if defined(PTW32_BUILD_INLINED)
+INLINE
+#endif /* PTW32_BUILD_INLINED */
+void
+ptw32_mcs_lock_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node)
+{
+ ptw32_mcs_local_node_t *pred;
+
+ node->lock = lock;
+ node->nextFlag = 0;
+ node->readyFlag = 0;
+ node->next = 0; /* initially, no successor */
+
+ /* queue for the lock */
+ pred = (ptw32_mcs_local_node_t *)PTW32_INTERLOCKED_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)lock,
+ (PTW32_INTERLOCKED_PVOID)node);
+
+ if (0 != pred)
+ {
+ /* the lock was not free. link behind predecessor. */
+ pred->next = node;
+ ptw32_mcs_flag_set(&pred->nextFlag);
+ ptw32_mcs_flag_wait(&node->readyFlag);
+ }
+}
+
+/*
+ * ptw32_mcs_lock_release -- release an MCS lock.
+ *
+ * See:
+ * J. M. Mellor-Crummey and M. L. Scott.
+ * Algorithms for Scalable Synchronization on Shared-Memory Multiprocessors.
+ * ACM Transactions on Computer Systems, 9(1):21-65, Feb. 1991.
+ */
+#if defined(PTW32_BUILD_INLINED)
+INLINE
+#endif /* PTW32_BUILD_INLINED */
+void
+ptw32_mcs_lock_release (ptw32_mcs_local_node_t * node)
+{
+ ptw32_mcs_lock_t *lock = node->lock;
+ ptw32_mcs_local_node_t *next =
+ (ptw32_mcs_local_node_t *)
+ PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE((PTW32_INTERLOCKED_SIZEPTR)&node->next, (PTW32_INTERLOCKED_SIZE)0); /* MBR fence */
+
+ if (0 == next)
+ {
+ /* no known successor */
+
+ if (node == (ptw32_mcs_local_node_t *)
+ PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)lock,
+ (PTW32_INTERLOCKED_PVOID)0,
+ (PTW32_INTERLOCKED_PVOID)node))
+ {
+ /* no successor, lock is free now */
+ return;
+ }
+
+ /* A successor has started enqueueing behind us so wait for them to link to us */
+ ptw32_mcs_flag_wait(&node->nextFlag);
+ next = (ptw32_mcs_local_node_t *)
+ PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE((PTW32_INTERLOCKED_SIZEPTR)&node->next, (PTW32_INTERLOCKED_SIZE)0); /* MBR fence */
+ }
+
+ /* pass the lock */
+ ptw32_mcs_flag_set(&next->readyFlag);
+}
+
+/*
+ * ptw32_mcs_lock_try_acquire
+ */
+#if defined(PTW32_BUILD_INLINED)
+INLINE
+#endif /* PTW32_BUILD_INLINED */
+int
+ptw32_mcs_lock_try_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node)
+{
+ node->lock = lock;
+ node->nextFlag = 0;
+ node->readyFlag = 0;
+ node->next = 0; /* initially, no successor */
+
+ return ((PTW32_INTERLOCKED_PVOID)PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)lock,
+ (PTW32_INTERLOCKED_PVOID)node,
+ (PTW32_INTERLOCKED_PVOID)0)
+ == (PTW32_INTERLOCKED_PVOID)0) ? 0 : EBUSY;
+}
+
+/*
+ * ptw32_mcs_node_transfer -- move an MCS lock local node, usually from thread
+ * space to, for example, global space so that another thread can release
+ * the lock on behalf of the current lock owner.
+ *
+ * Example: used in pthread_barrier_wait where we want the last thread out of
+ * the barrier to release the lock owned by the last thread to enter the barrier
+ * (the one that releases all threads but not necessarily the last to leave).
+ *
+ * Should only be called by the thread that has the lock.
+ */
+#if defined(PTW32_BUILD_INLINED)
+INLINE
+#endif /* PTW32_BUILD_INLINED */
+void
+ptw32_mcs_node_transfer (ptw32_mcs_local_node_t * new_node, ptw32_mcs_local_node_t * old_node)
+{
+ new_node->lock = old_node->lock;
+ new_node->nextFlag = 0; /* Not needed - used only in initial Acquire */
+ new_node->readyFlag = 0; /* Not needed - we were waiting on this */
+ new_node->next = 0;
+
+ if ((ptw32_mcs_local_node_t *)PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR((PTW32_INTERLOCKED_PVOID_PTR)new_node->lock,
+ (PTW32_INTERLOCKED_PVOID)new_node,
+ (PTW32_INTERLOCKED_PVOID)old_node)
+ != old_node)
+ {
+ /*
+ * A successor has queued after us, so wait for them to link to us
+ */
+ while (old_node->next == 0)
+ {
+ sched_yield();
+ }
+ new_node->next = old_node->next;
+ }
+}
diff --git a/libs/pthreads/src/ptw32_OLL_lock.c b/libs/pthreads/src/ptw32_OLL_lock.c
new file mode 100644
index 0000000000..789d0ad8c6
--- /dev/null
+++ b/libs/pthreads/src/ptw32_OLL_lock.c
@@ -0,0 +1,734 @@
+/*
+ * ptw32_OLL_lock.c
+ *
+ * Description:
+ * This translation unit implements extended reader/writer queue-based locks.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/*
+ * About the OLL lock (Scalable Reader-Writer Lock):
+ *
+ * OLL locks are queue-based locks similar to the MCS queue lock, where the queue
+ * nodes are local to the thread but where reader threads can enter the critical
+ * section immediately without going through a central guard lock if there are
+ * already readers holding the lock.
+ *
+ * Covered by United States Patent Application 20100241774 (Oracle)
+ */
+
+#include "pthread.h"
+#include "sched.h"
+#include "implement.h"
+
+/*
+ * C-SNZI support
+ */
+typedef union ptw32_oll_counter_t_ ptw32_oll_counter_t;
+typedef struct ptw32_oll_snziRoot_t_ ptw32_oll_snziRoot_t;
+typedef struct ptw32_oll_snziNode_t_ ptw32_oll_snziNode_t;
+typedef union ptw32_oll_snziNodeOrRoot_t_ ptw32_oll_snziNodeOrRoot_t;
+typedef struct ptw32_oll_queryResult_t_ ptw32_oll_queryResult_t;
+typedef struct ptw32_oll_ticket_t_ ptw32_oll_ticket_t;
+typedef struct ptw32_oll_csnzi_t_ ptw32_oll_csnzi_t;
+
+enum
+{
+ ptw32_archWidth = sizeof(size_t)*8,
+ ptw32_oll_countWidth = ptw32_archWidth-2
+};
+
+#define PTW32_OLL_MAXREADERS (((size_t)2<<(ptw32_oll_countWidth-1))-1)
+
+union ptw32_oll_counter_t_
+{
+ size_t word : ptw32_archWidth;
+ struct
+ {
+ /*
+ * This needs to be a single word
+ *
+ * ------------------------------------
+ * | STATE | ROOT | COUNT (readers) |
+ * ------------------------------------
+ * 63 / 31 62 / 30 61 / 29 .. 0
+ */
+ size_t count : ptw32_oll_countWidth;
+ size_t root : 1; /* ROOT or NODE */
+ size_t state : 1; /* OPEN or CLOSED (root only) */
+ } internal;
+};
+
+struct ptw32_oll_snziRoot_t_
+{
+ /*
+ * "counter" must be at same offset in both
+ * ptw32_oll_snziNode_t and ptw32_oll_snziRoot_t
+ */
+ ptw32_oll_counter_t counter;
+};
+
+enum
+{
+ ptw32_oll_snziRoot_open = 0,
+ ptw32_oll_snziRoot_closed = 1
+};
+
+enum
+{
+ ptw32_oll_snzi_root = 0,
+ ptw32_oll_snzi_node = 1
+};
+
+/*
+ * Some common SNZI root whole-word states that can be used to set or compare
+ * root words with a single operation.
+ */
+ptw32_oll_snziRoot_t ptw32_oll_snziRoot_openAndZero = {.counter.internal.count = 0,
+ .counter.internal.root = ptw32_oll_snzi_root,
+ .counter.internal.state = ptw32_oll_snziRoot_open};
+ptw32_oll_snziRoot_t ptw32_oll_snziRoot_closedAndZero = {.counter.internal.count = 0,
+ .counter.internal.root = ptw32_oll_snzi_root,
+ .counter.internal.state = ptw32_oll_snziRoot_closed};
+
+struct ptw32_oll_queryResult_t_
+{
+ BOOL nonZero;
+ BOOL open;
+};
+
+union ptw32_oll_snziNodeOrRoot_t_
+{
+ ptw32_oll_snziRoot_t* rootPtr;
+ ptw32_oll_snziNode_t* nodePtr;
+};
+
+struct ptw32_oll_snziNode_t_
+{
+ /* "counter" must be at same offset in both
+ * ptw32_oll_snziNode_t and ptw32_oll_snziRoot_t
+ */
+ ptw32_oll_counter_t counter;
+ ptw32_oll_snziNodeOrRoot_t parentPtr;
+};
+
+struct ptw32_oll_ticket_t_
+{
+ ptw32_oll_snziNodeOrRoot_t snziNodeOrRoot;
+};
+
+ptw32_oll_ticket_t ptw32_oll_ticket_null = {NULL};
+
+struct ptw32_oll_csnzi_t_
+{
+ ptw32_oll_snziRoot_t proxyRoot;
+ ptw32_oll_snziNode_t leafs[];
+};
+
+/*
+ * FOLL lock support
+ */
+
+typedef struct ptw32_foll_node_t_ ptw32_foll_node_t;
+typedef struct ptw32_foll_local_t_ ptw32_foll_local_t;
+typedef struct ptw32_foll_rwlock_t_ ptw32_foll_rwlock_t;
+
+enum
+{
+ ptw32_srwl_reader,
+ ptw32_srwl_writer
+};
+
+enum
+{
+ ptw32_srwl_free,
+ ptw32_srwl_in_use
+};
+
+struct ptw32_foll_node_t_
+{
+ ptw32_foll_node_t* qNextPtr;
+ ptw32_oll_csnzi_t* csnziPtr;
+ ptw32_foll_node_t* nextPtr;
+ int kind;
+ int allocState;
+ BOOL spin;
+};
+
+struct ptw32_foll_local_t_
+{
+ ptw32_foll_node_t* rNodePtr; // Default read node. Immutable
+ ptw32_foll_node_t* wNodePtr; // Write node. Immutable.
+ ptw32_foll_node_t* departFromPtr; // List node we last arrived at.
+ ptw32_oll_ticket_t ticket; // C-SNZI ticket
+};
+
+struct ptw32_foll_rwlock_t_
+{
+ ptw32_foll_node_t* tailPtr;
+ ptw32_foll_node_t* rNodesPtr; // Head of reader node
+};
+
+/*
+ * ShouldArriveAtTree() returns true if:
+ * the compare_exchange in Arrive() fails too often under read access; or
+ * ??
+ * Note that this is measured across all access to
+ * this lock, not just this attempt, so that highly
+ * read-contended locks will use C-SNZI. Lightly
+ * read-contended locks can reduce memory usage and some
+ * processing by using the root directly.
+ */
+BOOL
+ptw32_oll_ShouldArriveAtTree()
+{
+ return PTW32_FALSE;
+}
+
+size_t
+ptw32_oll_GetLeafForThread()
+{
+ return 0;
+}
+
+/*
+ * Only readers call ptw32_oll_Arrive()
+ *
+ * Checks whether the C-SNZI state is OPEN, and if so,
+ * increments the surplus of the C-SNZI by either directly
+ * arriving at the root node, or calling TreeArrive on one
+ * of the leaf nodes. Returns a ticket pointing to the node
+ * that was arrived at. If the state is CLOSED, makes no
+ * change and returns a ticket that contains no pointer.
+ */
+ptw32_oll_ticket_t
+ptw32_oll_Arrive(ptw32_oll_csnzi_t* csnzi)
+{
+ for (;;)
+ {
+ ptw32_oll_ticket_t ticket;
+ ptw32_oll_snziRoot_t oldProxy = csnzi->proxyRoot;
+ if (oldProxy.counter.internal.state != ptw32_oll_snziRoot_open)
+ {
+ ticket.snziNodeOrRoot.rootPtr = (ptw32_oll_snziRoot_t*)NULL;
+ return ticket;
+ }
+ if (!ptw32_oll_ShouldArriveAtTree())
+ {
+ ptw32_oll_snziRoot_t newProxy = oldProxy;
+ newProxy.counter.internal.count++;
+ if (PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE(
+ (PTW32_INTERLOCKED_SIZEPTR)&csnzi->proxyRoot.counter,
+ (PTW32_INTERLOCKED_SIZE)newProxy.counter.word,
+ (PTW32_INTERLOCKED_SIZE)oldProxy.counter.word)
+ == (PTW32_INTERLOCKED_SIZE)oldProxy.counter.word)
+ {
+ /* Exchange successful */
+ ticket.snziNodeOrRoot.rootPtr = &csnzi->proxyRoot;
+ return ticket;
+ }
+ }
+ else
+ {
+ ptw32_oll_snziNode_t* leafPtr = &csnzi->leafs[ptw32_oll_GetLeafForThread()];
+ ticket.snziNodeOrRoot.nodePtr = (ptw32_oll_TreeArrive(leafPtr) ? leafPtr : (ptw32_oll_snziNode_t*)NULL);
+ return ticket;
+ }
+ }
+}
+
+/*
+ * Decrements the C-SNZI surplus. Returns false iff the
+ * resulting state is CLOSED and the surplus is zero.
+ * Ticket must have been returned by an arrival. Must have
+ * received this ticket from Arrive more times than Depart
+ * has been called with the ticket. (Thus, the surplus
+ * must be greater than zero.)
+ */
+BOOL
+ptw32_oll_Depart(ptw32_oll_ticket_t ticket)
+{
+ return ptw32_oll_TreeDepart(ticket.snziNodeOrRoot);
+}
+
+/*
+ * Increments the C-SNZI surplus and returns true if the
+ * C-SNZI is open or has a surplus. Calls TreeArrive
+ * recursively on the node’s parent if needed.
+ * Otherwise, returns false without making any changes.
+ */
+BOOL
+ptw32_oll_TreeArrive(ptw32_oll_snziNodeOrRoot_t snziNodeOrRoot)
+{
+ if (snziNodeOrRoot.nodePtr->counter.internal.root != ptw32_oll_snzi_root)
+ {
+ /* Non-root node */
+ ptw32_oll_counter_t newCounter, oldCounter;
+ BOOL arrivedAtParent = PTW32_FALSE;
+ do
+ {
+ oldCounter = snziNodeOrRoot.nodePtr->counter;
+ if (0 == oldCounter.internal.count && !arrivedAtParent)
+ {
+ if (ptw32_oll_TreeArrive(snziNodeOrRoot.nodePtr->parentPtr))
+ arrivedAtParent = PTW32_TRUE;
+ else
+ return PTW32_FALSE;
+ }
+ newCounter = oldCounter;
+ newCounter.internal.count++;
+ } while (PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE(
+ (PTW32_INTERLOCKED_SIZEPTR)&snziNodeOrRoot.nodePtr->counter,
+ (PTW32_INTERLOCKED_SIZE)newCounter.word,
+ (PTW32_INTERLOCKED_SIZE)oldCounter.word)
+ != (PTW32_INTERLOCKED_SIZE)oldCounter.word);
+ if (newCounter.internal.count != 0 && arrivedAtParent)
+ ptw32_oll_TreeDepart(snziNodeOrRoot.nodePtr->parentPtr);
+ return PTW32_TRUE;
+ }
+ else
+ {
+ /* Root node */
+ ptw32_oll_snziRoot_t newRoot, oldRoot;
+ do
+ {
+ oldRoot = *(ptw32_oll_snziRoot_t*)snziNodeOrRoot.rootPtr;
+ if (oldRoot.counter.word == ptw32_oll_snziRoot_closedAndZero.counter.word)
+ return PTW32_FALSE;
+ newRoot = oldRoot;
+ newRoot.counter.internal.count++;
+ } while (PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE(
+ (PTW32_INTERLOCKED_SIZEPTR)&snziNodeOrRoot.rootPtr->counter,
+ (PTW32_INTERLOCKED_SIZE)newRoot.counter.word,
+ (PTW32_INTERLOCKED_SIZE)oldRoot.counter.word)
+ != (PTW32_INTERLOCKED_SIZE)oldRoot.counter.word);
+ return PTW32_TRUE;
+ }
+}
+
+/*
+ * Decrements the C-SNZI surplus, calling TreeDepart
+ * recursively on the node’s parent if needed. Returns
+ * false iff the resulting state of the C-SNZI is CLOSED
+ * and the surplus is zero. Otherwise, returns true.
+ */
+BOOL
+ptw32_oll_TreeDepart(ptw32_oll_snziNodeOrRoot_t snziNodeOrRoot)
+{
+ if (snziNodeOrRoot.nodePtr->counter.internal.root != ptw32_oll_snzi_root)
+ {
+ /* Non-root node */
+ ptw32_oll_counter_t newCounter, oldCounter;
+ do
+ {
+ newCounter = oldCounter = snziNodeOrRoot.nodePtr->counter;
+ newCounter.internal.count--;
+ } while (PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE(
+ (PTW32_INTERLOCKED_SIZEPTR)&snziNodeOrRoot.nodePtr->counter,
+ (PTW32_INTERLOCKED_SIZE)newCounter.word,
+ (PTW32_INTERLOCKED_SIZE)oldCounter.word)
+ != (PTW32_INTERLOCKED_SIZE)oldCounter.word);
+ return (0 == newCounter.internal.count)
+ ? ptw32_oll_TreeDepart(snziNodeOrRoot.nodePtr->parentPtr)
+ : PTW32_TRUE;
+ }
+ else
+ {
+ /* Root node */
+ ptw32_oll_snziRoot_t newRoot, oldRoot;
+ do
+ {
+ newRoot = oldRoot = *(ptw32_oll_snziRoot_t*)snziNodeOrRoot.rootPtr;
+ newRoot.counter.internal.count--;
+ } while (PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE(
+ (PTW32_INTERLOCKED_SIZEPTR)&snziNodeOrRoot.rootPtr->counter,
+ (PTW32_INTERLOCKED_SIZE)newRoot.counter.word,
+ (PTW32_INTERLOCKED_SIZE)oldRoot.counter.word)
+ != (PTW32_INTERLOCKED_SIZE)oldRoot.counter.word);
+ return (newRoot.counter.word != ptw32_oll_snziRoot_closedAndZero.counter.word);
+ }
+}
+
+/*
+ * Opens a C-SNZI object. Requires C-SNZI state to be
+ * CLOSED and the surplus to be zero.
+ */
+void
+ptw32_oll_Open(ptw32_oll_csnzi_t* csnziPtr)
+{
+ csnziPtr->proxyRoot = ptw32_oll_snziRoot_openAndZero;
+}
+
+/*
+ * Opens a C-SNZI object while atomically performing count
+ * arrivals. Requires C-SNZI state to be CLOSED and
+ * the surplus to be zero.
+ */
+void
+ptw32_oll_OpenWithArrivals(ptw32_oll_csnzi_t* csnziPtr, size_t count, BOOL close)
+{
+ csnziPtr->proxyRoot.counter.internal.count = count;
+ csnziPtr->proxyRoot.counter.internal.state = (close ? ptw32_oll_snziRoot_closed : ptw32_oll_snziRoot_open);
+}
+
+/*
+ * Closes a C-SNZI object. Returns true iff the C-SNZI
+ * state changed from OPEN to CLOSED and the surplus is
+ * zero.
+ */
+BOOL
+ptw32_oll_Close(ptw32_oll_csnzi_t* csnziPtr)
+{
+ ptw32_oll_snziRoot_t newProxy, oldProxy;
+ do
+ {
+ oldProxy = csnziPtr->proxyRoot;
+ if (oldProxy.counter.internal.state != ptw32_oll_snziRoot_open)
+ {
+ return PTW32_FALSE;
+ }
+ newProxy = oldProxy;
+ newProxy.counter.internal.state = ptw32_oll_snziRoot_closed;
+ } while (PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE(
+ (PTW32_INTERLOCKED_SIZEPTR)&csnziPtr->proxyRoot.counter,
+ (PTW32_INTERLOCKED_SIZE)newProxy.counter.word,
+ (PTW32_INTERLOCKED_SIZE)oldProxy.counter.word)
+ != (PTW32_INTERLOCKED_SIZE)oldProxy.counter.word);
+ return (newProxy.counter.word == ptw32_oll_snziRoot_closedAndZero.counter.word);
+}
+
+/*
+ * Closes a C-SNZI if its surplus is zero. Otherwise, does
+ * nothing. Returns true iff C-SNZI state changed from
+ * OPEN to CLOSED.
+ */
+BOOL
+ptw32_oll_CloseIfEmpty(ptw32_oll_csnzi_t* csnziPtr)
+{
+ ptw32_oll_snziRoot_t newProxy, oldProxy;
+ do
+ {
+ oldProxy = csnziPtr->proxyRoot;
+ if (oldProxy.counter.word != ptw32_oll_snziRoot_openAndZero.counter.word)
+ {
+ return PTW32_FALSE;
+ }
+ newProxy = ptw32_oll_snziRoot_closedAndZero;
+ } while (PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE(
+ (PTW32_INTERLOCKED_SIZEPTR)&csnziPtr->proxyRoot.counter,
+ (PTW32_INTERLOCKED_SIZE)newProxy.counter.word,
+ (PTW32_INTERLOCKED_SIZE)oldProxy.counter.word)
+ != (PTW32_INTERLOCKED_SIZE)oldProxy.counter.word);
+ return PTW32_TRUE;
+}
+
+/*
+ * Returns whether the C-SNZI has a nonzero surplus and
+ * whether the C-SNZI is open.
+ * "nonZero" doesn't appear to be used anywhere in the algorithms.
+ */
+ptw32_oll_queryResult_t
+ptw32_oll_Query(ptw32_oll_csnzi_t* csnziPtr)
+{
+ ptw32_oll_queryResult_t query;
+ ptw32_oll_snziRoot_t proxy = csnziPtr->proxyRoot;
+
+ query.nonZero = (proxy.counter.internal.count > 0);
+ query.open = (proxy.counter.internal.state == ptw32_oll_snziRoot_open);
+ return query;
+}
+
+/*
+ * Returns whether the Arrive operation that returned
+ * the ticket succeeded.
+ */
+BOOL
+ptw32_oll_Arrived(ptw32_oll_ticket_t t)
+{
+ return (t.snziNodeOrRoot.nodePtr != NULL);
+}
+
+/*
+ * Constructs and returns a ticket that can be used to
+ * depart from the root node.
+ */
+ptw32_oll_ticket_t
+ptw32_oll_DirectTicket(ptw32_oll_csnzi_t* csnziPtr)
+{
+ ptw32_oll_ticket_t ticket;
+ ticket.snziNodeOrRoot.rootPtr = &csnziPtr->proxyRoot;
+ return ticket;
+}
+
+/* Scalable RW Locks */
+
+typedef struct ptw32_srwl_rwlock_t_ ptw32_srwl_rwlock_t;
+typedef struct ptw32_srwl_node_t_ ptw32_srwl_node_t;
+typedef struct ptw32_srwl_local_t_ ptw32_srwl_local_t;
+
+enum
+{
+ ptw32_srwl_reader = 0,
+ ptw32_srwl_writer = 1
+};
+
+enum
+{
+ ptw32_srwl_free = 0,
+ ptw32_srwl_in_use = 1
+};
+
+struct ptw32_srwl_rwlock_t_
+{
+ ptw32_srwl_node_t* tailPtr;
+ ptw32_srwl_node_t* readerNodePtr;
+};
+
+struct ptw32_srwl_node_t_
+{
+ ptw32_srwl_node_t* qNextPtr;
+ ptw32_oll_csnzi_t* csnziPtr;
+ ptw32_srwl_node_t* nextReaderPtr;
+ int kind; /* ptw32_srwl_reader, ptw32_srwl_writer */
+ int allocState; /* ptw32_srwl_free, ptw32_srwl_in_use */
+ BOOL spin;
+};
+
+/*
+ * When a ptw32_srwl_local_t is instantiated the "kind" of each of
+ * rNode and wNode must be set as appropriate. This is the only
+ * time "kind" is set.
+ */
+struct ptw32_srwl_local_t_
+{
+ ptw32_srwl_node_t* rNodePtr;
+ ptw32_srwl_node_t* wNodePtr;
+ ptw32_srwl_node_t* departFromPtr;
+ ptw32_oll_ticket_t ticket;
+};
+
+/* Allocates a new reader node. */
+ptw32_srwl_node_t*
+ptw32_srwl_AllocReaderNode(ptw32_srwl_local_t* local)
+{
+ ptw32_srwl_node_t* currNodePtr = local->rNodePtr;
+ for (;;)
+ {
+ if (currNodePtr->allocState == ptw32_srwl_free)
+ {
+ if (PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(
+ (PTW32_INTERLOCKED_LONGPTR)&currNodePtr->allocState,
+ (PTW32_INTERLOCKED_LONG)ptw32_srwl_in_use,
+ (PTW32_INTERLOCKED_LONG)ptw32_srwl_free)
+ == (PTW32_INTERLOCKED_LONG)ptw32_srwl_in_use)
+ {
+ return currNodePtr;
+ }
+ }
+ currNodePtr = currNodePtr->next;
+ }
+}
+
+/*
+ * Frees a reader node. Requires that its allocState
+ * is ptw32_srwl_in_use.
+ */
+void
+ptw32_srwl_FreeReaderNode(ptw32_srwl_node_t* nodePtr)
+{
+ nodePtr->allocState := ptw32_srwl_free;
+}
+
+void
+ptw32_srwl_WriterLock(ptw32_srwl_rwlock_t* lockPtr, ptw32_srwl_local_t* localPtr)
+{
+ oldTailPtr = (ptw32_srwl_rwlock_t*)PTW32_INTERLOCKED_EXCHANGE_PTR(
+ (PTW32_INTERLOCKED_PVOID_PTR)&lockPtr->tailPtr,
+ (PTW32_INTERLOCKED_PVOID)localPtr->wNodePtr);
+ if (oldTailPtr != NULL)
+ {
+ localPtr->wNodePtr->spin := PTW32_TRUE;
+ oldTailPtr->qNextPtr = localPtr->wNodePtr;
+ if (oldTailPtr->kind == ptw32_srwl_writer)
+ {
+ while (localPtr->wNodePtr->spin);
+ }
+ else
+ {
+ /* Wait until node is properly recycled */
+ while (ptw32_oll_Query(oldTailPtr->csnzi).open);
+ /*
+ * Close C-SNZI of previous reader node.
+ * If there are no readers to signal us, spin on
+ * previous node and free it before entering
+ * critical section.
+ */
+ if (ptw32_oll_Close(oldTailPtr->csnzi))
+ {
+ while (oldTailPtr->spin);
+ ptw32_srwl_FreeReaderNode(oldTailPtr);
+ }
+ else
+ {
+ while (localPtr->wNodePtr->spin);
+ }
+ }
+ }
+}
+
+void
+ptw32_srwl_WriterUnlock(ptw32_srwl_rwlock_t* lockPtr, ptw32_srwl_local_t* localPtr)
+{
+ if (localPtr->wNodePtr->qNextPtr == NULL)
+ {
+ if (PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR(
+ (PTW32_INTERLOCKED_PVOIDPTR)&lockPtr->tailPtr,
+ (PTW32_INTERLOCKED_PVOID)NULL,
+ (PTW32_INTERLOCKED_PVOID)localPtr->wNodePtr)
+ == (PTW32_INTERLOCKED_PVOID)NULL)
+ {
+ return;
+ }
+ else
+ {
+ while (localPtr->wNodePtr->qNextPtr == NULL);
+ }
+ }
+ /* Clean up */
+ localPtr->wNodePtr->qNextPtr->spin = PTW32_FALSE;
+ localPtr->wNodePtr->qNextPtr = NULL;
+}
+
+void
+ptw32_srwl_ReaderLock(ptw32_srwl_rwlock_t* lockPtr, ptw32_srwl_local_t* localPtr)
+{
+ ptw32_srwl_node_t* rNodePtr = NULL;
+ for (;;)
+ {
+ ptw32_srwl_node_t* tailPtr = lockPtr->tailPtr;
+ /* If no nodes are in the queue */
+ if (tailPtr == NULL)
+ {
+ if (rNodePtr == NULL)
+ {
+ rNodePtr = ptw32_srwl_AllocReaderNode(localPtr);
+ }
+ rNodePtr->spin = PTW32_FALSE;
+ if (PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR(
+ (PTW32_INTERLOCKED_PVOIDPTR)&lockPtr->tailPtr,
+ (PTW32_INTERLOCKED_PVOID)rNodePtr,
+ (PTW32_INTERLOCKED_PVOID)NULL)
+ == (PTW32_INTERLOCKED_PVOID)rNodePtr)
+ {
+ ptw32_oll_Open(rNodePtr->csnzi);
+ localPtr->ticket = ptw32_oll_Arrive(rNodePtr->csnzi);
+ if (ptw32_oll_Arrived(localPtr->ticket))
+ {
+ localPtr->departFromPtr = rNodePtr;
+ return;
+ }
+ /* Avoid reusing inserted node */
+ rNodePtr = NULL;
+ }
+ }
+ /* Otherwise, there is a node in the queue */
+ else
+ {
+ /* Is last node a writer node? */
+ if (tailPtr->kind == ptw32_srwl_writer)
+ {
+ if (rNodePtr == NULL)
+ {
+ rNodePtr = ptw32_srwl_AllocReaderNode(localPtr);
+ }
+ rNodePtr->spin = PTW32_TRUE;
+ if (PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR(
+ (PTW32_INTERLOCKED_PVOIDPTR)&lockPtr->tailPtr,
+ (PTW32_INTERLOCKED_PVOID)rNodePtr,
+ (PTW32_INTERLOCKED_PVOID)tailPtr)
+ == (PTW32_INTERLOCKED_PVOID)rNodePtr)
+ {
+ tailPtr->qNextPtr = rNodePtr;
+ localPtr->ticket = ptw32_oll_Arrive(rNodePtr->csnzi);
+ if (ptw32_oll_Arrived(localPtr->ticket))
+ {
+ localPtr->departFromPtr = rNodePtr;
+ while (rNodePtr->spin);
+ return;
+ }
+ /* Avoid reusing inserted node */
+ rNodePtr = NULL;
+ }
+ }
+ /*
+ * Otherwise, last node is a reader node.
+ * (tailPtr->kind == ptw32_srwl_reader)
+ */
+ else
+ {
+ localPtr->ticket = ptw32_oll_Arrive(tailPtr->csnzi);
+ if (ptw32_oll_Arrived(localPtr->ticket))
+ {
+ if (rNodePtr != NULL)
+ {
+ ptw32_srwl_FreeReaderNode(rNodePtr);
+ }
+ localPtr->departFromPtr = tailPtr;
+ while (tailPtr->spin);
+ return;
+ }
+ }
+ }
+ }
+}
+
+void
+ptw32_srwl_ReaderUnlock(ptw32_srwl_rwlock_t* lockPtr, ptw32_srwl_local_t* localPtr)
+{
+ if (ptw32_oll_Depart(localPtr->departFromPtr->csnzi, localPtr->ticket))
+ {
+ return;
+ }
+ /* Clean up */
+ localPtr->departFromPtr->qNextPtr->spin = PTW32_FALSE;
+ localPtr->departFromPtr->qNextPtr = NULL;
+ ptw32_srwl_FreeReaderNode(localPtr->departFromPtr);
+}
+
+
+#include <stdio.h>
+
+int main()
+{
+ printf("%lx\n", PTW32_OLL_MAXREADERS);
+ return 0;
+}
+
diff --git a/libs/pthreads/src/ptw32_callUserDestroyRoutines.c b/libs/pthreads/src/ptw32_callUserDestroyRoutines.c
new file mode 100644
index 0000000000..f290f7ba54
--- /dev/null
+++ b/libs/pthreads/src/ptw32_callUserDestroyRoutines.c
@@ -0,0 +1,232 @@
+/*
+ * ptw32_callUserDestroyRoutines.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+#if defined(__CLEANUP_CXX)
+# if defined(_MSC_VER)
+# include <eh.h>
+# elif defined(__WATCOMC__)
+# include <eh.h>
+# include <exceptio.h>
+# else
+# if defined(__GNUC__) && __GNUC__ < 3
+# include <new.h>
+# else
+# include <new>
+ using
+ std::terminate;
+# endif
+# endif
+#endif
+
+void
+ptw32_callUserDestroyRoutines (pthread_t thread)
+ /*
+ * -------------------------------------------------------------------
+ * DOCPRIVATE
+ *
+ * This the routine runs through all thread keys and calls
+ * the destroy routines on the user's data for the current thread.
+ * It simulates the behaviour of POSIX Threads.
+ *
+ * PARAMETERS
+ * thread
+ * an instance of pthread_t
+ *
+ * RETURNS
+ * N/A
+ * -------------------------------------------------------------------
+ */
+{
+ ThreadKeyAssoc * assoc;
+
+ if (thread.p != NULL)
+ {
+ ptw32_mcs_local_node_t threadLock;
+ ptw32_mcs_local_node_t keyLock;
+ int assocsRemaining;
+ int iterations = 0;
+ ptw32_thread_t * sp = (ptw32_thread_t *) thread.p;
+
+ /*
+ * Run through all Thread<-->Key associations
+ * for the current thread.
+ *
+ * Do this process at most PTHREAD_DESTRUCTOR_ITERATIONS times.
+ */
+ do
+ {
+ assocsRemaining = 0;
+ iterations++;
+
+ ptw32_mcs_lock_acquire(&(sp->threadLock), &threadLock);
+ /*
+ * The pointer to the next assoc is stored in the thread struct so that
+ * the assoc destructor in pthread_key_delete can adjust it
+ * if it deletes this assoc. This can happen if we fail to acquire
+ * both locks below, and are forced to release all of our locks,
+ * leaving open the opportunity for pthread_key_delete to get in
+ * before us.
+ */
+ sp->nextAssoc = sp->keys;
+ ptw32_mcs_lock_release(&threadLock);
+
+ for (;;)
+ {
+ void * value;
+ pthread_key_t k;
+ void (*destructor) (void *);
+
+ /*
+ * First we need to serialise with pthread_key_delete by locking
+ * both assoc guards, but in the reverse order to our convention,
+ * so we must be careful to avoid deadlock.
+ */
+ ptw32_mcs_lock_acquire(&(sp->threadLock), &threadLock);
+
+ if ((assoc = (ThreadKeyAssoc *)sp->nextAssoc) == NULL)
+ {
+ /* Finished */
+ ptw32_mcs_lock_release(&threadLock);
+ break;
+ }
+ else
+ {
+ /*
+ * assoc->key must be valid because assoc can't change or be
+ * removed from our chain while we hold at least one lock. If
+ * the assoc was on our key chain then the key has not been
+ * deleted yet.
+ *
+ * Now try to acquire the second lock without deadlocking.
+ * If we fail, we need to relinquish the first lock and the
+ * processor and then try to acquire them all again.
+ */
+ if (ptw32_mcs_lock_try_acquire(&(assoc->key->keyLock), &keyLock) == EBUSY)
+ {
+ ptw32_mcs_lock_release(&threadLock);
+ Sleep(0);
+ /*
+ * Go around again.
+ * If pthread_key_delete has removed this assoc in the meantime,
+ * sp->nextAssoc will point to a new assoc.
+ */
+ continue;
+ }
+ }
+
+ /* We now hold both locks */
+
+ sp->nextAssoc = assoc->nextKey;
+
+ /*
+ * Key still active; pthread_key_delete
+ * will block on these same mutexes before
+ * it can release actual key; therefore,
+ * key is valid and we can call the destroy
+ * routine;
+ */
+ k = assoc->key;
+ destructor = k->destructor;
+ value = TlsGetValue(k->key);
+ TlsSetValue (k->key, NULL);
+
+ // Every assoc->key exists and has a destructor
+ if (value != NULL && iterations <= PTHREAD_DESTRUCTOR_ITERATIONS)
+ {
+ /*
+ * Unlock both locks before the destructor runs.
+ * POSIX says pthread_key_delete can be run from destructors,
+ * and that probably includes with this key as target.
+ * pthread_setspecific can also be run from destructors and
+ * also needs to be able to access the assocs.
+ */
+ ptw32_mcs_lock_release(&threadLock);
+ ptw32_mcs_lock_release(&keyLock);
+
+ assocsRemaining++;
+
+#if defined(__cplusplus)
+
+ try
+ {
+ /*
+ * Run the caller's cleanup routine.
+ */
+ destructor (value);
+ }
+ catch (...)
+ {
+ /*
+ * A system unexpected exception has occurred
+ * running the user's destructor.
+ * We get control back within this block in case
+ * the application has set up it's own terminate
+ * handler. Since we are leaving the thread we
+ * should not get any internal pthreads
+ * exceptions.
+ */
+ terminate ();
+ }
+
+#else /* __cplusplus */
+
+ /*
+ * Run the caller's cleanup routine.
+ */
+ destructor (value);
+
+#endif /* __cplusplus */
+
+ }
+ else
+ {
+ /*
+ * Remove association from both the key and thread chains
+ * and reclaim it's memory resources.
+ */
+ ptw32_tkAssocDestroy (assoc);
+ ptw32_mcs_lock_release(&threadLock);
+ ptw32_mcs_lock_release(&keyLock);
+ }
+ }
+ }
+ while (assocsRemaining);
+ }
+} /* ptw32_callUserDestroyRoutines */
diff --git a/libs/pthreads/src/ptw32_calloc.c b/libs/pthreads/src/ptw32_calloc.c
new file mode 100644
index 0000000000..e7b9e64fe6
--- /dev/null
+++ b/libs/pthreads/src/ptw32_calloc.c
@@ -0,0 +1,56 @@
+/*
+ * ptw32_calloc.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#if defined(NEED_CALLOC)
+void *
+ptw32_calloc (size_t n, size_t s)
+{
+ unsigned int m = n * s;
+ void *p;
+
+ p = malloc (m);
+ if (p == NULL)
+ return NULL;
+
+ memset (p, 0, m);
+
+ return p;
+}
+#endif
diff --git a/libs/pthreads/src/ptw32_cond_check_need_init.c b/libs/pthreads/src/ptw32_cond_check_need_init.c
new file mode 100644
index 0000000000..ec3e8bbd69
--- /dev/null
+++ b/libs/pthreads/src/ptw32_cond_check_need_init.c
@@ -0,0 +1,78 @@
+/*
+ * ptw32_cond_check_need_init.c
+ *
+ * Description:
+ * This translation unit implements condition variables and their primitives.
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+INLINE int
+ptw32_cond_check_need_init (pthread_cond_t * cond)
+{
+ int result = 0;
+ ptw32_mcs_local_node_t node;
+
+ /*
+ * The following guarded test is specifically for statically
+ * initialised condition variables (via PTHREAD_OBJECT_INITIALIZER).
+ */
+ ptw32_mcs_lock_acquire(&ptw32_cond_test_init_lock, &node);
+
+ /*
+ * We got here possibly under race
+ * conditions. Check again inside the critical section.
+ * If a static cv has been destroyed, the application can
+ * re-initialise it only by calling pthread_cond_init()
+ * explicitly.
+ */
+ if (*cond == PTHREAD_COND_INITIALIZER)
+ {
+ result = pthread_cond_init (cond, NULL);
+ }
+ else if (*cond == NULL)
+ {
+ /*
+ * The cv has been destroyed while we were waiting to
+ * initialise it, so the operation that caused the
+ * auto-initialisation should fail.
+ */
+ result = EINVAL;
+ }
+
+ ptw32_mcs_lock_release(&node);
+
+ return result;
+}
diff --git a/libs/pthreads/src/ptw32_getprocessors.c b/libs/pthreads/src/ptw32_getprocessors.c
new file mode 100644
index 0000000000..e60c3143f9
--- /dev/null
+++ b/libs/pthreads/src/ptw32_getprocessors.c
@@ -0,0 +1,91 @@
+/*
+ * ptw32_getprocessors.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+/*
+ * ptw32_getprocessors()
+ *
+ * Get the number of CPUs available to the process.
+ *
+ * If the available number of CPUs is 1 then pthread_spin_lock()
+ * will block rather than spin if the lock is already owned.
+ *
+ * pthread_spin_init() calls this routine when initialising
+ * a spinlock. If the number of available processors changes
+ * (after a call to SetProcessAffinityMask()) then only
+ * newly initialised spinlocks will notice.
+ */
+int
+ptw32_getprocessors (int *count)
+{
+ DWORD_PTR vProcessCPUs;
+ DWORD_PTR vSystemCPUs;
+ int result = 0;
+
+#if defined(NEED_PROCESS_AFFINITY_MASK)
+
+ *count = 1;
+
+#else
+
+ if (GetProcessAffinityMask (GetCurrentProcess (),
+ &vProcessCPUs, &vSystemCPUs))
+ {
+ DWORD_PTR bit;
+ int CPUs = 0;
+
+ for (bit = 1; bit != 0; bit <<= 1)
+ {
+ if (vProcessCPUs & bit)
+ {
+ CPUs++;
+ }
+ }
+ *count = CPUs;
+ }
+ else
+ {
+ result = EAGAIN;
+ }
+
+#endif
+
+ return (result);
+}
diff --git a/libs/pthreads/src/ptw32_is_attr.c b/libs/pthreads/src/ptw32_is_attr.c
new file mode 100644
index 0000000000..36395f81f0
--- /dev/null
+++ b/libs/pthreads/src/ptw32_is_attr.c
@@ -0,0 +1,47 @@
+/*
+ * ptw32_is_attr.c
+ *
+ * Description:
+ * This translation unit implements operations on thread attribute objects.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+ptw32_is_attr (const pthread_attr_t * attr)
+{
+ /* Return 0 if the attr object is valid, non-zero otherwise. */
+
+ return (attr == NULL ||
+ *attr == NULL || (*attr)->valid != PTW32_ATTR_VALID);
+}
diff --git a/libs/pthreads/src/ptw32_mutex_check_need_init.c b/libs/pthreads/src/ptw32_mutex_check_need_init.c
new file mode 100644
index 0000000000..897db3c68e
--- /dev/null
+++ b/libs/pthreads/src/ptw32_mutex_check_need_init.c
@@ -0,0 +1,92 @@
+/*
+ * ptw32_mutex_check_need_init.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+static struct pthread_mutexattr_t_ ptw32_recursive_mutexattr_s =
+ {PTHREAD_PROCESS_PRIVATE, PTHREAD_MUTEX_RECURSIVE};
+static struct pthread_mutexattr_t_ ptw32_errorcheck_mutexattr_s =
+ {PTHREAD_PROCESS_PRIVATE, PTHREAD_MUTEX_ERRORCHECK};
+static pthread_mutexattr_t ptw32_recursive_mutexattr = &ptw32_recursive_mutexattr_s;
+static pthread_mutexattr_t ptw32_errorcheck_mutexattr = &ptw32_errorcheck_mutexattr_s;
+
+
+INLINE int
+ptw32_mutex_check_need_init (pthread_mutex_t * mutex)
+{
+ register int result = 0;
+ register pthread_mutex_t mtx;
+ ptw32_mcs_local_node_t node;
+
+ ptw32_mcs_lock_acquire(&ptw32_mutex_test_init_lock, &node);
+
+ /*
+ * We got here possibly under race
+ * conditions. Check again inside the critical section
+ * and only initialise if the mutex is valid (not been destroyed).
+ * If a static mutex has been destroyed, the application can
+ * re-initialise it only by calling pthread_mutex_init()
+ * explicitly.
+ */
+ mtx = *mutex;
+
+ if (mtx == PTHREAD_MUTEX_INITIALIZER)
+ {
+ result = pthread_mutex_init (mutex, NULL);
+ }
+ else if (mtx == PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
+ {
+ result = pthread_mutex_init (mutex, &ptw32_recursive_mutexattr);
+ }
+ else if (mtx == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER)
+ {
+ result = pthread_mutex_init (mutex, &ptw32_errorcheck_mutexattr);
+ }
+ else if (mtx == NULL)
+ {
+ /*
+ * The mutex has been destroyed while we were waiting to
+ * initialise it, so the operation that caused the
+ * auto-initialisation should fail.
+ */
+ result = EINVAL;
+ }
+
+ ptw32_mcs_lock_release(&node);
+
+ return (result);
+}
diff --git a/libs/pthreads/src/ptw32_new.c b/libs/pthreads/src/ptw32_new.c
new file mode 100644
index 0000000000..ac836ead3a
--- /dev/null
+++ b/libs/pthreads/src/ptw32_new.c
@@ -0,0 +1,94 @@
+/*
+ * ptw32_new.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+pthread_t
+ptw32_new (void)
+{
+ pthread_t t;
+ pthread_t nil = {NULL, 0};
+ ptw32_thread_t * tp;
+
+ /*
+ * If there's a reusable pthread_t then use it.
+ */
+ t = ptw32_threadReusePop ();
+
+ if (NULL != t.p)
+ {
+ tp = (ptw32_thread_t *) t.p;
+ }
+ else
+ {
+ /* No reuse threads available */
+ tp = (ptw32_thread_t *) calloc (1, sizeof(ptw32_thread_t));
+
+ if (tp == NULL)
+ {
+ return nil;
+ }
+
+ /* ptHandle.p needs to point to it's parent ptw32_thread_t. */
+ t.p = tp->ptHandle.p = tp;
+ t.x = tp->ptHandle.x = 0;
+ }
+
+ /* Set default state. */
+ tp->seqNumber = ++ptw32_threadSeqNumber;
+ tp->sched_priority = THREAD_PRIORITY_NORMAL;
+ tp->detachState = PTHREAD_CREATE_JOINABLE;
+ tp->cancelState = PTHREAD_CANCEL_ENABLE;
+ tp->cancelType = PTHREAD_CANCEL_DEFERRED;
+ tp->stateLock = 0;
+ tp->threadLock = 0;
+ tp->robustMxListLock = 0;
+ tp->robustMxList = NULL;
+ tp->cancelEvent = CreateEvent (0, (int) PTW32_TRUE, /* manualReset */
+ (int) PTW32_FALSE, /* setSignaled */
+ NULL);
+
+ if (tp->cancelEvent == NULL)
+ {
+ ptw32_threadReusePush (tp->ptHandle);
+ return nil;
+ }
+
+ return t;
+
+}
diff --git a/libs/pthreads/src/ptw32_processInitialize.c b/libs/pthreads/src/ptw32_processInitialize.c
new file mode 100644
index 0000000000..8da3e41fa1
--- /dev/null
+++ b/libs/pthreads/src/ptw32_processInitialize.c
@@ -0,0 +1,92 @@
+/*
+ * ptw32_processInitialize.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+ptw32_processInitialize (void)
+ /*
+ * ------------------------------------------------------
+ * DOCPRIVATE
+ * This function performs process wide initialization for
+ * the pthread library.
+ *
+ * PARAMETERS
+ * N/A
+ *
+ * DESCRIPTION
+ * This function performs process wide initialization for
+ * the pthread library.
+ * If successful, this routine sets the global variable
+ * ptw32_processInitialized to TRUE.
+ *
+ * RESULTS
+ * TRUE if successful,
+ * FALSE otherwise
+ *
+ * ------------------------------------------------------
+ */
+{
+ if (ptw32_processInitialized)
+ {
+ /*
+ * Ignore if already initialized. this is useful for
+ * programs that uses a non-dll pthread
+ * library. Such programs must call ptw32_processInitialize() explicitly,
+ * since this initialization routine is automatically called only when
+ * the dll is loaded.
+ */
+ return PTW32_TRUE;
+ }
+
+ ptw32_processInitialized = PTW32_TRUE;
+
+ /*
+ * Initialize Keys
+ */
+ if ((pthread_key_create (&ptw32_selfThreadKey, NULL) != 0) ||
+ (pthread_key_create (&ptw32_cleanupKey, NULL) != 0))
+ {
+
+ ptw32_processTerminate ();
+ }
+
+ return (ptw32_processInitialized);
+
+} /* processInitialize */
diff --git a/libs/pthreads/src/ptw32_processTerminate.c b/libs/pthreads/src/ptw32_processTerminate.c
new file mode 100644
index 0000000000..83f0f23cab
--- /dev/null
+++ b/libs/pthreads/src/ptw32_processTerminate.c
@@ -0,0 +1,105 @@
+/*
+ * ptw32_processTerminate.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+void
+ptw32_processTerminate (void)
+ /*
+ * ------------------------------------------------------
+ * DOCPRIVATE
+ * This function performs process wide termination for
+ * the pthread library.
+ *
+ * PARAMETERS
+ * N/A
+ *
+ * DESCRIPTION
+ * This function performs process wide termination for
+ * the pthread library.
+ * This routine sets the global variable
+ * ptw32_processInitialized to FALSE
+ *
+ * RESULTS
+ * N/A
+ *
+ * ------------------------------------------------------
+ */
+{
+ if (ptw32_processInitialized)
+ {
+ ptw32_thread_t * tp, * tpNext;
+ ptw32_mcs_local_node_t node;
+
+ if (ptw32_selfThreadKey != NULL)
+ {
+ /*
+ * Release ptw32_selfThreadKey
+ */
+ pthread_key_delete (ptw32_selfThreadKey);
+
+ ptw32_selfThreadKey = NULL;
+ }
+
+ if (ptw32_cleanupKey != NULL)
+ {
+ /*
+ * Release ptw32_cleanupKey
+ */
+ pthread_key_delete (ptw32_cleanupKey);
+
+ ptw32_cleanupKey = NULL;
+ }
+
+ ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node);
+
+ tp = ptw32_threadReuseTop;
+ while (tp != PTW32_THREAD_REUSE_EMPTY)
+ {
+ tpNext = tp->prevReuse;
+ free (tp);
+ tp = tpNext;
+ }
+
+ ptw32_mcs_lock_release(&node);
+
+ ptw32_processInitialized = PTW32_FALSE;
+ }
+
+} /* processTerminate */
diff --git a/libs/pthreads/src/ptw32_relmillisecs.c b/libs/pthreads/src/ptw32_relmillisecs.c
new file mode 100644
index 0000000000..894d5c9d46
--- /dev/null
+++ b/libs/pthreads/src/ptw32_relmillisecs.c
@@ -0,0 +1,132 @@
+/*
+ * ptw32_relmillisecs.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#if !defined(NEED_FTIME)
+#include <sys/timeb.h>
+#endif
+
+
+#if defined(PTW32_BUILD_INLINED)
+INLINE
+#endif /* PTW32_BUILD_INLINED */
+DWORD
+ptw32_relmillisecs (const struct timespec * abstime)
+{
+ const int64_t NANOSEC_PER_MILLISEC = 1000000;
+ const int64_t MILLISEC_PER_SEC = 1000;
+ DWORD milliseconds;
+ int64_t tmpAbsMilliseconds;
+ int64_t tmpCurrMilliseconds;
+#if defined(NEED_FTIME)
+ struct timespec currSysTime;
+ FILETIME ft;
+ SYSTEMTIME st;
+#else /* ! NEED_FTIME */
+#if ( defined(_MSC_VER) && _MSC_VER >= 1300 ) || \
+ ( (defined(__MINGW64__) || defined(__MINGW32__)) && __MSVCRT_VERSION__ >= 0x0601 )
+ struct __timeb64 currSysTime;
+#else
+ struct _timeb currSysTime;
+#endif
+#endif /* NEED_FTIME */
+
+
+ /*
+ * Calculate timeout as milliseconds from current system time.
+ */
+
+ /*
+ * subtract current system time from abstime in a way that checks
+ * that abstime is never in the past, or is never equivalent to the
+ * defined INFINITE value (0xFFFFFFFF).
+ *
+ * Assume all integers are unsigned, i.e. cannot test if less than 0.
+ */
+ tmpAbsMilliseconds = (int64_t)abstime->tv_sec * MILLISEC_PER_SEC;
+ tmpAbsMilliseconds += ((int64_t)abstime->tv_nsec + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC;
+
+ /* get current system time */
+
+#if defined(NEED_FTIME)
+
+ GetSystemTime(&st);
+ SystemTimeToFileTime(&st, &ft);
+ /*
+ * GetSystemTimeAsFileTime(&ft); would be faster,
+ * but it does not exist on WinCE
+ */
+
+ ptw32_filetime_to_timespec(&ft, &currSysTime);
+
+ tmpCurrMilliseconds = (int64_t)currSysTime.tv_sec * MILLISEC_PER_SEC;
+ tmpCurrMilliseconds += ((int64_t)currSysTime.tv_nsec + (NANOSEC_PER_MILLISEC/2))
+ / NANOSEC_PER_MILLISEC;
+
+#else /* ! NEED_FTIME */
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ _ftime64_s(&currSysTime);
+#elif ( defined(_MSC_VER) && _MSC_VER >= 1300 ) || \
+ ( (defined(__MINGW64__) || defined(__MINGW32__)) && __MSVCRT_VERSION__ >= 0x0601 )
+ _ftime64(&currSysTime);
+#else
+ _ftime(&currSysTime);
+#endif
+
+ tmpCurrMilliseconds = (int64_t) currSysTime.time * MILLISEC_PER_SEC;
+ tmpCurrMilliseconds += (int64_t) currSysTime.millitm;
+
+#endif /* NEED_FTIME */
+
+ if (tmpAbsMilliseconds > tmpCurrMilliseconds)
+ {
+ milliseconds = (DWORD) (tmpAbsMilliseconds - tmpCurrMilliseconds);
+ if (milliseconds == INFINITE)
+ {
+ /* Timeouts must be finite */
+ milliseconds--;
+ }
+ }
+ else
+ {
+ /* The abstime given is in the past */
+ milliseconds = 0;
+ }
+
+ return milliseconds;
+}
diff --git a/libs/pthreads/src/ptw32_reuse.c b/libs/pthreads/src/ptw32_reuse.c
new file mode 100644
index 0000000000..7325857ba2
--- /dev/null
+++ b/libs/pthreads/src/ptw32_reuse.c
@@ -0,0 +1,151 @@
+/*
+ * ptw32_threadReuse.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+/*
+ * How it works:
+ * A pthread_t is a struct (2x32 bit scalar types on IA-32, 2x64 bit on IA-64)
+ * which is normally passed/returned by value to/from pthreads routines.
+ * Applications are therefore storing a copy of the struct as it is at that
+ * time.
+ *
+ * The original pthread_t struct plus all copies of it contain the address of
+ * the thread state struct ptw32_thread_t_ (p), plus a reuse counter (x). Each
+ * ptw32_thread_t contains the original copy of it's pthread_t.
+ * Once malloced, a ptw32_thread_t_ struct is not freed until the process exits.
+ *
+ * The thread reuse stack is a simple LILO stack managed through a singly
+ * linked list element in the ptw32_thread_t.
+ *
+ * Each time a thread is destroyed, the ptw32_thread_t address is pushed onto the
+ * reuse stack after it's ptHandle's reuse counter has been incremented.
+ *
+ * The following can now be said from this:
+ * - two pthread_t's are identical if their ptw32_thread_t reference pointers
+ * are equal and their reuse counters are equal. That is,
+ *
+ * equal = (a.p == b.p && a.x == b.x)
+ *
+ * - a pthread_t copy refers to a destroyed thread if the reuse counter in
+ * the copy is not equal to the reuse counter in the original.
+ *
+ * threadDestroyed = (copy.x != ((ptw32_thread_t *)copy.p)->ptHandle.x)
+ *
+ */
+
+/*
+ * Pop a clean pthread_t struct off the reuse stack.
+ */
+pthread_t
+ptw32_threadReusePop (void)
+{
+ pthread_t t = {NULL, 0};
+ ptw32_mcs_local_node_t node;
+
+ ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node);
+
+ if (PTW32_THREAD_REUSE_EMPTY != ptw32_threadReuseTop)
+ {
+ ptw32_thread_t * tp;
+
+ tp = ptw32_threadReuseTop;
+
+ ptw32_threadReuseTop = tp->prevReuse;
+
+ if (PTW32_THREAD_REUSE_EMPTY == ptw32_threadReuseTop)
+ {
+ ptw32_threadReuseBottom = PTW32_THREAD_REUSE_EMPTY;
+ }
+
+ tp->prevReuse = NULL;
+
+ t = tp->ptHandle;
+ }
+
+ ptw32_mcs_lock_release(&node);
+
+ return t;
+
+}
+
+/*
+ * Push a clean pthread_t struct onto the reuse stack.
+ * Must be re-initialised when reused.
+ * All object elements (mutexes, events etc) must have been either
+ * detroyed before this, or never initialised.
+ */
+void
+ptw32_threadReusePush (pthread_t thread)
+{
+ ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
+ pthread_t t;
+ ptw32_mcs_local_node_t node;
+
+ ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node);
+
+ t = tp->ptHandle;
+ memset(tp, 0, sizeof(ptw32_thread_t));
+
+ /* Must restore the original POSIX handle that we just wiped. */
+ tp->ptHandle = t;
+
+ /* Bump the reuse counter now */
+#if defined(PTW32_THREAD_ID_REUSE_INCREMENT)
+ tp->ptHandle.x += PTW32_THREAD_ID_REUSE_INCREMENT;
+#else
+ tp->ptHandle.x++;
+#endif
+
+ tp->state = PThreadStateReuse;
+
+ tp->prevReuse = PTW32_THREAD_REUSE_EMPTY;
+
+ if (PTW32_THREAD_REUSE_EMPTY != ptw32_threadReuseBottom)
+ {
+ ptw32_threadReuseBottom->prevReuse = tp;
+ }
+ else
+ {
+ ptw32_threadReuseTop = tp;
+ }
+
+ ptw32_threadReuseBottom = tp;
+
+ ptw32_mcs_lock_release(&node);
+}
diff --git a/libs/pthreads/src/ptw32_rwlock_cancelwrwait.c b/libs/pthreads/src/ptw32_rwlock_cancelwrwait.c
new file mode 100644
index 0000000000..a057bd1d72
--- /dev/null
+++ b/libs/pthreads/src/ptw32_rwlock_cancelwrwait.c
@@ -0,0 +1,50 @@
+/*
+ * ptw32_rwlock_cancelwrwait.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+void
+ptw32_rwlock_cancelwrwait (void *arg)
+{
+ pthread_rwlock_t rwl = (pthread_rwlock_t) arg;
+
+ rwl->nSharedAccessCount = -rwl->nCompletedSharedAccessCount;
+ rwl->nCompletedSharedAccessCount = 0;
+
+ (void) pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted));
+ (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
+}
diff --git a/libs/pthreads/src/ptw32_rwlock_check_need_init.c b/libs/pthreads/src/ptw32_rwlock_check_need_init.c
new file mode 100644
index 0000000000..858ee271ce
--- /dev/null
+++ b/libs/pthreads/src/ptw32_rwlock_check_need_init.c
@@ -0,0 +1,77 @@
+/*
+ * pthread_rwlock_check_need_init.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+INLINE int
+ptw32_rwlock_check_need_init (pthread_rwlock_t * rwlock)
+{
+ int result = 0;
+ ptw32_mcs_local_node_t node;
+
+ /*
+ * The following guarded test is specifically for statically
+ * initialised rwlocks (via PTHREAD_RWLOCK_INITIALIZER).
+ */
+ ptw32_mcs_lock_acquire(&ptw32_rwlock_test_init_lock, &node);
+
+ /*
+ * We got here possibly under race
+ * conditions. Check again inside the critical section
+ * and only initialise if the rwlock is valid (not been destroyed).
+ * If a static rwlock has been destroyed, the application can
+ * re-initialise it only by calling pthread_rwlock_init()
+ * explicitly.
+ */
+ if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+ {
+ result = pthread_rwlock_init (rwlock, NULL);
+ }
+ else if (*rwlock == NULL)
+ {
+ /*
+ * The rwlock has been destroyed while we were waiting to
+ * initialise it, so the operation that caused the
+ * auto-initialisation should fail.
+ */
+ result = EINVAL;
+ }
+
+ ptw32_mcs_lock_release(&node);
+
+ return result;
+}
diff --git a/libs/pthreads/src/ptw32_semwait.c b/libs/pthreads/src/ptw32_semwait.c
new file mode 100644
index 0000000000..c3c4fd0e5e
--- /dev/null
+++ b/libs/pthreads/src/ptw32_semwait.c
@@ -0,0 +1,135 @@
+/*
+ * ptw32_semwait.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#if !defined(_UWIN)
+/*# include <process.h> */
+#endif
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+ptw32_semwait (sem_t * sem)
+ /*
+ * ------------------------------------------------------
+ * DESCRIPTION
+ * This function waits on a POSIX semaphore. If the
+ * semaphore value is greater than zero, it decreases
+ * its value by one. If the semaphore value is zero, then
+ * the calling thread (or process) is blocked until it can
+ * successfully decrease the value.
+ *
+ * Unlike sem_wait(), this routine is non-cancelable.
+ *
+ * RESULTS
+ * 0 successfully decreased semaphore,
+ * -1 failed, error in errno.
+ * ERRNO
+ * EINVAL 'sem' is not a valid semaphore,
+ * ENOSYS semaphores are not supported,
+ * EINTR the function was interrupted by a signal,
+ * EDEADLK a deadlock condition was detected.
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ sem_t s = *sem;
+
+ if (s == NULL)
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ if ((result = pthread_mutex_lock (&s->lock)) == 0)
+ {
+ int v;
+
+ /* See sem_destroy.c
+ */
+ if (*sem == NULL)
+ {
+ (void) pthread_mutex_unlock (&s->lock);
+ errno = EINVAL;
+ return -1;
+ }
+
+ v = --s->value;
+ (void) pthread_mutex_unlock (&s->lock);
+
+ if (v < 0)
+ {
+ /* Must wait */
+ if (WaitForSingleObject (s->sem, INFINITE) == WAIT_OBJECT_0)
+ {
+#if defined(NEED_SEM)
+ if (pthread_mutex_lock (&s->lock) == 0)
+ {
+ if (*sem == NULL)
+ {
+ (void) pthread_mutex_unlock (&s->lock);
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (s->leftToUnblock > 0)
+ {
+ --s->leftToUnblock;
+ SetEvent(s->sem);
+ }
+ (void) pthread_mutex_unlock (&s->lock);
+ }
+#endif
+ return 0;
+ }
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ }
+
+ if (result != 0)
+ {
+ errno = result;
+ return -1;
+ }
+
+ return 0;
+
+} /* ptw32_semwait */
diff --git a/libs/pthreads/src/ptw32_spinlock_check_need_init.c b/libs/pthreads/src/ptw32_spinlock_check_need_init.c
new file mode 100644
index 0000000000..8808454ee8
--- /dev/null
+++ b/libs/pthreads/src/ptw32_spinlock_check_need_init.c
@@ -0,0 +1,78 @@
+/*
+ * ptw32_spinlock_check_need_init.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+INLINE int
+ptw32_spinlock_check_need_init (pthread_spinlock_t * lock)
+{
+ int result = 0;
+ ptw32_mcs_local_node_t node;
+
+ /*
+ * The following guarded test is specifically for statically
+ * initialised spinlocks (via PTHREAD_SPINLOCK_INITIALIZER).
+ */
+ ptw32_mcs_lock_acquire(&ptw32_spinlock_test_init_lock, &node);
+
+ /*
+ * We got here possibly under race
+ * conditions. Check again inside the critical section
+ * and only initialise if the spinlock is valid (not been destroyed).
+ * If a static spinlock has been destroyed, the application can
+ * re-initialise it only by calling pthread_spin_init()
+ * explicitly.
+ */
+ if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
+ {
+ result = pthread_spin_init (lock, PTHREAD_PROCESS_PRIVATE);
+ }
+ else if (*lock == NULL)
+ {
+ /*
+ * The spinlock has been destroyed while we were waiting to
+ * initialise it, so the operation that caused the
+ * auto-initialisation should fail.
+ */
+ result = EINVAL;
+ }
+
+ ptw32_mcs_lock_release(&node);
+
+ return (result);
+}
diff --git a/libs/pthreads/src/ptw32_threadDestroy.c b/libs/pthreads/src/ptw32_threadDestroy.c
new file mode 100644
index 0000000000..41499b11b6
--- /dev/null
+++ b/libs/pthreads/src/ptw32_threadDestroy.c
@@ -0,0 +1,79 @@
+/*
+ * ptw32_threadDestroy.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+void
+ptw32_threadDestroy (pthread_t thread)
+{
+ ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
+ ptw32_thread_t threadCopy;
+
+ if (tp != NULL)
+ {
+ /*
+ * Copy thread state so that the thread can be atomically NULLed.
+ */
+ memcpy (&threadCopy, tp, sizeof (threadCopy));
+
+ /*
+ * Thread ID structs are never freed. They're NULLed and reused.
+ * This also sets the thread to PThreadStateInitial (invalid).
+ */
+ ptw32_threadReusePush (thread);
+
+ /* Now work on the copy. */
+ if (threadCopy.cancelEvent != NULL)
+ {
+ CloseHandle (threadCopy.cancelEvent);
+ }
+
+#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
+ /*
+ * See documentation for endthread vs endthreadex.
+ */
+ if (threadCopy.threadH != 0)
+ {
+ CloseHandle (threadCopy.threadH);
+ }
+#endif
+
+ }
+} /* ptw32_threadDestroy */
+
diff --git a/libs/pthreads/src/ptw32_threadStart.c b/libs/pthreads/src/ptw32_threadStart.c
new file mode 100644
index 0000000000..e83ede0ec4
--- /dev/null
+++ b/libs/pthreads/src/ptw32_threadStart.c
@@ -0,0 +1,357 @@
+/*
+ * ptw32_threadStart.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include <stdio.h>
+
+#if defined(__CLEANUP_C)
+# include <setjmp.h>
+#endif
+
+#if defined(__CLEANUP_SEH)
+
+static DWORD
+ExceptionFilter (EXCEPTION_POINTERS * ep, DWORD * ei)
+{
+ switch (ep->ExceptionRecord->ExceptionCode)
+ {
+ case EXCEPTION_PTW32_SERVICES:
+ {
+ DWORD param;
+ DWORD numParams = ep->ExceptionRecord->NumberParameters;
+
+ numParams = (numParams > 3) ? 3 : numParams;
+
+ for (param = 0; param < numParams; param++)
+ {
+ ei[param] = ep->ExceptionRecord->ExceptionInformation[param];
+ }
+
+ return EXCEPTION_EXECUTE_HANDLER;
+ break;
+ }
+ default:
+ {
+ /*
+ * A system unexpected exception has occurred running the user's
+ * routine. We need to cleanup before letting the exception
+ * out of thread scope.
+ */
+ pthread_t self = pthread_self ();
+
+ ptw32_callUserDestroyRoutines (self);
+
+ return EXCEPTION_CONTINUE_SEARCH;
+ break;
+ }
+ }
+}
+
+#elif defined(__CLEANUP_CXX)
+
+#if defined(_MSC_VER)
+# include <eh.h>
+#elif defined(__WATCOMC__)
+# include <eh.h>
+# include <exceptio.h>
+typedef terminate_handler
+ terminate_function;
+#else
+# if defined(__GNUC__) && __GNUC__ < 3
+# include <new.h>
+# else
+# include <new>
+using
+ std::terminate_handler;
+using
+ std::terminate;
+using
+ std::set_terminate;
+# endif
+typedef terminate_handler
+ terminate_function;
+#endif
+
+static terminate_function
+ ptw32_oldTerminate;
+
+void
+ptw32_terminate ()
+{
+ set_terminate (ptw32_oldTerminate);
+ (void) pthread_win32_thread_detach_np ();
+ terminate ();
+}
+
+#endif
+
+#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || (defined (__MSVCRT__) && ! defined (__DMC__))
+unsigned
+ __stdcall
+#else
+void
+#endif
+ptw32_threadStart (void *vthreadParms)
+{
+ ThreadParms * threadParms = (ThreadParms *) vthreadParms;
+ pthread_t self;
+ ptw32_thread_t * sp;
+ void * (PTW32_CDECL *start) (void *);
+ void * arg;
+
+#if defined(__CLEANUP_SEH)
+ DWORD
+ ei[] = { 0, 0, 0 };
+#endif
+
+#if defined(__CLEANUP_C)
+ int setjmp_rc;
+#endif
+
+ ptw32_mcs_local_node_t stateLock;
+ void * status = (void *) 0;
+
+ self = threadParms->tid;
+ sp = (ptw32_thread_t *) self.p;
+ start = threadParms->start;
+ arg = threadParms->arg;
+
+ free (threadParms);
+
+#if (defined(__MINGW64__) || defined(__MINGW32__)) && ! defined (__MSVCRT__)
+ /*
+ * beginthread does not return the thread id and is running
+ * before it returns us the thread handle, and so we do it here.
+ */
+ sp->thread = GetCurrentThreadId ();
+ /*
+ * Here we're using stateLock as a general-purpose lock
+ * to make the new thread wait until the creating thread
+ * has the new handle.
+ */
+ ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
+ pthread_setspecific (ptw32_selfThreadKey, sp);
+#else
+ pthread_setspecific (ptw32_selfThreadKey, sp);
+ ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
+#endif
+
+ sp->state = PThreadStateRunning;
+ ptw32_mcs_lock_release (&stateLock);
+
+#if defined(__CLEANUP_SEH)
+
+ __try
+ {
+ /*
+ * Run the caller's routine;
+ */
+ status = sp->exitStatus = (*start) (arg);
+ sp->state = PThreadStateExiting;
+
+#if defined(_UWIN)
+ if (--pthread_count <= 0)
+ exit (0);
+#endif
+
+ }
+ __except (ExceptionFilter (GetExceptionInformation (), ei))
+ {
+ switch (ei[0])
+ {
+ case PTW32_EPS_CANCEL:
+ status = sp->exitStatus = PTHREAD_CANCELED;
+#if defined(_UWIN)
+ if (--pthread_count <= 0)
+ exit (0);
+#endif
+ break;
+ case PTW32_EPS_EXIT:
+ status = sp->exitStatus;
+ break;
+ default:
+ status = sp->exitStatus = PTHREAD_CANCELED;
+ break;
+ }
+ }
+
+#else /* __CLEANUP_SEH */
+
+#if defined(__CLEANUP_C)
+
+ setjmp_rc = setjmp (sp->start_mark);
+
+ if (0 == setjmp_rc)
+ {
+
+ /*
+ * Run the caller's routine;
+ */
+ status = sp->exitStatus = (*start) (arg);
+ sp->state = PThreadStateExiting;
+ }
+ else
+ {
+ switch (setjmp_rc)
+ {
+ case PTW32_EPS_CANCEL:
+ status = sp->exitStatus = PTHREAD_CANCELED;
+ break;
+ case PTW32_EPS_EXIT:
+ status = sp->exitStatus;
+ break;
+ default:
+ status = sp->exitStatus = PTHREAD_CANCELED;
+ break;
+ }
+ }
+
+#else /* __CLEANUP_C */
+
+#if defined(__CLEANUP_CXX)
+
+ ptw32_oldTerminate = set_terminate (&ptw32_terminate);
+
+ try
+ {
+ /*
+ * Run the caller's routine in a nested try block so that we
+ * can run the user's terminate function, which may call
+ * pthread_exit() or be canceled.
+ */
+ try
+ {
+ status = sp->exitStatus = (*start) (arg);
+ sp->state = PThreadStateExiting;
+ }
+ catch (ptw32_exception &)
+ {
+ /*
+ * Pass these through to the outer block.
+ */
+ throw;
+ }
+ catch (...)
+ {
+ /*
+ * We want to run the user's terminate function if supplied.
+ * That function may call pthread_exit() or be canceled, which will
+ * be handled by the outer try block.
+ *
+ * ptw32_terminate() will be called if there is no user
+ * supplied function.
+ */
+ terminate_function
+ term_func = set_terminate (0);
+ set_terminate (term_func);
+
+ if (term_func != 0)
+ {
+ term_func ();
+ }
+ throw;
+ }
+ }
+ catch (ptw32_exception_cancel &)
+ {
+ /*
+ * Thread was canceled.
+ */
+ status = sp->exitStatus = PTHREAD_CANCELED;
+ }
+ catch (ptw32_exception_exit &)
+ {
+ /*
+ * Thread was exited via pthread_exit().
+ */
+ status = sp->exitStatus;
+ }
+ catch (...)
+ {
+ /*
+ * A system unexpected exception has occurred running the user's
+ * terminate routine. We get control back within this block
+ * and exit with a substitute status. If the thread was not
+ * cancelled then this indicates the unhandled exception.
+ */
+ status = sp->exitStatus = PTHREAD_CANCELED;
+ }
+
+ (void) set_terminate (ptw32_oldTerminate);
+
+#else
+
+#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
+
+#endif /* __CLEANUP_CXX */
+#endif /* __CLEANUP_C */
+#endif /* __CLEANUP_SEH */
+
+#if defined(PTW32_STATIC_LIB)
+ /*
+ * We need to cleanup the pthread now if we have
+ * been statically linked, in which case the cleanup
+ * in dllMain won't get done. Joinable threads will
+ * only be partially cleaned up and must be fully cleaned
+ * up by pthread_join() or pthread_detach().
+ *
+ * Note: if this library has been statically linked,
+ * implicitly created pthreads (those created
+ * for Win32 threads which have called pthreads routines)
+ * must be cleaned up explicitly by the application
+ * (by calling pthread_win32_thread_detach_np()).
+ * For the dll, dllMain will do the cleanup automatically.
+ */
+ (void) pthread_win32_thread_detach_np ();
+#endif
+
+#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
+ _endthreadex ((unsigned)(size_t) status);
+#else
+ _endthread ();
+#endif
+
+ /*
+ * Never reached.
+ */
+
+#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
+ return (unsigned)(size_t) status;
+#endif
+
+} /* ptw32_threadStart */
diff --git a/libs/pthreads/src/ptw32_throw.c b/libs/pthreads/src/ptw32_throw.c
new file mode 100644
index 0000000000..1404e940f5
--- /dev/null
+++ b/libs/pthreads/src/ptw32_throw.c
@@ -0,0 +1,189 @@
+/*
+ * ptw32_throw.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+#if defined(__CLEANUP_C)
+# include <setjmp.h>
+#endif
+
+/*
+ * ptw32_throw
+ *
+ * All canceled and explicitly exited POSIX threads go through
+ * here. This routine knows how to exit both POSIX initiated threads and
+ * 'implicit' POSIX threads for each of the possible language modes (C,
+ * C++, and SEH).
+ */
+#if defined(_MSC_VER)
+/*
+ * Ignore the warning:
+ * "C++ exception specification ignored except to indicate that
+ * the function is not __declspec(nothrow)."
+ */
+#pragma warning(disable:4290)
+#endif
+void
+ptw32_throw (DWORD exception)
+#if defined(__CLEANUP_CXX)
+ throw(ptw32_exception_cancel,ptw32_exception_exit)
+#endif
+{
+ /*
+ * Don't use pthread_self() to avoid creating an implicit POSIX thread handle
+ * unnecessarily.
+ */
+ ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
+
+#if defined(__CLEANUP_SEH)
+ DWORD exceptionInformation[3];
+#endif
+
+ sp->state = PThreadStateExiting;
+
+ if (exception != PTW32_EPS_CANCEL && exception != PTW32_EPS_EXIT)
+ {
+ /* Should never enter here */
+ exit (1);
+ }
+
+ if (NULL == sp || sp->implicit)
+ {
+ /*
+ * We're inside a non-POSIX initialised Win32 thread
+ * so there is no point to jump or throw back to. Just do an
+ * explicit thread exit here after cleaning up POSIX
+ * residue (i.e. cleanup handlers, POSIX thread handle etc).
+ */
+#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
+ unsigned exitCode = 0;
+
+ switch (exception)
+ {
+ case PTW32_EPS_CANCEL:
+ exitCode = (unsigned)(size_t) PTHREAD_CANCELED;
+ break;
+ case PTW32_EPS_EXIT:
+ if (NULL != sp)
+ {
+ exitCode = (unsigned)(size_t) sp->exitStatus;
+ }
+ break;
+ }
+#endif
+
+#if defined(PTW32_STATIC_LIB)
+
+ pthread_win32_thread_detach_np ();
+
+#endif
+
+#if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
+ _endthreadex (exitCode);
+#else
+ _endthread ();
+#endif
+
+ }
+
+#if defined(__CLEANUP_SEH)
+
+
+ exceptionInformation[0] = (DWORD) (exception);
+ exceptionInformation[1] = (DWORD) (0);
+ exceptionInformation[2] = (DWORD) (0);
+
+ RaiseException (EXCEPTION_PTW32_SERVICES, 0, 3, exceptionInformation);
+
+#else /* __CLEANUP_SEH */
+
+#if defined(__CLEANUP_C)
+
+ ptw32_pop_cleanup_all (1);
+ longjmp (sp->start_mark, exception);
+
+#else /* __CLEANUP_C */
+
+#if defined(__CLEANUP_CXX)
+
+ switch (exception)
+ {
+ case PTW32_EPS_CANCEL:
+ throw ptw32_exception_cancel ();
+ break;
+ case PTW32_EPS_EXIT:
+ throw ptw32_exception_exit ();
+ break;
+ }
+
+#else
+
+#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* __CLEANUP_C */
+
+#endif /* __CLEANUP_SEH */
+
+ /* Never reached */
+}
+
+
+void
+ptw32_pop_cleanup_all (int execute)
+{
+ while (NULL != ptw32_pop_cleanup (execute))
+ {
+ }
+}
+
+
+DWORD
+ptw32_get_exception_services_code (void)
+{
+#if defined(__CLEANUP_SEH)
+
+ return EXCEPTION_PTW32_SERVICES;
+
+#else
+
+ return (DWORD)0;
+
+#endif
+}
diff --git a/libs/pthreads/src/ptw32_timespec.c b/libs/pthreads/src/ptw32_timespec.c
new file mode 100644
index 0000000000..6318957a89
--- /dev/null
+++ b/libs/pthreads/src/ptw32_timespec.c
@@ -0,0 +1,83 @@
+/*
+ * ptw32_timespec.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#if defined(NEED_FTIME)
+
+/*
+ * time between jan 1, 1601 and jan 1, 1970 in units of 100 nanoseconds
+ */
+#define PTW32_TIMESPEC_TO_FILETIME_OFFSET \
+ ( ((int64_t) 27111902 << 32) + (int64_t) 3577643008 )
+
+INLINE void
+ptw32_timespec_to_filetime (const struct timespec *ts, FILETIME * ft)
+ /*
+ * -------------------------------------------------------------------
+ * converts struct timespec
+ * where the time is expressed in seconds and nanoseconds from Jan 1, 1970.
+ * into FILETIME (as set by GetSystemTimeAsFileTime), where the time is
+ * expressed in 100 nanoseconds from Jan 1, 1601,
+ * -------------------------------------------------------------------
+ */
+{
+ *(int64_t *) ft = ts->tv_sec * 10000000
+ + (ts->tv_nsec + 50) / 100 + PTW32_TIMESPEC_TO_FILETIME_OFFSET;
+}
+
+INLINE void
+ptw32_filetime_to_timespec (const FILETIME * ft, struct timespec *ts)
+ /*
+ * -------------------------------------------------------------------
+ * converts FILETIME (as set by GetSystemTimeAsFileTime), where the time is
+ * expressed in 100 nanoseconds from Jan 1, 1601,
+ * into struct timespec
+ * where the time is expressed in seconds and nanoseconds from Jan 1, 1970.
+ * -------------------------------------------------------------------
+ */
+{
+ ts->tv_sec =
+ (int) ((*(int64_t *) ft - PTW32_TIMESPEC_TO_FILETIME_OFFSET) / 10000000);
+ ts->tv_nsec =
+ (int) ((*(int64_t *) ft - PTW32_TIMESPEC_TO_FILETIME_OFFSET -
+ ((int64_t) ts->tv_sec * (int64_t) 10000000)) * 100);
+}
+
+#endif /* NEED_FTIME */
diff --git a/libs/pthreads/src/ptw32_tkAssocCreate.c b/libs/pthreads/src/ptw32_tkAssocCreate.c
new file mode 100644
index 0000000000..50d6c500c3
--- /dev/null
+++ b/libs/pthreads/src/ptw32_tkAssocCreate.c
@@ -0,0 +1,118 @@
+/*
+ * ptw32_tkAssocCreate.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+ptw32_tkAssocCreate (ptw32_thread_t * sp, pthread_key_t key)
+ /*
+ * -------------------------------------------------------------------
+ * This routine creates an association that
+ * is unique for the given (thread,key) combination.The association
+ * is referenced by both the thread and the key.
+ * This association allows us to determine what keys the
+ * current thread references and what threads a given key
+ * references.
+ * See the detailed description
+ * at the beginning of this file for further details.
+ *
+ * Notes:
+ * 1) New associations are pushed to the beginning of the
+ * chain so that the internal ptw32_selfThreadKey association
+ * is always last, thus allowing selfThreadExit to
+ * be implicitly called last by pthread_exit.
+ * 2)
+ *
+ * Parameters:
+ * thread
+ * current running thread.
+ * key
+ * key on which to create an association.
+ * Returns:
+ * 0 - if successful,
+ * ENOMEM - not enough memory to create assoc or other object
+ * EINVAL - an internal error occurred
+ * ENOSYS - an internal error occurred
+ * -------------------------------------------------------------------
+ */
+{
+ ThreadKeyAssoc *assoc;
+
+ /*
+ * Have to create an association and add it
+ * to both the key and the thread.
+ *
+ * Both key->keyLock and thread->threadLock are locked before
+ * entry to this routine.
+ */
+ assoc = (ThreadKeyAssoc *) calloc (1, sizeof (*assoc));
+
+ if (assoc == NULL)
+ {
+ return ENOMEM;
+ }
+
+ assoc->thread = sp;
+ assoc->key = key;
+
+ /*
+ * Register assoc with key
+ */
+ assoc->prevThread = NULL;
+ assoc->nextThread = (ThreadKeyAssoc *) key->threads;
+ if (assoc->nextThread != NULL)
+ {
+ assoc->nextThread->prevThread = assoc;
+ }
+ key->threads = (void *) assoc;
+
+ /*
+ * Register assoc with thread
+ */
+ assoc->prevKey = NULL;
+ assoc->nextKey = (ThreadKeyAssoc *) sp->keys;
+ if (assoc->nextKey != NULL)
+ {
+ assoc->nextKey->prevKey = assoc;
+ }
+ sp->keys = (void *) assoc;
+
+ return (0);
+
+} /* ptw32_tkAssocCreate */
diff --git a/libs/pthreads/src/ptw32_tkAssocDestroy.c b/libs/pthreads/src/ptw32_tkAssocDestroy.c
new file mode 100644
index 0000000000..fedebf5935
--- /dev/null
+++ b/libs/pthreads/src/ptw32_tkAssocDestroy.c
@@ -0,0 +1,114 @@
+/*
+ * ptw32_tkAssocDestroy.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+void
+ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc)
+ /*
+ * -------------------------------------------------------------------
+ * This routine releases all resources for the given ThreadKeyAssoc
+ * once it is no longer being referenced
+ * ie) either the key or thread has stopped referencing it.
+ *
+ * Parameters:
+ * assoc
+ * an instance of ThreadKeyAssoc.
+ * Returns:
+ * N/A
+ * -------------------------------------------------------------------
+ */
+{
+
+ /*
+ * Both key->keyLock and thread->threadLock are locked before
+ * entry to this routine.
+ */
+ if (assoc != NULL)
+ {
+ ThreadKeyAssoc * prev, * next;
+
+ /* Remove assoc from thread's keys chain */
+ prev = assoc->prevKey;
+ next = assoc->nextKey;
+ if (prev != NULL)
+ {
+ prev->nextKey = next;
+ }
+ if (next != NULL)
+ {
+ next->prevKey = prev;
+ }
+
+ if (assoc->thread->keys == assoc)
+ {
+ /* We're at the head of the thread's keys chain */
+ assoc->thread->keys = next;
+ }
+ if (assoc->thread->nextAssoc == assoc)
+ {
+ /*
+ * Thread is exiting and we're deleting the assoc to be processed next.
+ * Hand thread the assoc after this one.
+ */
+ assoc->thread->nextAssoc = next;
+ }
+
+ /* Remove assoc from key's threads chain */
+ prev = assoc->prevThread;
+ next = assoc->nextThread;
+ if (prev != NULL)
+ {
+ prev->nextThread = next;
+ }
+ if (next != NULL)
+ {
+ next->prevThread = prev;
+ }
+
+ if (assoc->key->threads == assoc)
+ {
+ /* We're at the head of the key's threads chain */
+ assoc->key->threads = next;
+ }
+
+ free (assoc);
+ }
+
+} /* ptw32_tkAssocDestroy */
diff --git a/libs/pthreads/src/rwlock.c b/libs/pthreads/src/rwlock.c
new file mode 100644
index 0000000000..4a3cd2594c
--- /dev/null
+++ b/libs/pthreads/src/rwlock.c
@@ -0,0 +1,51 @@
+/*
+ * rwlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "ptw32_rwlock_check_need_init.c"
+#include "ptw32_rwlock_cancelwrwait.c"
+#include "pthread_rwlock_init.c"
+#include "pthread_rwlock_destroy.c"
+#include "pthread_rwlockattr_init.c"
+#include "pthread_rwlockattr_destroy.c"
+#include "pthread_rwlockattr_getpshared.c"
+#include "pthread_rwlockattr_setpshared.c"
+#include "pthread_rwlock_rdlock.c"
+#include "pthread_rwlock_timedrdlock.c"
+#include "pthread_rwlock_wrlock.c"
+#include "pthread_rwlock_timedwrlock.c"
+#include "pthread_rwlock_unlock.c"
+#include "pthread_rwlock_tryrdlock.c"
+#include "pthread_rwlock_trywrlock.c"
diff --git a/libs/pthreads/src/sched.c b/libs/pthreads/src/sched.c
new file mode 100644
index 0000000000..ed30ea7b24
--- /dev/null
+++ b/libs/pthreads/src/sched.c
@@ -0,0 +1,53 @@
+/*
+ * sched.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+#include "pthread_attr_setschedpolicy.c"
+#include "pthread_attr_getschedpolicy.c"
+#include "pthread_attr_setschedparam.c"
+#include "pthread_attr_getschedparam.c"
+#include "pthread_attr_setinheritsched.c"
+#include "pthread_attr_getinheritsched.c"
+#include "pthread_setschedparam.c"
+#include "pthread_getschedparam.c"
+#include "sched_get_priority_max.c"
+#include "sched_get_priority_min.c"
+#include "sched_setscheduler.c"
+#include "sched_getscheduler.c"
+#include "sched_yield.c"
diff --git a/libs/pthreads/src/sched.h b/libs/pthreads/src/sched.h
new file mode 100644
index 0000000000..f36a97a66b
--- /dev/null
+++ b/libs/pthreads/src/sched.h
@@ -0,0 +1,183 @@
+/*
+ * Module: sched.h
+ *
+ * Purpose:
+ * Provides an implementation of POSIX realtime extensions
+ * as defined in
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+#if !defined(_SCHED_H)
+#define _SCHED_H
+
+#undef PTW32_SCHED_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_SCHED_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_SCHED_LEVEL
+#define PTW32_SCHED_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_SCHED_LEVEL
+#define PTW32_SCHED_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_SCHED_LEVEL_MAX 3
+
+#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_SCHED_LEVEL)
+#define PTW32_SCHED_LEVEL PTW32_SCHED_LEVEL_MAX
+/* Include everything */
+#endif
+
+
+#if defined(__GNUC__) && !defined(__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the library, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the library,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#if !defined(PTW32_STATIC_LIB)
+# if defined(PTW32_BUILD)
+# define PTW32_DLLPORT __declspec (dllexport)
+# else
+# define PTW32_DLLPORT __declspec (dllimport)
+# endif
+#else
+# define PTW32_DLLPORT
+#endif
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#if !defined(PTW32_CONFIG_H)
+# if defined(WINCE)
+# define NEED_ERRNO
+# define NEED_SEM
+# endif
+# if defined(__MINGW64__)
+# define HAVE_STRUCT_TIMESPEC
+# define HAVE_MODE_T
+# elif defined(_UWIN) || defined(__MINGW32__)
+# define HAVE_MODE_T
+# endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX
+#if defined(NEED_ERRNO)
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX */
+
+#if (defined(__MINGW64__) || defined(__MINGW32__)) || defined(_UWIN)
+# if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX
+/* For pid_t */
+# include <sys/types.h>
+/* Required by Unix 98 */
+# include <time.h>
+# else
+ typedef int pid_t;
+# endif
+#else
+ typedef int pid_t;
+#endif
+
+/* Thread scheduling policies */
+
+enum {
+ SCHED_OTHER = 0,
+ SCHED_FIFO,
+ SCHED_RR,
+ SCHED_MIN = SCHED_OTHER,
+ SCHED_MAX = SCHED_RR
+};
+
+struct sched_param {
+ int sched_priority;
+};
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif /* __cplusplus */
+
+PTW32_DLLPORT int __cdecl sched_yield (void);
+
+PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy);
+
+PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy);
+
+PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy);
+
+PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid);
+
+/*
+ * Note that this macro returns ENOTSUP rather than
+ * ENOSYS as might be expected. However, returning ENOSYS
+ * should mean that sched_get_priority_{min,max} are
+ * not implemented as well as sched_rr_get_interval.
+ * This is not the case, since we just don't support
+ * round-robin scheduling. Therefore I have chosen to
+ * return the same value as sched_setscheduler when
+ * SCHED_RR is passed to it.
+ */
+#define sched_rr_get_interval(_pid, _interval) \
+ ( errno = ENOTSUP, (int) -1 )
+
+
+#if defined(__cplusplus)
+} /* End of extern "C" */
+#endif /* __cplusplus */
+
+#undef PTW32_SCHED_LEVEL
+#undef PTW32_SCHED_LEVEL_MAX
+
+#endif /* !_SCHED_H */
+
diff --git a/libs/pthreads/src/sched_get_priority_max.c b/libs/pthreads/src/sched_get_priority_max.c
new file mode 100644
index 0000000000..cabf2320a7
--- /dev/null
+++ b/libs/pthreads/src/sched_get_priority_max.c
@@ -0,0 +1,134 @@
+/*
+ * sched_get_priority_max.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+/*
+ * On Windows98, THREAD_PRIORITY_LOWEST is (-2) and
+ * THREAD_PRIORITY_HIGHEST is 2, and everything works just fine.
+ *
+ * On WinCE 3.0, it so happen that THREAD_PRIORITY_LOWEST is 5
+ * and THREAD_PRIORITY_HIGHEST is 1 (yes, I know, it is funny:
+ * highest priority use smaller numbers) and the following happens:
+ *
+ * sched_get_priority_min() returns 5
+ * sched_get_priority_max() returns 1
+ *
+ * The following table shows the base priority levels for combinations
+ * of priority class and priority value in Win32.
+ *
+ * Process Priority Class Thread Priority Level
+ * -----------------------------------------------------------------
+ * 1 IDLE_PRIORITY_CLASS THREAD_PRIORITY_IDLE
+ * 1 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE
+ * 1 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE
+ * 1 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE
+ * 1 HIGH_PRIORITY_CLASS THREAD_PRIORITY_IDLE
+ * 2 IDLE_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
+ * 3 IDLE_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
+ * 4 IDLE_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
+ * 4 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
+ * 5 IDLE_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
+ * 5 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
+ * 5 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
+ * 6 IDLE_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
+ * 6 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
+ * 6 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
+ * 7 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
+ * 7 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
+ * 7 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
+ * 8 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
+ * 8 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
+ * 8 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
+ * 8 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
+ * 9 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
+ * 9 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
+ * 9 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
+ * 10 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
+ * 10 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
+ * 11 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
+ * 11 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
+ * 11 HIGH_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
+ * 12 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
+ * 12 HIGH_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
+ * 13 HIGH_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
+ * 14 HIGH_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
+ * 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
+ * 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
+ * 15 IDLE_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
+ * 15 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
+ * 15 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
+ * 15 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
+ * 16 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_IDLE
+ * 17 REALTIME_PRIORITY_CLASS -7
+ * 18 REALTIME_PRIORITY_CLASS -6
+ * 19 REALTIME_PRIORITY_CLASS -5
+ * 20 REALTIME_PRIORITY_CLASS -4
+ * 21 REALTIME_PRIORITY_CLASS -3
+ * 22 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
+ * 23 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
+ * 24 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
+ * 25 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
+ * 26 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
+ * 27 REALTIME_PRIORITY_CLASS 3
+ * 28 REALTIME_PRIORITY_CLASS 4
+ * 29 REALTIME_PRIORITY_CLASS 5
+ * 30 REALTIME_PRIORITY_CLASS 6
+ * 31 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
+ *
+ * Windows NT: Values -7, -6, -5, -4, -3, 3, 4, 5, and 6 are not supported.
+ */
+
+
+int
+sched_get_priority_max (int policy)
+{
+ if (policy < SCHED_MIN || policy > SCHED_MAX)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL)
+ /* WinCE? */
+ return PTW32_MAX (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
+#else
+ /* This is independent of scheduling policy in Win32. */
+ return PTW32_MAX (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
+#endif
+}
diff --git a/libs/pthreads/src/sched_get_priority_min.c b/libs/pthreads/src/sched_get_priority_min.c
new file mode 100644
index 0000000000..9c4f8591e5
--- /dev/null
+++ b/libs/pthreads/src/sched_get_priority_min.c
@@ -0,0 +1,135 @@
+/*
+ * sched_get_priority_min.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+/*
+ * On Windows98, THREAD_PRIORITY_LOWEST is (-2) and
+ * THREAD_PRIORITY_HIGHEST is 2, and everything works just fine.
+ *
+ * On WinCE 3.0, it so happen that THREAD_PRIORITY_LOWEST is 5
+ * and THREAD_PRIORITY_HIGHEST is 1 (yes, I know, it is funny:
+ * highest priority use smaller numbers) and the following happens:
+ *
+ * sched_get_priority_min() returns 5
+ * sched_get_priority_max() returns 1
+ *
+ * The following table shows the base priority levels for combinations
+ * of priority class and priority value in Win32.
+ *
+ * Process Priority Class Thread Priority Level
+ * -----------------------------------------------------------------
+ * 1 IDLE_PRIORITY_CLASS THREAD_PRIORITY_IDLE
+ * 1 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE
+ * 1 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE
+ * 1 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_IDLE
+ * 1 HIGH_PRIORITY_CLASS THREAD_PRIORITY_IDLE
+ * 2 IDLE_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
+ * 3 IDLE_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
+ * 4 IDLE_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
+ * 4 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
+ * 5 IDLE_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
+ * 5 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
+ * 5 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
+ * 6 IDLE_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
+ * 6 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
+ * 6 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
+ * 7 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
+ * 7 Background NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
+ * 7 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
+ * 8 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
+ * 8 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
+ * 8 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
+ * 8 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
+ * 9 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
+ * 9 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
+ * 9 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
+ * 10 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
+ * 10 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
+ * 11 Foreground NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
+ * 11 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
+ * 11 HIGH_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
+ * 12 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
+ * 12 HIGH_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
+ * 13 HIGH_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
+ * 14 HIGH_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
+ * 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
+ * 15 HIGH_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
+ * 15 IDLE_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
+ * 15 BELOW_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
+ * 15 NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
+ * 15 ABOVE_NORMAL_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
+ * 16 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_IDLE
+ * 17 REALTIME_PRIORITY_CLASS -7
+ * 18 REALTIME_PRIORITY_CLASS -6
+ * 19 REALTIME_PRIORITY_CLASS -5
+ * 20 REALTIME_PRIORITY_CLASS -4
+ * 21 REALTIME_PRIORITY_CLASS -3
+ * 22 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_LOWEST
+ * 23 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_BELOW_NORMAL
+ * 24 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_NORMAL
+ * 25 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL
+ * 26 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_HIGHEST
+ * 27 REALTIME_PRIORITY_CLASS 3
+ * 28 REALTIME_PRIORITY_CLASS 4
+ * 29 REALTIME_PRIORITY_CLASS 5
+ * 30 REALTIME_PRIORITY_CLASS 6
+ * 31 REALTIME_PRIORITY_CLASS THREAD_PRIORITY_TIME_CRITICAL
+ *
+ * Windows NT: Values -7, -6, -5, -4, -3, 3, 4, 5, and 6 are not supported.
+ *
+ */
+
+
+int
+sched_get_priority_min (int policy)
+{
+ if (policy < SCHED_MIN || policy > SCHED_MAX)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL)
+ /* WinCE? */
+ return PTW32_MIN (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
+#else
+ /* This is independent of scheduling policy in Win32. */
+ return PTW32_MIN (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
+#endif
+}
diff --git a/libs/pthreads/src/sched_getscheduler.c b/libs/pthreads/src/sched_getscheduler.c
new file mode 100644
index 0000000000..8769c15e5a
--- /dev/null
+++ b/libs/pthreads/src/sched_getscheduler.c
@@ -0,0 +1,71 @@
+/*
+ * sched_getscheduler.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+sched_getscheduler (pid_t pid)
+{
+ /*
+ * Win32 only has one policy which we call SCHED_OTHER.
+ * However, we try to provide other valid side-effects
+ * such as EPERM and ESRCH errors.
+ */
+ if (0 != pid)
+ {
+ int selfPid = (int) GetCurrentProcessId ();
+
+ if (pid != selfPid)
+ {
+ HANDLE h =
+ OpenProcess (PROCESS_QUERY_INFORMATION, PTW32_FALSE, (DWORD) pid);
+
+ if (NULL == h)
+ {
+ errno =
+ (GetLastError () ==
+ (0xFF & ERROR_ACCESS_DENIED)) ? EPERM : ESRCH;
+ return -1;
+ }
+ else
+ CloseHandle(h);
+ }
+ }
+
+ return SCHED_OTHER;
+}
diff --git a/libs/pthreads/src/sched_setscheduler.c b/libs/pthreads/src/sched_setscheduler.c
new file mode 100644
index 0000000000..8691316371
--- /dev/null
+++ b/libs/pthreads/src/sched_setscheduler.c
@@ -0,0 +1,83 @@
+/*
+ * sched_setscheduler.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+sched_setscheduler (pid_t pid, int policy)
+{
+ /*
+ * Win32 only has one policy which we call SCHED_OTHER.
+ * However, we try to provide other valid side-effects
+ * such as EPERM and ESRCH errors. Choosing to check
+ * for a valid policy last allows us to get the most value out
+ * of this function.
+ */
+ if (0 != pid)
+ {
+ int selfPid = (int) GetCurrentProcessId ();
+
+ if (pid != selfPid)
+ {
+ HANDLE h =
+ OpenProcess (PROCESS_SET_INFORMATION, PTW32_FALSE, (DWORD) pid);
+
+ if (NULL == h)
+ {
+ errno =
+ (GetLastError () ==
+ (0xFF & ERROR_ACCESS_DENIED)) ? EPERM : ESRCH;
+ return -1;
+ }
+ else
+ CloseHandle(h);
+ }
+ }
+
+ if (SCHED_OTHER != policy)
+ {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ /*
+ * Don't set anything because there is nothing to set.
+ * Just return the current (the only possible) value.
+ */
+ return SCHED_OTHER;
+}
diff --git a/libs/pthreads/src/sched_yield.c b/libs/pthreads/src/sched_yield.c
new file mode 100644
index 0000000000..6ac5ed9263
--- /dev/null
+++ b/libs/pthreads/src/sched_yield.c
@@ -0,0 +1,71 @@
+/*
+ * sched_yield.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+sched_yield (void)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function indicates that the calling thread is
+ * willing to give up some time slices to other threads.
+ *
+ * PARAMETERS
+ * N/A
+ *
+ *
+ * DESCRIPTION
+ * This function indicates that the calling thread is
+ * willing to give up some time slices to other threads.
+ * NOTE: Since this is part of POSIX 1003.1b
+ * (realtime extensions), it is defined as returning
+ * -1 if an error occurs and sets errno to the actual
+ * error.
+ *
+ * RESULTS
+ * 0 successfully created semaphore,
+ * ENOSYS sched_yield not supported,
+ *
+ * ------------------------------------------------------
+ */
+{
+ Sleep (0);
+
+ return 0;
+}
diff --git a/libs/pthreads/src/sem_close.c b/libs/pthreads/src/sem_close.c
new file mode 100644
index 0000000000..6d7280f299
--- /dev/null
+++ b/libs/pthreads/src/sem_close.c
@@ -0,0 +1,58 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_close.c
+ *
+ * Purpose:
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+/* ignore warning "unreferenced formal parameter" */
+#if defined(_MSC_VER)
+#pragma warning( disable : 4100 )
+#endif
+
+int
+sem_close (sem_t * sem)
+{
+ errno = ENOSYS;
+ return -1;
+} /* sem_close */
diff --git a/libs/pthreads/src/sem_destroy.c b/libs/pthreads/src/sem_destroy.c
new file mode 100644
index 0000000000..6c98e80b93
--- /dev/null
+++ b/libs/pthreads/src/sem_destroy.c
@@ -0,0 +1,144 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_destroy.c
+ *
+ * Purpose:
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+
+int
+sem_destroy (sem_t * sem)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function destroys an unnamed semaphore.
+ *
+ * PARAMETERS
+ * sem
+ * pointer to an instance of sem_t
+ *
+ * DESCRIPTION
+ * This function destroys an unnamed semaphore.
+ *
+ * RESULTS
+ * 0 successfully destroyed semaphore,
+ * -1 failed, error in errno
+ * ERRNO
+ * EINVAL 'sem' is not a valid semaphore,
+ * ENOSYS semaphores are not supported,
+ * EBUSY threads (or processes) are currently
+ * blocked on 'sem'
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ sem_t s = NULL;
+
+ if (sem == NULL || *sem == NULL)
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ s = *sem;
+
+ if ((result = pthread_mutex_lock (&s->lock)) == 0)
+ {
+ if (s->value < 0)
+ {
+ (void) pthread_mutex_unlock (&s->lock);
+ result = EBUSY;
+ }
+ else
+ {
+ /* There are no threads currently blocked on this semaphore. */
+
+ if (!CloseHandle (s->sem))
+ {
+ (void) pthread_mutex_unlock (&s->lock);
+ result = EINVAL;
+ }
+ else
+ {
+ /*
+ * Invalidate the semaphore handle when we have the lock.
+ * Other sema operations should test this after acquiring the lock
+ * to check that the sema is still valid, i.e. before performing any
+ * operations. This may only be necessary before the sema op routine
+ * returns so that the routine can return EINVAL - e.g. if setting
+ * s->value to SEM_VALUE_MAX below does force a fall-through.
+ */
+ *sem = NULL;
+
+ /* Prevent anyone else actually waiting on or posting this sema.
+ */
+ s->value = SEM_VALUE_MAX;
+
+ (void) pthread_mutex_unlock (&s->lock);
+
+ do
+ {
+ /* Give other threads a chance to run and exit any sema op
+ * routines. Due to the SEM_VALUE_MAX value, if sem_post or
+ * sem_wait were blocked by us they should fall through.
+ */
+ Sleep(0);
+ }
+ while (pthread_mutex_destroy (&s->lock) == EBUSY);
+ }
+ }
+ }
+ }
+
+ if (result != 0)
+ {
+ errno = result;
+ return -1;
+ }
+
+ free (s);
+
+ return 0;
+
+} /* sem_destroy */
diff --git a/libs/pthreads/src/sem_getvalue.c b/libs/pthreads/src/sem_getvalue.c
new file mode 100644
index 0000000000..baafb02cf0
--- /dev/null
+++ b/libs/pthreads/src/sem_getvalue.c
@@ -0,0 +1,110 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_getvalue.c
+ *
+ * Purpose:
+ * Semaphores aren't actually part of PThreads.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1-2001
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+
+int
+sem_getvalue (sem_t * sem, int *sval)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function stores the current count value of the
+ * semaphore.
+ * RESULTS
+ *
+ * Return value
+ *
+ * 0 sval has been set.
+ * -1 failed, error in errno
+ *
+ * in global errno
+ *
+ * EINVAL 'sem' is not a valid semaphore,
+ * ENOSYS this function is not supported,
+ *
+ *
+ * PARAMETERS
+ *
+ * sem pointer to an instance of sem_t
+ *
+ * sval pointer to int.
+ *
+ * DESCRIPTION
+ * This function stores the current count value of the semaphore
+ * pointed to by sem in the int pointed to by sval.
+ */
+{
+ if (sem == NULL || *sem == NULL || sval == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ else
+ {
+ long value;
+ register sem_t s = *sem;
+ int result = 0;
+
+ if ((result = pthread_mutex_lock(&s->lock)) == 0)
+ {
+ /* See sem_destroy.c
+ */
+ if (*sem == NULL)
+ {
+ (void) pthread_mutex_unlock (&s->lock);
+ errno = EINVAL;
+ return -1;
+ }
+
+ value = s->value;
+ (void) pthread_mutex_unlock(&s->lock);
+ *sval = value;
+ }
+
+ return result;
+ }
+
+} /* sem_getvalue */
diff --git a/libs/pthreads/src/sem_init.c b/libs/pthreads/src/sem_init.c
new file mode 100644
index 0000000000..f682f4b204
--- /dev/null
+++ b/libs/pthreads/src/sem_init.c
@@ -0,0 +1,169 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_init.c
+ *
+ * Purpose:
+ * Semaphores aren't actually part of PThreads.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1-2001
+ *
+ * -------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+int
+sem_init (sem_t * sem, int pshared, unsigned int value)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function initializes a semaphore. The
+ * initial value of the semaphore is 'value'
+ *
+ * PARAMETERS
+ * sem
+ * pointer to an instance of sem_t
+ *
+ * pshared
+ * if zero, this semaphore may only be shared between
+ * threads in the same process.
+ * if nonzero, the semaphore can be shared between
+ * processes
+ *
+ * value
+ * initial value of the semaphore counter
+ *
+ * DESCRIPTION
+ * This function initializes a semaphore. The
+ * initial value of the semaphore is set to 'value'.
+ *
+ * RESULTS
+ * 0 successfully created semaphore,
+ * -1 failed, error in errno
+ * ERRNO
+ * EINVAL 'sem' is not a valid semaphore, or
+ * 'value' >= SEM_VALUE_MAX
+ * ENOMEM out of memory,
+ * ENOSPC a required resource has been exhausted,
+ * ENOSYS semaphores are not supported,
+ * EPERM the process lacks appropriate privilege
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ sem_t s = NULL;
+
+ if (pshared != 0)
+ {
+ /*
+ * Creating a semaphore that can be shared between
+ * processes
+ */
+ result = EPERM;
+ }
+ else if (value > (unsigned int)SEM_VALUE_MAX)
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ s = (sem_t) calloc (1, sizeof (*s));
+
+ if (NULL == s)
+ {
+ result = ENOMEM;
+ }
+ else
+ {
+
+ s->value = value;
+ if (pthread_mutex_init(&s->lock, NULL) == 0)
+ {
+
+#if defined(NEED_SEM)
+
+ s->sem = CreateEvent (NULL,
+ PTW32_FALSE, /* auto (not manual) reset */
+ PTW32_FALSE, /* initial state is unset */
+ NULL);
+
+ if (0 == s->sem)
+ {
+ free (s);
+ (void) pthread_mutex_destroy(&s->lock);
+ result = ENOSPC;
+ }
+ else
+ {
+ s->leftToUnblock = 0;
+ }
+
+#else /* NEED_SEM */
+
+ if ((s->sem = CreateSemaphore (NULL, /* Always NULL */
+ (long) 0, /* Force threads to wait */
+ (long) SEM_VALUE_MAX, /* Maximum value */
+ NULL)) == 0) /* Name */
+ {
+ (void) pthread_mutex_destroy(&s->lock);
+ result = ENOSPC;
+ }
+
+#endif /* NEED_SEM */
+
+ }
+ else
+ {
+ result = ENOSPC;
+ }
+
+ if (result != 0)
+ {
+ free(s);
+ }
+ }
+ }
+
+ if (result != 0)
+ {
+ errno = result;
+ return -1;
+ }
+
+ *sem = s;
+
+ return 0;
+
+} /* sem_init */
diff --git a/libs/pthreads/src/sem_open.c b/libs/pthreads/src/sem_open.c
new file mode 100644
index 0000000000..fb1cc541f8
--- /dev/null
+++ b/libs/pthreads/src/sem_open.c
@@ -0,0 +1,58 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_open.c
+ *
+ * Purpose:
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+/* ignore warning "unreferenced formal parameter" */
+#if defined(_MSC_VER)
+#pragma warning( disable : 4100 )
+#endif
+
+int
+sem_open (const char *name, int oflag, mode_t mode, unsigned int value)
+{
+ errno = ENOSYS;
+ return -1;
+} /* sem_open */
diff --git a/libs/pthreads/src/sem_post.c b/libs/pthreads/src/sem_post.c
new file mode 100644
index 0000000000..34832527b8
--- /dev/null
+++ b/libs/pthreads/src/sem_post.c
@@ -0,0 +1,128 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_post.c
+ *
+ * Purpose:
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+
+int
+sem_post (sem_t * sem)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function posts a wakeup to a semaphore.
+ *
+ * PARAMETERS
+ * sem
+ * pointer to an instance of sem_t
+ *
+ * DESCRIPTION
+ * This function posts a wakeup to a semaphore. If there
+ * are waiting threads (or processes), one is awakened;
+ * otherwise, the semaphore value is incremented by one.
+ *
+ * RESULTS
+ * 0 successfully posted semaphore,
+ * -1 failed, error in errno
+ * ERRNO
+ * EINVAL 'sem' is not a valid semaphore,
+ * ENOSYS semaphores are not supported,
+ * ERANGE semaphore count is too big
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ sem_t s = *sem;
+
+ if (s == NULL)
+ {
+ result = EINVAL;
+ }
+ else if ((result = pthread_mutex_lock (&s->lock)) == 0)
+ {
+ /* See sem_destroy.c
+ */
+ if (*sem == NULL)
+ {
+ (void) pthread_mutex_unlock (&s->lock);
+ result = EINVAL;
+ return -1;
+ }
+
+ if (s->value < SEM_VALUE_MAX)
+ {
+#if defined(NEED_SEM)
+ if (++s->value <= 0
+ && !SetEvent(s->sem))
+ {
+ s->value--;
+ result = EINVAL;
+ }
+#else
+ if (++s->value <= 0
+ && !ReleaseSemaphore (s->sem, 1, NULL))
+ {
+ s->value--;
+ result = EINVAL;
+ }
+#endif /* NEED_SEM */
+ }
+ else
+ {
+ result = ERANGE;
+ }
+
+ (void) pthread_mutex_unlock (&s->lock);
+ }
+
+ if (result != 0)
+ {
+ errno = result;
+ return -1;
+ }
+
+ return 0;
+
+} /* sem_post */
diff --git a/libs/pthreads/src/sem_post_multiple.c b/libs/pthreads/src/sem_post_multiple.c
new file mode 100644
index 0000000000..44c168c6cf
--- /dev/null
+++ b/libs/pthreads/src/sem_post_multiple.c
@@ -0,0 +1,142 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_post_multiple.c
+ *
+ * Purpose:
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+
+int
+sem_post_multiple (sem_t * sem, int count)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function posts multiple wakeups to a semaphore.
+ *
+ * PARAMETERS
+ * sem
+ * pointer to an instance of sem_t
+ *
+ * count
+ * counter, must be greater than zero.
+ *
+ * DESCRIPTION
+ * This function posts multiple wakeups to a semaphore. If there
+ * are waiting threads (or processes), n <= count are awakened;
+ * the semaphore value is incremented by count - n.
+ *
+ * RESULTS
+ * 0 successfully posted semaphore,
+ * -1 failed, error in errno
+ * ERRNO
+ * EINVAL 'sem' is not a valid semaphore
+ * or count is less than or equal to zero.
+ * ERANGE semaphore count is too big
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ long waiters;
+ sem_t s = *sem;
+
+ if (s == NULL || count <= 0)
+ {
+ result = EINVAL;
+ }
+ else if ((result = pthread_mutex_lock (&s->lock)) == 0)
+ {
+ /* See sem_destroy.c
+ */
+ if (*sem == NULL)
+ {
+ (void) pthread_mutex_unlock (&s->lock);
+ result = EINVAL;
+ return -1;
+ }
+
+ if (s->value <= (SEM_VALUE_MAX - count))
+ {
+ waiters = -s->value;
+ s->value += count;
+ if (waiters > 0)
+ {
+#if defined(NEED_SEM)
+ if (SetEvent(s->sem))
+ {
+ waiters--;
+ s->leftToUnblock += count - 1;
+ if (s->leftToUnblock > waiters)
+ {
+ s->leftToUnblock = waiters;
+ }
+ }
+#else
+ if (ReleaseSemaphore (s->sem, (waiters<=count)?waiters:count, 0))
+ {
+ /* No action */
+ }
+#endif
+ else
+ {
+ s->value -= count;
+ result = EINVAL;
+ }
+ }
+ }
+ else
+ {
+ result = ERANGE;
+ }
+ (void) pthread_mutex_unlock (&s->lock);
+ }
+
+ if (result != 0)
+ {
+ errno = result;
+ return -1;
+ }
+
+ return 0;
+
+} /* sem_post_multiple */
diff --git a/libs/pthreads/src/sem_timedwait.c b/libs/pthreads/src/sem_timedwait.c
new file mode 100644
index 0000000000..638431cf1f
--- /dev/null
+++ b/libs/pthreads/src/sem_timedwait.c
@@ -0,0 +1,238 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_timedwait.c
+ *
+ * Purpose:
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+
+typedef struct {
+ sem_t sem;
+ int * resultPtr;
+} sem_timedwait_cleanup_args_t;
+
+
+static void PTW32_CDECL
+ptw32_sem_timedwait_cleanup (void * args)
+{
+ sem_timedwait_cleanup_args_t * a = (sem_timedwait_cleanup_args_t *)args;
+ sem_t s = a->sem;
+
+ if (pthread_mutex_lock (&s->lock) == 0)
+ {
+ /*
+ * We either timed out or were cancelled.
+ * If someone has posted between then and now we try to take the semaphore.
+ * Otherwise the semaphore count may be wrong after we
+ * return. In the case of a cancellation, it is as if we
+ * were cancelled just before we return (after taking the semaphore)
+ * which is ok.
+ */
+ if (WaitForSingleObject(s->sem, 0) == WAIT_OBJECT_0)
+ {
+ /* We got the semaphore on the second attempt */
+ *(a->resultPtr) = 0;
+ }
+ else
+ {
+ /* Indicate we're no longer waiting */
+ s->value++;
+#if defined(NEED_SEM)
+ if (s->value > 0)
+ {
+ s->leftToUnblock = 0;
+ }
+#else
+ /*
+ * Don't release the W32 sema, it doesn't need adjustment
+ * because it doesn't record the number of waiters.
+ */
+#endif
+ }
+ (void) pthread_mutex_unlock (&s->lock);
+ }
+}
+
+
+int
+sem_timedwait (sem_t * sem, const struct timespec *abstime)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function waits on a semaphore possibly until
+ * 'abstime' time.
+ *
+ * PARAMETERS
+ * sem
+ * pointer to an instance of sem_t
+ *
+ * abstime
+ * pointer to an instance of struct timespec
+ *
+ * DESCRIPTION
+ * This function waits on a semaphore. If the
+ * semaphore value is greater than zero, it decreases
+ * its value by one. If the semaphore value is zero, then
+ * the calling thread (or process) is blocked until it can
+ * successfully decrease the value or until interrupted by
+ * a signal.
+ *
+ * If 'abstime' is a NULL pointer then this function will
+ * block until it can successfully decrease the value or
+ * until interrupted by a signal.
+ *
+ * RESULTS
+ * 0 successfully decreased semaphore,
+ * -1 failed, error in errno
+ * ERRNO
+ * EINVAL 'sem' is not a valid semaphore,
+ * ENOSYS semaphores are not supported,
+ * EINTR the function was interrupted by a signal,
+ * EDEADLK a deadlock condition was detected.
+ * ETIMEDOUT abstime elapsed before success.
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ sem_t s = *sem;
+
+ pthread_testcancel();
+
+ if (sem == NULL)
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ DWORD milliseconds;
+
+ if (abstime == NULL)
+ {
+ milliseconds = INFINITE;
+ }
+ else
+ {
+ /*
+ * Calculate timeout as milliseconds from current system time.
+ */
+ milliseconds = ptw32_relmillisecs (abstime);
+ }
+
+ if ((result = pthread_mutex_lock (&s->lock)) == 0)
+ {
+ int v;
+
+ /* See sem_destroy.c
+ */
+ if (*sem == NULL)
+ {
+ (void) pthread_mutex_unlock (&s->lock);
+ errno = EINVAL;
+ return -1;
+ }
+
+ v = --s->value;
+ (void) pthread_mutex_unlock (&s->lock);
+
+ if (v < 0)
+ {
+#if defined(NEED_SEM)
+ int timedout;
+#endif
+ sem_timedwait_cleanup_args_t cleanup_args;
+
+ cleanup_args.sem = s;
+ cleanup_args.resultPtr = &result;
+
+#if defined(_MSC_VER) && _MSC_VER < 1400
+#pragma inline_depth(0)
+#endif
+ /* Must wait */
+ pthread_cleanup_push(ptw32_sem_timedwait_cleanup, (void *) &cleanup_args);
+#if defined(NEED_SEM)
+ timedout =
+#endif
+ result = pthreadCancelableTimedWait (s->sem, milliseconds);
+ pthread_cleanup_pop(result);
+#if defined(_MSC_VER) && _MSC_VER < 1400
+#pragma inline_depth()
+#endif
+
+#if defined(NEED_SEM)
+
+ if (!timedout && pthread_mutex_lock (&s->lock) == 0)
+ {
+ if (*sem == NULL)
+ {
+ (void) pthread_mutex_unlock (&s->lock);
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (s->leftToUnblock > 0)
+ {
+ --s->leftToUnblock;
+ SetEvent(s->sem);
+ }
+ (void) pthread_mutex_unlock (&s->lock);
+ }
+
+#endif /* NEED_SEM */
+
+ }
+ }
+
+ }
+
+ if (result != 0)
+ {
+
+ errno = result;
+ return -1;
+
+ }
+
+ return 0;
+
+} /* sem_timedwait */
diff --git a/libs/pthreads/src/sem_trywait.c b/libs/pthreads/src/sem_trywait.c
new file mode 100644
index 0000000000..63614ba2b8
--- /dev/null
+++ b/libs/pthreads/src/sem_trywait.c
@@ -0,0 +1,117 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_trywait.c
+ *
+ * Purpose:
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+
+int
+sem_trywait (sem_t * sem)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function tries to wait on a semaphore.
+ *
+ * PARAMETERS
+ * sem
+ * pointer to an instance of sem_t
+ *
+ * DESCRIPTION
+ * This function tries to wait on a semaphore. If the
+ * semaphore value is greater than zero, it decreases
+ * its value by one. If the semaphore value is zero, then
+ * this function returns immediately with the error EAGAIN
+ *
+ * RESULTS
+ * 0 successfully decreased semaphore,
+ * -1 failed, error in errno
+ * ERRNO
+ * EAGAIN the semaphore was already locked,
+ * EINVAL 'sem' is not a valid semaphore,
+ * ENOTSUP sem_trywait is not supported,
+ * EINTR the function was interrupted by a signal,
+ * EDEADLK a deadlock condition was detected.
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ sem_t s = *sem;
+
+ if (s == NULL)
+ {
+ result = EINVAL;
+ }
+ else if ((result = pthread_mutex_lock (&s->lock)) == 0)
+ {
+ /* See sem_destroy.c
+ */
+ if (*sem == NULL)
+ {
+ (void) pthread_mutex_unlock (&s->lock);
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (s->value > 0)
+ {
+ s->value--;
+ }
+ else
+ {
+ result = EAGAIN;
+ }
+
+ (void) pthread_mutex_unlock (&s->lock);
+ }
+
+ if (result != 0)
+ {
+ errno = result;
+ return -1;
+ }
+
+ return 0;
+
+} /* sem_trywait */
diff --git a/libs/pthreads/src/sem_unlink.c b/libs/pthreads/src/sem_unlink.c
new file mode 100644
index 0000000000..fb80569a0a
--- /dev/null
+++ b/libs/pthreads/src/sem_unlink.c
@@ -0,0 +1,58 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_unlink.c
+ *
+ * Purpose:
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+/* ignore warning "unreferenced formal parameter" */
+#if defined(_MSC_VER)
+#pragma warning( disable : 4100 )
+#endif
+
+int
+sem_unlink (const char *name)
+{
+ errno = ENOSYS;
+ return -1;
+} /* sem_unlink */
diff --git a/libs/pthreads/src/sem_wait.c b/libs/pthreads/src/sem_wait.c
new file mode 100644
index 0000000000..50c11d8080
--- /dev/null
+++ b/libs/pthreads/src/sem_wait.c
@@ -0,0 +1,187 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: sem_wait.c
+ *
+ * Purpose:
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+
+static void PTW32_CDECL
+ptw32_sem_wait_cleanup(void * sem)
+{
+ sem_t s = (sem_t) sem;
+
+ if (pthread_mutex_lock (&s->lock) == 0)
+ {
+ /*
+ * If sema is destroyed do nothing, otherwise:-
+ * If the sema is posted between us being cancelled and us locking
+ * the sema again above then we need to consume that post but cancel
+ * anyway. If we don't get the semaphore we indicate that we're no
+ * longer waiting.
+ */
+ if (*((sem_t *)sem) != NULL && !(WaitForSingleObject(s->sem, 0) == WAIT_OBJECT_0))
+ {
+ ++s->value;
+#if defined(NEED_SEM)
+ if (s->value > 0)
+ {
+ s->leftToUnblock = 0;
+ }
+#else
+ /*
+ * Don't release the W32 sema, it doesn't need adjustment
+ * because it doesn't record the number of waiters.
+ */
+#endif /* NEED_SEM */
+ }
+ (void) pthread_mutex_unlock (&s->lock);
+ }
+}
+
+int
+sem_wait (sem_t * sem)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function waits on a semaphore.
+ *
+ * PARAMETERS
+ * sem
+ * pointer to an instance of sem_t
+ *
+ * DESCRIPTION
+ * This function waits on a semaphore. If the
+ * semaphore value is greater than zero, it decreases
+ * its value by one. If the semaphore value is zero, then
+ * the calling thread (or process) is blocked until it can
+ * successfully decrease the value or until interrupted by
+ * a signal.
+ *
+ * RESULTS
+ * 0 successfully decreased semaphore,
+ * -1 failed, error in errno
+ * ERRNO
+ * EINVAL 'sem' is not a valid semaphore,
+ * ENOSYS semaphores are not supported,
+ * EINTR the function was interrupted by a signal,
+ * EDEADLK a deadlock condition was detected.
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ sem_t s = *sem;
+
+ pthread_testcancel();
+
+ if (s == NULL)
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ if ((result = pthread_mutex_lock (&s->lock)) == 0)
+ {
+ int v;
+
+ /* See sem_destroy.c
+ */
+ if (*sem == NULL)
+ {
+ (void) pthread_mutex_unlock (&s->lock);
+ errno = EINVAL;
+ return -1;
+ }
+
+ v = --s->value;
+ (void) pthread_mutex_unlock (&s->lock);
+
+ if (v < 0)
+ {
+#if defined(_MSC_VER) && _MSC_VER < 1400
+#pragma inline_depth(0)
+#endif
+ /* Must wait */
+ pthread_cleanup_push(ptw32_sem_wait_cleanup, (void *) s);
+ result = pthreadCancelableWait (s->sem);
+ /* Cleanup if we're canceled or on any other error */
+ pthread_cleanup_pop(result);
+#if defined(_MSC_VER) && _MSC_VER < 1400
+#pragma inline_depth()
+#endif
+ }
+#if defined(NEED_SEM)
+
+ if (!result && pthread_mutex_lock (&s->lock) == 0)
+ {
+ if (*sem == NULL)
+ {
+ (void) pthread_mutex_unlock (&s->lock);
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (s->leftToUnblock > 0)
+ {
+ --s->leftToUnblock;
+ SetEvent(s->sem);
+ }
+ (void) pthread_mutex_unlock (&s->lock);
+ }
+
+#endif /* NEED_SEM */
+
+ }
+
+ }
+
+ if (result != 0)
+ {
+ errno = result;
+ return -1;
+ }
+
+ return 0;
+
+} /* sem_wait */
diff --git a/libs/pthreads/src/semaphore.c b/libs/pthreads/src/semaphore.c
new file mode 100644
index 0000000000..64fc0e366d
--- /dev/null
+++ b/libs/pthreads/src/semaphore.c
@@ -0,0 +1,69 @@
+/*
+ * -------------------------------------------------------------
+ *
+ * Module: semaphore.c
+ *
+ * Purpose:
+ * Concatenated version of separate modules to allow
+ * inlining optimisation, which it is assumed can only
+ * be effective within a single module.
+ *
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * -------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#if !defined(NEED_FTIME)
+# include <sys/timeb.h>
+#endif
+
+#include <limits.h>
+
+#include "pthread.h"
+#include "semaphore.h"
+#include "implement.h"
+
+
+#include "sem_init.c"
+#include "sem_destroy.c"
+#include "sem_trywait.c"
+#include "sem_wait.c"
+#include "sem_timedwait.c"
+#include "sem_post.c"
+#include "sem_post_multiple.c"
+#include "sem_getvalue.c"
+#include "sem_open.c"
+#include "sem_close.c"
+#include "sem_unlink.c"
diff --git a/libs/pthreads/src/semaphore.h b/libs/pthreads/src/semaphore.h
new file mode 100644
index 0000000000..c6e9407e25
--- /dev/null
+++ b/libs/pthreads/src/semaphore.h
@@ -0,0 +1,169 @@
+/*
+ * Module: semaphore.h
+ *
+ * Purpose:
+ * Semaphores aren't actually part of the PThreads standard.
+ * They are defined by the POSIX Standard:
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+#if !defined( SEMAPHORE_H )
+#define SEMAPHORE_H
+
+#undef PTW32_SEMAPHORE_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_SEMAPHORE_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_SEMAPHORE_LEVEL
+#define PTW32_SEMAPHORE_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_SEMAPHORE_LEVEL
+#define PTW32_SEMAPHORE_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_SEMAPHORE_LEVEL_MAX 3
+
+#if !defined(PTW32_SEMAPHORE_LEVEL)
+#define PTW32_SEMAPHORE_LEVEL PTW32_SEMAPHORE_LEVEL_MAX
+/* Include everything */
+#endif
+
+#if defined(__GNUC__) && ! defined (__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the library, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the library,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#if !defined(PTW32_STATIC_LIB)
+# if defined(PTW32_BUILD)
+# define PTW32_DLLPORT __declspec (dllexport)
+# else
+# define PTW32_DLLPORT __declspec (dllimport)
+# endif
+#else
+# define PTW32_DLLPORT
+#endif
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#if !defined(PTW32_CONFIG_H)
+# if defined(WINCE)
+# define NEED_ERRNO
+# define NEED_SEM
+# endif
+# if defined(__MINGW64__)
+# define HAVE_STRUCT_TIMESPEC
+# define HAVE_MODE_T
+# elif defined(_UWIN) || defined(__MINGW32__)
+# define HAVE_MODE_T
+# endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX
+#if defined(NEED_ERRNO)
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX */
+
+#define _POSIX_SEMAPHORES
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if !defined(HAVE_MODE_T)
+typedef unsigned int mode_t;
+#endif
+
+
+typedef struct sem_t_ * sem_t;
+
+PTW32_DLLPORT int __cdecl sem_init (sem_t * sem,
+ int pshared,
+ unsigned int value);
+
+PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem,
+ const struct timespec * abstime);
+
+PTW32_DLLPORT int __cdecl sem_post (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem,
+ int count);
+
+PTW32_DLLPORT int __cdecl sem_open (const char * name,
+ int oflag,
+ mode_t mode,
+ unsigned int value);
+
+PTW32_DLLPORT int __cdecl sem_close (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_unlink (const char * name);
+
+PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem,
+ int * sval);
+
+#if defined(__cplusplus)
+} /* End of extern "C" */
+#endif /* __cplusplus */
+
+#undef PTW32_SEMAPHORE_LEVEL
+#undef PTW32_SEMAPHORE_LEVEL_MAX
+
+#endif /* !SEMAPHORE_H */
diff --git a/libs/pthreads/src/signal.c b/libs/pthreads/src/signal.c
new file mode 100644
index 0000000000..eef466962b
--- /dev/null
+++ b/libs/pthreads/src/signal.c
@@ -0,0 +1,179 @@
+/*
+ * signal.c
+ *
+ * Description:
+ * Thread-aware signal functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/*
+ * Possible future strategy for implementing pthread_kill()
+ * ========================================================
+ *
+ * Win32 does not implement signals.
+ * Signals are simply software interrupts.
+ * pthread_kill() asks the system to deliver a specified
+ * signal (interrupt) to a specified thread in the same
+ * process.
+ * Signals are always asynchronous (no deferred signals).
+ * Pthread-win32 has an async cancelation mechanism.
+ * A similar system can be written to deliver signals
+ * within the same process (on ix86 processors at least).
+ *
+ * Each thread maintains information about which
+ * signals it will respond to. Handler routines
+ * are set on a per-process basis - not per-thread.
+ * When signalled, a thread will check it's sigmask
+ * and, if the signal is not being ignored, call the
+ * handler routine associated with the signal. The
+ * thread must then (except for some signals) return to
+ * the point where it was interrupted.
+ *
+ * Ideally the system itself would check the target thread's
+ * mask before possibly needlessly bothering the thread
+ * itself. This could be done by pthread_kill(), that is,
+ * in the signaling thread since it has access to
+ * all pthread_t structures. It could also retrieve
+ * the handler routine address to minimise the target
+ * threads response overhead. This may also simplify
+ * serialisation of the access to the per-thread signal
+ * structures.
+ *
+ * pthread_kill() eventually calls a routine similar to
+ * ptw32_cancel_thread() which manipulates the target
+ * threads processor context to cause the thread to
+ * run the handler launcher routine. pthread_kill() must
+ * save the target threads current context so that the
+ * handler launcher routine can restore the context after
+ * the signal handler has returned. Some handlers will not
+ * return, eg. the default SIGKILL handler may simply
+ * call pthread_exit().
+ *
+ * The current context is saved in the target threads
+ * pthread_t structure.
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+#if defined(HAVE_SIGSET_T)
+
+static void
+ptw32_signal_thread ()
+{
+}
+
+static void
+ptw32_signal_callhandler ()
+{
+}
+
+int
+pthread_sigmask (int how, sigset_t const *set, sigset_t * oset)
+{
+ pthread_t thread = pthread_self ();
+
+ if (thread.p == NULL)
+ {
+ return ENOENT;
+ }
+
+ /* Validate the `how' argument. */
+ if (set != NULL)
+ {
+ switch (how)
+ {
+ case SIG_BLOCK:
+ break;
+ case SIG_UNBLOCK:
+ break;
+ case SIG_SETMASK:
+ break;
+ default:
+ /* Invalid `how' argument. */
+ return EINVAL;
+ }
+ }
+
+ /* Copy the old mask before modifying it. */
+ if (oset != NULL)
+ {
+ memcpy (oset, &(thread.p->sigmask), sizeof (sigset_t));
+ }
+
+ if (set != NULL)
+ {
+ unsigned int i;
+
+ /* FIXME: this code assumes that sigmask is an even multiple of
+ the size of a long integer. */
+
+ unsigned long *src = (unsigned long const *) set;
+ unsigned long *dest = (unsigned long *) &(thread.p->sigmask);
+
+ switch (how)
+ {
+ case SIG_BLOCK:
+ for (i = 0; i < (sizeof (sigset_t) / sizeof (unsigned long)); i++)
+ {
+ /* OR the bit field longword-wise. */
+ *dest++ |= *src++;
+ }
+ break;
+ case SIG_UNBLOCK:
+ for (i = 0; i < (sizeof (sigset_t) / sizeof (unsigned long)); i++)
+ {
+ /* XOR the bitfield longword-wise. */
+ *dest++ ^= *src++;
+ }
+ case SIG_SETMASK:
+ /* Replace the whole sigmask. */
+ memcpy (&(thread.p->sigmask), set, sizeof (sigset_t));
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int
+sigwait (const sigset_t * set, int *sig)
+{
+ /* This routine is a cancellation point */
+ pthread_test_cancel();
+}
+
+int
+sigaction (int signum, const struct sigaction *act, struct sigaction *oldact)
+{
+}
+
+#endif /* HAVE_SIGSET_T */
diff --git a/libs/pthreads/src/spin.c b/libs/pthreads/src/spin.c
new file mode 100644
index 0000000000..41b5aa5251
--- /dev/null
+++ b/libs/pthreads/src/spin.c
@@ -0,0 +1,46 @@
+/*
+ * spin.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#include "ptw32_spinlock_check_need_init.c"
+#include "pthread_spin_init.c"
+#include "pthread_spin_destroy.c"
+#include "pthread_spin_lock.c"
+#include "pthread_spin_unlock.c"
+#include "pthread_spin_trylock.c"
diff --git a/libs/pthreads/src/sync.c b/libs/pthreads/src/sync.c
new file mode 100644
index 0000000000..5e56fa9a1f
--- /dev/null
+++ b/libs/pthreads/src/sync.c
@@ -0,0 +1,43 @@
+/*
+ * sync.c
+ *
+ * Description:
+ * This translation unit implements functions related to thread
+ * synchronisation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#include "pthread_detach.c"
+#include "pthread_join.c"
diff --git a/libs/pthreads/src/tsd.c b/libs/pthreads/src/tsd.c
new file mode 100644
index 0000000000..ed44fe6cb4
--- /dev/null
+++ b/libs/pthreads/src/tsd.c
@@ -0,0 +1,44 @@
+/*
+ * tsd.c
+ *
+ * Description:
+ * POSIX thread functions which implement thread-specific data (TSD).
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#include "pthread_key_create.c"
+#include "pthread_key_delete.c"
+#include "pthread_setspecific.c"
+#include "pthread_getspecific.c"
diff --git a/libs/pthreads/src/w32_CancelableWait.c b/libs/pthreads/src/w32_CancelableWait.c
new file mode 100644
index 0000000000..070633e0f9
--- /dev/null
+++ b/libs/pthreads/src/w32_CancelableWait.c
@@ -0,0 +1,161 @@
+/*
+ * w32_CancelableWait.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+static INLINE int
+ptw32_cancelable_wait (HANDLE waitHandle, DWORD timeout)
+ /*
+ * -------------------------------------------------------------------
+ * This provides an extra hook into the pthread_cancel
+ * mechanism that will allow you to wait on a Windows handle and make it a
+ * cancellation point. This function blocks until the given WIN32 handle is
+ * signaled or pthread_cancel has been called. It is implemented using
+ * WaitForMultipleObjects on 'waitHandle' and a manually reset WIN32
+ * event used to implement pthread_cancel.
+ *
+ * Given this hook it would be possible to implement more of the cancellation
+ * points.
+ * -------------------------------------------------------------------
+ */
+{
+ int result;
+ pthread_t self;
+ ptw32_thread_t * sp;
+ HANDLE handles[2];
+ DWORD nHandles = 1;
+ DWORD status;
+
+ handles[0] = waitHandle;
+
+ self = pthread_self();
+ sp = (ptw32_thread_t *) self.p;
+
+ if (sp != NULL)
+ {
+ /*
+ * Get cancelEvent handle
+ */
+ if (sp->cancelState == PTHREAD_CANCEL_ENABLE)
+ {
+
+ if ((handles[1] = sp->cancelEvent) != NULL)
+ {
+ nHandles++;
+ }
+ }
+ }
+ else
+ {
+ handles[1] = NULL;
+ }
+
+ status = WaitForMultipleObjects (nHandles, handles, PTW32_FALSE, timeout);
+
+ switch (status - WAIT_OBJECT_0)
+ {
+ case 0:
+ /*
+ * Got the handle.
+ * In the event that both handles are signalled, the smallest index
+ * value (us) is returned. As it has been arranged, this ensures that
+ * we don't drop a signal that we should act on (i.e. semaphore,
+ * mutex, or condition variable etc).
+ */
+ result = 0;
+ break;
+
+ case 1:
+ /*
+ * Got cancel request.
+ * In the event that both handles are signaled, the cancel will
+ * be ignored (see case 0 comment).
+ */
+ ResetEvent (handles[1]);
+
+ if (sp != NULL)
+ {
+ ptw32_mcs_local_node_t stateLock;
+ /*
+ * Should handle POSIX and implicit POSIX threads..
+ * Make sure we haven't been async-canceled in the meantime.
+ */
+ ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
+ if (sp->state < PThreadStateCanceling)
+ {
+ sp->state = PThreadStateCanceling;
+ sp->cancelState = PTHREAD_CANCEL_DISABLE;
+ ptw32_mcs_lock_release (&stateLock);
+ ptw32_throw (PTW32_EPS_CANCEL);
+
+ /* Never reached */
+ }
+ ptw32_mcs_lock_release (&stateLock);
+ }
+
+ /* Should never get to here. */
+ result = EINVAL;
+ break;
+
+ default:
+ if (status == WAIT_TIMEOUT)
+ {
+ result = ETIMEDOUT;
+ }
+ else
+ {
+ result = EINVAL;
+ }
+ break;
+ }
+
+ return (result);
+
+} /* CancelableWait */
+
+int
+pthreadCancelableWait (HANDLE waitHandle)
+{
+ return (ptw32_cancelable_wait (waitHandle, INFINITE));
+}
+
+int
+pthreadCancelableTimedWait (HANDLE waitHandle, DWORD timeout)
+{
+ return (ptw32_cancelable_wait (waitHandle, timeout));
+}
diff --git a/libs/win32/libjson.lib b/libs/win32/libjson.lib
index 933a1a240e..b7787d39d1 100644
--- a/libs/win32/libjson.lib
+++ b/libs/win32/libjson.lib
Binary files differ
diff --git a/libs/win32/mir_app.lib b/libs/win32/mir_app.lib
index 98c7ad2967..1ad4944bc5 100644
--- a/libs/win32/mir_app.lib
+++ b/libs/win32/mir_app.lib
Binary files differ
diff --git a/libs/win32/mir_core.lib b/libs/win32/mir_core.lib
index 2e3ef00691..cb83c2c2b2 100644
--- a/libs/win32/mir_core.lib
+++ b/libs/win32/mir_core.lib
Binary files differ
diff --git a/libs/win64/libjson.lib b/libs/win64/libjson.lib
index 840159782d..75de0f2cab 100644
--- a/libs/win64/libjson.lib
+++ b/libs/win64/libjson.lib
Binary files differ
diff --git a/libs/win64/mir_app.lib b/libs/win64/mir_app.lib
index a24d42c3c8..3a4f05d465 100644
--- a/libs/win64/mir_app.lib
+++ b/libs/win64/mir_app.lib
Binary files differ
diff --git a/libs/win64/mir_core.lib b/libs/win64/mir_core.lib
index c1328f007e..189b02e354 100644
--- a/libs/win64/mir_core.lib
+++ b/libs/win64/mir_core.lib
Binary files differ
diff --git a/plugins/AVS/src/main.cpp b/plugins/AVS/src/main.cpp
index 766c758af6..c082c6d43e 100644
--- a/plugins/AVS/src/main.cpp
+++ b/plugins/AVS/src/main.cpp
@@ -71,7 +71,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/AVS/src/version.h b/plugins/AVS/src/version.h
index 0475c9ef0c..3473705c14 100644
--- a/plugins/AVS/src/version.h
+++ b/plugins/AVS/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "AVS.dll"
#define __DESCRIPTION "Loads and manages contact pictures for other plugins."
#define __AUTHOR "Nightwish, Pescuma"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/AVS/"
#define __COPYRIGHT "© 2000-2012 Miranda-IM project, 2012-17 Miranda NG team"
diff --git a/plugins/Actman/actman.dpr b/plugins/Actman/actman.dpr
index 3608e7d906..c22251e46a 100644
--- a/plugins/Actman/actman.dpr
+++ b/plugins/Actman/actman.dpr
@@ -76,7 +76,6 @@ begin
PluginInfo.description:='Plugin for manage hotkeys to open contact window, insert text, '+
'run program and call services';
PluginInfo.author :='Awkward';
- PluginInfo.authorEmail:='panda75@bk.ru; awk1975@ya.ru';
PluginInfo.copyright :='(c) 2007-2013 Awkward';
PluginInfo.homepage :='http://code.google.com/p/delphi-miranda-plugins/';
PluginInfo.flags :=UNICODE_AWARE;
diff --git a/plugins/AddContactPlus/src/addcontact.cpp b/plugins/AddContactPlus/src/addcontact.cpp
index 85bab9265a..44ce81bad8 100644
--- a/plugins/AddContactPlus/src/addcontact.cpp
+++ b/plugins/AddContactPlus/src/addcontact.cpp
@@ -25,7 +25,6 @@ struct AddDialogParam : public MZeroedObject
{
AddDialogParam() {}
- int handleType;
HANDLE handle;
CMStringA proto;
PROTOSEARCHRESULT *psr;
@@ -155,7 +154,6 @@ INT_PTR CALLBACK AddContactDlgProc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM)
switch (msg) {
case WM_INITDIALOG:
acs = new AddDialogParam();
- acs->handleType = HANDLE_SEARCHRESULT;
SetWindowLongPtr(hdlg, GWLP_USERDATA, (LONG_PTR)acs);
Utils_RestoreWindowPositionNoSize(hdlg, NULL, "AddContact", "");
diff --git a/plugins/AddContactPlus/src/main.cpp b/plugins/AddContactPlus/src/main.cpp
index cfe6f2e09c..0220d8cdf9 100644
--- a/plugins/AddContactPlus/src/main.cpp
+++ b/plugins/AddContactPlus/src/main.cpp
@@ -39,7 +39,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/AddContactPlus/src/stdafx.h b/plugins/AddContactPlus/src/stdafx.h
index db8647b8b6..bd1c6996d8 100644
--- a/plugins/AddContactPlus/src/stdafx.h
+++ b/plugins/AddContactPlus/src/stdafx.h
@@ -32,7 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <m_langpack.h>
#include <m_message.h>
#include <m_protosvc.h>
-#include <m_addcontact.h>
+#include <m_contacts.h>
#include <m_string.h>
#include "m_toptoolbar.h"
diff --git a/plugins/AddContactPlus/src/version.h b/plugins/AddContactPlus/src/version.h
index b713e1b69f..e80935759d 100644
--- a/plugins/AddContactPlus/src/version.h
+++ b/plugins/AddContactPlus/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "AddContactPlus.dll"
#define __DESCRIPTION "Provides the ability to quickly add new contacts."
#define __AUTHOR "Bartosz 'Dezeath' Białek"
-#define __AUTHOREMAIL "dezred@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/AddContactPlus/"
#define __COPYRIGHT "© 2007-17 Bartosz 'Dezeath' Białek, Miranda NG Team"
diff --git a/plugins/AdvaImg/src/main.cpp b/plugins/AdvaImg/src/main.cpp
index d2294db9a9..9becaa631c 100644
--- a/plugins/AdvaImg/src/main.cpp
+++ b/plugins/AdvaImg/src/main.cpp
@@ -41,7 +41,6 @@ static const PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE | STATIC_PLUGIN,
diff --git a/plugins/AdvaImg/src/version.h b/plugins/AdvaImg/src/version.h
index e2da56456d..7fd84ae00a 100644
--- a/plugins/AdvaImg/src/version.h
+++ b/plugins/AdvaImg/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "AdvaImg.dll"
#define __DESCRIPTION "Generic image services for Miranda NG."
#define __AUTHOR "Nightwish, The FreeImage project (http://freeimage.sourceforge.net/)"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/AdvaImg/"
#define __COPYRIGHT "© 2000-2012 Miranda-IM project, 2012-17 Miranda NG project uses the FreeImage distribution"
diff --git a/plugins/Alarms/src/alarms.cpp b/plugins/Alarms/src/alarms.cpp
index 0e3139bc50..81de39ed09 100644
--- a/plugins/Alarms/src/alarms.cpp
+++ b/plugins/Alarms/src/alarms.cpp
@@ -30,7 +30,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Alarms/src/version.h b/plugins/Alarms/src/version.h
index 3c291c46d3..682c6f7df3 100755
--- a/plugins/Alarms/src/version.h
+++ b/plugins/Alarms/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Alarms.dll"
#define __DESCRIPTION "Sets once-off, daily, weekly and weekday alarms."
#define __AUTHOR "Scott Ellis"
-#define __AUTHOREMAIL "mail@scottellis.com.au"
#define __AUTHORWEB "https://miranda-ng.org/p/Alarms/"
#define __COPYRIGHT "© 2005 Scott Ellis"
diff --git a/plugins/AsSingleWindow/src/AsSingleWindow.cpp b/plugins/AsSingleWindow/src/AsSingleWindow.cpp
index 371db5e7f3..a2447bdd7b 100644
--- a/plugins/AsSingleWindow/src/AsSingleWindow.cpp
+++ b/plugins/AsSingleWindow/src/AsSingleWindow.cpp
@@ -13,7 +13,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/AsSingleWindow/src/version.h b/plugins/AsSingleWindow/src/version.h
index 751dc2b189..e482a3d770 100644
--- a/plugins/AsSingleWindow/src/version.h
+++ b/plugins/AsSingleWindow/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "AsSingleWindow.dll"
#define __DESCRIPTION "Allows you to move, minimize and activate Miranda's windows as if it were a single window."
#define __AUTHOR "Aleksey Smyrnov aka Soar"
-#define __AUTHOREMAIL "i@soar.name"
#define __AUTHORWEB "https://miranda-ng.org/p/AsSingleWindow/"
#define __COPYRIGHT "© 2010-2011 Soar, 2017 Miranda NG team"
diff --git a/plugins/AssocMgr/src/main.cpp b/plugins/AssocMgr/src/main.cpp
index 5f7d515073..a5287b7a4c 100644
--- a/plugins/AssocMgr/src/main.cpp
+++ b/plugins/AssocMgr/src/main.cpp
@@ -33,7 +33,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/AssocMgr/src/test.cpp b/plugins/AssocMgr/src/test.cpp
index 1175e20807..cce177b15f 100644
--- a/plugins/AssocMgr/src/test.cpp
+++ b/plugins/AssocMgr/src/test.cpp
@@ -23,7 +23,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "stdafx.h"
/*
-#define AIM_SUPPORT_TEST
#define ICQ_SUPPORT_TEST
#define YAHOO_SUPPORT_TEST
#define MSN_SUPPORT_TEST
@@ -66,138 +65,6 @@ static int __inline AssocMgr_AddNewUrlType(const char *prefix, const char *desc,
// -----------------------------------------
-#ifdef AIM_SUPPORT_TEST
-
-#define AIM_PROTOCOL_NAME "AIM"
-#define IDI_AOL 28
-#define MOD_KEY_CL "CList"
-#define AIM_KEY_NL "NotOnList"
-struct oscar_data { HINSTANCE hInstance; } static conn;
-static __inline HANDLE find_contact(const char *nick) { nick; return NULL; }
-static __inline HANDLE add_contact(const char *nick) { nick; return db_find_first(); }
-static __inline void aim_gchat_joinrequest(const char *room, int exchange) { room; exchange; MessageBoxA(NULL, "Join group chat!", room, MB_OK); return; }
-#include <m_protosvc.h>
-#include <m_message.h>
-
-#include "m_assocmgr.h"
-static HANDLE hHookModulesLoaded;
-static HANDLE hServiceParseLink;
-
-static int ServiceParseAimLink(WPARAM, LPARAM lParam)
-{
- char *arg = (char*)lParam;
- if (arg == NULL) return 1; /* sanity check */
- /* skip leading prefix */
- arg = strchr(arg, ':');
- if (arg == NULL) return 1; /* parse failed */
- for (++arg; *arg == '/'; ++arg);
- /*
- add user: aim:addbuddy?screenname=NICK&groupname=GROUP
- send message: aim:goim?screenname=NICK&message=MSG
- open chatroom: aim:gochat?roomname=ROOM&exchange=NUM
- */
- /* add a contact to the list */
- if (!_strnicmp(arg, "addbuddy?", 9)) {
- char *tok, *sn = NULL, *group = NULL;
- ADDCONTACTSTRUCT acs;
- PROTOSEARCHRESULT psr;
- if (*(arg += 9) == 0) return 1; /* parse failed */
- tok = strtok(arg, "&"); /* first token */
- while (tok != NULL) {
- if (!_strnicmp(tok, "screenname=", 11) && *(tok + 11) != 0)
- sn = Netlib_UrlDecode(tok + 11);
- if (!_strnicmp(tok, "groupname=", 10) && *(tok + 10) != 0)
- group = Netlib_UrlDecode(tok + 10); /* group is currently ignored */
- tok = strtok(NULL, "&"); /* next token */
- }
- if (sn == NULL) return 1; /* parse failed */
- if (find_contact(sn) == NULL) { /* does not yet check if sn is current user */
- acs.handleType = HANDLE_SEARCHRESULT;
- acs.szProto = AIM_PROTOCOL_NAME;
- acs.psr = &psr;
- memset(&psr, 0, sizeof(PROTOSEARCHRESULT));
- psr.cbSize = sizeof(PROTOSEARCHRESULT);
- psr.nick.w = sn;
- CallService(MS_ADDCONTACT_SHOW, 0, (LPARAM)&acs);
- }
- return 0;
- }
- /* send a message to a contact */
- else if (!_strnicmp(arg, "goim?", 5)) {
- char *tok, *sn = NULL, *msg = NULL;
- MCONTACT hContact;
- if (*(arg += 5) == 0) return 1; /* parse failed */
- tok = strtok(arg, "&"); /* first token */
- while (tok != NULL) {
- if (!_strnicmp(tok, "screenname=", 11) && *(tok + 11) != 0)
- sn = Netlib_UrlDecode(tok + 11);
- if (!_strnicmp(tok, "message=", 8) && *(tok + 8) != 0)
- msg = Netlib_UrlDecode(tok + 8);
- tok = strtok(NULL, "&"); /* next token */
- }
- if (sn == NULL) return 1; /* parse failed */
- if (ServiceExists(MS_MSG_SENDMESSAGE)) {
- hContact = find_contact(sn);
- if (hContact == NULL) {
- hContact = add_contact(sn); /* does not yet check if sn is current user */
- if (hContact != NULL)
- db_set_b(hContact, MOD_KEY_CL, AIM_KEY_NL, 1);
- }
- if (hContact != NULL)
- CallService(MS_MSG_SENDMESSAGE, hContact, (LPARAM)msg);
- }
- return 0;
- }
- /* open a chatroom */
- else if (!_strnicmp(arg, "gochat?", 7)) {
- char *tok, *rm = NULL;
- int exchange = 0;
- if (*(arg += 7) == 0) return 1; /* parse failed */
- tok = strtok(arg, "&"); /* first token */
- while (tok != NULL) {
- if (!_strnicmp(tok, "roomname=", 9) && *(tok + 9) != 0)
- rm = Netlib_UrlDecode(tok + 9);
- if (!_strnicmp(tok, "exchange=", 9))
- exchange = atoi(Netlib_UrlDecode(tok + 9));
- tok = strtok(NULL, "&"); /* next token */
- }
- if (rm == NULL || exchange <= 0) return 1; /* parse failed */
- aim_gchat_joinrequest(rm, exchange);
- return 0;
- }
- return 1; /* parse failed */
-}
-
-static int AimLinksModulesLoaded(WPARAM wParam, LPARAM lParam)
-{
- char service_name[MAXMODULELABELLENGTH];
- UNREFERENCED_PARAMETER(wParam);
- UNREFERENCED_PARAMETER(lParam);
- mir_snprintf(service_name, _countof(service_name), "%s%s", AIM_PROTOCOL_NAME, "ParseAimLink");
- /* or "AOL Instant Messenger Links" */
- AssocMgr_AddNewUrlType("aim:", Translate("AIM link protocol"), conn.hInstance, IDI_AOL, service_name, 0);
- return 0;
-}
-
-void aim_links_init()
-{
- char service_name[MAXMODULELABELLENGTH];
- //LOG(LOG_DEBUG,"Links: init");
- mir_snprintf(service_name, _countof(service_name), "%s%s", AIM_PROTOCOL_NAME, "ParseAimLink");
- hServiceParseLink = CreateServiceFunction(service_name, ServiceParseAimLink);
- hHookModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, AimLinksModulesLoaded);
-}
-
-void aim_links_destroy()
-{
- //LOG(LOG_DEBUG,"Links: destroy");
- UnhookEvent(hHookModulesLoaded);
- DestroyServiceFunction(hServiceParseLink);
-}
-#endif
-
-// -----------------------------------------
-
#ifdef ICQ_SUPPORT_TEST
#define gpszICQProtoName "ICQ"
@@ -808,10 +675,6 @@ int JabberLinksUninit()
void InitTest(void)
{
- #ifdef AIM_SUPPORT_TEST
- conn.hInstance = GetModuleHandleA("AIM");
- aim_links_init();
- #endif
#ifdef ICQ_SUPPORT_TEST
InitIcqFiles();
#endif
@@ -833,9 +696,6 @@ void InitTest(void)
void UninitTest(void)
{
- #ifdef AIM_SUPPORT_TEST
- aim_links_destroy();
- #endif
#ifdef ICQ_SUPPORT_TEST
UninitIcqFiles();
#endif
diff --git a/plugins/AssocMgr/src/version.h b/plugins/AssocMgr/src/version.h
index a44ef73797..34cd557e93 100644
--- a/plugins/AssocMgr/src/version.h
+++ b/plugins/AssocMgr/src/version.h
@@ -28,8 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define __PLUGIN_NAME "File association manager"
#define __FILENAME "AssocMgr.dll"
-#define __DESCRIPTION "Handles file type associations and URLs like aim, gg, mirpu, wpmsg, xmpp, ymsgr."
+#define __DESCRIPTION "Handles file type associations and URLs like gg, mirpu, wpmsg, xmpp, ymsgr."
#define __AUTHOR "H. Herkenrath"
-#define __AUTHOREMAIL "hrathh@users.sourceforge.net"
#define __AUTHORWEB "https://miranda-ng.org/p/AssocMgr/"
#define __COPYRIGHT "© 2005-2007 H. Herkenrath"
diff --git a/plugins/AuthState/src/main.cpp b/plugins/AuthState/src/main.cpp
index db2de1db13..25f3810ac0 100644
--- a/plugins/AuthState/src/main.cpp
+++ b/plugins/AuthState/src/main.cpp
@@ -47,7 +47,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/AuthState/src/version.h b/plugins/AuthState/src/version.h
index 2c5e7c555e..4150d6ab48 100644
--- a/plugins/AuthState/src/version.h
+++ b/plugins/AuthState/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "AuthState.dll"
#define __DESCRIPTION "If a contact didn't authorize you, this plugin puts an icon in front of the contact's name."
#define __AUTHOR "Thief, idea by snwbrdr"
-#define __AUTHOREMAIL "thief@miranda.im"
#define __AUTHORWEB "https://miranda-ng.org/p/AuthState/"
#define __COPYRIGHT "© 2006-2010 Alexander Turyak"
diff --git a/plugins/AutoRun/src/main.cpp b/plugins/AutoRun/src/main.cpp
index 559f636240..3ff33f1192 100644
--- a/plugins/AutoRun/src/main.cpp
+++ b/plugins/AutoRun/src/main.cpp
@@ -10,7 +10,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/AutoRun/src/version.h b/plugins/AutoRun/src/version.h
index f20a747e70..c3cc5bf0d3 100644
--- a/plugins/AutoRun/src/version.h
+++ b/plugins/AutoRun/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "AutoRun.dll"
#define __DESCRIPTION "This plugin is a simple way to enable/disable to launch Miranda NG with system startup."
#define __AUTHOR "Sergey V. Gershovich a.k.a. Jazzy$ (fixed by Wolfram3D)"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/AutoRun/"
#define __COPYRIGHT "© 2002-2007 Sergey V. Gershovich a.k.a. Jazzy$"
diff --git a/plugins/AutoShutdown/src/main.cpp b/plugins/AutoShutdown/src/main.cpp
index 2d68004d38..8f7b49e539 100644
--- a/plugins/AutoShutdown/src/main.cpp
+++ b/plugins/AutoShutdown/src/main.cpp
@@ -30,7 +30,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/AutoShutdown/src/version.h b/plugins/AutoShutdown/src/version.h
index f5d42980ae..70bd98da09 100644
--- a/plugins/AutoShutdown/src/version.h
+++ b/plugins/AutoShutdown/src/version.h
@@ -30,6 +30,5 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define __FILENAME "AutoShutdown.dll"
#define __DESCRIPTION "Adds the possibility to shutdown the computer when a specified event occurs."
#define __AUTHOR "H. Herkenrath"
-#define __AUTHOREMAIL "hrathh@users.sourceforge.net"
#define __AUTHORWEB "https://miranda-ng.org/p/AutoShutdown/"
#define __COPYRIGHT "© 2004-2007 H. Herkenrath"
diff --git a/plugins/AvatarHistory/src/AvatarHistory.cpp b/plugins/AvatarHistory/src/AvatarHistory.cpp
index cc4704a7c2..3e1d86f3f8 100644
--- a/plugins/AvatarHistory/src/AvatarHistory.cpp
+++ b/plugins/AvatarHistory/src/AvatarHistory.cpp
@@ -49,7 +49,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/AvatarHistory/src/version.h b/plugins/AvatarHistory/src/version.h
index e5d722027d..1845c37b13 100644
--- a/plugins/AvatarHistory/src/version.h
+++ b/plugins/AvatarHistory/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "AvatarHistory.dll"
#define __DESCRIPTION "This plugin keeps backups of all your contacts' avatar changes and/or shows popups."
#define __AUTHOR "Matthew Wild (MattJ), Ricardo Pescuma Domenecci"
-#define __AUTHOREMAIL "mwild1@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/AvatarHistory/"
#define __COPYRIGHT "© 2006-2012 Matthew Wild, Ricardo Pescuma Domenecci"
diff --git a/plugins/BASS_interface/src/Main.cpp b/plugins/BASS_interface/src/Main.cpp
index 372bfb8d1a..a7277ed097 100644
--- a/plugins/BASS_interface/src/Main.cpp
+++ b/plugins/BASS_interface/src/Main.cpp
@@ -40,7 +40,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/BASS_interface/src/version.h b/plugins/BASS_interface/src/version.h
index 0e5ddf90f1..3e759149d5 100644
--- a/plugins/BASS_interface/src/version.h
+++ b/plugins/BASS_interface/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "BASS_interface.dll"
#define __DESCRIPTION "Un4seen's BASS interface Miranda NG plugin."
#define __AUTHOR "tico-tico"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/BASS_interface/"
#define __COPYRIGHT "© 2010, 2011 tico-tico"
diff --git a/plugins/BasicHistory/res/BasicHistory.rc b/plugins/BasicHistory/res/BasicHistory.rc
index c32965b95b..3cc23aeebf 100644
--- a/plugins/BasicHistory/res/BasicHistory.rc
+++ b/plugins/BasicHistory/res/BasicHistory.rc
@@ -150,7 +150,7 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
EXSTYLE WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
- GROUPBOX "Export to txt",IDC_STATIC,4,5,298,37
+ GROUPBOX "Export to text file",IDC_STATIC,4,5,298,37
COMBOBOX IDC_TXTENC,142,20,152,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
LTEXT "File encoding*",IDC_STATIC,12,23,115,8
GROUPBOX "Export to plain HTML",IDC_STATIC,4,47,298,50
diff --git a/plugins/BasicHistory/src/BasicHistory.cpp b/plugins/BasicHistory/src/BasicHistory.cpp
index ee6d36e9a7..9240b619aa 100644
--- a/plugins/BasicHistory/src/BasicHistory.cpp
+++ b/plugins/BasicHistory/src/BasicHistory.cpp
@@ -45,7 +45,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/BasicHistory/src/Options.cpp b/plugins/BasicHistory/src/Options.cpp
index abb6c6dcf2..900ff701a1 100644
--- a/plugins/BasicHistory/src/Options.cpp
+++ b/plugins/BasicHistory/src/Options.cpp
@@ -220,7 +220,7 @@ static HotkeyOptionsList g_HotkeyOptionsList[] = {
{ "basichistory_hot_delete", LPGENW("Delete"), LPGENW("History"), nullptr, VK_DELETE, HISTORY_HK_DELETE },
{ "basichistory_hot_exrhtml", LPGENW("Export to rich HTML"), LPGENW("History"), nullptr, 0, HISTORY_HK_EXRHTML },
{ "basichistory_hot_exphtml", LPGENW("Export to plain HTML"), LPGENW("History"), nullptr, 0, HISTORY_HK_EXPHTML },
- { "basichistory_hot_extxt", LPGENW("Export to txt"), LPGENW("History"), nullptr, 0, HISTORY_HK_EXTXT },
+ { "basichistory_hot_extxt", LPGENW("Export to text file"), LPGENW("History"), nullptr, 0, HISTORY_HK_EXTXT },
{ "basichistory_hot_exbin", LPGENW("Export to binary"), LPGENW("History"), nullptr, 0, HISTORY_HK_EXBIN },
{ "basichistory_hot_impbin", LPGENW("Import from binary"), LPGENW("History"), nullptr, 0, HISTORY_HK_IMPBIN },
{ "basichistory_hot_exdat", LPGENW("Export to dat (mContacts)"), LPGENW("History"), nullptr, 0, HISTORY_HK_EXDAT },
diff --git a/plugins/BasicHistory/src/version.h b/plugins/BasicHistory/src/version.h
index c35aa19fb6..c5dd484953 100644
--- a/plugins/BasicHistory/src/version.h
+++ b/plugins/BasicHistory/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "BasicHistory.dll"
#define __DESCRIPTION "History viewer for Miranda NG."
#define __AUTHOR "Krzysztof Kral"
-#define __AUTHOREMAIL "krzysztof.kral@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/BasicHistory/"
#define __COPYRIGHT "© 2011-2012 Krzysztof Kral"
diff --git a/plugins/Boltun/src/boltun.cpp b/plugins/Boltun/src/boltun.cpp
index c0efda901f..09e2949a95 100644
--- a/plugins/Boltun/src/boltun.cpp
+++ b/plugins/Boltun/src/boltun.cpp
@@ -38,7 +38,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Boltun/src/version.h b/plugins/Boltun/src/version.h
index 7b357643f1..2597b1cf34 100644
--- a/plugins/Boltun/src/version.h
+++ b/plugins/Boltun/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Boltun.dll"
#define __DESCRIPTION "Boltun, the chat bot in the russian language."
#define __AUTHOR "Alexander S. Kiselev, Valentin Pavlyuchenko"
-#define __AUTHOREMAIL "Valentin.Pavlyuchenko@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/Boltun/"
#define __COPYRIGHT "© 2003-2008 Alexander S. Kiselev A.K.A. KAS, Valentin Pavlyuchenko"
diff --git a/plugins/BossKeyPlus/src/BossKey.cpp b/plugins/BossKeyPlus/src/BossKey.cpp
index 9d7df65878..f5b7dfca1a 100644
--- a/plugins/BossKeyPlus/src/BossKey.cpp
+++ b/plugins/BossKeyPlus/src/BossKey.cpp
@@ -47,7 +47,6 @@ static PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/BossKeyPlus/src/version.h b/plugins/BossKeyPlus/src/version.h
index e945144c80..8bae3d9f5d 100644
--- a/plugins/BossKeyPlus/src/version.h
+++ b/plugins/BossKeyPlus/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "BossKey.dll"
#define __DESCRIPTION "Anti-Boss plugin. Makes your Miranda NG hidden or password-protected."
#define __AUTHOR "Goblineye Entertainment, Billy_Bons"
-#define __AUTHOREMAIL "tatarinov.sergey@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/BossKey/"
#define __COPYRIGHT "© 2002-2003 Goblineye Entertainment, 2007-2010 Billy_Bons"
diff --git a/plugins/BuddyExpectator/src/BuddyExpectator.cpp b/plugins/BuddyExpectator/src/BuddyExpectator.cpp
index d8b1ef3749..23ff90150d 100644
--- a/plugins/BuddyExpectator/src/BuddyExpectator.cpp
+++ b/plugins/BuddyExpectator/src/BuddyExpectator.cpp
@@ -44,7 +44,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/BuddyExpectator/src/version.h b/plugins/BuddyExpectator/src/version.h
index 1fa45b1cbd..b273356d67 100644
--- a/plugins/BuddyExpectator/src/version.h
+++ b/plugins/BuddyExpectator/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "BuddyExpectator.dll"
#define __DESCRIPTION "Reacts to the return of contacts, or to the extended absence of contacts, with notifications and other actions."
#define __AUTHOR "Anar Ibragimoff, sje, Thief"
-#define __AUTHOREMAIL "thief@miranda.im"
#define __AUTHORWEB "https://miranda-ng.org/p/BuddyExpectator/"
#define __COPYRIGHT "© 2005 Anar Ibragimoff, 2006 Scott Ellis, 2007-2009 Alexander Turyak"
diff --git a/plugins/BuddyPounce/src/main.cpp b/plugins/BuddyPounce/src/main.cpp
index 250e76658f..7b9a7d2087 100644
--- a/plugins/BuddyPounce/src/main.cpp
+++ b/plugins/BuddyPounce/src/main.cpp
@@ -11,7 +11,6 @@ PLUGININFOEX pluginInfo={
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/BuddyPounce/src/version.h b/plugins/BuddyPounce/src/version.h
index 2d34dbc48c..a6bd8c6de4 100644
--- a/plugins/BuddyPounce/src/version.h
+++ b/plugins/BuddyPounce/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "BuddyPounce.dll"
#define __DESCRIPTION "Allows you to send a message to contacts if they change status."
#define __AUTHOR "Jonathan Gordon"
-#define __AUTHOREMAIL "jdgordy@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/BuddyPounce/"
#define __COPYRIGHT "© 2004 Jonathan Gordon"
diff --git a/plugins/CSList/src/cslist.cpp b/plugins/CSList/src/cslist.cpp
index eda2793387..d90e0181d4 100644
--- a/plugins/CSList/src/cslist.cpp
+++ b/plugins/CSList/src/cslist.cpp
@@ -1,28 +1,28 @@
/* ========================================================================
- Custom Status List
- __________________
-
- Custom Status List plugin for Miranda-IM (www.miranda-im.org)
- Follower of Custom Status History List by HANAX
- Copyright © 2006-2008 HANAX
- Copyright © 2007-2009 jarvis
- Occasionally rewritten in 2012 by George Hazan
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- ======================================================================== */
+Custom Status List
+__________________
+
+Custom Status List plugin for Miranda-IM (www.miranda-im.org)
+Follower of Custom Status History List by HANAX
+Copyright © 2006-2008 HANAX
+Copyright © 2007-2009 jarvis
+Occasionally rewritten in 2012 by George Hazan
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+======================================================================== */
#include "stdafx.h"
#include "strpos.h"
@@ -40,7 +40,6 @@ PLUGININFOEX pluginInfoEx =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/CSList/src/version.h b/plugins/CSList/src/version.h
index 5f304453c5..075828514c 100644
--- a/plugins/CSList/src/version.h
+++ b/plugins/CSList/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "CSList.dll"
#define __DESCRIPTION "This plugin offers simple management functions to keep your extra statuses on one place."
#define __AUTHOR "Mataes, jarvis"
-#define __AUTHOREMAIL "mataes2007@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/CSList/"
#define __COPYRIGHT "© 2010-17 Mataes, 2007-09 jarvis"
diff --git a/plugins/ChangeKeyboardLayout/src/main.cpp b/plugins/ChangeKeyboardLayout/src/main.cpp
index 7aeb901eeb..5286a2f871 100644
--- a/plugins/ChangeKeyboardLayout/src/main.cpp
+++ b/plugins/ChangeKeyboardLayout/src/main.cpp
@@ -17,7 +17,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/ChangeKeyboardLayout/src/version.h b/plugins/ChangeKeyboardLayout/src/version.h
index 6af003e08e..7e728b45e1 100644
--- a/plugins/ChangeKeyboardLayout/src/version.h
+++ b/plugins/ChangeKeyboardLayout/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "ChangeKeyboardLayout.dll"
#define __DESCRIPTION "Plugin for changing keyboard layout of text (multilayout)."
#define __AUTHOR "Yasnovidyashii"
-#define __AUTHOREMAIL "Yasnovidyashii@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/ChangeKeyboardLayout/"
#define __COPYRIGHT "© 2006-2009 Mikhail Yur'ev"
diff --git a/plugins/ClientChangeNotify/src/ClientChangeNotify.cpp b/plugins/ClientChangeNotify/src/ClientChangeNotify.cpp
index 05a4423f30..13d278ad16 100644
--- a/plugins/ClientChangeNotify/src/ClientChangeNotify.cpp
+++ b/plugins/ClientChangeNotify/src/ClientChangeNotify.cpp
@@ -34,7 +34,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/ClientChangeNotify/src/version.h b/plugins/ClientChangeNotify/src/version.h
index c47192ad2f..1c2ba5b5d1 100644
--- a/plugins/ClientChangeNotify/src/version.h
+++ b/plugins/ClientChangeNotify/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "ClientChangeNotify.dll"
#define __DESCRIPTION "Shows a notification when someone in your contact list changes his client."
#define __AUTHOR "Deathdemon"
-#define __AUTHOREMAIL "dchervov@yahoo.com"
#define __AUTHORWEB "https://miranda-ng.org/p/ClientChangeNotify/"
#define __COPYRIGHT "© 2006-2008 Chervov Dmitry"
diff --git a/plugins/Clist_blind/src/init.cpp b/plugins/Clist_blind/src/init.cpp
index 2d9bc0046c..d26e31f06c 100644
--- a/plugins/Clist_blind/src/init.cpp
+++ b/plugins/Clist_blind/src/init.cpp
@@ -69,7 +69,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Clist_blind/src/version.h b/plugins/Clist_blind/src/version.h
index acdb1e35d7..fe89420bb4 100644
--- a/plugins/Clist_blind/src/version.h
+++ b/plugins/Clist_blind/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Clist_blind.dll"
#define __DESCRIPTION "A contact list for blind folks."
#define __AUTHOR "Ricardo Pescuma Domenecci, based on previous work from Miranda IM project"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/Clist_blind/"
#define __COPYRIGHT "© 2000-2009 Miranda IM project, Ricardo Pescuma Domenecci, 2013-17 Miranda NG project"
diff --git a/plugins/Clist_modern/src/init.cpp b/plugins/Clist_modern/src/init.cpp
index 93ba4e9d21..7adc9acd78 100644
--- a/plugins/Clist_modern/src/init.cpp
+++ b/plugins/Clist_modern/src/init.cpp
@@ -48,7 +48,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Clist_modern/src/version.h b/plugins/Clist_modern/src/version.h
index 31af1f54d3..4d7628f1f1 100644
--- a/plugins/Clist_modern/src/version.h
+++ b/plugins/Clist_modern/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Clist_modern.dll"
#define __DESCRIPTION "Displays contacts, event notifications, protocol status with advanced visual modifications. Supported multi-window modifications, enhanced metacontact cooperation."
#define __AUTHOR "Artem Shpynov, Ricardo Pescuma Domenecci and Anton Senko based on clist_mw by Bethoven"
-#define __AUTHOREMAIL "ashpynov@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/Clist_modern/"
#define __COPYRIGHT "© 2000-2010 Miranda-IM project"
diff --git a/plugins/Clist_nicer/src/clistmenus.cpp b/plugins/Clist_nicer/src/clistmenus.cpp
index 5076f93f09..f1a57c2dac 100644
--- a/plugins/Clist_nicer/src/clistmenus.cpp
+++ b/plugins/Clist_nicer/src/clistmenus.cpp
@@ -173,13 +173,8 @@ static INT_PTR CALLBACK IgnoreDialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPA
break;
case IDC_IGN_ADDPERMANENTLY:
- {
- ADDCONTACTSTRUCT acs = { 0 };
- acs.hContact = hContact;
- acs.handleType = HANDLE_CONTACT;
- CallService(MS_ADDCONTACT_SHOW, (WPARAM)hWnd, (LPARAM)&acs);
- Utils::enableDlgControl(hWnd, IDC_IGN_ADDPERMANENTLY, db_get_b(hContact, "CList", "NotOnList", 0));
- }
+ Contact_Add(hContact, hWnd);
+ Utils::enableDlgControl(hWnd, IDC_IGN_ADDPERMANENTLY, db_get_b(hContact, "CList", "NotOnList", 0));
break;
case IDC_DSP_LOADDEFAULT:
diff --git a/plugins/Clist_nicer/src/init.cpp b/plugins/Clist_nicer/src/init.cpp
index 48628a673b..3d99ee7197 100644
--- a/plugins/Clist_nicer/src/init.cpp
+++ b/plugins/Clist_nicer/src/init.cpp
@@ -69,7 +69,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Clist_nicer/src/stdafx.h b/plugins/Clist_nicer/src/stdafx.h
index 9754475682..71ccf05041 100644
--- a/plugins/Clist_nicer/src/stdafx.h
+++ b/plugins/Clist_nicer/src/stdafx.h
@@ -48,7 +48,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <m_options.h>
#include <m_protosvc.h>
#include <m_skin.h>
-#include <m_addcontact.h>
+#include <m_contacts.h>
#include <m_timezones.h>
#include <m_cluiframes.h>
#include <m_icolib.h>
diff --git a/plugins/Clist_nicer/src/version.h b/plugins/Clist_nicer/src/version.h
index 13f6690c71..982fee189e 100644
--- a/plugins/Clist_nicer/src/version.h
+++ b/plugins/Clist_nicer/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Clist_nicer.dll"
#define __DESCRIPTION "Displays contacts, event notifications, protocol status."
#define __AUTHOR "Pixel, egoDust, cyreve, Nightwish"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/Clist_nicer/"
#define __COPYRIGHT "© 2000-2010 Miranda-IM project"
diff --git a/plugins/Cln_skinedit/src/main.cpp b/plugins/Cln_skinedit/src/main.cpp
index 4f1fbd08fe..70e1916972 100644
--- a/plugins/Cln_skinedit/src/main.cpp
+++ b/plugins/Cln_skinedit/src/main.cpp
@@ -32,7 +32,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Cln_skinedit/src/version.h b/plugins/Cln_skinedit/src/version.h
index 49d9d2c68f..bd97cdf19e 100644
--- a/plugins/Cln_skinedit/src/version.h
+++ b/plugins/Cln_skinedit/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Cln_skinedit.dll"
#define __DESCRIPTION "Allows inline skin item editing for Clist nicer."
#define __AUTHOR "Nightwish, Pixel"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/Cln_skinedit/"
#define __COPYRIGHT "© 2000-2006 Miranda-IM project"
diff --git a/plugins/CloudFile/src/http_request.h b/plugins/CloudFile/src/http_request.h
index 39d0d98b57..aed8167b98 100644
--- a/plugins/CloudFile/src/http_request.h
+++ b/plugins/CloudFile/src/http_request.h
@@ -60,7 +60,7 @@ protected:
szLogin,
szPassword);
- ptrA ePair(mir_base64_encode((BYTE*)(char*)cPair, length));
+ ptrA ePair(mir_base64_encode(cPair, length));
length = mir_strlen(ePair) + 7;
char *value = (char*)mir_calloc(length + 1);
diff --git a/plugins/CloudFile/src/main.cpp b/plugins/CloudFile/src/main.cpp
index 15f87f8bf3..ffdf7bfeb5 100644
--- a/plugins/CloudFile/src/main.cpp
+++ b/plugins/CloudFile/src/main.cpp
@@ -11,7 +11,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/CloudFile/src/version.h b/plugins/CloudFile/src/version.h
index 23b1f2094f..a528b9ed70 100644
--- a/plugins/CloudFile/src/version.h
+++ b/plugins/CloudFile/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "CloudFile.dll"
#define __DESCRIPTION "Allows you to transfer files via cloud services."
#define __AUTHOR "Miranda NG Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/CloudFile/"
#define __COPYRIGHT "© 2017 Miranda NG project"
diff --git a/plugins/CmdLine/src/CmdLine.cpp b/plugins/CmdLine/src/CmdLine.cpp
index 6c6bf029c2..b84d0e75e5 100644
--- a/plugins/CmdLine/src/CmdLine.cpp
+++ b/plugins/CmdLine/src/CmdLine.cpp
@@ -31,7 +31,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/CmdLine/src/version.h b/plugins/CmdLine/src/version.h
index 6f9d7a7e52..489988db0c 100644
--- a/plugins/CmdLine/src/version.h
+++ b/plugins/CmdLine/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "CmdLine.dll"
#define __DESCRIPTION "This plugin lets you control Miranda from the command line."
#define __AUTHOR "Cristian Libotean"
-#define __AUTHOREMAIL "eblis102@yahoo.com"
#define __AUTHORWEB "https://miranda-ng.org/p/CmdLine/"
#define __COPYRIGHT "© 2007-2011 Cristian Libotean"
diff --git a/plugins/ConnectionNotify/src/ConnectionNotify.cpp b/plugins/ConnectionNotify/src/ConnectionNotify.cpp
index a989e81651..c0b09a621a 100644
--- a/plugins/ConnectionNotify/src/ConnectionNotify.cpp
+++ b/plugins/ConnectionNotify/src/ConnectionNotify.cpp
@@ -47,7 +47,6 @@ PLUGININFOEX pluginInfo = {
__VERSION_DWORD,
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE, //not transient
diff --git a/plugins/ConnectionNotify/src/version.h b/plugins/ConnectionNotify/src/version.h
index a147192ba9..fbfc5a21c5 100644
--- a/plugins/ConnectionNotify/src/version.h
+++ b/plugins/ConnectionNotify/src/version.h
@@ -30,7 +30,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define __DESCRIPTION "Notify with popup if some connection established"
#define __AUTHOR "MaKaR"
-#define __AUTHOREMAIL "makar@poczta.of.pl"
#define __COPYRIGHT "© 2011-2013 MaKaRSoFT"
#define __AUTHORWEB "https://miranda-ng.org/p/ConnectionNotify/"
#define __PLUGIN_DISPLAY_NAME "ConnectionNotify"
diff --git a/plugins/Console/src/init.cpp b/plugins/Console/src/init.cpp
index 096090c674..ce90769d08 100644
--- a/plugins/Console/src/init.cpp
+++ b/plugins/Console/src/init.cpp
@@ -34,7 +34,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Console/src/version.h b/plugins/Console/src/version.h
index 57d5d11c65..f0f464486b 100644
--- a/plugins/Console/src/version.h
+++ b/plugins/Console/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Console.dll"
#define __DESCRIPTION "Console log window for Miranda."
#define __AUTHOR "Bio"
-#define __AUTHOREMAIL "bio@ktaspb.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/Console/"
#define __COPYRIGHT "© 2005-2012 Bio"
diff --git a/plugins/ContactsPlus/src/main.cpp b/plugins/ContactsPlus/src/main.cpp
index 5a878c8c05..fed2bd4394 100644
--- a/plugins/ContactsPlus/src/main.cpp
+++ b/plugins/ContactsPlus/src/main.cpp
@@ -43,7 +43,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/ContactsPlus/src/receive.cpp b/plugins/ContactsPlus/src/receive.cpp
index 67b2290358..5b919d71fe 100644
--- a/plugins/ContactsPlus/src/receive.cpp
+++ b/plugins/ContactsPlus/src/receive.cpp
@@ -355,7 +355,7 @@ INT_PTR CALLBACK RecvDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPara
case ID_POPUP_ADDUSER:
hContact = CreateTemporaryContactForItem(hwndDlg, wndData, wndData->iPopupItem);
if (hContact)
- DialogAddContactExecute(hwndDlg, hContact);
+ Contact_Add(hContact, hwndDlg);
break;
case ID_POPUP_USERDETAILS:
@@ -389,7 +389,7 @@ INT_PTR CALLBACK RecvDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPara
break;
case IDC_ADD:
- DialogAddContactExecute(hwndDlg, wndData->mhContact);
+ Contact_Add(wndData->mhContact, hwndDlg);
break;
}
}
diff --git a/plugins/ContactsPlus/src/send.cpp b/plugins/ContactsPlus/src/send.cpp
index 9887b10071..6176597a39 100644
--- a/plugins/ContactsPlus/src/send.cpp
+++ b/plugins/ContactsPlus/src/send.cpp
@@ -372,7 +372,7 @@ INT_PTR CALLBACK SendDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPara
break;
case IDC_ADD:
- DialogAddContactExecute(hwndDlg, wndData->hContact);
+ Contact_Add(wndData->hContact, hwndDlg);
break;
}
break;
diff --git a/plugins/ContactsPlus/src/stdafx.h b/plugins/ContactsPlus/src/stdafx.h
index 14b3a280b9..6ae4c02e89 100644
--- a/plugins/ContactsPlus/src/stdafx.h
+++ b/plugins/ContactsPlus/src/stdafx.h
@@ -35,7 +35,7 @@
#include "m_clist.h"
#include "m_clistint.h"
#include "m_clc.h"
-#include "m_addcontact.h"
+#include "m_contacts.h"
#include "m_history.h"
#include "m_userinfo.h"
#include "m_button.h"
diff --git a/plugins/ContactsPlus/src/utils.cpp b/plugins/ContactsPlus/src/utils.cpp
index c6c079cf3a..acc2c47a16 100644
--- a/plugins/ContactsPlus/src/utils.cpp
+++ b/plugins/ContactsPlus/src/utils.cpp
@@ -87,15 +87,6 @@ wchar_t* GetContactUID(MCONTACT hContact)
return nullptr;
}
-void DialogAddContactExecute(HWND hwndDlg, MCONTACT hNewContact)
-{
- ADDCONTACTSTRUCT acs = { 0 };
- acs.hContact = hNewContact;
- acs.handleType = HANDLE_CONTACT;
- CallService(MS_ADDCONTACT_SHOW, (WPARAM)hwndDlg, (LPARAM)&acs);
-}
-
-
void DrawProtocolIcon(HWND hwndDlg, LPARAM lParam, MCONTACT hContact)
{
LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
diff --git a/plugins/ContactsPlus/src/utils.h b/plugins/ContactsPlus/src/utils.h
index 01eee73411..6a15ed06c9 100644
--- a/plugins/ContactsPlus/src/utils.h
+++ b/plugins/ContactsPlus/src/utils.h
@@ -40,8 +40,6 @@ void UpdateDialogAddButton(HWND hwndDlg, MCONTACT hContact);
HICON InitMButton(HWND hDlg, int idButton, int idIcon, wchar_t *szTip);
-void DialogAddContactExecute(HWND hwndDlg, MCONTACT hNewContact);
-
HICON LoadContactProtoIcon(MCONTACT hContact);
void EnableDlgItem(HWND hwndDlg, UINT control, int state);
diff --git a/plugins/ContactsPlus/src/version.h b/plugins/ContactsPlus/src/version.h
index 0e8658af31..0fc50cc6ba 100644
--- a/plugins/ContactsPlus/src/version.h
+++ b/plugins/ContactsPlus/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Contacts.dll"
#define __DESCRIPTION "Allows you to send and receive contacts."
#define __AUTHOR "Joe Kucera, Todor Totev"
-#define __AUTHOREMAIL "jokusoftware@miranda-im.org"
#define __AUTHORWEB "https://miranda-ng.org/p/Contacts/"
#define __COPYRIGHT "© 2004-2008 Joe Kucera, Original code © 2002 Dominus Procellarum"
diff --git a/plugins/ContextHelp/src/main.cpp b/plugins/ContextHelp/src/main.cpp
index a5bd86455e..b5dff62eb1 100644
--- a/plugins/ContextHelp/src/main.cpp
+++ b/plugins/ContextHelp/src/main.cpp
@@ -32,7 +32,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/ContextHelp/src/stdafx.h b/plugins/ContextHelp/src/stdafx.h
index 98cea224c5..ca918fd4f0 100644
--- a/plugins/ContextHelp/src/stdafx.h
+++ b/plugins/ContextHelp/src/stdafx.h
@@ -47,7 +47,5 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
extern HINSTANCE hInstance;
-#define USERAGENT_VERSION "0.2.1.2"
-
#endif //CONTEXTHELP_COMMONHEADERS_H \ No newline at end of file
diff --git a/plugins/ContextHelp/src/version.h b/plugins/ContextHelp/src/version.h
index 482a4d75f3..7338062bf1 100644
--- a/plugins/ContextHelp/src/version.h
+++ b/plugins/ContextHelp/src/version.h
@@ -17,26 +17,6 @@ along with this program (Help-License.txt); if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-/*
-#define NEEDED_MIRANDA_VERSION PLUGIN_MAKE_VERSION(0,6,0,0)
-#define NEEDED_MIRANDA_VERSION_STR "0.6"
-#define PLUGIN_VERSION PLUGIN_MAKE_VERSION(0,2,1,2)
-#define FILE_VERSION 0,2,1,2
-
-#ifdef _DEBUG
- #define FILE_VERSION_STR "0.2.1.3 alpha"
- #define USERAGENT_VERSION "0.2.1.3 (alpha)"
-#else
- #define FILE_VERSION_STR "0.2.1.2"
- #define USERAGENT_VERSION "0.2.1.2"
-#endif
-
-#define PLUGIN_EMAIL "hrathh users.sourceforge.net"
-#define PLUGIN_EMAIL_ATT_POS 7 // position of the @-sign in the email adress above
-
- #define PLUGIN_WEBSITE "http://addons.miranda-im.org/details.php?action=viewfile&id=3475"
-*/
-
#define __MAJOR_VERSION 0
#define __MINOR_VERSION 2
#define __RELEASE_NUM 1
@@ -48,6 +28,5 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define __FILENAME "ContextHelp.dll"
#define __DESCRIPTION "Provides context sensitive help in all of the Miranda NG dialog boxes."
#define __AUTHOR "Richard Hughes, H. Herkenrath, Miranda NG Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/ContextHelp/"
#define __COPYRIGHT "© 2002 Richard Hughes, 2005-2007 H. Herkenrath, 2016-17 Miranda NG Team"
diff --git a/plugins/CountryFlags/src/main.cpp b/plugins/CountryFlags/src/main.cpp
index 674e60f913..e34ff660be 100644
--- a/plugins/CountryFlags/src/main.cpp
+++ b/plugins/CountryFlags/src/main.cpp
@@ -31,7 +31,6 @@ static PLUGININFOEX pluginInfo={
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/CountryFlags/src/version.h b/plugins/CountryFlags/src/version.h
index 7db3bc805b..5ec53d6bc9 100644
--- a/plugins/CountryFlags/src/version.h
+++ b/plugins/CountryFlags/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Flags.dll"
#define __DESCRIPTION "Service offering misc country utilities as flag icons and an IP-to-Country database."
#define __AUTHOR "H. Herkenrath"
-#define __AUTHOREMAIL "hrathh@users.sourceforge.net"
#define __AUTHORWEB "https://miranda-ng.org/p/Flags/"
#define __COPYRIGHT "© 2006-2007 H. Herkenrath"
diff --git a/plugins/CrashDumper/src/crshdmp.cpp b/plugins/CrashDumper/src/crshdmp.cpp
index f31de55e7c..d775326ea1 100644
--- a/plugins/CrashDumper/src/crshdmp.cpp
+++ b/plugins/CrashDumper/src/crshdmp.cpp
@@ -44,7 +44,6 @@ static const PLUGININFOEX pluginInfoEx =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/CrashDumper/src/upload.cpp b/plugins/CrashDumper/src/upload.cpp
index 9b3b501b89..62baee1071 100644
--- a/plugins/CrashDumper/src/upload.cpp
+++ b/plugins/CrashDumper/src/upload.cpp
@@ -83,7 +83,7 @@ void CreateAuthString(char* auth)
char str[110];
int len = mir_snprintf(str, "%s:%s", user, pass);
- mir_snprintf(auth, 250, "Basic %s", ptrA(mir_base64_encode((PBYTE)str, len)));
+ mir_snprintf(auth, 250, "Basic %s", ptrA(mir_base64_encode(str, len)));
}
diff --git a/plugins/CrashDumper/src/version.h b/plugins/CrashDumper/src/version.h
index 9b0f464e2a..7eb818204e 100644
--- a/plugins/CrashDumper/src/version.h
+++ b/plugins/CrashDumper/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "CrashDumper.dll"
#define __DESCRIPTION "Crash Dumper and Version Information for Miranda NG."
#define __AUTHOR "borkra"
-#define __AUTHOREMAIL "borkra@miranda-im.org"
#define __AUTHORWEB "https://miranda-ng.org/p/CrashDumper/"
#define __COPYRIGHT "© 2008-12 Boris Krasnovskiy, 2012-17 Miranda NG team"
diff --git a/plugins/CryptoPP/src/base16.cpp b/plugins/CryptoPP/src/base16.cpp
index e716b4be4f..f75ebe1d1b 100644
--- a/plugins/CryptoPP/src/base16.cpp
+++ b/plugins/CryptoPP/src/base16.cpp
@@ -1,6 +1,6 @@
#include "commonheaders.h"
-char *base16encode(const char *inBuffer, int count)
+char* base16encode(const char *inBuffer, size_t count)
{
char *outBuffer = (char *)malloc(count * 2 + 1);
char *outBufferPtr = outBuffer;
@@ -16,7 +16,7 @@ char *base16encode(const char *inBuffer, int count)
return outBuffer;
}
-char *base16decode(const char *inBuffer, unsigned int *count)
+char* base16decode(const char *inBuffer, size_t *count)
{
char *outBuffer = (char *)mir_alloc(*count);
BYTE *outBufferPtr = (BYTE *)outBuffer;
@@ -53,6 +53,6 @@ char *base16decode(const char *inBuffer, unsigned int *count)
char *base16decode(const char *inBuffer)
{
- unsigned count = (unsigned)strlen(inBuffer);
+ size_t count = strlen(inBuffer);
return base16decode(inBuffer, &count);
}
diff --git a/plugins/CryptoPP/src/base16.h b/plugins/CryptoPP/src/base16.h
index 871bca3fbd..0146428abc 100644
--- a/plugins/CryptoPP/src/base16.h
+++ b/plugins/CryptoPP/src/base16.h
@@ -43,9 +43,9 @@ static const byte asciiToBin16[] =
static const byte binToAscii16[] = "0123456789ABCDEF";
-char *base16encode(const char *, const int);
-char *base16decode(const char *, unsigned*);
-char *base16decode(const char *);
+char* base16encode(const char*, size_t);
+char* base16decode(const char*, size_t*);
+char* base16decode(const char*);
#define encode16(data) binToAscii16[data]
#define decode16(data) asciiToBin16[data]
diff --git a/plugins/CryptoPP/src/base64.cpp b/plugins/CryptoPP/src/base64.cpp
index 9a855cdb8d..779e33e5b1 100644
--- a/plugins/CryptoPP/src/base64.cpp
+++ b/plugins/CryptoPP/src/base64.cpp
@@ -2,19 +2,19 @@
string base64encode(const string& buf)
{
- return (char*)ptrA(mir_base64_encode((PBYTE)buf.data(), (unsigned)buf.length()));
+ return (char*)ptrA(mir_base64_encode(buf.data(), buf.length()));
}
string base64decode(const string& buf)
{
- unsigned len;
+ size_t len;
ptrA plain((char*)mir_base64_decode(buf.data(), &len));
return (plain == NULL) ? string() : string(plain, len);
}
string base64decode(const char *buf)
{
- unsigned len;
+ size_t len;
ptrA plain((char*)mir_base64_decode(buf, &len));
return (plain == NULL) ? string() : string(plain, len);
}
diff --git a/plugins/CryptoPP/src/cpp_keys.cpp b/plugins/CryptoPP/src/cpp_keys.cpp
index 8cfea1c040..ffcf0645a0 100644
--- a/plugins/CryptoPP/src/cpp_keys.cpp
+++ b/plugins/CryptoPP/src/cpp_keys.cpp
@@ -74,7 +74,7 @@ int __cdecl cpp_init_keyb(HANDLE context, LPCSTR key)
pCNTX ptr = get_context_on_id(context); if (!ptr) return 0;
pSIMDATA p = (pSIMDATA)cpp_alloc_pdata(ptr);
- unsigned clen = (unsigned)rtrim(key);
+ size_t clen = rtrim(key);
ptr->features = 0;
LPSTR pub_binary;
diff --git a/plugins/CryptoPP/src/cpp_svcs.cpp b/plugins/CryptoPP/src/cpp_svcs.cpp
index 089d535a8f..00f8b19d8a 100644
--- a/plugins/CryptoPP/src/cpp_svcs.cpp
+++ b/plugins/CryptoPP/src/cpp_svcs.cpp
@@ -50,7 +50,7 @@ LPSTR __cdecl cpp_encrypt(pCNTX ptr, LPCSTR szPlainMsg)
clen = (unsigned)ciphered.length();
mir_free(ptr->tmp);
if (ptr->features & FEATURES_BASE64)
- ptr->tmp = mir_base64_encode((PBYTE)ciphered.data(), clen);
+ ptr->tmp = mir_base64_encode(ciphered.data(), clen);
else {
char *base16 = base16encode(ciphered.data(), clen);
ptr->tmp = mir_strdup(base16);
@@ -70,7 +70,7 @@ LPSTR __cdecl cpp_decrypt(pCNTX ptr, LPCSTR szEncMsg)
ptr->error = ERROR_SEH;
pSIMDATA p = (pSIMDATA)ptr->pdata;
- unsigned clen = (unsigned)strlen(szEncMsg);
+ size_t clen = strlen(szEncMsg);
if (ptr->features & FEATURES_BASE64)
ciphered = (LPSTR)mir_base64_decode(szEncMsg, &clen);
diff --git a/plugins/CryptoPP/src/main.cpp b/plugins/CryptoPP/src/main.cpp
index 9adee52785..72c1dc1e2e 100644
--- a/plugins/CryptoPP/src/main.cpp
+++ b/plugins/CryptoPP/src/main.cpp
@@ -17,7 +17,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/CryptoPP/src/version.h b/plugins/CryptoPP/src/version.h
index 60042bfccb..658fc10dfb 100644
--- a/plugins/CryptoPP/src/version.h
+++ b/plugins/CryptoPP/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "CryptoPP.dll"
#define __DESCRIPTION "Crypto++ library for SecureIM plugin."
#define __AUTHOR "Baloo"
-#define __AUTHOREMAIL "baloo@bk.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/CryptoPP/"
#define __COPYRIGHT "© 2006-09 Baloo"
diff --git a/plugins/CyrTranslit/src/main.cpp b/plugins/CyrTranslit/src/main.cpp
index 5f8b499f08..e78a6732d1 100644
--- a/plugins/CyrTranslit/src/main.cpp
+++ b/plugins/CyrTranslit/src/main.cpp
@@ -28,7 +28,6 @@ PLUGININFOEX pluginInfoEx={
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/CyrTranslit/src/version.h b/plugins/CyrTranslit/src/version.h
index a2e119f5b5..d55f0500cd 100644
--- a/plugins/CyrTranslit/src/version.h
+++ b/plugins/CyrTranslit/src/version.h
@@ -28,6 +28,5 @@
#define __FILENAME "CyrTranslit.dll"
#define __DESCRIPTION "Replaces (for the selected contacts only) the Cyrillic letters in the outgoing messages with the phonetically equivalent Latin letter combinations."
#define __AUTHOR "ValeraVi, Ivan Krechetov"
-#define __AUTHOREMAIL "valeravi@vi-soft.com.ua"
#define __AUTHORWEB "https://miranda-ng.org/p/CyrTranslit/"
#define __COPYRIGHT "© 2005-2009 ValeraVi, Ivan Krechetov"
diff --git a/plugins/Db3x_mmap/src/init.cpp b/plugins/Db3x_mmap/src/init.cpp
index 28467c2e62..2c80069676 100644
--- a/plugins/Db3x_mmap/src/init.cpp
+++ b/plugins/Db3x_mmap/src/init.cpp
@@ -32,7 +32,6 @@ static PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE | STATIC_PLUGIN,
diff --git a/plugins/Db3x_mmap/src/version.h b/plugins/Db3x_mmap/src/version.h
index f15fb07b2a..1ef99c71f7 100644
--- a/plugins/Db3x_mmap/src/version.h
+++ b/plugins/Db3x_mmap/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Dbx_mmap.dll"
#define __DESCRIPTION "Provides Miranda database support: global settings, contacts, history, settings per contact."
#define __AUTHOR "Miranda-NG project"
-#define __AUTHOREMAIL "bio@msx.ru; ghazan@miranda.im"
#define __AUTHORWEB "https://miranda-ng.org/p/Dbx_mmap/"
#define __COPYRIGHT "© 2012-17 Miranda NG project"
diff --git a/plugins/DbChecker/src/main.cpp b/plugins/DbChecker/src/main.cpp
index 1f9ed55889..438a32f6d4 100644
--- a/plugins/DbChecker/src/main.cpp
+++ b/plugins/DbChecker/src/main.cpp
@@ -32,7 +32,6 @@ PLUGININFOEX pluginInfoEx =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE | STATIC_PLUGIN,
diff --git a/plugins/DbChecker/src/version.h b/plugins/DbChecker/src/version.h
index c7e5045807..55f5323d2c 100644
--- a/plugins/DbChecker/src/version.h
+++ b/plugins/DbChecker/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "DbChecker.dll"
#define __DESCRIPTION "Miranda NG Database Checker."
#define __AUTHOR "George Hazan"
-#define __AUTHOREMAIL "ghazan@miranda-ng.org"
#define __AUTHORWEB "https://miranda-ng.org/p/DbChecker/"
#define __COPYRIGHT "© 2012-17 George Hazan"
diff --git a/plugins/DbEditorPP/src/main.cpp b/plugins/DbEditorPP/src/main.cpp
index e3c6084450..2fa66baa6d 100644
--- a/plugins/DbEditorPP/src/main.cpp
+++ b/plugins/DbEditorPP/src/main.cpp
@@ -28,7 +28,6 @@ PLUGININFOEX pluginInfoEx =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/DbEditorPP/src/version.h b/plugins/DbEditorPP/src/version.h
index 001417d300..740684ca3a 100644
--- a/plugins/DbEditorPP/src/version.h
+++ b/plugins/DbEditorPP/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "DbEditorPP.dll"
#define __DESCRIPTION "Advanced Database Editor."
#define __AUTHOR "Bio, Jonathan Gordon"
-#define __AUTHOREMAIL "bio@ktaspb.ru, jdgordy@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/DbEditorPP/"
#define __COPYRIGHT "© 2003-2017 Bio, Jonathan Gordon"
diff --git a/plugins/Db_autobackups/src/main.cpp b/plugins/Db_autobackups/src/main.cpp
index a0a2e37751..9aa48d8c6d 100644
--- a/plugins/Db_autobackups/src/main.cpp
+++ b/plugins/Db_autobackups/src/main.cpp
@@ -12,7 +12,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Db_autobackups/src/version.h b/plugins/Db_autobackups/src/version.h
index 5f72c4b2e6..ef803e937a 100644
--- a/plugins/Db_autobackups/src/version.h
+++ b/plugins/Db_autobackups/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Db_autobackups.dll"
#define __DESCRIPTION "Database autobackuper plugin."
#define __AUTHOR "chaos.persei, sje, Kildor, Billy_Bons"
-#define __AUTHOREMAIL "chaos.persei@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/Db_autobackups/"
#define __COPYRIGHT "© 2005-2017 chaos.persei, sje, Kildor, Billy_Bons, Vasilich, Miranda NG team"
diff --git a/plugins/Dbx_mdb/dbx_lmdb.vcxproj b/plugins/Dbx_mdb/dbx_lmdb.vcxproj
index 41afd957be..a4016eb5b6 100644
--- a/plugins/Dbx_mdb/dbx_lmdb.vcxproj
+++ b/plugins/Dbx_mdb/dbx_lmdb.vcxproj
@@ -26,10 +26,16 @@
<Import Project="$(ProjectDir)..\..\build\vc.common\plugin.props" />
</ImportGroup>
<ItemGroup>
- <ClCompile Include="src\mdbx\*.c">
+ <ClCompile Include="src\libmdbx\src\lck-windows.c">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
- <ClCompile Include="src\mdbx\*.cpp">
+ <ClCompile Include="src\libmdbx\src\mdbx.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\libmdbx\src\osal.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\libmdbx\src\version.c">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
</ItemGroup>
diff --git a/plugins/Dbx_mdb/src/dbintf.cpp b/plugins/Dbx_mdb/src/dbintf.cpp
index daa0f884bd..17715957d8 100644
--- a/plugins/Dbx_mdb/src/dbintf.cpp
+++ b/plugins/Dbx_mdb/src/dbintf.cpp
@@ -125,7 +125,7 @@ int CDbxMdb::Load(bool bSkipInit)
if (InitModules()) return EGROKPRF_DAMAGED;
- if (InitCrypt()) return EGROKPRF_DAMAGED;
+ if (InitCrypt()) return EGROKPRF_DAMAGED;
// everything is ok, go on
if (!m_bReadOnly) {
@@ -183,13 +183,12 @@ STDMETHODIMP_(void) CDbxMdb::SetCacheSafetyMode(BOOL bIsSet)
int CDbxMdb::Map()
{
- unsigned int mode = MDBX_NOSUBDIR | MDBX_NOTLS | MDBX_MAPASYNC | MDBX_WRITEMAP | MDBX_NOSYNC;
+ unsigned int mode = MDBX_NOSUBDIR | MDBX_MAPASYNC | MDBX_WRITEMAP | MDBX_NOSYNC;
if (m_bReadOnly)
mode |= MDBX_RDONLY;
mdbx_env_open(m_pMdbEnv, _T2A(m_tszProfileName), mode, 0664);
mdbx_env_set_mapsize(m_pMdbEnv, 0x1000000);
return MDBX_SUCCESS;
-
}
bool CDbxMdb::Remap()
@@ -199,7 +198,6 @@ bool CDbxMdb::Remap()
return mdbx_env_set_geometry(m_pMdbEnv, -1, -1, ei.mi_mapsize + 0x100000, 0x100000, -1, -1) == MDBX_SUCCESS;
}
-
/////////////////////////////////////////////////////////////////////////////////////////
static DWORD DatabaseCorrupted = 0;
diff --git a/plugins/Dbx_mdb/src/init.cpp b/plugins/Dbx_mdb/src/init.cpp
index 253dff78e9..406c2988f5 100644
--- a/plugins/Dbx_mdb/src/init.cpp
+++ b/plugins/Dbx_mdb/src/init.cpp
@@ -32,7 +32,6 @@ static PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE | STATIC_PLUGIN,
diff --git a/plugins/Dbx_mdb/src/libmdbx b/plugins/Dbx_mdb/src/libmdbx
new file mode 160000
+Subproject 24a8bdec49ee360bf0412631ff8931de91e109f
diff --git a/plugins/Dbx_mdb/src/mdbx/bits.h b/plugins/Dbx_mdb/src/mdbx/bits.h
deleted file mode 100644
index d1ebb7cd2d..0000000000
--- a/plugins/Dbx_mdb/src/mdbx/bits.h
+++ /dev/null
@@ -1,1226 +0,0 @@
-/*
- * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
- * and other libmdbx authors: please see AUTHORS file.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>. */
-
-#pragma once
-/* *INDENT-OFF* */
-/* clang-format off */
-
-#ifndef MDBX_DEBUG
-# define MDBX_DEBUG 0
-#endif
-
-#if MDBX_DEBUG
-# undef NDEBUG
-#endif
-
-/* Features under development */
-#ifndef MDBX_DEVEL
-# define MDBX_DEVEL 1
-#endif
-
-/*----------------------------------------------------------------------------*/
-
-/* Should be defined before any includes */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-#endif
-#ifndef _FILE_OFFSET_BITS
-# define _FILE_OFFSET_BITS 64
-#endif
-
-#ifdef _MSC_VER
-# ifndef _CRT_SECURE_NO_WARNINGS
-# define _CRT_SECURE_NO_WARNINGS
-# endif
-#if _MSC_VER > 1800
-# pragma warning(disable : 4464) /* relative include path contains '..' */
-#endif
-#pragma warning(disable : 4710) /* 'xyz': function not inlined */
-#pragma warning(disable : 4711) /* function 'xyz' selected for automatic inline expansion */
-#pragma warning(disable : 4201) /* nonstandard extension used : nameless struct / union */
-#pragma warning(disable : 4702) /* unreachable code */
-#pragma warning(disable : 4706) /* assignment within conditional expression */
-#pragma warning(disable : 4127) /* conditional expression is constant */
-#pragma warning(disable : 4324) /* 'xyz': structure was padded due to alignment specifier */
-#pragma warning(disable : 4310) /* cast truncates constant value */
-#pragma warning(disable : 4820) /* bytes padding added after data member for aligment */
-#pragma warning(disable : 4548) /* expression before comma has no effect; expected expression with side - effect */
-#endif /* _MSC_VER (warnings) */
-
-#include "./mdbx.h"
-#include "./defs.h"
-
-#if defined(__GNUC__) && !__GNUC_PREREQ(4,2)
- /* Actualy libmdbx was not tested with compilers older than GCC from RHEL6.
- * But you could remove this #error and try to continue at your own risk.
- * In such case please don't rise up an issues related ONLY to old compilers.
- */
-# warning "libmdbx required at least GCC 4.2 compatible C/C++ compiler."
-#endif
-
-#if defined(__GLIBC__) && !__GLIBC_PREREQ(2,12)
- /* Actualy libmdbx was not tested with something older than glibc 2.12 (from RHEL6).
- * But you could remove this #error and try to continue at your own risk.
- * In such case please don't rise up an issues related ONLY to old systems.
- */
-# warning "libmdbx required at least GLIBC 2.12."
-#endif
-
-#ifdef __SANITIZE_THREAD__
-# warning "libmdbx don't compatible with ThreadSanitizer, you will get a lot of false-positive issues."
-#endif /* __SANITIZE_THREAD__ */
-
-#include "./osal.h"
-
-/* *INDENT-ON* */
-/* clang-format on */
-
-/*----------------------------------------------------------------------------*/
-/* Basic constants and types */
-
-/* The minimum number of keys required in a database page.
- * Setting this to a larger value will place a smaller bound on the
- * maximum size of a data item. Data items larger than this size will
- * be pushed into overflow pages instead of being stored directly in
- * the B-tree node. This value used to default to 4. With a page size
- * of 4096 bytes that meant that any item larger than 1024 bytes would
- * go into an overflow page. That also meant that on average 2-3KB of
- * each overflow page was wasted space. The value cannot be lower than
- * 2 because then there would no longer be a tree structure. With this
- * value, items larger than 2KB will go into overflow pages, and on
- * average only 1KB will be wasted. */
-#define MDBX_MINKEYS 2
-
-/* A stamp that identifies a file as an MDBX file.
- * There's nothing special about this value other than that it is easily
- * recognizable, and it will reflect any byte order mismatches. */
-#define MDBX_MAGIC UINT64_C(/* 56-bit prime */ 0x59659DBDEF4C11)
-
-/* The version number for a database's datafile format. */
-#define MDBX_DATA_VERSION ((MDBX_DEVEL) ? 255 : 2)
-/* The version number for a database's lockfile format. */
-#define MDBX_LOCK_VERSION ((MDBX_DEVEL) ? 255 : 2)
-
-/* handle for the DB used to track free pages. */
-#define FREE_DBI 0
-/* handle for the default DB. */
-#define MAIN_DBI 1
-/* Number of DBs in metapage (free and main) - also hardcoded elsewhere */
-#define CORE_DBS 2
-#define MAX_DBI (INT16_MAX - CORE_DBS)
-
-/* Number of meta pages - also hardcoded elsewhere */
-#define NUM_METAS 3
-
-/* A page number in the database.
- *
- * MDBX uses 32 bit for page numbers. This limits database
- * size up to 2^44 bytes, in case of 4K pages. */
-typedef uint32_t pgno_t;
-#define PRIaPGNO PRIu32
-#define MAX_PAGENO ((pgno_t)UINT64_C(0xffffFFFFffff))
-#define MIN_PAGENO NUM_METAS
-
-/* A transaction ID. */
-typedef uint64_t txnid_t;
-#define PRIaTXN PRIi64
-#if MDBX_DEVEL
-#define MIN_TXNID (UINT64_MAX - UINT32_MAX)
-#elif MDBX_DEBUG
-#define MIN_TXNID UINT64_C(0x100000000)
-#else
-#define MIN_TXNID UINT64_C(1)
-#endif /* MIN_TXNID */
-
-/* Used for offsets within a single page.
- * Since memory pages are typically 4 or 8KB in size, 12-13 bits,
- * this is plenty. */
-typedef uint16_t indx_t;
-
-#define MEGABYTE ((size_t)1 << 20)
-
-/*----------------------------------------------------------------------------*/
-/* Core structures for database and shared memory (i.e. format definition) */
-#pragma pack(push, 1)
-
-/* Reader Lock Table
- *
- * Readers don't acquire any locks for their data access. Instead, they
- * simply record their transaction ID in the reader table. The reader
- * mutex is needed just to find an empty slot in the reader table. The
- * slot's address is saved in thread-specific data so that subsequent
- * read transactions started by the same thread need no further locking to
- * proceed.
- *
- * If MDBX_NOTLS is set, the slot address is not saved in thread-specific data.
- * No reader table is used if the database is on a read-only filesystem.
- *
- * Since the database uses multi-version concurrency control, readers don't
- * actually need any locking. This table is used to keep track of which
- * readers are using data from which old transactions, so that we'll know
- * when a particular old transaction is no longer in use. Old transactions
- * that have discarded any data pages can then have those pages reclaimed
- * for use by a later write transaction.
- *
- * The lock table is constructed such that reader slots are aligned with the
- * processor's cache line size. Any slot is only ever used by one thread.
- * This alignment guarantees that there will be no contention or cache
- * thrashing as threads update their own slot info, and also eliminates
- * any need for locking when accessing a slot.
- *
- * A writer thread will scan every slot in the table to determine the oldest
- * outstanding reader transaction. Any freed pages older than this will be
- * reclaimed by the writer. The writer doesn't use any locks when scanning
- * this table. This means that there's no guarantee that the writer will
- * see the most up-to-date reader info, but that's not required for correct
- * operation - all we need is to know the upper bound on the oldest reader,
- * we don't care at all about the newest reader. So the only consequence of
- * reading stale information here is that old pages might hang around a
- * while longer before being reclaimed. That's actually good anyway, because
- * the longer we delay reclaiming old pages, the more likely it is that a
- * string of contiguous pages can be found after coalescing old pages from
- * many old transactions together. */
-
-/* The actual reader record, with cacheline padding. */
-typedef struct MDBX_reader {
- /* Current Transaction ID when this transaction began, or (txnid_t)-1.
- * Multiple readers that start at the same time will probably have the
- * same ID here. Again, it's not important to exclude them from
- * anything; all we need to know is which version of the DB they
- * started from so we can avoid overwriting any data used in that
- * particular version. */
- volatile txnid_t mr_txnid;
-
- /* The information we store in a single slot of the reader table.
- * In addition to a transaction ID, we also record the process and
- * thread ID that owns a slot, so that we can detect stale information,
- * e.g. threads or processes that went away without cleaning up.
- *
- * NOTE: We currently don't check for stale records.
- * We simply re-init the table when we know that we're the only process
- * opening the lock file. */
-
- /* The process ID of the process owning this reader txn. */
- volatile mdbx_pid_t mr_pid;
- /* The thread ID of the thread owning this txn. */
- volatile mdbx_tid_t mr_tid;
-
- /* cache line alignment */
- uint8_t pad[MDBX_CACHELINE_SIZE -
- (sizeof(txnid_t) + sizeof(mdbx_pid_t) + sizeof(mdbx_tid_t)) %
- MDBX_CACHELINE_SIZE];
-} __cache_aligned MDBX_reader;
-
-/* Information about a single database in the environment. */
-typedef struct MDBX_db {
- uint16_t md_flags; /* see mdbx_dbi_open */
- uint16_t md_depth; /* depth of this tree */
- uint32_t md_xsize; /* also ksize for LEAF2 pages */
- pgno_t md_root; /* the root page of this tree */
- pgno_t md_branch_pages; /* number of internal pages */
- pgno_t md_leaf_pages; /* number of leaf pages */
- pgno_t md_overflow_pages; /* number of overflow pages */
- uint64_t md_seq; /* table sequence counter */
- uint64_t md_entries; /* number of data items */
- uint64_t md_merkle; /* Merkle tree checksum */
-} MDBX_db;
-
-/* Meta page content.
- * A meta page is the start point for accessing a database snapshot.
- * Pages 0-1 are meta pages. Transaction N writes meta page (N % 2). */
-typedef struct MDBX_meta {
- /* Stamp identifying this as an MDBX file.
- * It must be set to MDBX_MAGIC with MDBX_DATA_VERSION. */
- uint64_t mm_magic_and_version;
-
- /* txnid that committed this page, the first of a two-phase-update pair */
- volatile txnid_t mm_txnid_a;
-
- uint16_t mm_extra_flags; /* extra DB flags, zero (nothing) for now */
- uint8_t mm_validator_id; /* ID of checksum and page validation method,
- * zero (nothing) for now */
- uint8_t mm_extra_pagehdr; /* extra bytes in the page header,
- * zero (nothing) for now */
-
- struct {
- uint16_t grow; /* datafile growth step in pages */
- uint16_t shrink; /* datafile shrink threshold in pages */
- pgno_t lower; /* minimal size of datafile in pages */
- pgno_t upper; /* maximal size of datafile in pages */
- pgno_t now; /* current size of datafile in pages */
- pgno_t next; /* first unused page in the datafile,
- * but actually the file may be shorter. */
- } mm_geo;
-
- MDBX_db mm_dbs[CORE_DBS]; /* first is free space, 2nd is main db */
- /* The size of pages used in this DB */
-#define mm_psize mm_dbs[FREE_DBI].md_xsize
-/* Any persistent environment flags, see mdbx_env */
-#define mm_flags mm_dbs[FREE_DBI].md_flags
- mdbx_canary mm_canary;
-
-#define MDBX_DATASIGN_NONE 0u
-#define MDBX_DATASIGN_WEAK 1u
-#define SIGN_IS_WEAK(sign) ((sign) == MDBX_DATASIGN_WEAK)
-#define SIGN_IS_STEADY(sign) ((sign) > MDBX_DATASIGN_WEAK)
-#define META_IS_WEAK(meta) SIGN_IS_WEAK((meta)->mm_datasync_sign)
-#define META_IS_STEADY(meta) SIGN_IS_STEADY((meta)->mm_datasync_sign)
- volatile uint64_t mm_datasync_sign;
-
- /* txnid that committed this page, the second of a two-phase-update pair */
- volatile txnid_t mm_txnid_b;
-} MDBX_meta;
-
-/* Common header for all page types. The page type depends on mp_flags.
- *
- * P_BRANCH and P_LEAF pages have unsorted 'MDBX_node's at the end, with
- * sorted mp_ptrs[] entries referring to them. Exception: P_LEAF2 pages
- * omit mp_ptrs and pack sorted MDBX_DUPFIXED values after the page header.
- *
- * P_OVERFLOW records occupy one or more contiguous pages where only the
- * first has a page header. They hold the real data of F_BIGDATA nodes.
- *
- * P_SUBP sub-pages are small leaf "pages" with duplicate data.
- * A node with flag F_DUPDATA but not F_SUBDATA contains a sub-page.
- * (Duplicate data can also go in sub-databases, which use normal pages.)
- *
- * P_META pages contain MDBX_meta, the start point of an MDBX snapshot.
- *
- * Each non-metapage up to MDBX_meta.mm_last_pg is reachable exactly once
- * in the snapshot: Either used by a database or listed in a freeDB record. */
-typedef struct MDBX_page {
- union {
- struct MDBX_page *mp_next; /* for in-memory list of freed pages,
- * must be first field, see NEXT_LOOSE_PAGE */
- uint64_t mp_validator; /* checksum of page content or a txnid during
- * which the page has been updated */
- };
- uint16_t mp_leaf2_ksize; /* key size if this is a LEAF2 page */
-#define P_BRANCH 0x01 /* branch page */
-#define P_LEAF 0x02 /* leaf page */
-#define P_OVERFLOW 0x04 /* overflow page */
-#define P_META 0x08 /* meta page */
-#define P_DIRTY 0x10 /* dirty page, also set for P_SUBP pages */
-#define P_LEAF2 0x20 /* for MDBX_DUPFIXED records */
-#define P_SUBP 0x40 /* for MDBX_DUPSORT sub-pages */
-#define P_LOOSE 0x4000 /* page was dirtied then freed, can be reused */
-#define P_KEEP 0x8000 /* leave this page alone during spill */
- uint16_t mp_flags;
- union {
- struct {
- indx_t mp_lower; /* lower bound of free space */
- indx_t mp_upper; /* upper bound of free space */
- };
- uint32_t mp_pages; /* number of overflow pages */
- };
- pgno_t mp_pgno; /* page number */
-
- /* dynamic size */
- union {
- indx_t mp_ptrs[1];
- MDBX_meta mp_meta;
- uint8_t mp_data[1];
- };
-} MDBX_page;
-
-/* Size of the page header, excluding dynamic data at the end */
-#define PAGEHDRSZ ((unsigned)offsetof(MDBX_page, mp_data))
-
-/* The maximum size of a database page.
-*
-* It is 64K, but value-PAGEHDRSZ must fit in MDBX_page.mp_upper.
-*
-* MDBX will use database pages < OS pages if needed.
-* That causes more I/O in write transactions: The OS must
-* know (read) the whole page before writing a partial page.
-*
-* Note that we don't currently support Huge pages. On Linux,
-* regular data files cannot use Huge pages, and in general
-* Huge pages aren't actually pageable. We rely on the OS
-* demand-pager to read our data and page it out when memory
-* pressure from other processes is high. So until OSs have
-* actual paging support for Huge pages, they're not viable. */
-#define MAX_PAGESIZE 0x10000u
-#define MIN_PAGESIZE 512u
-
-#define MIN_MAPSIZE (MIN_PAGESIZE * MIN_PAGENO)
-#if defined(_WIN32) || defined(_WIN64)
-#define MAX_MAPSIZE32 UINT32_C(0x38000000)
-#else
-#define MAX_MAPSIZE32 UINT32_C(0x7ff80000)
-#endif
-#define MAX_MAPSIZE64 \
- ((sizeof(pgno_t) > 4) ? UINT64_C(0x7fffFFFFfff80000) \
- : MAX_PAGENO * (uint64_t)MAX_PAGESIZE)
-
-#define MAX_MAPSIZE ((sizeof(size_t) < 8) ? MAX_MAPSIZE32 : MAX_MAPSIZE64)
-
-/* The header for the reader table (a memory-mapped lock file). */
-typedef struct MDBX_lockinfo {
- /* Stamp identifying this as an MDBX file.
- * It must be set to MDBX_MAGIC with with MDBX_LOCK_VERSION. */
- uint64_t mti_magic_and_version;
-
- /* Format of this lock file. Must be set to MDBX_LOCK_FORMAT. */
- uint32_t mti_os_and_format;
-
- /* Flags which environment was opened. */
- volatile uint32_t mti_envmode;
-
- union {
-#ifdef MDBX_OSAL_LOCK
- MDBX_OSAL_LOCK mti_wmutex;
-#endif
- uint64_t align_wmutex;
- };
-
- union {
- /* The number of slots that have been used in the reader table.
- * This always records the maximum count, it is not decremented
- * when readers release their slots. */
- volatile unsigned __cache_aligned mti_numreaders;
- uint64_t align_numreaders;
- };
-
- union {
-#ifdef MDBX_OSAL_LOCK
- /* Mutex protecting access to this table. */
- MDBX_OSAL_LOCK mti_rmutex;
-#endif
- uint64_t align_rmutex;
- };
-
- union {
- volatile txnid_t mti_oldest;
- uint64_t align_oldest;
- };
-
- union {
- volatile uint32_t mti_readers_refresh_flag;
- uint64_t align_reader_finished_flag;
- };
-
- uint8_t pad_align[MDBX_CACHELINE_SIZE - sizeof(uint64_t) * 7];
-
- MDBX_reader __cache_aligned mti_readers[1];
-} MDBX_lockinfo;
-
-#ifdef _MSC_VER
-#pragma pack(pop)
-#endif /* MSVC: Enable aligment */
-
-#define MDBX_LOCKINFO_WHOLE_SIZE \
- ((sizeof(MDBX_lockinfo) + MDBX_CACHELINE_SIZE - 1) & \
- ~((size_t)MDBX_CACHELINE_SIZE - 1))
-
-/* Lockfile format signature: version, features and field layout */
-#define MDBX_LOCK_FORMAT \
- ((MDBX_OSAL_LOCK_SIGN << 16) + \
- (uint16_t)(MDBX_LOCKINFO_WHOLE_SIZE + MDBX_CACHELINE_SIZE - 1))
-
-#define MDBX_DATA_MAGIC ((MDBX_MAGIC << 8) + MDBX_DATA_VERSION)
-
-#define MDBX_LOCK_MAGIC ((MDBX_MAGIC << 8) + MDBX_LOCK_VERSION)
-
-/*----------------------------------------------------------------------------*/
-/* Two kind lists of pages (aka PNL) */
-
-/* An PNL is an Page Number List, a sorted array of IDs. The first element of
- * the array is a counter for how many actual page-numbers are in the list.
- * PNLs are sorted in descending order, this allow cut off a page with lowest
- * pgno (at the tail) just truncating the list */
-#define MDBX_PNL_ASCENDING 0
-typedef pgno_t *MDBX_PNL;
-
-#if MDBX_PNL_ASCENDING
-#define MDBX_PNL_ORDERED(first, last) ((first) < (last))
-#define MDBX_PNL_DISORDERED(first, last) ((first) >= (last))
-#else
-#define MDBX_PNL_ORDERED(first, last) ((first) > (last))
-#define MDBX_PNL_DISORDERED(first, last) ((first) <= (last))
-#endif
-
-/* List of txnid, only for MDBX_env.mt_lifo_reclaimed */
-typedef txnid_t *MDBX_TXL;
-
-/* An ID2 is an ID/pointer pair. */
-typedef struct MDBX_ID2 {
- pgno_t mid; /* The ID */
- void *mptr; /* The pointer */
-} MDBX_ID2;
-
-/* An ID2L is an ID2 List, a sorted array of ID2s.
- * The first element's mid member is a count of how many actual
- * elements are in the array. The mptr member of the first element is
- * unused. The array is sorted in ascending order by mid. */
-typedef MDBX_ID2 *MDBX_ID2L;
-
-/* PNL sizes - likely should be even bigger
- * limiting factors: sizeof(pgno_t), thread stack size */
-#define MDBX_PNL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */
-#define MDBX_PNL_DB_SIZE (1 << MDBX_PNL_LOGN)
-#define MDBX_PNL_UM_SIZE (1 << (MDBX_PNL_LOGN + 1))
-
-#define MDBX_PNL_DB_MAX (MDBX_PNL_DB_SIZE - 1)
-#define MDBX_PNL_UM_MAX (MDBX_PNL_UM_SIZE - 1)
-
-#define MDBX_PNL_SIZEOF(pl) (((pl)[0] + 1) * sizeof(pgno_t))
-#define MDBX_PNL_IS_ZERO(pl) ((pl)[0] == 0)
-#define MDBX_PNL_CPY(dst, src) (memcpy(dst, src, MDBX_PNL_SIZEOF(src)))
-#define MDBX_PNL_FIRST(pl) ((pl)[1])
-#define MDBX_PNL_LAST(pl) ((pl)[(pl)[0]])
-
-/* Current max length of an mdbx_pnl_alloc()ed PNL */
-#define MDBX_PNL_ALLOCLEN(pl) ((pl)[-1])
-
-/*----------------------------------------------------------------------------*/
-/* Internal structures */
-
-/* Auxiliary DB info.
- * The information here is mostly static/read-only. There is
- * only a single copy of this record in the environment. */
-typedef struct MDBX_dbx {
- MDBX_val md_name; /* name of the database */
- MDBX_cmp_func *md_cmp; /* function for comparing keys */
- MDBX_cmp_func *md_dcmp; /* function for comparing data items */
-} MDBX_dbx;
-
-/* A database transaction.
- * Every operation requires a transaction handle. */
-struct MDBX_txn {
-#define MDBX_MT_SIGNATURE UINT32_C(0x93D53A31)
- size_t mt_signature;
- MDBX_txn *mt_parent; /* parent of a nested txn */
- /* Nested txn under this txn, set together with flag MDBX_TXN_HAS_CHILD */
- MDBX_txn *mt_child;
- pgno_t mt_next_pgno; /* next unallocated page */
- pgno_t mt_end_pgno; /* corresponding to the current size of datafile */
- /* The ID of this transaction. IDs are integers incrementing from 1.
- * Only committed write transactions increment the ID. If a transaction
- * aborts, the ID may be re-used by the next writer. */
- txnid_t mt_txnid;
- MDBX_env *mt_env; /* the DB environment */
- /* The list of reclaimed txns from freeDB */
- MDBX_TXL mt_lifo_reclaimed;
- /* The list of pages that became unused during this transaction. */
- MDBX_PNL mt_befree_pages;
- /* The list of loose pages that became unused and may be reused
- * in this transaction, linked through NEXT_LOOSE_PAGE(page). */
- MDBX_page *mt_loose_pages;
- /* Number of loose pages (mt_loose_pages) */
- unsigned mt_loose_count;
- /* The sorted list of dirty pages we temporarily wrote to disk
- * because the dirty list was full. page numbers in here are
- * shifted left by 1, deleted slots have the LSB set. */
- MDBX_PNL mt_spill_pages;
- union {
- /* For write txns: Modified pages. Sorted when not MDBX_WRITEMAP. */
- MDBX_ID2L mt_rw_dirtylist;
- /* For read txns: This thread/txn's reader table slot, or NULL. */
- MDBX_reader *mt_ro_reader;
- };
- /* Array of records for each DB known in the environment. */
- MDBX_dbx *mt_dbxs;
- /* Array of MDBX_db records for each known DB */
- MDBX_db *mt_dbs;
- /* Array of sequence numbers for each DB handle */
- unsigned *mt_dbiseqs;
-
-/* Transaction DB Flags */
-#define DB_DIRTY MDBX_TBL_DIRTY /* DB was written in this txn */
-#define DB_STALE MDBX_TBL_STALE /* Named-DB record is older than txnID */
-#define DB_NEW MDBX_TBL_NEW /* Named-DB handle opened in this txn */
-#define DB_VALID 0x08 /* DB handle is valid, see also MDBX_VALID */
-#define DB_USRVALID 0x10 /* As DB_VALID, but not set for FREE_DBI */
-#define DB_DUPDATA 0x20 /* DB is MDBX_DUPSORT data */
- /* In write txns, array of cursors for each DB */
- MDBX_cursor **mt_cursors;
- /* Array of flags for each DB */
- uint8_t *mt_dbflags;
- /* Number of DB records in use, or 0 when the txn is finished.
- * This number only ever increments until the txn finishes; we
- * don't decrement it when individual DB handles are closed. */
- MDBX_dbi mt_numdbs;
-
-/* Transaction Flags */
-/* mdbx_txn_begin() flags */
-#define MDBX_TXN_BEGIN_FLAGS \
- (MDBX_NOMETASYNC | MDBX_NOSYNC | MDBX_RDONLY | MDBX_TRYTXN)
-#define MDBX_TXN_NOMETASYNC \
- MDBX_NOMETASYNC /* don't sync meta for this txn on commit */
-#define MDBX_TXN_NOSYNC MDBX_NOSYNC /* don't sync this txn on commit */
-#define MDBX_TXN_RDONLY MDBX_RDONLY /* read-only transaction */
- /* internal txn flags */
-#define MDBX_TXN_WRITEMAP MDBX_WRITEMAP /* copy of MDBX_env flag in writers */
-#define MDBX_TXN_FINISHED 0x01 /* txn is finished or never began */
-#define MDBX_TXN_ERROR 0x02 /* txn is unusable after an error */
-#define MDBX_TXN_DIRTY 0x04 /* must write, even if dirty list is empty */
-#define MDBX_TXN_SPILLS 0x08 /* txn or a parent has spilled pages */
-#define MDBX_TXN_HAS_CHILD 0x10 /* txn has an MDBX_txn.mt_child */
-/* most operations on the txn are currently illegal */
-#define MDBX_TXN_BLOCKED \
- (MDBX_TXN_FINISHED | MDBX_TXN_ERROR | MDBX_TXN_HAS_CHILD)
- unsigned mt_flags;
- /* dirtylist room: Array size - dirty pages visible to this txn.
- * Includes ancestor txns' dirty pages not hidden by other txns'
- * dirty/spilled pages. Thus commit(nested txn) has room to merge
- * dirtylist into mt_parent after freeing hidden mt_parent pages. */
- unsigned mt_dirtyroom;
- mdbx_tid_t mt_owner; /* thread ID that owns this transaction */
- mdbx_canary mt_canary;
-};
-
-/* Enough space for 2^32 nodes with minimum of 2 keys per node. I.e., plenty.
- * At 4 keys per node, enough for 2^64 nodes, so there's probably no need to
- * raise this on a 64 bit machine. */
-#define CURSOR_STACK 32
-
-struct MDBX_xcursor;
-
-/* Cursors are used for all DB operations.
- * A cursor holds a path of (page pointer, key index) from the DB
- * root to a position in the DB, plus other state. MDBX_DUPSORT
- * cursors include an xcursor to the current data item. Write txns
- * track their cursors and keep them up to date when data moves.
- * Exception: An xcursor's pointer to a P_SUBP page can be stale.
- * (A node with F_DUPDATA but no F_SUBDATA contains a subpage). */
-struct MDBX_cursor {
-#define MDBX_MC_SIGNATURE UINT32_C(0xFE05D5B1)
-#define MDBX_MC_READY4CLOSE UINT32_C(0x2817A047)
-#define MDBX_MC_WAIT4EOT UINT32_C(0x90E297A7)
- uint32_t mc_signature;
- /* The database handle this cursor operates on */
- MDBX_dbi mc_dbi;
- /* Next cursor on this DB in this txn */
- MDBX_cursor *mc_next;
- /* Backup of the original cursor if this cursor is a shadow */
- MDBX_cursor *mc_backup;
- /* Context used for databases with MDBX_DUPSORT, otherwise NULL */
- struct MDBX_xcursor *mc_xcursor;
- /* The transaction that owns this cursor */
- MDBX_txn *mc_txn;
- /* The database record for this cursor */
- MDBX_db *mc_db;
- /* The database auxiliary record for this cursor */
- MDBX_dbx *mc_dbx;
- /* The mt_dbflag for this database */
- uint8_t *mc_dbflag;
- uint16_t mc_snum; /* number of pushed pages */
- uint16_t mc_top; /* index of top page, normally mc_snum-1 */
- /* Cursor state flags. */
-#define C_INITIALIZED 0x01 /* cursor has been initialized and is valid */
-#define C_EOF 0x02 /* No more data */
-#define C_SUB 0x04 /* Cursor is a sub-cursor */
-#define C_DEL 0x08 /* last op was a cursor_del */
-#define C_UNTRACK 0x40 /* Un-track cursor when closing */
-#define C_RECLAIMING 0x80 /* FreeDB lookup is prohibited */
- unsigned mc_flags; /* see mdbx_cursor */
- MDBX_page *mc_pg[CURSOR_STACK]; /* stack of pushed pages */
- indx_t mc_ki[CURSOR_STACK]; /* stack of page indices */
-};
-
-/* Context for sorted-dup records.
- * We could have gone to a fully recursive design, with arbitrarily
- * deep nesting of sub-databases. But for now we only handle these
- * levels - main DB, optional sub-DB, sorted-duplicate DB. */
-typedef struct MDBX_xcursor {
- /* A sub-cursor for traversing the Dup DB */
- MDBX_cursor mx_cursor;
- /* The database record for this Dup DB */
- MDBX_db mx_db;
- /* The auxiliary DB record for this Dup DB */
- MDBX_dbx mx_dbx;
- /* The mt_dbflag for this Dup DB */
- uint8_t mx_dbflag;
-} MDBX_xcursor;
-
-/* Check if there is an inited xcursor, so XCURSOR_REFRESH() is proper */
-#define XCURSOR_INITED(mc) \
- ((mc)->mc_xcursor && ((mc)->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED))
-
-/* Update sub-page pointer, if any, in mc->mc_xcursor.
- * Needed when the node which contains the sub-page may have moved.
- * Called with mp = mc->mc_pg[mc->mc_top], ki = mc->mc_ki[mc->mc_top]. */
-#define XCURSOR_REFRESH(mc, mp, ki) \
- do { \
- MDBX_page *xr_pg = (mp); \
- MDBX_node *xr_node = NODEPTR(xr_pg, ki); \
- if ((xr_node->mn_flags & (F_DUPDATA | F_SUBDATA)) == F_DUPDATA) \
- (mc)->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(xr_node); \
- } while (0)
-
-/* State of FreeDB old pages, stored in the MDBX_env */
-typedef struct MDBX_pgstate {
- pgno_t *mf_reclaimed_pglist; /* Reclaimed freeDB pages, or NULL before use */
- txnid_t mf_last_reclaimed; /* ID of last used record, or 0 if
- !mf_reclaimed_pglist */
-} MDBX_pgstate;
-
-/* The database environment. */
-struct MDBX_env {
-#define MDBX_ME_SIGNATURE UINT32_C(0x9A899641)
- size_t me_signature;
- mdbx_mmap_t me_dxb_mmap; /* The main data file */
-#define me_map me_dxb_mmap.dxb
-#define me_fd me_dxb_mmap.fd
-#define me_mapsize me_dxb_mmap.length
- mdbx_mmap_t me_lck_mmap; /* The lock file */
-#define me_lfd me_lck_mmap.fd
-#define me_lck me_lck_mmap.lck
-
-/* Failed to update the meta page. Probably an I/O error. */
-#define MDBX_FATAL_ERROR UINT32_C(0x80000000)
-/* Additional flag for mdbx_sync_locked() */
-#define MDBX_SHRINK_ALLOWED UINT32_C(0x40000000)
-/* Some fields are initialized. */
-#define MDBX_ENV_ACTIVE UINT32_C(0x20000000)
-/* me_txkey is set */
-#define MDBX_ENV_TXKEY UINT32_C(0x10000000)
- uint32_t me_flags; /* see mdbx_env */
- unsigned me_psize; /* DB page size, inited from me_os_psize */
- unsigned me_psize2log; /* log2 of DB page size */
- unsigned me_os_psize; /* OS page size, from mdbx_syspagesize() */
- unsigned me_maxreaders; /* size of the reader table */
- /* Max MDBX_lockinfo.mti_numreaders of interest to mdbx_env_close() */
- unsigned me_close_readers;
- mdbx_fastmutex_t me_dbi_lock;
- MDBX_dbi me_numdbs; /* number of DBs opened */
- MDBX_dbi me_maxdbs; /* size of the DB table */
- mdbx_pid_t me_pid; /* process ID of this env */
- mdbx_thread_key_t me_txkey; /* thread-key for readers */
- char *me_path; /* path to the DB files */
- void *me_pbuf; /* scratch area for DUPSORT put() */
- MDBX_txn *me_txn; /* current write transaction */
- MDBX_txn *me_txn0; /* prealloc'd write transaction */
- MDBX_dbx *me_dbxs; /* array of static DB info */
- uint16_t *me_dbflags; /* array of flags from MDBX_db.md_flags */
- unsigned *me_dbiseqs; /* array of dbi sequence numbers */
- volatile txnid_t *me_oldest; /* ID of oldest reader last time we looked */
- MDBX_pgstate me_pgstate; /* state of old pages from freeDB */
-#define me_last_reclaimed me_pgstate.mf_last_reclaimed
-#define me_reclaimed_pglist me_pgstate.mf_reclaimed_pglist
- MDBX_page *me_dpages; /* list of malloc'd blocks for re-use */
- /* PNL of pages that became unused in a write txn */
- MDBX_PNL me_free_pgs;
- /* ID2L of pages written during a write txn. Length MDBX_PNL_UM_SIZE. */
- MDBX_ID2L me_dirtylist;
- /* Max number of freelist items that can fit in a single overflow page */
- unsigned me_maxfree_1pg;
- /* Max size of a node on a page */
- unsigned me_nodemax;
- unsigned me_maxkey_limit; /* max size of a key */
- mdbx_pid_t me_live_reader; /* have liveness lock in reader table */
- void *me_userctx; /* User-settable context */
- size_t me_sync_pending; /* Total dirty/non-sync'ed bytes
- * since the last mdbx_env_sync() */
- size_t me_sync_threshold; /* Treshold of above to force synchronous flush */
- MDBX_oom_func *me_oom_func; /* Callback for kicking laggard readers */
- txnid_t me_oldest_stub;
-#if MDBX_DEBUG
- MDBX_assert_func *me_assert_func; /* Callback for assertion failures */
-#endif
-#ifdef USE_VALGRIND
- int me_valgrind_handle;
-#endif
-
- struct {
- size_t lower; /* minimal size of datafile */
- size_t upper; /* maximal size of datafile */
- size_t now; /* current size of datafile */
- size_t grow; /* step to grow datafile */
- size_t shrink; /* threshold to shrink datafile */
- } me_dbgeo; /* */
-};
-
-/* Nested transaction */
-typedef struct MDBX_ntxn {
- MDBX_txn mnt_txn; /* the transaction */
- MDBX_pgstate mnt_pgstate; /* parent transaction's saved freestate */
-} MDBX_ntxn;
-
-/*----------------------------------------------------------------------------*/
-/* Debug and Logging stuff */
-
-extern int mdbx_runtime_flags;
-extern MDBX_debug_func *mdbx_debug_logger;
-extern txnid_t mdbx_debug_edge;
-
-void mdbx_debug_log(int type, const char *function, int line, const char *fmt,
- ...)
-#if defined(__GNUC__) || __has_attribute(format)
- __attribute__((format(printf, 4, 5)))
-#endif
- ;
-
-void mdbx_panic(const char *fmt, ...)
-#if defined(__GNUC__) || __has_attribute(format)
- __attribute__((format(printf, 1, 2)))
-#endif
- ;
-
-#if MDBX_DEBUG
-
-#define mdbx_assert_enabled() unlikely(mdbx_runtime_flags &MDBX_DBG_ASSERT)
-
-#define mdbx_audit_enabled() unlikely(mdbx_runtime_flags &MDBX_DBG_AUDIT)
-
-#define mdbx_debug_enabled(type) \
- unlikely(mdbx_runtime_flags &(type & (MDBX_DBG_TRACE | MDBX_DBG_EXTRA)))
-
-#else
-#define mdbx_debug_enabled(type) (0)
-#define mdbx_audit_enabled() (0)
-#ifndef NDEBUG
-#define mdbx_assert_enabled() (1)
-#else
-#define mdbx_assert_enabled() (0)
-#endif /* NDEBUG */
-#endif /* MDBX_DEBUG */
-
-#define mdbx_print(fmt, ...) \
- mdbx_debug_log(MDBX_DBG_PRINT, NULL, 0, fmt, ##__VA_ARGS__)
-
-#define mdbx_trace(fmt, ...) \
- do { \
- if (mdbx_debug_enabled(MDBX_DBG_TRACE)) \
- mdbx_debug_log(MDBX_DBG_TRACE, __FUNCTION__, __LINE__, fmt "\n", \
- ##__VA_ARGS__); \
- } while (0)
-
-#define mdbx_verbose(fmt, ...) \
- do { \
- if (mdbx_debug_enabled(MDBX_DBG_TRACE /* FIXME */)) \
- mdbx_debug_log(MDBX_DBG_TRACE /* FIXME */, __FUNCTION__, __LINE__, \
- fmt "\n", ##__VA_ARGS__); \
- } while (0)
-
-#define mdbx_info(fmt, ...) \
- do { \
- if (mdbx_debug_enabled(MDBX_DBG_TRACE /* FIXME */)) \
- mdbx_debug_log(MDBX_DBG_TRACE /* FIXME */, __FUNCTION__, __LINE__, \
- fmt "\n", ##__VA_ARGS__); \
- } while (0)
-
-#define mdbx_notice(fmt, ...) \
- do { \
- if (mdbx_debug_enabled(MDBX_DBG_TRACE /* FIXME */)) \
- mdbx_debug_log(MDBX_DBG_TRACE /* FIXME */, __FUNCTION__, __LINE__, \
- fmt "\n", ##__VA_ARGS__); \
- } while (0)
-
-#define mdbx_warning(fmt, ...) \
- do { \
- if (mdbx_debug_enabled(MDBX_DBG_TRACE /* FIXME */)) \
- mdbx_debug_log(MDBX_DBG_TRACE /* FIXME */, __FUNCTION__, __LINE__, \
- fmt "\n", ##__VA_ARGS__); \
- } while (0)
-
-#define mdbx_error(fmt, ...) \
- do { \
- if (mdbx_debug_enabled(MDBX_DBG_TRACE /* FIXME */)) \
- mdbx_debug_log(MDBX_DBG_TRACE /* FIXME */, __FUNCTION__, __LINE__, \
- fmt "\n", ##__VA_ARGS__); \
- } while (0)
-
-#define mdbx_fatal(fmt, ...) \
- do { \
- if (mdbx_debug_enabled(MDBX_DBG_TRACE /* FIXME */)) \
- mdbx_debug_log(MDBX_DBG_TRACE /* FIXME */, __FUNCTION__, __LINE__, \
- fmt "\n", ##__VA_ARGS__); \
- } while (0)
-
-#define mdbx_debug(fmt, ...) \
- do { \
- if (mdbx_debug_enabled(MDBX_DBG_TRACE)) \
- mdbx_debug_log(MDBX_DBG_TRACE, __FUNCTION__, __LINE__, fmt "\n", \
- ##__VA_ARGS__); \
- } while (0)
-
-#define mdbx_debug_print(fmt, ...) \
- do { \
- if (mdbx_debug_enabled(MDBX_DBG_TRACE)) \
- mdbx_debug_log(MDBX_DBG_TRACE, NULL, 0, fmt, ##__VA_ARGS__); \
- } while (0)
-
-#define mdbx_debug_extra(fmt, ...) \
- do { \
- if (mdbx_debug_enabled(MDBX_DBG_EXTRA)) \
- mdbx_debug_log(MDBX_DBG_EXTRA, __FUNCTION__, __LINE__, fmt, \
- ##__VA_ARGS__); \
- } while (0)
-
-#define mdbx_debug_extra_print(fmt, ...) \
- do { \
- if (mdbx_debug_enabled(MDBX_DBG_EXTRA)) \
- mdbx_debug_log(MDBX_DBG_EXTRA, NULL, 0, fmt, ##__VA_ARGS__); \
- } while (0)
-
-#define mdbx_ensure_msg(env, expr, msg) \
- do { \
- if (unlikely(!(expr))) \
- mdbx_assert_fail(env, msg, __FUNCTION__, __LINE__); \
- } while (0)
-
-#define mdbx_ensure(env, expr) mdbx_ensure_msg(env, expr, #expr)
-
-/* assert(3) variant in environment context */
-#define mdbx_assert(env, expr) \
- do { \
- if (mdbx_assert_enabled()) \
- mdbx_ensure(env, expr); \
- } while (0)
-
-/* assert(3) variant in cursor context */
-#define mdbx_cassert(mc, expr) mdbx_assert((mc)->mc_txn->mt_env, expr)
-
-/* assert(3) variant in transaction context */
-#define mdbx_tassert(txn, expr) mdbx_assert((txn)->mt_env, expr)
-
-static __inline void mdbx_jitter4testing(bool tiny) {
-#ifndef NDEBUG
- if (MDBX_DBG_JITTER & mdbx_runtime_flags)
- mdbx_osal_jitter(tiny);
-#else
- (void)tiny;
-#endif
-}
-
-/*----------------------------------------------------------------------------*/
-/* Internal prototypes and inlines */
-
-int mdbx_reader_check0(MDBX_env *env, int rlocked, int *dead);
-void mdbx_rthc_dtor(void *rthc);
-void mdbx_rthc_lock(void);
-void mdbx_rthc_unlock(void);
-int mdbx_rthc_alloc(mdbx_thread_key_t *key, MDBX_reader *begin,
- MDBX_reader *end);
-void mdbx_rthc_remove(mdbx_thread_key_t key);
-void mdbx_rthc_cleanup(void);
-
-static __inline bool mdbx_is_power2(size_t x) { return (x & (x - 1)) == 0; }
-
-static __inline size_t mdbx_roundup2(size_t value, size_t granularity) {
- assert(mdbx_is_power2(granularity));
- return (value + granularity - 1) & ~(granularity - 1);
-}
-
-static __inline unsigned mdbx_log2(size_t value) {
- assert(mdbx_is_power2(value));
-
- unsigned log = 0;
- while (value > 1) {
- log += 1;
- value >>= 1;
- }
- return log;
-}
-
-#define MDBX_IS_ERROR(rc) \
- ((rc) != MDBX_RESULT_TRUE && (rc) != MDBX_RESULT_FALSE)
-
-/* Internal error codes, not exposed outside libmdbx */
-#define MDBX_NO_ROOT (MDBX_LAST_ERRCODE + 10)
-
-/* Debuging output value of a cursor DBI: Negative in a sub-cursor. */
-#define DDBI(mc) \
- (((mc)->mc_flags & C_SUB) ? -(int)(mc)->mc_dbi : (int)(mc)->mc_dbi)
-
-/* Key size which fits in a DKBUF. */
-#define DKBUF_MAXKEYSIZE 511 /* FIXME */
-
-#if MDBX_DEBUG
-#define DKBUF char _kbuf[DKBUF_MAXKEYSIZE * 4 + 2]
-#define DKEY(x) mdbx_dkey(x, _kbuf, DKBUF_MAXKEYSIZE * 2 + 1)
-#define DVAL(x) \
- mdbx_dkey(x, _kbuf + DKBUF_MAXKEYSIZE * 2 + 1, DKBUF_MAXKEYSIZE * 2 + 1)
-#else
-#define DKBUF ((void)(0))
-#define DKEY(x) ("-")
-#define DVAL(x) ("-")
-#endif
-
-/* An invalid page number.
- * Mainly used to denote an empty tree. */
-#define P_INVALID (~(pgno_t)0)
-
-/* Test if the flags f are set in a flag word w. */
-#define F_ISSET(w, f) (((w) & (f)) == (f))
-
-/* Round n up to an even number. */
-#define EVEN(n) (((n) + 1U) & -2) /* sign-extending -2 to match n+1U */
-
-/* Default size of memory map.
- * This is certainly too small for any actual applications. Apps should
- * always set the size explicitly using mdbx_env_set_mapsize(). */
-#define DEFAULT_MAPSIZE 1048576
-
-/* Number of slots in the reader table.
- * This value was chosen somewhat arbitrarily. The 61 is a prime number,
- * and such readers plus a couple mutexes fit into single 4KB page.
- * Applications should set the table size using mdbx_env_set_maxreaders(). */
-#define DEFAULT_READERS 61
-
-/* Address of first usable data byte in a page, after the header */
-#define PAGEDATA(p) ((void *)((char *)(p) + PAGEHDRSZ))
-
-/* Number of nodes on a page */
-#define NUMKEYS(p) ((unsigned)(p)->mp_lower >> 1)
-
-/* The amount of space remaining in the page */
-#define SIZELEFT(p) (indx_t)((p)->mp_upper - (p)->mp_lower)
-
-/* The percentage of space used in the page, in tenths of a percent. */
-#define PAGEFILL(env, p) \
- (1024UL * ((env)->me_psize - PAGEHDRSZ - SIZELEFT(p)) / \
- ((env)->me_psize - PAGEHDRSZ))
-/* The minimum page fill factor, in tenths of a percent.
- * Pages emptier than this are candidates for merging. */
-#define FILL_THRESHOLD 256
-
-/* Test if a page is a leaf page */
-#define IS_LEAF(p) F_ISSET((p)->mp_flags, P_LEAF)
-/* Test if a page is a LEAF2 page */
-#define IS_LEAF2(p) F_ISSET((p)->mp_flags, P_LEAF2)
-/* Test if a page is a branch page */
-#define IS_BRANCH(p) F_ISSET((p)->mp_flags, P_BRANCH)
-/* Test if a page is an overflow page */
-#define IS_OVERFLOW(p) unlikely(F_ISSET((p)->mp_flags, P_OVERFLOW))
-/* Test if a page is a sub page */
-#define IS_SUBP(p) F_ISSET((p)->mp_flags, P_SUBP)
-
-/* The number of overflow pages needed to store the given size. */
-#define OVPAGES(env, size) (bytes2pgno(env, PAGEHDRSZ - 1 + (size)) + 1)
-
-/* Link in MDBX_txn.mt_loose_pages list.
- * Kept outside the page header, which is needed when reusing the page. */
-#define NEXT_LOOSE_PAGE(p) (*(MDBX_page **)((p) + 2))
-
-/* Header for a single key/data pair within a page.
- * Used in pages of type P_BRANCH and P_LEAF without P_LEAF2.
- * We guarantee 2-byte alignment for 'MDBX_node's.
- *
- * mn_lo and mn_hi are used for data size on leaf nodes, and for child
- * pgno on branch nodes. On 64 bit platforms, mn_flags is also used
- * for pgno. (Branch nodes have no flags). Lo and hi are in host byte
- * order in case some accesses can be optimized to 32-bit word access.
- *
- * Leaf node flags describe node contents. F_BIGDATA says the node's
- * data part is the page number of an overflow page with actual data.
- * F_DUPDATA and F_SUBDATA can be combined giving duplicate data in
- * a sub-page/sub-database, and named databases (just F_SUBDATA). */
-typedef struct MDBX_node {
- union {
- struct {
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- union {
- struct {
- uint16_t mn_lo, mn_hi; /* part of data size or pgno */
- };
- uint32_t mn_dsize;
- };
- uint16_t mn_flags; /* see mdbx_node */
- uint16_t mn_ksize; /* key size */
-#else
- uint16_t mn_ksize; /* key size */
- uint16_t mn_flags; /* see mdbx_node */
- union {
- struct {
- uint16_t mn_hi, mn_lo; /* part of data size or pgno */
- };
- uint32_t mn_dsize;
- };
-#endif
- };
- pgno_t mn_ksize_and_pgno;
- };
-
-/* mdbx_node Flags */
-#define F_BIGDATA 0x01 /* data put on overflow page */
-#define F_SUBDATA 0x02 /* data is a sub-database */
-#define F_DUPDATA 0x04 /* data has duplicates */
-
-/* valid flags for mdbx_node_add() */
-#define NODE_ADD_FLAGS (F_DUPDATA | F_SUBDATA | MDBX_RESERVE | MDBX_APPEND)
- uint8_t mn_data[1]; /* key and data are appended here */
-} MDBX_node;
-
-/* Size of the node header, excluding dynamic data at the end */
-#define NODESIZE offsetof(MDBX_node, mn_data)
-
-/* Bit position of top word in page number, for shifting mn_flags */
-#define PGNO_TOPWORD ((pgno_t)-1 > 0xffffffffu ? 32 : 0)
-
-/* Size of a node in a branch page with a given key.
- * This is just the node header plus the key, there is no data. */
-#define INDXSIZE(k) (NODESIZE + ((k) == NULL ? 0 : (k)->iov_len))
-
-/* Size of a node in a leaf page with a given key and data.
- * This is node header plus key plus data size. */
-#define LEAFSIZE(k, d) (NODESIZE + (k)->iov_len + (d)->iov_len)
-
-/* Address of node i in page p */
-static __inline MDBX_node *NODEPTR(MDBX_page *p, unsigned i) {
- assert(NUMKEYS(p) > (unsigned)(i));
- return (MDBX_node *)((char *)(p) + (p)->mp_ptrs[i] + PAGEHDRSZ);
-}
-
-/* Address of the key for the node */
-#define NODEKEY(node) (void *)((node)->mn_data)
-
-/* Address of the data for a node */
-#define NODEDATA(node) (void *)((char *)(node)->mn_data + (node)->mn_ksize)
-
-/* Get the page number pointed to by a branch node */
-static __inline pgno_t NODEPGNO(const MDBX_node *node) {
- pgno_t pgno;
- if (UNALIGNED_OK) {
- pgno = node->mn_ksize_and_pgno;
- if (sizeof(pgno_t) > 4)
- pgno &= MAX_PAGENO;
- } else {
- pgno = node->mn_lo | ((pgno_t)node->mn_hi << 16);
- if (sizeof(pgno_t) > 4)
- pgno |= ((uint64_t)node->mn_flags) << 32;
- }
- return pgno;
-}
-
-/* Set the page number in a branch node */
-static __inline void SETPGNO(MDBX_node *node, pgno_t pgno) {
- assert(pgno <= MAX_PAGENO);
-
- if (UNALIGNED_OK) {
- if (sizeof(pgno_t) > 4)
- pgno |= ((uint64_t)node->mn_ksize) << 48;
- node->mn_ksize_and_pgno = pgno;
- } else {
- node->mn_lo = (uint16_t)pgno;
- node->mn_hi = (uint16_t)(pgno >> 16);
- if (sizeof(pgno_t) > 4)
- node->mn_flags = (uint16_t)((uint64_t)pgno >> 32);
- }
-}
-
-/* Get the size of the data in a leaf node */
-static __inline size_t NODEDSZ(const MDBX_node *node) {
- size_t size;
- if (UNALIGNED_OK) {
- size = node->mn_dsize;
- } else {
- size = node->mn_lo | ((size_t)node->mn_hi << 16);
- }
- return size;
-}
-
-/* Set the size of the data for a leaf node */
-static __inline void SETDSZ(MDBX_node *node, size_t size) {
- assert(size < INT_MAX);
- if (UNALIGNED_OK) {
- node->mn_dsize = (uint32_t)size;
- } else {
- node->mn_lo = (uint16_t)size;
- node->mn_hi = (uint16_t)(size >> 16);
- }
-}
-
-/* The size of a key in a node */
-#define NODEKSZ(node) ((node)->mn_ksize)
-
-/* The address of a key in a LEAF2 page.
- * LEAF2 pages are used for MDBX_DUPFIXED sorted-duplicate sub-DBs.
- * There are no node headers, keys are stored contiguously. */
-#define LEAF2KEY(p, i, ks) ((char *)(p) + PAGEHDRSZ + ((i) * (ks)))
-
-/* Set the node's key into keyptr, if requested. */
-#define MDBX_GET_KEY(node, keyptr) \
- do { \
- if ((keyptr) != NULL) { \
- (keyptr)->iov_len = NODEKSZ(node); \
- (keyptr)->iov_base = NODEKEY(node); \
- } \
- } while (0)
-
-/* Set the node's key into key. */
-#define MDBX_GET_KEY2(node, key) \
- do { \
- key.iov_len = NODEKSZ(node); \
- key.iov_base = NODEKEY(node); \
- } while (0)
-
-#define MDBX_VALID 0x8000 /* DB handle is valid, for me_dbflags */
-#define PERSISTENT_FLAGS (0xffff & ~(MDBX_VALID))
-/* mdbx_dbi_open() flags */
-#define VALID_FLAGS \
- (MDBX_REVERSEKEY | MDBX_DUPSORT | MDBX_INTEGERKEY | MDBX_DUPFIXED | \
- MDBX_INTEGERDUP | MDBX_REVERSEDUP | MDBX_CREATE)
-
-/* max number of pages to commit in one writev() call */
-#define MDBX_COMMIT_PAGES 64
-#if defined(IOV_MAX) && IOV_MAX < MDBX_COMMIT_PAGES /* sysconf(_SC_IOV_MAX) */
-#undef MDBX_COMMIT_PAGES
-#define MDBX_COMMIT_PAGES IOV_MAX
-#endif
-
-/* Check txn and dbi arguments to a function */
-#define TXN_DBI_EXIST(txn, dbi, validity) \
- ((dbi) < (txn)->mt_numdbs && ((txn)->mt_dbflags[dbi] & (validity)))
-
-/* Check for misused dbi handles */
-#define TXN_DBI_CHANGED(txn, dbi) \
- ((txn)->mt_dbiseqs[dbi] != (txn)->mt_env->me_dbiseqs[dbi])
-
-/* LY: fast enough on most systems
- *
- * /
- * | -1, a < b
- * cmp2int(a,b) = < 0, a == b
- * | 1, a > b
- * \
- */
-#if 1
-#define mdbx_cmp2int(a, b) (((b) > (a)) ? -1 : (a) > (b))
-#else
-#define mdbx_cmp2int(a, b) (((a) > (b)) - ((b) > (a)))
-#endif
-
-static __inline size_t pgno2bytes(const MDBX_env *env, pgno_t pgno) {
- mdbx_assert(env, (1u << env->me_psize2log) == env->me_psize);
- return ((size_t)pgno) << env->me_psize2log;
-}
-
-static __inline MDBX_page *pgno2page(const MDBX_env *env, pgno_t pgno) {
- return (MDBX_page *)(env->me_map + pgno2bytes(env, pgno));
-}
-
-static __inline pgno_t bytes2pgno(const MDBX_env *env, size_t bytes) {
- mdbx_assert(env, (env->me_psize >> env->me_psize2log) == 1);
- return (pgno_t)(bytes >> env->me_psize2log);
-}
-
-static __inline pgno_t pgno_add(pgno_t base, pgno_t augend) {
- assert(base <= MAX_PAGENO);
- return (augend < MAX_PAGENO - base) ? base + augend : MAX_PAGENO;
-}
-
-static __inline pgno_t pgno_sub(pgno_t base, pgno_t subtrahend) {
- assert(base >= MIN_PAGENO);
- return (subtrahend < base - MIN_PAGENO) ? base - subtrahend : MIN_PAGENO;
-}
-
-static __inline size_t pgno_align2os_bytes(const MDBX_env *env, pgno_t pgno) {
- return mdbx_roundup2(pgno2bytes(env, pgno), env->me_os_psize);
-}
-
-static __inline pgno_t pgno_align2os_pgno(const MDBX_env *env, pgno_t pgno) {
- return bytes2pgno(env, pgno_align2os_bytes(env, pgno));
-}
diff --git a/plugins/Dbx_mdb/src/mdbx/defs.h b/plugins/Dbx_mdb/src/mdbx/defs.h
deleted file mode 100644
index 800553bb17..0000000000
--- a/plugins/Dbx_mdb/src/mdbx/defs.h
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
- * and other libmdbx authors: please see AUTHORS file.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#pragma once
-/* *INDENT-OFF* */
-/* clang-format off */
-
-#ifndef __GNUC_PREREQ
-# if defined(__GNUC__) && defined(__GNUC_MINOR__)
-# define __GNUC_PREREQ(maj, min) \
- ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
-# else
-# define __GNUC_PREREQ(maj, min) (0)
-# endif
-#endif /* __GNUC_PREREQ */
-
-#ifndef __CLANG_PREREQ
-# ifdef __clang__
-# define __CLANG_PREREQ(maj,min) \
- ((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min))
-# else
-# define __CLANG_PREREQ(maj,min) (0)
-# endif
-#endif /* __CLANG_PREREQ */
-
-#ifndef __GLIBC_PREREQ
-# if defined(__GLIBC__) && defined(__GLIBC_MINOR__)
-# define __GLIBC_PREREQ(maj, min) \
- ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min))
-# else
-# define __GLIBC_PREREQ(maj, min) (0)
-# endif
-#endif /* __GLIBC_PREREQ */
-
-#ifndef __has_attribute
-# define __has_attribute(x) (0)
-#endif
-
-#ifndef __has_feature
-# define __has_feature(x) (0)
-#endif
-
-#ifndef __has_extension
-# define __has_extension(x) (0)
-#endif
-
-#ifndef __has_builtin
-# define __has_builtin(x) (0)
-#endif
-
-#if __has_feature(thread_sanitizer)
-# define __SANITIZE_THREAD__ 1
-#endif
-
-#if __has_feature(address_sanitizer)
-# define __SANITIZE_ADDRESS__ 1
-#endif
-
-/*----------------------------------------------------------------------------*/
-
-#ifndef __extern_C
-# ifdef __cplusplus
-# define __extern_C extern "C"
-# else
-# define __extern_C
-# endif
-#endif /* __extern_C */
-
-#ifndef __cplusplus
-# ifndef bool
-# define bool _Bool
-# endif
-# ifndef true
-# define true (1)
-# endif
-# ifndef false
-# define false (0)
-# endif
-#endif
-
-#if !defined(nullptr) && !defined(__cplusplus) || (__cplusplus < 201103L && !defined(_MSC_VER))
-# define nullptr NULL
-#endif
-
-/*----------------------------------------------------------------------------*/
-
-#if !defined(__thread) && (defined(_MSC_VER) || defined(__DMC__))
-# define __thread __declspec(thread)
-#endif /* __thread */
-
-#ifndef __alwaysinline
-# if defined(__GNUC__) || __has_attribute(always_inline)
-# define __alwaysinline __inline __attribute__((always_inline))
-# elif defined(_MSC_VER)
-# define __alwaysinline __forceinline
-# else
-# define __alwaysinline
-# endif
-#endif /* __alwaysinline */
-
-#ifndef __noinline
-# if defined(__GNUC__) || __has_attribute(noinline)
-# define __noinline __attribute__((noinline))
-# elif defined(_MSC_VER)
-# define __noinline __declspec(noinline)
-# elif defined(__SUNPRO_C) || defined(__sun) || defined(sun)
-# define __noinline inline
-# elif !defined(__INTEL_COMPILER)
-# define __noinline /* FIXME ? */
-# endif
-#endif /* __noinline */
-
-#ifndef __must_check_result
-# if defined(__GNUC__) || __has_attribute(warn_unused_result)
-# define __must_check_result __attribute__((warn_unused_result))
-# else
-# define __must_check_result
-# endif
-#endif /* __must_check_result */
-
-#ifndef __deprecated
-# if defined(__GNUC__) || __has_attribute(deprecated)
-# define __deprecated __attribute__((deprecated))
-# elif defined(_MSC_VER)
-# define __deprecated __declspec(deprecated)
-# else
-# define __deprecated
-# endif
-#endif /* __deprecated */
-
-#if !defined(__noop) && !defined(_MSC_VER)
-# ifdef __cplusplus
- static inline void __noop_consume_args() {}
- template <typename First, typename... Rest>
- static inline void
- __noop_consume_args(const First &first, const Rest &... rest) {
- (void) first; __noop_consume_args(rest...);
- }
-# define __noop(...) __noop_consume_args(__VA_ARGS__)
-# elif defined(__GNUC__) && (!defined(__STRICT_ANSI__) || !__STRICT_ANSI__)
- static __inline void __noop_consume_args(void* anchor, ...) {
- (void) anchor;
- }
-# define __noop(...) __noop_consume_args(0, ##__VA_ARGS__)
-# else
-# define __noop(...) do {} while(0)
-# endif
-#endif /* __noop */
-
-#ifndef __fallthrough
-# if __GNUC_PREREQ(7, 0) || __has_attribute(fallthrough)
-# define __fallthrough __attribute__((fallthrough))
-# else
-# define __fallthrough __noop()
-# endif
-#endif /* __fallthrough */
-
-#ifndef __unreachable
-# if __GNUC_PREREQ(4,5)
-# define __unreachable() __builtin_unreachable()
-# elif defined(_MSC_VER)
-# define __unreachable() __assume(0)
-# else
-# define __unreachable() __noop()
-# endif
-#endif /* __unreachable */
-
-#ifndef __prefetch
-# if defined(__GNUC__) || defined(__clang__)
-# define __prefetch(ptr) __builtin_prefetch(ptr)
-# else
-# define __prefetch(ptr) __noop(ptr)
-# endif
-#endif /* __prefetch */
-
-#ifndef __aligned
-# if defined(__GNUC__) || __has_attribute(aligned)
-# define __aligned(N) __attribute__((aligned(N)))
-# elif defined(_MSC_VER)
-# define __aligned(N) __declspec(align(N))
-# else
-# define __aligned(N)
-# endif
-#endif /* __aligned */
-
-#ifndef __noreturn
-# if defined(__GNUC__) || __has_attribute(noreturn)
-# define __noreturn __attribute__((noreturn))
-# elif defined(_MSC_VER)
-# define __noreturn __declspec(noreturn)
-# else
-# define __noreturn
-# endif
-#endif /* __noreturn */
-
-#ifndef __nothrow
-# if defined(__GNUC__) || __has_attribute(nothrow)
-# define __nothrow __attribute__((nothrow))
-# elif defined(_MSC_VER) && defined(__cplusplus)
-# define __nothrow __declspec(nothrow)
-# else
-# define __nothrow
-# endif
-#endif /* __nothrow */
-
-#ifndef __pure_function
- /* Many functions have no effects except the return value and their
- * return value depends only on the parameters and/or global variables.
- * Such a function can be subject to common subexpression elimination
- * and loop optimization just as an arithmetic operator would be.
- * These functions should be declared with the attribute pure. */
-# if defined(__GNUC__) || __has_attribute(pure)
-# define __pure_function __attribute__((pure))
-# else
-# define __pure_function
-# endif
-#endif /* __pure_function */
-
-#ifndef __const_function
- /* Many functions do not examine any values except their arguments,
- * and have no effects except the return value. Basically this is just
- * slightly more strict class than the PURE attribute, since function
- * is not allowed to read global memory.
- *
- * Note that a function that has pointer arguments and examines the
- * data pointed to must not be declared const. Likewise, a function
- * that calls a non-const function usually must not be const.
- * It does not make sense for a const function to return void. */
-# if defined(__GNUC__) || __has_attribute(const)
-# define __const_function __attribute__((const))
-# else
-# define __const_function
-# endif
-#endif /* __const_function */
-
-#ifndef __dll_hidden
-# if defined(__GNUC__) || __has_attribute(visibility)
-# define __hidden __attribute__((visibility("hidden")))
-# else
-# define __hidden
-# endif
-#endif /* __dll_hidden */
-
-#ifndef __optimize
-# if defined(__OPTIMIZE__)
-# if defined(__clang__) && !__has_attribute(optimize)
-# define __optimize(ops)
-# elif defined(__GNUC__) || __has_attribute(optimize)
-# define __optimize(ops) __attribute__((optimize(ops)))
-# else
-# define __optimize(ops)
-# endif
-# else
-# define __optimize(ops)
-# endif
-#endif /* __optimize */
-
-#ifndef __hot
-# if defined(__OPTIMIZE__)
-# if defined(__clang__) && !__has_attribute(hot)
- /* just put frequently used functions in separate section */
-# define __hot __attribute__((section("text.hot"))) __optimize("O3")
-# elif defined(__GNUC__) || __has_attribute(hot)
-# define __hot __attribute__((hot)) __optimize("O3")
-# else
-# define __hot __optimize("O3")
-# endif
-# else
-# define __hot
-# endif
-#endif /* __hot */
-
-#ifndef __cold
-# if defined(__OPTIMIZE__)
-# if defined(__clang__) && !__has_attribute(cold)
- /* just put infrequently used functions in separate section */
-# define __cold __attribute__((section("text.unlikely"))) __optimize("Os")
-# elif defined(__GNUC__) || __has_attribute(cold)
-# define __cold __attribute__((cold)) __optimize("Os")
-# else
-# define __cold __optimize("Os")
-# endif
-# else
-# define __cold
-# endif
-#endif /* __cold */
-
-#ifndef __flatten
-# if defined(__OPTIMIZE__) && (defined(__GNUC__) || __has_attribute(flatten))
-# define __flatten __attribute__((flatten))
-# else
-# define __flatten
-# endif
-#endif /* __flatten */
-
-#ifndef likely
-# if defined(__GNUC__) || defined(__clang__)
-# define likely(cond) __builtin_expect(!!(cond), 1)
-# else
-# define likely(x) (x)
-# endif
-#endif /* likely */
-
-#ifndef unlikely
-# if defined(__GNUC__) || defined(__clang__)
-# define unlikely(cond) __builtin_expect(!!(cond), 0)
-# else
-# define unlikely(x) (x)
-# endif
-#endif /* unlikely */
-
-/* Wrapper around __func__, which is a C99 feature */
-#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-# define mdbx_func_ __func__
-#elif (defined(__GNUC__) && __GNUC__ >= 2) || defined(__clang__) || defined(_MSC_VER)
-# define mdbx_func_ __FUNCTION__
-#else
-# define mdbx_func_ "<mdbx_unknown>"
-#endif
-
-/*----------------------------------------------------------------------------*/
-
-#if defined(USE_VALGRIND)
-# include <valgrind/memcheck.h>
-# ifndef VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE
- /* LY: available since Valgrind 3.10 */
-# define VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s)
-# define VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s)
-# endif
-#else
-# define VALGRIND_CREATE_MEMPOOL(h,r,z)
-# define VALGRIND_DESTROY_MEMPOOL(h)
-# define VALGRIND_MEMPOOL_TRIM(h,a,s)
-# define VALGRIND_MEMPOOL_ALLOC(h,a,s)
-# define VALGRIND_MEMPOOL_FREE(h,a)
-# define VALGRIND_MEMPOOL_CHANGE(h,a,b,s)
-# define VALGRIND_MAKE_MEM_NOACCESS(a,s)
-# define VALGRIND_MAKE_MEM_DEFINED(a,s)
-# define VALGRIND_MAKE_MEM_UNDEFINED(a,s)
-# define VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s)
-# define VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s)
-# define VALGRIND_CHECK_MEM_IS_ADDRESSABLE(a,s) (0)
-# define VALGRIND_CHECK_MEM_IS_DEFINED(a,s) (0)
-# define RUNNING_ON_VALGRIND (0)
-#endif /* USE_VALGRIND */
-
-#ifdef __SANITIZE_ADDRESS__
-# include <sanitizer/asan_interface.h>
-#else
-# define ASAN_POISON_MEMORY_REGION(addr, size) \
- ((void)(addr), (void)(size))
-# define ASAN_UNPOISON_MEMORY_REGION(addr, size) \
- ((void)(addr), (void)(size))
-#endif /* __SANITIZE_ADDRESS__ */
-
-/*----------------------------------------------------------------------------*/
-
-#ifndef ARRAY_LENGTH
-# ifdef __cplusplus
- template <typename T, size_t N>
- char (&__ArraySizeHelper(T (&array)[N]))[N];
-# define ARRAY_LENGTH(array) (sizeof(::__ArraySizeHelper(array)))
-# else
-# define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0]))
-# endif
-#endif /* ARRAY_LENGTH */
-
-#ifndef ARRAY_END
-# define ARRAY_END(array) (&array[ARRAY_LENGTH(array)])
-#endif /* ARRAY_END */
-
-#ifndef STRINGIFY
-# define STRINGIFY_HELPER(x) #x
-# define STRINGIFY(x) STRINGIFY_HELPER(x)
-#endif /* STRINGIFY */
-
-#ifndef offsetof
-# define offsetof(type, member) __builtin_offsetof(type, member)
-#endif /* offsetof */
-
-#ifndef container_of
-# define container_of(ptr, type, member) \
- ((type *)((char *)(ptr) - offsetof(type, member)))
-#endif /* container_of */
-
-#define MDBX_TETRAD(a, b, c, d) \
- ((uint32_t)(a) << 24 | (uint32_t)(b) << 16 | (uint32_t)(c) << 8 | (d))
-
-#define MDBX_STRING_TETRAD(str) MDBX_TETRAD(str[0], str[1], str[2], str[3])
-
-#define FIXME "FIXME: " __FILE__ ", " STRINGIFY(__LINE__)
-
-#ifndef STATIC_ASSERT_MSG
-# if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) \
- || __has_feature(c_static_assert)
-# define STATIC_ASSERT_MSG(expr, msg) _Static_assert(expr, msg)
-# elif defined(static_assert)
-# define STATIC_ASSERT_MSG(expr, msg) static_assert(expr, msg)
-# elif defined(_MSC_VER)
-# include <crtdbg.h>
-# define STATIC_ASSERT_MSG(expr, msg) _STATIC_ASSERT(expr)
-# else
-# define STATIC_ASSERT_MSG(expr, msg) switch (0) {case 0:case (expr):;}
-# endif
-#endif /* STATIC_ASSERT */
-
-#ifndef STATIC_ASSERT
-# define STATIC_ASSERT(expr) STATIC_ASSERT_MSG(expr, #expr)
-#endif
-
-/* *INDENT-ON* */
-/* clang-format on */
diff --git a/plugins/Dbx_mdb/src/mdbx/lck-windows.c b/plugins/Dbx_mdb/src/mdbx/lck-windows.c
deleted file mode 100644
index 0582b28d78..0000000000
--- a/plugins/Dbx_mdb/src/mdbx/lck-windows.c
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
- * and other libmdbx authors: please see AUTHORS file.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "./bits.h"
-
-/* PREAMBLE FOR WINDOWS:
- *
- * We are not concerned for performance here.
- * If you are running Windows a performance could NOT be the goal.
- * Otherwise please use Linux.
- *
- * Regards,
- * LY
- */
-
-/*----------------------------------------------------------------------------*/
-/* rthc */
-
-static CRITICAL_SECTION rthc_critical_section;
-
-static void NTAPI tls_callback(PVOID module, DWORD reason, PVOID reserved) {
- (void)module;
- (void)reserved;
- switch (reason) {
- case DLL_PROCESS_ATTACH:
- InitializeCriticalSection(&rthc_critical_section);
- break;
- case DLL_PROCESS_DETACH:
- DeleteCriticalSection(&rthc_critical_section);
- break;
-
- case DLL_THREAD_ATTACH:
- break;
- case DLL_THREAD_DETACH:
- mdbx_rthc_cleanup();
- break;
- }
-}
-
-void mdbx_rthc_lock(void) { EnterCriticalSection(&rthc_critical_section); }
-
-void mdbx_rthc_unlock(void) { LeaveCriticalSection(&rthc_critical_section); }
-
-/* *INDENT-OFF* */
-/* clang-format off */
-#if defined(_MSC_VER)
-# pragma const_seg(push)
-# pragma data_seg(push)
-
-# ifdef _WIN64
- /* kick a linker to create the TLS directory if not already done */
-# pragma comment(linker, "/INCLUDE:_tls_used")
- /* Force some symbol references. */
-# pragma comment(linker, "/INCLUDE:mdbx_tls_callback")
- /* specific const-segment for WIN64 */
-# pragma const_seg(".CRT$XLB")
- const
-# else
- /* kick a linker to create the TLS directory if not already done */
-# pragma comment(linker, "/INCLUDE:__tls_used")
- /* Force some symbol references. */
-# pragma comment(linker, "/INCLUDE:_mdbx_tls_callback")
- /* specific data-segment for WIN32 */
-# pragma data_seg(".CRT$XLB")
-# endif
-
- PIMAGE_TLS_CALLBACK mdbx_tls_callback = tls_callback;
-# pragma data_seg(pop)
-# pragma const_seg(pop)
-
-#elif defined(__GNUC__)
-# ifdef _WIN64
- const
-# endif
- PIMAGE_TLS_CALLBACK mdbx_tls_callback __attribute__((section(".CRT$XLB"), used))
- = tls_callback;
-#else
-# error FIXME
-#endif
-/* *INDENT-ON* */
-/* clang-format on */
-
-/*----------------------------------------------------------------------------*/
-
-#define LCK_SHARED 0
-#define LCK_EXCLUSIVE LOCKFILE_EXCLUSIVE_LOCK
-#define LCK_WAITFOR 0
-#define LCK_DONTWAIT LOCKFILE_FAIL_IMMEDIATELY
-
-static __inline BOOL flock(mdbx_filehandle_t fd, DWORD flags, uint64_t offset,
- size_t bytes) {
- OVERLAPPED ov;
- ov.hEvent = 0;
- ov.Offset = (DWORD)offset;
- ov.OffsetHigh = HIGH_DWORD(offset);
- return LockFileEx(fd, flags, 0, (DWORD)bytes, HIGH_DWORD(bytes), &ov);
-}
-
-static __inline BOOL funlock(mdbx_filehandle_t fd, uint64_t offset,
- size_t bytes) {
- return UnlockFile(fd, (DWORD)offset, HIGH_DWORD(offset), (DWORD)bytes,
- HIGH_DWORD(bytes));
-}
-
-/*----------------------------------------------------------------------------*/
-/* global `write` lock for write-txt processing,
- * exclusive locking both meta-pages) */
-
-#define LCK_MAXLEN (1u + (size_t)(MAXSSIZE_T))
-#define LCK_META_OFFSET 0
-#define LCK_META_LEN 0x10000u
-#define LCK_BODY_OFFSET LCK_META_LEN
-#define LCK_BODY_LEN (LCK_MAXLEN - LCK_BODY_OFFSET + 1u)
-#define LCK_META LCK_META_OFFSET, LCK_META_LEN
-#define LCK_BODY LCK_BODY_OFFSET, LCK_BODY_LEN
-#define LCK_WHOLE 0, LCK_MAXLEN
-
-int mdbx_txn_lock(MDBX_env *env, bool dontwait) {
- if (flock(env->me_fd, dontwait ? (LCK_EXCLUSIVE | LCK_DONTWAIT)
- : (LCK_EXCLUSIVE | LCK_WAITFOR),
- LCK_BODY))
- return MDBX_SUCCESS;
- int rc = GetLastError();
- return (!dontwait || rc != ERROR_LOCK_VIOLATION) ? rc : MDBX_BUSY;
-}
-
-void mdbx_txn_unlock(MDBX_env *env) {
- if (!funlock(env->me_fd, LCK_BODY))
- mdbx_panic("%s failed: errcode %u", mdbx_func_, GetLastError());
-}
-
-/*----------------------------------------------------------------------------*/
-/* global `read` lock for readers registration,
- * exclusive locking `mti_numreaders` (second) cacheline */
-
-#define LCK_LO_OFFSET 0
-#define LCK_LO_LEN offsetof(MDBX_lockinfo, mti_numreaders)
-#define LCK_UP_OFFSET LCK_LO_LEN
-#define LCK_UP_LEN (MDBX_LOCKINFO_WHOLE_SIZE - LCK_UP_OFFSET)
-#define LCK_LOWER LCK_LO_OFFSET, LCK_LO_LEN
-#define LCK_UPPER LCK_UP_OFFSET, LCK_UP_LEN
-
-int mdbx_rdt_lock(MDBX_env *env) {
- if (env->me_lfd == INVALID_HANDLE_VALUE)
- return MDBX_SUCCESS; /* readonly database in readonly filesystem */
-
- /* transite from S-? (used) to S-E (locked), e.g. exclusive lock upper-part */
- if (flock(env->me_lfd, LCK_EXCLUSIVE | LCK_WAITFOR, LCK_UPPER))
- return MDBX_SUCCESS;
- return GetLastError();
-}
-
-void mdbx_rdt_unlock(MDBX_env *env) {
- if (env->me_lfd != INVALID_HANDLE_VALUE) {
- /* transite from S-E (locked) to S-? (used), e.g. unlock upper-part */
- if (!funlock(env->me_lfd, LCK_UPPER))
- mdbx_panic("%s failed: errcode %u", mdbx_func_, GetLastError());
- }
-}
-
-/*----------------------------------------------------------------------------*/
-/* global `initial` lock for lockfile initialization,
- * exclusive/shared locking first cacheline */
-
-/* FIXME: locking schema/algo descritpion.
- ?-? = free
- S-? = used
- E-? = exclusive-read
- ?-S
- ?-E = middle
- S-S
- S-E = locked
- E-S
- E-E = exclusive-write
-*/
-
-int mdbx_lck_init(MDBX_env *env) {
- (void)env;
- return MDBX_SUCCESS;
-}
-
-/* Seize state as 'exclusive-write' (E-E and returns MDBX_RESULT_TRUE)
- * or as 'used' (S-? and returns MDBX_RESULT_FALSE), otherwise returns an error
- */
-static int internal_seize_lck(HANDLE lfd) {
- int rc;
- assert(lfd != INVALID_HANDLE_VALUE);
-
- /* 1) now on ?-? (free), get ?-E (middle) */
- mdbx_jitter4testing(false);
- if (!flock(lfd, LCK_EXCLUSIVE | LCK_WAITFOR, LCK_UPPER)) {
- rc = GetLastError() /* 2) something went wrong, give up */;
- mdbx_error("%s(%s) failed: errcode %u", mdbx_func_,
- "?-?(free) >> ?-E(middle)", rc);
- return rc;
- }
-
- /* 3) now on ?-E (middle), try E-E (exclusive-write) */
- mdbx_jitter4testing(false);
- if (flock(lfd, LCK_EXCLUSIVE | LCK_DONTWAIT, LCK_LOWER))
- return MDBX_RESULT_TRUE /* 4) got E-E (exclusive-write), done */;
-
- /* 5) still on ?-E (middle) */
- rc = GetLastError();
- mdbx_jitter4testing(false);
- if (rc != ERROR_SHARING_VIOLATION && rc != ERROR_LOCK_VIOLATION) {
- /* 6) something went wrong, give up */
- if (!funlock(lfd, LCK_UPPER))
- mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
- "?-E(middle) >> ?-?(free)", GetLastError());
- return rc;
- }
-
- /* 7) still on ?-E (middle), try S-E (locked) */
- mdbx_jitter4testing(false);
- rc = flock(lfd, LCK_SHARED | LCK_DONTWAIT, LCK_LOWER) ? MDBX_RESULT_FALSE
- : GetLastError();
-
- mdbx_jitter4testing(false);
- if (rc != MDBX_RESULT_FALSE)
- mdbx_error("%s(%s) failed: errcode %u", mdbx_func_,
- "?-E(middle) >> S-E(locked)", rc);
-
- /* 8) now on S-E (locked) or still on ?-E (middle),
- * transite to S-? (used) or ?-? (free) */
- if (!funlock(lfd, LCK_UPPER))
- mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
- "X-E(locked/middle) >> X-?(used/free)", GetLastError());
-
- /* 9) now on S-? (used, DONE) or ?-? (free, FAILURE) */
- return rc;
-}
-
-int mdbx_lck_seize(MDBX_env *env) {
- int rc;
-
- assert(env->me_fd != INVALID_HANDLE_VALUE);
- if (env->me_lfd == INVALID_HANDLE_VALUE) {
- /* LY: without-lck mode (e.g. on read-only filesystem) */
- mdbx_jitter4testing(false);
- if (!flock(env->me_fd, LCK_SHARED | LCK_DONTWAIT, LCK_WHOLE)) {
- rc = GetLastError();
- mdbx_error("%s(%s) failed: errcode %u", mdbx_func_, "without-lck", rc);
- return rc;
- }
- return MDBX_RESULT_FALSE;
- }
-
- rc = internal_seize_lck(env->me_lfd);
- mdbx_jitter4testing(false);
- if (rc == MDBX_RESULT_TRUE && (env->me_flags & MDBX_RDONLY) == 0) {
- /* Check that another process don't operates in without-lck mode.
- * Doing such check by exclusive locking the body-part of db. Should be
- * noted:
- * - we need an exclusive lock for do so;
- * - we can't lock meta-pages, otherwise other process could get an error
- * while opening db in valid (non-conflict) mode. */
- if (!flock(env->me_fd, LCK_EXCLUSIVE | LCK_DONTWAIT, LCK_BODY)) {
- rc = GetLastError();
- mdbx_error("%s(%s) failed: errcode %u", mdbx_func_,
- "lock-against-without-lck", rc);
- mdbx_jitter4testing(false);
- mdbx_lck_destroy(env);
- } else {
- mdbx_jitter4testing(false);
- if (!funlock(env->me_fd, LCK_BODY))
- mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
- "unlock-against-without-lck", GetLastError());
- }
- }
-
- return rc;
-}
-
-int mdbx_lck_downgrade(MDBX_env *env, bool complete) {
- /* Transite from exclusive state (E-?) to used (S-?) */
- assert(env->me_fd != INVALID_HANDLE_VALUE);
- assert(env->me_lfd != INVALID_HANDLE_VALUE);
-
- /* 1) must be at E-E (exclusive-write) */
- if (!complete) {
- /* transite from E-E to E_? (exclusive-read) */
- if (!funlock(env->me_lfd, LCK_UPPER))
- mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
- "E-E(exclusive-write) >> E-?(exclusive-read)", GetLastError());
- return MDBX_SUCCESS /* 2) now at E-? (exclusive-read), done */;
- }
-
- /* 3) now at E-E (exclusive-write), transite to ?_E (middle) */
- if (!funlock(env->me_lfd, LCK_LOWER))
- mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
- "E-E(exclusive-write) >> ?-E(middle)", GetLastError());
-
- /* 4) now at ?-E (middle), transite to S-E (locked) */
- if (!flock(env->me_lfd, LCK_SHARED | LCK_DONTWAIT, LCK_LOWER)) {
- int rc = GetLastError() /* 5) something went wrong, give up */;
- mdbx_error("%s(%s) failed: errcode %u", mdbx_func_,
- "?-E(middle) >> S-E(locked)", rc);
- return rc;
- }
-
- /* 6) got S-E (locked), continue transition to S-? (used) */
- if (!funlock(env->me_lfd, LCK_UPPER))
- mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
- "S-E(locked) >> S-?(used)", GetLastError());
-
- return MDBX_SUCCESS /* 7) now at S-? (used), done */;
-}
-
-int mdbx_lck_upgrade(MDBX_env *env) {
- /* Transite from locked state (S-E) to exclusive-write (E-E) */
- assert(env->me_fd != INVALID_HANDLE_VALUE);
- assert(env->me_lfd != INVALID_HANDLE_VALUE);
-
- /* 1) must be at S-E (locked), transite to ?_E (middle) */
- if (!funlock(env->me_lfd, LCK_LOWER))
- mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
- "S-E(locked) >> ?-E(middle)", GetLastError());
-
- /* 3) now on ?-E (middle), try E-E (exclusive-write) */
- mdbx_jitter4testing(false);
- if (flock(env->me_lfd, LCK_EXCLUSIVE | LCK_DONTWAIT, LCK_LOWER))
- return MDBX_RESULT_TRUE; /* 4) got E-E (exclusive-write), done */
-
- /* 5) still on ?-E (middle) */
- int rc = GetLastError();
- mdbx_jitter4testing(false);
- if (rc != ERROR_SHARING_VIOLATION && rc != ERROR_LOCK_VIOLATION) {
- /* 6) something went wrong, report but continue */
- mdbx_error("%s(%s) failed: errcode %u", mdbx_func_,
- "?-E(middle) >> E-E(exclusive-write)", rc);
- }
-
- /* 7) still on ?-E (middle), try restore S-E (locked) */
- mdbx_jitter4testing(false);
- rc = flock(env->me_lfd, LCK_SHARED | LCK_DONTWAIT, LCK_LOWER)
- ? MDBX_RESULT_FALSE
- : GetLastError();
-
- mdbx_jitter4testing(false);
- if (rc != MDBX_RESULT_FALSE) {
- mdbx_fatal("%s(%s) failed: errcode %u", mdbx_func_,
- "?-E(middle) >> S-E(locked)", rc);
- return rc;
- }
-
- /* 8) now on S-E (locked) */
- return MDBX_RESULT_FALSE;
-}
-
-void mdbx_lck_destroy(MDBX_env *env) {
- int rc;
-
- if (env->me_lfd != INVALID_HANDLE_VALUE) {
- /* double `unlock` for robustly remove overlapped shared/exclusive locks */
- while (funlock(env->me_lfd, LCK_LOWER))
- ;
- rc = GetLastError();
- assert(rc == ERROR_NOT_LOCKED);
- (void)rc;
- SetLastError(ERROR_SUCCESS);
-
- while (funlock(env->me_lfd, LCK_UPPER))
- ;
- rc = GetLastError();
- assert(rc == ERROR_NOT_LOCKED);
- (void)rc;
- SetLastError(ERROR_SUCCESS);
- }
-
- if (env->me_fd != INVALID_HANDLE_VALUE) {
- /* explicitly unlock to avoid latency for other processes (windows kernel
- * releases such locks via deferred queues) */
- while (funlock(env->me_fd, LCK_BODY))
- ;
- rc = GetLastError();
- assert(rc == ERROR_NOT_LOCKED);
- (void)rc;
- SetLastError(ERROR_SUCCESS);
-
- while (funlock(env->me_fd, LCK_META))
- ;
- rc = GetLastError();
- assert(rc == ERROR_NOT_LOCKED);
- (void)rc;
- SetLastError(ERROR_SUCCESS);
-
- while (funlock(env->me_fd, LCK_WHOLE))
- ;
- rc = GetLastError();
- assert(rc == ERROR_NOT_LOCKED);
- (void)rc;
- SetLastError(ERROR_SUCCESS);
- }
-}
-
-/*----------------------------------------------------------------------------*/
-/* reader checking (by pid) */
-
-int mdbx_rpid_set(MDBX_env *env) {
- (void)env;
- return MDBX_SUCCESS;
-}
-
-int mdbx_rpid_clear(MDBX_env *env) {
- (void)env;
- return MDBX_SUCCESS;
-}
-
-/* Checks reader by pid.
- *
- * Returns:
- * MDBX_RESULT_TRUE, if pid is live (unable to acquire lock)
- * MDBX_RESULT_FALSE, if pid is dead (lock acquired)
- * or otherwise the errcode. */
-int mdbx_rpid_check(MDBX_env *env, mdbx_pid_t pid) {
- (void)env;
- HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
- int rc;
- if (hProcess) {
- rc = WaitForSingleObject(hProcess, 0);
- CloseHandle(hProcess);
- } else {
- rc = GetLastError();
- }
-
- switch (rc) {
- case ERROR_INVALID_PARAMETER:
- /* pid seem invalid */
- return MDBX_RESULT_FALSE;
- case WAIT_OBJECT_0:
- /* process just exited */
- return MDBX_RESULT_FALSE;
- case WAIT_TIMEOUT:
- /* pid running */
- return MDBX_RESULT_TRUE;
- default:
- /* failure */
- return rc;
- }
-}
diff --git a/plugins/Dbx_mdb/src/mdbx/mdbx.c b/plugins/Dbx_mdb/src/mdbx/mdbx.c
deleted file mode 100644
index 6e4182cfb2..0000000000
--- a/plugins/Dbx_mdb/src/mdbx/mdbx.c
+++ /dev/null
@@ -1,11611 +0,0 @@
-/*
- * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
- * and other libmdbx authors: please see AUTHORS file.
- * All rights reserved.
- *
- * This code is derived from "LMDB engine" written by
- * Howard Chu (Symas Corporation), which itself derived from btree.c
- * written by Martin Hedenfalk.
- *
- * ---
- *
- * Portions Copyright 2011-2015 Howard Chu, Symas Corp. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- *
- * ---
- *
- * Portions Copyright (c) 2009, 2010 Martin Hedenfalk <martin@bzero.se>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-
-#include "./bits.h"
-
-/*----------------------------------------------------------------------------*/
-/* rthc (tls keys and destructors) */
-
-typedef struct rthc_entry_t {
- MDBX_reader *begin;
- MDBX_reader *end;
- mdbx_thread_key_t key;
-} rthc_entry_t;
-
-#if MDBX_DEBUG
-#define RTHC_INITIAL_LIMIT 1
-#else
-#define RTHC_INITIAL_LIMIT 16
-#endif
-
-static unsigned rthc_count;
-static unsigned rthc_limit = RTHC_INITIAL_LIMIT;
-static rthc_entry_t rthc_table_static[RTHC_INITIAL_LIMIT];
-static rthc_entry_t *rthc_table = rthc_table_static;
-
-__cold void mdbx_rthc_dtor(void *ptr) {
- MDBX_reader *rthc = (MDBX_reader *)ptr;
-
- mdbx_rthc_lock();
- const mdbx_pid_t self_pid = mdbx_getpid();
- for (unsigned i = 0; i < rthc_count; ++i) {
- if (rthc >= rthc_table[i].begin && rthc < rthc_table[i].end) {
- if (rthc->mr_pid == self_pid) {
- rthc->mr_pid = 0;
- mdbx_coherent_barrier();
- }
- break;
- }
- }
- mdbx_rthc_unlock();
-}
-
-__cold void mdbx_rthc_cleanup(void) {
- mdbx_rthc_lock();
- const mdbx_pid_t self_pid = mdbx_getpid();
- for (unsigned i = 0; i < rthc_count; ++i) {
- mdbx_thread_key_t key = rthc_table[i].key;
- MDBX_reader *rthc = mdbx_thread_rthc_get(key);
- if (rthc) {
- mdbx_thread_rthc_set(key, NULL);
- if (rthc->mr_pid == self_pid) {
- rthc->mr_pid = 0;
- mdbx_coherent_barrier();
- }
- }
- }
- mdbx_rthc_unlock();
-}
-
-__cold int mdbx_rthc_alloc(mdbx_thread_key_t *key, MDBX_reader *begin,
- MDBX_reader *end) {
-#ifndef NDEBUG
- *key = (mdbx_thread_key_t)0xBADBADBAD;
-#endif /* NDEBUG */
- int rc = mdbx_thread_key_create(key);
- if (rc != MDBX_SUCCESS)
- return rc;
-
- mdbx_rthc_lock();
- if (rthc_count == rthc_limit) {
- rthc_entry_t *new_table =
- realloc((rthc_table == rthc_table_static) ? NULL : rthc_table,
- sizeof(rthc_entry_t) * rthc_limit * 2);
- if (new_table == NULL) {
- rc = MDBX_ENOMEM;
- goto bailout;
- }
- if (rthc_table == rthc_table_static)
- memcpy(new_table, rthc_table_static, sizeof(rthc_table_static));
- rthc_table = new_table;
- rthc_limit *= 2;
- }
-
- rthc_table[rthc_count].key = *key;
- rthc_table[rthc_count].begin = begin;
- rthc_table[rthc_count].end = end;
- ++rthc_count;
- mdbx_rthc_unlock();
- return MDBX_SUCCESS;
-
-bailout:
- mdbx_thread_key_delete(*key);
- mdbx_rthc_unlock();
- return rc;
-}
-
-__cold void mdbx_rthc_remove(mdbx_thread_key_t key) {
- mdbx_rthc_lock();
- mdbx_thread_key_delete(key);
-
- for (unsigned i = 0; i < rthc_count; ++i) {
- if (key == rthc_table[i].key) {
- const mdbx_pid_t self_pid = mdbx_getpid();
- for (MDBX_reader *rthc = rthc_table[i].begin; rthc < rthc_table[i].end;
- ++rthc)
- if (rthc->mr_pid == self_pid)
- rthc->mr_pid = 0;
- mdbx_coherent_barrier();
- if (--rthc_count > 0)
- rthc_table[i] = rthc_table[rthc_count];
- else if (rthc_table != rthc_table_static) {
- free(rthc_table);
- rthc_table = rthc_table_static;
- rthc_limit = RTHC_INITIAL_LIMIT;
- }
- break;
- }
- }
-
- mdbx_rthc_unlock();
-}
-
-/*----------------------------------------------------------------------------*/
-
-/* Allocate an PNL.
- * Allocates memory for an PNL of the given size.
- * Returns PNL on success, NULL on failure. */
-static MDBX_PNL mdbx_pnl_alloc(size_t size) {
- MDBX_PNL pl = malloc((size + 2) * sizeof(pgno_t));
- if (likely(pl)) {
- *pl++ = (pgno_t)size;
- *pl = 0;
- }
- return pl;
-}
-
-static MDBX_TXL mdbx_txl_alloc(void) {
- const size_t malloc_overhead = sizeof(void *) * 2;
- const size_t bytes = mdbx_roundup2(malloc_overhead + sizeof(txnid_t) * 61,
- MDBX_CACHELINE_SIZE) -
- malloc_overhead;
- MDBX_TXL ptr = malloc(bytes);
- if (likely(ptr)) {
- *ptr++ = bytes / sizeof(txnid_t) - 2;
- *ptr = 0;
- }
- return ptr;
-}
-
-/* Free an PNL.
- * [in] pl The PNL to free. */
-static void mdbx_pnl_free(MDBX_PNL pl) {
- if (likely(pl))
- free(pl - 1);
-}
-
-static void mdbx_txl_free(MDBX_TXL list) {
- if (likely(list))
- free(list - 1);
-}
-
-/* Append ID to PNL. The PNL must be big enough. */
-static __inline void mdbx_pnl_xappend(MDBX_PNL pl, pgno_t id) {
- assert(pl[0] + (size_t)1 < MDBX_PNL_ALLOCLEN(pl));
- pl[pl[0] += 1] = id;
-}
-
-static bool mdbx_pnl_check(MDBX_PNL pl) {
- if (pl) {
- for (const pgno_t *ptr = pl + pl[0]; --ptr > pl;) {
- assert(MDBX_PNL_ORDERED(ptr[0], ptr[1]));
- assert(ptr[0] >= NUM_METAS);
- if (unlikely(MDBX_PNL_DISORDERED(ptr[0], ptr[1]) || ptr[0] < NUM_METAS))
- return false;
- }
- }
- return true;
-}
-
-/* Sort an PNL.
- * [in,out] pnl The PNL to sort. */
-static void __hot mdbx_pnl_sort(MDBX_PNL pnl) {
- /* Max possible depth of int-indexed tree * 2 items/level */
- int istack[sizeof(int) * CHAR_BIT * 2];
- int i, j, k, l, ir, jstack;
- pgno_t a;
-
-/* Quicksort + Insertion sort for small arrays */
-#define PNL_SMALL 8
-#define PNL_SWAP(a, b) \
- do { \
- pgno_t tmp_pgno = (a); \
- (a) = (b); \
- (b) = tmp_pgno; \
- } while (0)
-
- ir = (int)pnl[0];
- l = 1;
- jstack = 0;
- while (1) {
- if (ir - l < PNL_SMALL) { /* Insertion sort */
- for (j = l + 1; j <= ir; j++) {
- a = pnl[j];
- for (i = j - 1; i >= 1; i--) {
- if (MDBX_PNL_DISORDERED(a, pnl[i]))
- break;
- pnl[i + 1] = pnl[i];
- }
- pnl[i + 1] = a;
- }
- if (jstack == 0)
- break;
- ir = istack[jstack--];
- l = istack[jstack--];
- } else {
- k = (l + ir) >> 1; /* Choose median of left, center, right */
- PNL_SWAP(pnl[k], pnl[l + 1]);
- if (MDBX_PNL_ORDERED(pnl[ir], pnl[l]))
- PNL_SWAP(pnl[l], pnl[ir]);
-
- if (MDBX_PNL_ORDERED(pnl[ir], pnl[l + 1]))
- PNL_SWAP(pnl[l + 1], pnl[ir]);
-
- if (MDBX_PNL_ORDERED(pnl[l + 1], pnl[l]))
- PNL_SWAP(pnl[l], pnl[l + 1]);
-
- i = l + 1;
- j = ir;
- a = pnl[l + 1];
- while (1) {
- do
- i++;
- while (MDBX_PNL_ORDERED(pnl[i], a));
- do
- j--;
- while (MDBX_PNL_ORDERED(a, pnl[j]));
- if (j < i)
- break;
- PNL_SWAP(pnl[i], pnl[j]);
- }
- pnl[l + 1] = pnl[j];
- pnl[j] = a;
- jstack += 2;
- if (ir - i + 1 >= j - l) {
- istack[jstack] = ir;
- istack[jstack - 1] = i;
- ir = j - 1;
- } else {
- istack[jstack] = j - 1;
- istack[jstack - 1] = l;
- l = i;
- }
- }
- }
-#undef PNL_SMALL
-#undef PNL_SWAP
- assert(mdbx_pnl_check(pnl));
-}
-
-/* Search for an ID in an PNL.
- * [in] pl The PNL to search.
- * [in] id The ID to search for.
- * Returns The index of the first ID greater than or equal to id. */
-static unsigned __hot mdbx_pnl_search(MDBX_PNL pnl, pgno_t id) {
- assert(mdbx_pnl_check(pnl));
-
- /* binary search of id in pl
- * if found, returns position of id
- * if not found, returns first position greater than id */
- unsigned base = 0;
- unsigned cursor = 1;
- int val = 0;
- unsigned n = pnl[0];
-
- while (n > 0) {
- unsigned pivot = n >> 1;
- cursor = base + pivot + 1;
- val = MDBX_PNL_ASCENDING ? mdbx_cmp2int(pnl[cursor], id)
- : mdbx_cmp2int(id, pnl[cursor]);
-
- if (val < 0) {
- n = pivot;
- } else if (val > 0) {
- base = cursor;
- n -= pivot + 1;
- } else {
- return cursor;
- }
- }
-
- if (val > 0)
- ++cursor;
-
- return cursor;
-}
-
-/* Shrink an PNL.
- * Return the PNL to the default size if it has grown larger.
- * [in,out] ppl Address of the PNL to shrink. */
-static void mdbx_pnl_shrink(MDBX_PNL *ppl) {
- MDBX_PNL pl = *ppl - 1;
- if (unlikely(*pl > MDBX_PNL_UM_MAX)) {
- /* shrink to MDBX_PNL_UM_MAX */
- pl = realloc(pl, (MDBX_PNL_UM_MAX + 2) * sizeof(pgno_t));
- if (likely(pl)) {
- *pl++ = MDBX_PNL_UM_MAX;
- *ppl = pl;
- }
- }
-}
-
-/* Grow an PNL.
- * Return the PNL to the size growed by given number.
- * [in,out] ppl Address of the PNL to grow. */
-static int mdbx_pnl_grow(MDBX_PNL *ppl, size_t num) {
- MDBX_PNL idn = *ppl - 1;
- /* grow it */
- idn = realloc(idn, (*idn + num + 2) * sizeof(pgno_t));
- if (unlikely(!idn))
- return MDBX_ENOMEM;
- *idn++ += (pgno_t)num;
- *ppl = idn;
- return 0;
-}
-
-static int mdbx_txl_grow(MDBX_TXL *ptr, size_t num) {
- MDBX_TXL list = *ptr - 1;
- /* grow it */
- list = realloc(list, ((size_t)*list + num + 2) * sizeof(txnid_t));
- if (unlikely(!list))
- return MDBX_ENOMEM;
- *list++ += num;
- *ptr = list;
- return 0;
-}
-
-/* Make room for num additional elements in an PNL.
- * [in,out] ppl Address of the PNL.
- * [in] num Number of elements to make room for.
- * Returns 0 on success, MDBX_ENOMEM on failure. */
-static int mdbx_pnl_need(MDBX_PNL *ppl, size_t num) {
- MDBX_PNL pl = *ppl;
- num += pl[0];
- if (unlikely(num > pl[-1])) {
- num = (num + num / 4 + (256 + 2)) & -256;
- pl = realloc(pl - 1, num * sizeof(pgno_t));
- if (unlikely(!pl))
- return MDBX_ENOMEM;
- *pl++ = (pgno_t)num - 2;
- *ppl = pl;
- }
- return 0;
-}
-
-/* Append an ID onto an PNL.
- * [in,out] ppl Address of the PNL to append to.
- * [in] id The ID to append.
- * Returns 0 on success, MDBX_ENOMEM if the PNL is too large. */
-static int mdbx_pnl_append(MDBX_PNL *ppl, pgno_t id) {
- MDBX_PNL pl = *ppl;
- /* Too big? */
- if (unlikely(pl[0] >= pl[-1])) {
- if (mdbx_pnl_grow(ppl, MDBX_PNL_UM_MAX))
- return MDBX_ENOMEM;
- pl = *ppl;
- }
- pl[0]++;
- pl[pl[0]] = id;
- return 0;
-}
-
-static int mdbx_txl_append(MDBX_TXL *ptr, txnid_t id) {
- MDBX_TXL list = *ptr;
- /* Too big? */
- if (unlikely(list[0] >= list[-1])) {
- if (mdbx_txl_grow(ptr, (size_t)list[0]))
- return MDBX_ENOMEM;
- list = *ptr;
- }
- list[0]++;
- list[list[0]] = id;
- return 0;
-}
-
-/* Append an PNL onto an PNL.
- * [in,out] ppl Address of the PNL to append to.
- * [in] app The PNL to append.
- * Returns 0 on success, MDBX_ENOMEM if the PNL is too large. */
-static int mdbx_pnl_append_list(MDBX_PNL *ppl, MDBX_PNL app) {
- MDBX_PNL pnl = *ppl;
- /* Too big? */
- if (unlikely(pnl[0] + app[0] >= pnl[-1])) {
- if (mdbx_pnl_grow(ppl, app[0]))
- return MDBX_ENOMEM;
- pnl = *ppl;
- }
- memcpy(&pnl[pnl[0] + 1], &app[1], app[0] * sizeof(pgno_t));
- pnl[0] += app[0];
- return 0;
-}
-
-static int mdbx_txl_append_list(MDBX_TXL *ptr, MDBX_TXL append) {
- MDBX_TXL list = *ptr;
- /* Too big? */
- if (unlikely(list[0] + append[0] >= list[-1])) {
- if (mdbx_txl_grow(ptr, (size_t)append[0]))
- return MDBX_ENOMEM;
- list = *ptr;
- }
- memcpy(&list[list[0] + 1], &append[1], (size_t)append[0] * sizeof(txnid_t));
- list[0] += append[0];
- return 0;
-}
-
-/* Append an ID range onto an PNL.
- * [in,out] ppl Address of the PNL to append to.
- * [in] id The lowest ID to append.
- * [in] n Number of IDs to append.
- * Returns 0 on success, MDBX_ENOMEM if the PNL is too large. */
-static int mdbx_pnl_append_range(MDBX_PNL *ppl, pgno_t id, size_t n) {
- pgno_t *pnl = *ppl, len = pnl[0];
- /* Too big? */
- if (unlikely(len + n > pnl[-1])) {
- if (mdbx_pnl_grow(ppl, n | MDBX_PNL_UM_MAX))
- return MDBX_ENOMEM;
- pnl = *ppl;
- }
- pnl[0] = len + (pgno_t)n;
- pnl += len;
- while (n)
- pnl[n--] = id++;
- return 0;
-}
-
-/* Merge an PNL onto an PNL. The destination PNL must be big enough.
- * [in] pl The PNL to merge into.
- * [in] merge The PNL to merge. */
-static void __hot mdbx_pnl_xmerge(MDBX_PNL pnl, MDBX_PNL merge) {
- assert(mdbx_pnl_check(pnl));
- assert(mdbx_pnl_check(merge));
- pgno_t old_id, merge_id, i = merge[0], j = pnl[0], k = i + j, total = k;
- pnl[0] =
- MDBX_PNL_ASCENDING ? 0 : ~(pgno_t)0; /* delimiter for pl scan below */
- old_id = pnl[j];
- while (i) {
- merge_id = merge[i--];
- for (; MDBX_PNL_ORDERED(merge_id, old_id); old_id = pnl[--j])
- pnl[k--] = old_id;
- pnl[k--] = merge_id;
- }
- pnl[0] = total;
- assert(mdbx_pnl_check(pnl));
-}
-
-/* Search for an ID in an ID2L.
- * [in] pnl The ID2L to search.
- * [in] id The ID to search for.
- * Returns The index of the first ID2 whose mid member is greater than
- * or equal to id. */
-static unsigned __hot mdbx_mid2l_search(MDBX_ID2L pnl, pgno_t id) {
- /* binary search of id in pnl
- * if found, returns position of id
- * if not found, returns first position greater than id */
- unsigned base = 0;
- unsigned cursor = 1;
- int val = 0;
- unsigned n = (unsigned)pnl[0].mid;
-
-#if MDBX_DEBUG
- for (const MDBX_ID2 *ptr = pnl + pnl[0].mid; --ptr > pnl;) {
- assert(ptr[0].mid < ptr[1].mid);
- assert(ptr[0].mid >= NUM_METAS);
- }
-#endif
-
- while (n > 0) {
- unsigned pivot = n >> 1;
- cursor = base + pivot + 1;
- val = mdbx_cmp2int(id, pnl[cursor].mid);
-
- if (val < 0) {
- n = pivot;
- } else if (val > 0) {
- base = cursor;
- n -= pivot + 1;
- } else {
- return cursor;
- }
- }
-
- if (val > 0)
- ++cursor;
-
- return cursor;
-}
-
-/* Insert an ID2 into a ID2L.
- * [in,out] pnl The ID2L to insert into.
- * [in] id The ID2 to insert.
- * Returns 0 on success, -1 if the ID was already present in the ID2L. */
-static int mdbx_mid2l_insert(MDBX_ID2L pnl, MDBX_ID2 *id) {
- unsigned x = mdbx_mid2l_search(pnl, id->mid);
- if (unlikely(x < 1))
- return /* internal error */ -2;
-
- if (x <= pnl[0].mid && pnl[x].mid == id->mid)
- return /* duplicate */ -1;
-
- if (unlikely(pnl[0].mid >= MDBX_PNL_UM_MAX))
- return /* too big */ -2;
-
- /* insert id */
- pnl[0].mid++;
- for (unsigned i = (unsigned)pnl[0].mid; i > x; i--)
- pnl[i] = pnl[i - 1];
- pnl[x] = *id;
- return 0;
-}
-
-/* Append an ID2 into a ID2L.
- * [in,out] pnl The ID2L to append into.
- * [in] id The ID2 to append.
- * Returns 0 on success, -2 if the ID2L is too big. */
-static int mdbx_mid2l_append(MDBX_ID2L pnl, MDBX_ID2 *id) {
-#if MDBX_DEBUG
- for (unsigned i = pnl[0].mid; i > 0; --i) {
- assert(pnl[i].mid != id->mid);
- if (unlikely(pnl[i].mid == id->mid))
- return -1;
- }
-#endif
-
- /* Too big? */
- if (unlikely(pnl[0].mid >= MDBX_PNL_UM_MAX))
- return -2;
-
- pnl[0].mid++;
- pnl[pnl[0].mid] = *id;
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int mdbx_runtime_flags = MDBX_DBG_PRINT
-#if MDBX_DEBUG
- | MDBX_DBG_ASSERT
-#endif
-#if MDBX_DEBUG > 1
- | MDBX_DBG_TRACE
-#endif
-#if MDBX_DEBUG > 2
- | MDBX_DBG_AUDIT
-#endif
-#if MDBX_DEBUG > 3
- | MDBX_DBG_EXTRA
-#endif
- ;
-
-MDBX_debug_func *mdbx_debug_logger;
-
-static int mdbx_page_alloc(MDBX_cursor *mc, unsigned num, MDBX_page **mp,
- int flags);
-static int mdbx_page_new(MDBX_cursor *mc, uint32_t flags, unsigned num,
- MDBX_page **mp);
-static int mdbx_page_touch(MDBX_cursor *mc);
-static int mdbx_cursor_touch(MDBX_cursor *mc);
-
-#define MDBX_END_NAMES \
- { \
- "committed", "empty-commit", "abort", "reset", "reset-tmp", "fail-begin", \
- "fail-beginchild" \
- }
-enum {
- /* mdbx_txn_end operation number, for logging */
- MDBX_END_COMMITTED,
- MDBX_END_EMPTY_COMMIT,
- MDBX_END_ABORT,
- MDBX_END_RESET,
- MDBX_END_RESET_TMP,
- MDBX_END_FAIL_BEGIN,
- MDBX_END_FAIL_BEGINCHILD
-};
-#define MDBX_END_OPMASK 0x0F /* mask for mdbx_txn_end() operation number */
-#define MDBX_END_UPDATE 0x10 /* update env state (DBIs) */
-#define MDBX_END_FREE 0x20 /* free txn unless it is MDBX_env.me_txn0 */
-#define MDBX_END_EOTDONE 0x40 /* txn's cursors already closed */
-#define MDBX_END_SLOT 0x80 /* release any reader slot if MDBX_NOTLS */
-static int mdbx_txn_end(MDBX_txn *txn, unsigned mode);
-
-static int mdbx_page_get(MDBX_cursor *mc, pgno_t pgno, MDBX_page **mp,
- int *lvl);
-static int mdbx_page_search_root(MDBX_cursor *mc, MDBX_val *key, int modify);
-
-#define MDBX_PS_MODIFY 1
-#define MDBX_PS_ROOTONLY 2
-#define MDBX_PS_FIRST 4
-#define MDBX_PS_LAST 8
-static int mdbx_page_search(MDBX_cursor *mc, MDBX_val *key, int flags);
-static int mdbx_page_merge(MDBX_cursor *csrc, MDBX_cursor *cdst);
-
-#define MDBX_SPLIT_REPLACE MDBX_APPENDDUP /* newkey is not new */
-static int mdbx_page_split(MDBX_cursor *mc, MDBX_val *newkey, MDBX_val *newdata,
- pgno_t newpgno, unsigned nflags);
-
-static int mdbx_read_header(MDBX_env *env, MDBX_meta *meta);
-static int mdbx_sync_locked(MDBX_env *env, unsigned flags,
- MDBX_meta *const pending);
-static void mdbx_env_close0(MDBX_env *env);
-
-static MDBX_node *mdbx_node_search(MDBX_cursor *mc, MDBX_val *key, int *exactp);
-static int mdbx_node_add(MDBX_cursor *mc, unsigned indx, MDBX_val *key,
- MDBX_val *data, pgno_t pgno, unsigned flags);
-static void mdbx_node_del(MDBX_cursor *mc, size_t ksize);
-static void mdbx_node_shrink(MDBX_page *mp, unsigned indx);
-static int mdbx_node_move(MDBX_cursor *csrc, MDBX_cursor *cdst, int fromleft);
-static int mdbx_node_read(MDBX_cursor *mc, MDBX_node *leaf, MDBX_val *data);
-static size_t mdbx_leaf_size(MDBX_env *env, MDBX_val *key, MDBX_val *data);
-static size_t mdbx_branch_size(MDBX_env *env, MDBX_val *key);
-
-static int mdbx_rebalance(MDBX_cursor *mc);
-static int mdbx_update_key(MDBX_cursor *mc, MDBX_val *key);
-
-static void mdbx_cursor_pop(MDBX_cursor *mc);
-static int mdbx_cursor_push(MDBX_cursor *mc, MDBX_page *mp);
-
-static int mdbx_cursor_del0(MDBX_cursor *mc);
-static int mdbx_del0(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data,
- unsigned flags);
-static int mdbx_cursor_sibling(MDBX_cursor *mc, int move_right);
-static int mdbx_cursor_next(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
- MDBX_cursor_op op);
-static int mdbx_cursor_prev(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
- MDBX_cursor_op op);
-static int mdbx_cursor_set(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
- MDBX_cursor_op op, int *exactp);
-static int mdbx_cursor_first(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data);
-static int mdbx_cursor_last(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data);
-
-static void mdbx_cursor_init(MDBX_cursor *mc, MDBX_txn *txn, MDBX_dbi dbi,
- MDBX_xcursor *mx);
-static void mdbx_xcursor_init0(MDBX_cursor *mc);
-static void mdbx_xcursor_init1(MDBX_cursor *mc, MDBX_node *node);
-static void mdbx_xcursor_init2(MDBX_cursor *mc, MDBX_xcursor *src_mx,
- int force);
-
-static int mdbx_drop0(MDBX_cursor *mc, int subs);
-
-static MDBX_cmp_func mdbx_cmp_memn, mdbx_cmp_memnr, mdbx_cmp_int_ai,
- mdbx_cmp_int_a2, mdbx_cmp_int_ua;
-
-static const char *__mdbx_strerr(int errnum) {
- /* Table of descriptions for MDBX errors */
- static const char *const tbl[] = {
- "MDBX_KEYEXIST: Key/data pair already exists",
- "MDBX_NOTFOUND: No matching key/data pair found",
- "MDBX_PAGE_NOTFOUND: Requested page not found",
- "MDBX_CORRUPTED: Database is corrupted",
- "MDBX_PANIC: Update of meta page failed or environment had fatal error",
- "MDBX_VERSION_MISMATCH: DB version mismatch libmdbx",
- "MDBX_INVALID: File is not an MDBX file",
- "MDBX_MAP_FULL: Environment mapsize limit reached",
- "MDBX_DBS_FULL: Too may DBI (maxdbs reached)",
- "MDBX_READERS_FULL: Too many readers (maxreaders reached)",
- NULL /* MDBX_TLS_FULL (-30789): unused in MDBX */,
- "MDBX_TXN_FULL: Transaction has too many dirty pages - transaction too "
- "big",
- "MDBX_CURSOR_FULL: Internal error - cursor stack limit reached",
- "MDBX_PAGE_FULL: Internal error - page has no more space",
- "MDBX_MAP_RESIZED: Database contents grew beyond environment mapsize",
- "MDBX_INCOMPATIBLE: Operation and DB incompatible, or DB flags changed",
- "MDBX_BAD_RSLOT: Invalid reuse of reader locktable slot",
- "MDBX_BAD_TXN: Transaction must abort, has a child, or is invalid",
- "MDBX_BAD_VALSIZE: Unsupported size of key/DB name/data, or wrong "
- "DUPFIXED size",
- "MDBX_BAD_DBI: The specified DBI handle was closed/changed unexpectedly",
- "MDBX_PROBLEM: Unexpected problem - txn should abort",
- "MDBX_BUSY: Another write transation is started",
- };
-
- if (errnum >= MDBX_KEYEXIST && errnum <= MDBX_LAST_ERRCODE) {
- int i = errnum - MDBX_KEYEXIST;
- return tbl[i];
- }
-
- switch (errnum) {
- case MDBX_SUCCESS:
- return "MDBX_SUCCESS: Successful";
- case MDBX_EMULTIVAL:
- return "MDBX_EMULTIVAL: Unable to update multi-value for the given key";
- case MDBX_EBADSIGN:
- return "MDBX_EBADSIGN: Wrong signature of a runtime object(s)";
- case MDBX_WANNA_RECOVERY:
- return "MDBX_WANNA_RECOVERY: Database should be recovered, but this could "
- "NOT be done in a read-only mode";
- case MDBX_EKEYMISMATCH:
- return "MDBX_EKEYMISMATCH: The given key value is mismatched to the "
- "current cursor position";
- case MDBX_TOO_LARGE:
- return "MDBX_TOO_LARGE: Database is too large for current system, "
- "e.g. could NOT be mapped into RAM";
- case MDBX_THREAD_MISMATCH:
- return "MDBX_THREAD_MISMATCH: A thread has attempted to use a not "
- "owned object, e.g. a transaction that started by another thread";
- default:
- return NULL;
- }
-}
-
-const char *__cold mdbx_strerror_r(int errnum, char *buf, size_t buflen) {
- const char *msg = __mdbx_strerr(errnum);
- if (!msg) {
- if (!buflen || buflen > INT_MAX)
- return NULL;
-#ifdef _MSC_VER
- size_t size = FormatMessageA(
- FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
- errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (DWORD)buflen,
- NULL);
- return size ? buf : NULL;
-#elif defined(_GNU_SOURCE)
- /* GNU-specific */
- msg = strerror_r(errnum, buf, buflen);
-#elif (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600)
- /* XSI-compliant */
- int rc = strerror_r(errnum, buf, buflen);
- if (rc) {
- rc = snprintf(buf, buflen, "error %d", errnum);
- assert(rc > 0);
- }
- return buf;
-#else
- strncpy(buf, strerror(errnum), buflen);
- buf[buflen - 1] = '\0';
- return buf;
-#endif
- }
- return msg;
-}
-
-const char *__cold mdbx_strerror(int errnum) {
- const char *msg = __mdbx_strerr(errnum);
- if (!msg) {
-#ifdef _MSC_VER
- static __thread char buffer[1024];
- size_t size = FormatMessageA(
- FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
- errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer,
- sizeof(buffer), NULL);
- if (size)
- msg = buffer;
-#else
- msg = strerror(errnum);
-#endif
- }
- return msg;
-}
-
-static txnid_t mdbx_oomkick(MDBX_env *env, const txnid_t laggard);
-
-void __cold mdbx_debug_log(int type, const char *function, int line,
- const char *fmt, ...) {
- va_list args;
-
- va_start(args, fmt);
- if (mdbx_debug_logger)
- mdbx_debug_logger(type, function, line, fmt, args);
- else {
- if (function && line > 0)
- fprintf(stderr, "%s:%d ", function, line);
- else if (function)
- fprintf(stderr, "%s: ", function);
- else if (line > 0)
- fprintf(stderr, "%d: ", line);
- vfprintf(stderr, fmt, args);
- }
- va_end(args);
-}
-
-/* Dump a key in ascii or hexadecimal. */
-char *mdbx_dkey(const MDBX_val *key, char *const buf, const size_t bufsize) {
- if (!key)
- return "<null>";
- if (!buf || bufsize < 4)
- return nullptr;
- if (!key->iov_len)
- return "<empty>";
-
- const uint8_t *const data = key->iov_base;
- bool is_ascii = true;
- unsigned i;
- for (i = 0; is_ascii && i < key->iov_len; i++)
- if (data[i] < ' ' || data[i] > 127)
- is_ascii = false;
-
- if (is_ascii) {
- int len =
- snprintf(buf, bufsize, "%.*s",
- (key->iov_len > INT_MAX) ? INT_MAX : (int)key->iov_len, data);
- assert(len > 0 && (unsigned)len < bufsize);
- (void)len;
- } else {
- char *const detent = buf + bufsize - 2;
- char *ptr = buf;
- *ptr++ = '<';
- for (i = 0; i < key->iov_len; i++) {
- const ptrdiff_t left = detent - ptr;
- assert(left > 0);
- int len = snprintf(ptr, left, "%02x", data[i]);
- if (len < 0 || len >= left)
- break;
- ptr += len;
- }
- if (ptr < detent) {
- ptr[0] = '>';
- ptr[1] = '\0';
- }
- }
- return buf;
-}
-
-#if 0 /* LY: debug stuff */
-static const char *mdbx_leafnode_type(MDBX_node *n) {
- static char *const tp[2][2] = {{"", ": DB"}, {": sub-page", ": sub-DB"}};
- return F_ISSET(n->mn_flags, F_BIGDATA) ? ": overflow page"
- : tp[F_ISSET(n->mn_flags, F_DUPDATA)]
- [F_ISSET(n->mn_flags, F_SUBDATA)];
-}
-
-/* Display all the keys in the page. */
-static void mdbx_page_list(MDBX_page *mp) {
- pgno_t pgno = mp->mp_pgno;
- const char *type, *state = (mp->mp_flags & P_DIRTY) ? ", dirty" : "";
- MDBX_node *node;
- unsigned i, nkeys, nsize, total = 0;
- MDBX_val key;
- DKBUF;
-
- switch (mp->mp_flags &
- (P_BRANCH | P_LEAF | P_LEAF2 | P_META | P_OVERFLOW | P_SUBP)) {
- case P_BRANCH:
- type = "Branch page";
- break;
- case P_LEAF:
- type = "Leaf page";
- break;
- case P_LEAF | P_SUBP:
- type = "Sub-page";
- break;
- case P_LEAF | P_LEAF2:
- type = "LEAF2 page";
- break;
- case P_LEAF | P_LEAF2 | P_SUBP:
- type = "LEAF2 sub-page";
- break;
- case P_OVERFLOW:
- mdbx_print("Overflow page %" PRIu64 " pages %u%s\n", pgno, mp->mp_pages,
- state);
- return;
- case P_META:
- mdbx_print("Meta-page %" PRIu64 " txnid %" PRIu64 "\n", pgno,
- ((MDBX_meta *)PAGEDATA(mp))->mm_txnid);
- return;
- default:
- mdbx_print("Bad page %" PRIu64 " flags 0x%X\n", pgno, mp->mp_flags);
- return;
- }
-
- nkeys = NUMKEYS(mp);
- mdbx_print("%s %" PRIu64 " numkeys %u%s\n", type, pgno, nkeys, state);
-
- for (i = 0; i < nkeys; i++) {
- if (IS_LEAF2(mp)) { /* LEAF2 pages have no mp_ptrs[] or node headers */
- key.iov_len = nsize = mp->mp_leaf2_ksize;
- key.iov_base = LEAF2KEY(mp, i, nsize);
- total += nsize;
- mdbx_print("key %u: nsize %u, %s\n", i, nsize, DKEY(&key));
- continue;
- }
- node = NODEPTR(mp, i);
- key.iov_len = node->mn_ksize;
- key.iov_base = node->mn_data;
- nsize = NODESIZE + key.iov_len;
- if (IS_BRANCH(mp)) {
- mdbx_print("key %u: page %" PRIu64 ", %s\n", i, NODEPGNO(node),
- DKEY(&key));
- total += nsize;
- } else {
- if (F_ISSET(node->mn_flags, F_BIGDATA))
- nsize += sizeof(pgno_t);
- else
- nsize += NODEDSZ(node);
- total += nsize;
- nsize += sizeof(indx_t);
- mdbx_print("key %u: nsize %u, %s%s\n", i, nsize, DKEY(&key),
- mdbx_leafnode_type(node));
- }
- total = EVEN(total);
- }
- mdbx_print("Total: header %u + contents %u + unused %u\n",
- IS_LEAF2(mp) ? PAGEHDRSZ : PAGEHDRSZ + mp->mp_lower, total,
- SIZELEFT(mp));
-}
-
-static void mdbx_cursor_chk(MDBX_cursor *mc) {
- unsigned i;
- MDBX_node *node;
- MDBX_page *mp;
-
- if (!mc->mc_snum || !(mc->mc_flags & C_INITIALIZED))
- return;
- for (i = 0; i < mc->mc_top; i++) {
- mp = mc->mc_pg[i];
- node = NODEPTR(mp, mc->mc_ki[i]);
- if (unlikely(NODEPGNO(node) != mc->mc_pg[i + 1]->mp_pgno))
- mdbx_print("oops!\n");
- }
- if (unlikely(mc->mc_ki[i] >= NUMKEYS(mc->mc_pg[i])))
- mdbx_print("ack!\n");
- if (XCURSOR_INITED(mc)) {
- node = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
- if (((node->mn_flags & (F_DUPDATA | F_SUBDATA)) == F_DUPDATA) &&
- mc->mc_xcursor->mx_cursor.mc_pg[0] != NODEDATA(node)) {
- mdbx_print("blah!\n");
- }
- }
-}
-#endif /* 0 */
-
-/* Count all the pages in each DB and in the freelist and make sure
- * it matches the actual number of pages being used.
- * All named DBs must be open for a correct count. */
-static void mdbx_audit(MDBX_txn *txn) {
- MDBX_cursor mc;
- MDBX_val key, data;
- int rc;
-
- pgno_t freecount = 0;
- mdbx_cursor_init(&mc, txn, FREE_DBI, NULL);
- while ((rc = mdbx_cursor_get(&mc, &key, &data, MDBX_NEXT)) == 0)
- freecount += *(pgno_t *)data.iov_base;
- mdbx_tassert(txn, rc == MDBX_NOTFOUND);
-
- pgno_t count = 0;
- for (MDBX_dbi i = 0; i < txn->mt_numdbs; i++) {
- MDBX_xcursor mx;
- if (!(txn->mt_dbflags[i] & DB_VALID))
- continue;
- mdbx_cursor_init(&mc, txn, i, &mx);
- if (txn->mt_dbs[i].md_root == P_INVALID)
- continue;
- count += txn->mt_dbs[i].md_branch_pages + txn->mt_dbs[i].md_leaf_pages +
- txn->mt_dbs[i].md_overflow_pages;
- if (txn->mt_dbs[i].md_flags & MDBX_DUPSORT) {
- rc = mdbx_page_search(&mc, NULL, MDBX_PS_FIRST);
- for (; rc == MDBX_SUCCESS; rc = mdbx_cursor_sibling(&mc, 1)) {
- MDBX_page *mp = mc.mc_pg[mc.mc_top];
- for (unsigned j = 0; j < NUMKEYS(mp); j++) {
- MDBX_node *leaf = NODEPTR(mp, j);
- if (leaf->mn_flags & F_SUBDATA) {
- MDBX_db db;
- memcpy(&db, NODEDATA(leaf), sizeof(db));
- count +=
- db.md_branch_pages + db.md_leaf_pages + db.md_overflow_pages;
- }
- }
- }
- mdbx_tassert(txn, rc == MDBX_NOTFOUND);
- }
- }
- if (freecount + count + NUM_METAS != txn->mt_next_pgno) {
- mdbx_print("audit: %" PRIaTXN " freecount: %" PRIaPGNO " count: %" PRIaPGNO
- " total: %" PRIaPGNO " next_pgno: %" PRIaPGNO "\n",
- txn->mt_txnid, freecount, count + NUM_METAS,
- freecount + count + NUM_METAS, txn->mt_next_pgno);
- }
-}
-
-int mdbx_cmp(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *a,
- const MDBX_val *b) {
- mdbx_assert(NULL, txn->mt_signature == MDBX_MT_SIGNATURE);
- return txn->mt_dbxs[dbi].md_cmp(a, b);
-}
-
-int mdbx_dcmp(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *a,
- const MDBX_val *b) {
- mdbx_assert(NULL, txn->mt_signature == MDBX_MT_SIGNATURE);
- return txn->mt_dbxs[dbi].md_dcmp(a, b);
-}
-
-/* Allocate memory for a page.
- * Re-use old malloc'd pages first for singletons, otherwise just malloc.
- * Set MDBX_TXN_ERROR on failure. */
-static MDBX_page *mdbx_page_malloc(MDBX_txn *txn, unsigned num) {
- MDBX_env *env = txn->mt_env;
- MDBX_page *np = env->me_dpages;
- size_t size = env->me_psize;
- if (likely(num == 1 && np)) {
- ASAN_UNPOISON_MEMORY_REGION(np, size);
- VALGRIND_MEMPOOL_ALLOC(env, np, size);
- VALGRIND_MAKE_MEM_DEFINED(&np->mp_next, sizeof(np->mp_next));
- env->me_dpages = np->mp_next;
- } else {
- size = pgno2bytes(env, num);
- np = malloc(size);
- if (unlikely(!np)) {
- txn->mt_flags |= MDBX_TXN_ERROR;
- return np;
- }
- VALGRIND_MEMPOOL_ALLOC(env, np, size);
- }
-
- if ((env->me_flags & MDBX_NOMEMINIT) == 0) {
- /* For a single page alloc, we init everything after the page header.
- * For multi-page, we init the final page; if the caller needed that
- * many pages they will be filling in at least up to the last page. */
- size_t skip = PAGEHDRSZ;
- if (num > 1)
- skip += pgno2bytes(env, num - 1);
- memset((char *)np + skip, 0, size - skip);
- }
-#if MDBX_DEBUG
- np->mp_pgno = 0;
-#endif
- VALGRIND_MAKE_MEM_UNDEFINED(np, size);
- np->mp_flags = 0;
- np->mp_pages = num;
- return np;
-}
-
-/* Free a single page.
- * Saves single pages to a list, for future reuse.
- * (This is not used for multi-page overflow pages.) */
-static __inline void mdbx_page_free(MDBX_env *env, MDBX_page *mp) {
-#if MDBX_DEBUG
- mp->mp_pgno = MAX_PAGENO;
-#endif
- mp->mp_next = env->me_dpages;
- VALGRIND_MEMPOOL_FREE(env, mp);
- env->me_dpages = mp;
-}
-
-/* Free a dirty page */
-static void mdbx_dpage_free(MDBX_env *env, MDBX_page *dp) {
- if (!IS_OVERFLOW(dp) || dp->mp_pages == 1) {
- mdbx_page_free(env, dp);
- } else {
- /* large pages just get freed directly */
- VALGRIND_MEMPOOL_FREE(env, dp);
- free(dp);
- }
-}
-
-/* Return all dirty pages to dpage list */
-static void mdbx_dlist_free(MDBX_txn *txn) {
- MDBX_env *env = txn->mt_env;
- MDBX_ID2L dl = txn->mt_rw_dirtylist;
- size_t i, n = dl[0].mid;
-
- for (i = 1; i <= n; i++)
- mdbx_dpage_free(env, dl[i].mptr);
-
- dl[0].mid = 0;
-}
-
-static size_t bytes_align2os_bytes(const MDBX_env *env, size_t bytes) {
- return mdbx_roundup2(mdbx_roundup2(bytes, env->me_psize), env->me_os_psize);
-}
-
-static void __cold mdbx_kill_page(MDBX_env *env, pgno_t pgno) {
- const size_t offs = pgno2bytes(env, pgno);
- const size_t shift = offsetof(MDBX_page, mp_pages);
-
- if (env->me_flags & MDBX_WRITEMAP) {
- MDBX_page *mp = (MDBX_page *)(env->me_map + offs);
- memset(&mp->mp_pages, 0x6F /* 'o', 111 */, env->me_psize - shift);
- VALGRIND_MAKE_MEM_NOACCESS(&mp->mp_pages, env->me_psize - shift);
- ASAN_POISON_MEMORY_REGION(&mp->mp_pages, env->me_psize - shift);
- } else {
- intptr_t len = env->me_psize - shift;
- void *buf = alloca(len);
- memset(buf, 0x6F /* 'o', 111 */, len);
- (void)mdbx_pwrite(env->me_fd, buf, len, offs + shift);
- }
-}
-
-/* Loosen or free a single page.
- *
- * Saves single pages to a list for future reuse
- * in this same txn. It has been pulled from the freeDB
- * and already resides on the dirty list, but has been
- * deleted. Use these pages first before pulling again
- * from the freeDB.
- *
- * If the page wasn't dirtied in this txn, just add it
- * to this txn's free list. */
-static int mdbx_page_loose(MDBX_cursor *mc, MDBX_page *mp) {
- int loose = 0;
- const pgno_t pgno = mp->mp_pgno;
- MDBX_txn *txn = mc->mc_txn;
-
- if ((mp->mp_flags & P_DIRTY) && mc->mc_dbi != FREE_DBI) {
- if (txn->mt_parent) {
- mdbx_cassert(mc, (txn->mt_env->me_flags & MDBX_WRITEMAP) == 0);
- MDBX_ID2 *dl = txn->mt_rw_dirtylist;
- /* If txn has a parent,
- * make sure the page is in our dirty list. */
- if (dl[0].mid) {
- unsigned x = mdbx_mid2l_search(dl, pgno);
- if (x <= dl[0].mid && dl[x].mid == pgno) {
- if (unlikely(mp != dl[x].mptr)) { /* bad cursor? */
- mdbx_error("wrong page 0x%p #%" PRIaPGNO
- " in the dirtylist[%d], expecting %p",
- dl[x].mptr, pgno, x, mp);
- mc->mc_flags &= ~(C_INITIALIZED | C_EOF);
- txn->mt_flags |= MDBX_TXN_ERROR;
- return MDBX_PROBLEM;
- }
- /* ok, it's ours */
- loose = 1;
- }
- }
- } else {
- /* no parent txn, so it's just ours */
- loose = 1;
- }
- }
- if (loose) {
- mdbx_debug("loosen db %d page %" PRIaPGNO, DDBI(mc), mp->mp_pgno);
- MDBX_page **link = &NEXT_LOOSE_PAGE(mp);
- if (unlikely(txn->mt_env->me_flags & MDBX_PAGEPERTURB)) {
- mdbx_kill_page(txn->mt_env, pgno);
- VALGRIND_MAKE_MEM_UNDEFINED(link, sizeof(MDBX_page *));
- ASAN_UNPOISON_MEMORY_REGION(link, sizeof(MDBX_page *));
- }
- *link = txn->mt_loose_pages;
- txn->mt_loose_pages = mp;
- txn->mt_loose_count++;
- mp->mp_flags |= P_LOOSE;
- } else {
- int rc = mdbx_pnl_append(&txn->mt_befree_pages, pgno);
- if (unlikely(rc))
- return rc;
- }
-
- return MDBX_SUCCESS;
-}
-
-/* Set or clear P_KEEP in dirty, non-overflow, non-sub pages watched by txn.
- *
- * [in] mc A cursor handle for the current operation.
- * [in] pflags Flags of the pages to update:
- * - P_DIRTY to set P_KEEP,
- * - P_DIRTY|P_KEEP to clear it.
- * [in] all No shortcuts. Needed except after a full mdbx_page_flush().
- *
- * Returns 0 on success, non-zero on failure. */
-static int mdbx_pages_xkeep(MDBX_cursor *mc, unsigned pflags, bool all) {
- const unsigned Mask = P_SUBP | P_DIRTY | P_LOOSE | P_KEEP;
- MDBX_txn *txn = mc->mc_txn;
- MDBX_cursor *m3, *m0 = mc;
- MDBX_xcursor *mx;
- MDBX_page *dp, *mp;
- MDBX_node *leaf;
- unsigned i, j;
- int rc = MDBX_SUCCESS, level;
-
- /* Mark pages seen by cursors: First m0, then tracked cursors */
- for (i = txn->mt_numdbs;;) {
- if (mc->mc_flags & C_INITIALIZED) {
- for (m3 = mc;; m3 = &mx->mx_cursor) {
- mp = NULL;
- for (j = 0; j < m3->mc_snum; j++) {
- mp = m3->mc_pg[j];
- if ((mp->mp_flags & Mask) == pflags)
- mp->mp_flags ^= P_KEEP;
- }
- mx = m3->mc_xcursor;
- /* Proceed to mx if it is at a sub-database */
- if (!(mx && (mx->mx_cursor.mc_flags & C_INITIALIZED)))
- break;
- if (!(mp && (mp->mp_flags & P_LEAF)))
- break;
- leaf = NODEPTR(mp, m3->mc_ki[j - 1]);
- if (!(leaf->mn_flags & F_SUBDATA))
- break;
- }
- }
- mc = mc->mc_next;
- for (; !mc || mc == m0; mc = txn->mt_cursors[--i])
- if (i == 0)
- goto mark_done;
- }
-
-mark_done:
- if (all) {
- /* Mark dirty root pages */
- for (i = 0; i < txn->mt_numdbs; i++) {
- if (txn->mt_dbflags[i] & DB_DIRTY) {
- pgno_t pgno = txn->mt_dbs[i].md_root;
- if (pgno == P_INVALID)
- continue;
- if (unlikely((rc = mdbx_page_get(m0, pgno, &dp, &level)) !=
- MDBX_SUCCESS))
- break;
- if ((dp->mp_flags & Mask) == pflags && level <= 1)
- dp->mp_flags ^= P_KEEP;
- }
- }
- }
-
- return rc;
-}
-
-static int mdbx_page_flush(MDBX_txn *txn, pgno_t keep);
-
-/* Spill pages from the dirty list back to disk.
- * This is intended to prevent running into MDBX_TXN_FULL situations,
- * but note that they may still occur in a few cases:
- *
- * 1) our estimate of the txn size could be too small. Currently this
- * seems unlikely, except with a large number of MDBX_MULTIPLE items.
- *
- * 2) child txns may run out of space if their parents dirtied a
- * lot of pages and never spilled them. TODO: we probably should do
- * a preemptive spill during mdbx_txn_begin() of a child txn, if
- * the parent's dirtyroom is below a given threshold.
- *
- * Otherwise, if not using nested txns, it is expected that apps will
- * not run into MDBX_TXN_FULL any more. The pages are flushed to disk
- * the same way as for a txn commit, e.g. their P_DIRTY flag is cleared.
- * If the txn never references them again, they can be left alone.
- * If the txn only reads them, they can be used without any fuss.
- * If the txn writes them again, they can be dirtied immediately without
- * going thru all of the work of mdbx_page_touch(). Such references are
- * handled by mdbx_page_unspill().
- *
- * Also note, we never spill DB root pages, nor pages of active cursors,
- * because we'll need these back again soon anyway. And in nested txns,
- * we can't spill a page in a child txn if it was already spilled in a
- * parent txn. That would alter the parent txns' data even though
- * the child hasn't committed yet, and we'd have no way to undo it if
- * the child aborted.
- *
- * [in] m0 cursor A cursor handle identifying the transaction and
- * database for which we are checking space.
- * [in] key For a put operation, the key being stored.
- * [in] data For a put operation, the data being stored.
- *
- * Returns 0 on success, non-zero on failure. */
-static int mdbx_page_spill(MDBX_cursor *m0, MDBX_val *key, MDBX_val *data) {
- MDBX_txn *txn = m0->mc_txn;
- MDBX_ID2L dl = txn->mt_rw_dirtylist;
-
- if (m0->mc_flags & C_SUB)
- return MDBX_SUCCESS;
-
- /* Estimate how much space this op will take */
- pgno_t i = m0->mc_db->md_depth;
- /* Named DBs also dirty the main DB */
- if (m0->mc_dbi >= CORE_DBS)
- i += txn->mt_dbs[MAIN_DBI].md_depth;
- /* For puts, roughly factor in the key+data size */
- if (key)
- i += bytes2pgno(txn->mt_env, LEAFSIZE(key, data) + txn->mt_env->me_psize);
- i += i; /* double it for good measure */
- pgno_t need = i;
-
- if (txn->mt_dirtyroom > i)
- return MDBX_SUCCESS;
-
- if (!txn->mt_spill_pages) {
- txn->mt_spill_pages = mdbx_pnl_alloc(MDBX_PNL_UM_MAX);
- if (unlikely(!txn->mt_spill_pages))
- return MDBX_ENOMEM;
- } else {
- /* purge deleted slots */
- MDBX_PNL sl = txn->mt_spill_pages;
- pgno_t num = sl[0], j = 0;
- for (i = 1; i <= num; i++) {
- if (!(sl[i] & 1))
- sl[++j] = sl[i];
- }
- sl[0] = j;
- }
-
- /* Preserve pages which may soon be dirtied again */
- int rc = mdbx_pages_xkeep(m0, P_DIRTY, true);
- if (unlikely(rc != MDBX_SUCCESS))
- goto bailout;
-
- /* Less aggressive spill - we originally spilled the entire dirty list,
- * with a few exceptions for cursor pages and DB root pages. But this
- * turns out to be a lot of wasted effort because in a large txn many
- * of those pages will need to be used again. So now we spill only 1/8th
- * of the dirty pages. Testing revealed this to be a good tradeoff,
- * better than 1/2, 1/4, or 1/10. */
- if (need < MDBX_PNL_UM_MAX / 8)
- need = MDBX_PNL_UM_MAX / 8;
-
- /* Save the page IDs of all the pages we're flushing */
- /* flush from the tail forward, this saves a lot of shifting later on. */
- for (i = dl[0].mid; i && need; i--) {
- pgno_t pn = dl[i].mid << 1;
- MDBX_page *dp = dl[i].mptr;
- if (dp->mp_flags & (P_LOOSE | P_KEEP))
- continue;
- /* Can't spill twice,
- * make sure it's not already in a parent's spill list. */
- if (txn->mt_parent) {
- MDBX_txn *tx2;
- for (tx2 = txn->mt_parent; tx2; tx2 = tx2->mt_parent) {
- if (tx2->mt_spill_pages) {
- unsigned j = mdbx_pnl_search(tx2->mt_spill_pages, pn);
- if (j <= tx2->mt_spill_pages[0] && tx2->mt_spill_pages[j] == pn) {
- dp->mp_flags |= P_KEEP;
- break;
- }
- }
- }
- if (tx2)
- continue;
- }
- rc = mdbx_pnl_append(&txn->mt_spill_pages, pn);
- if (unlikely(rc != MDBX_SUCCESS))
- goto bailout;
- need--;
- }
- mdbx_pnl_sort(txn->mt_spill_pages);
-
- /* Flush the spilled part of dirty list */
- rc = mdbx_page_flush(txn, i);
- if (unlikely(rc != MDBX_SUCCESS))
- goto bailout;
-
- /* Reset any dirty pages we kept that page_flush didn't see */
- rc = mdbx_pages_xkeep(m0, P_DIRTY | P_KEEP, i != 0);
-
-bailout:
- txn->mt_flags |= rc ? MDBX_TXN_ERROR : MDBX_TXN_SPILLS;
- return rc;
-}
-
-/*----------------------------------------------------------------------------*/
-
-#define METAPAGE(env, n) (&pgno2page(env, n)->mp_meta)
-
-#define METAPAGE_END(env) METAPAGE(env, NUM_METAS)
-
-static __inline txnid_t meta_txnid(const MDBX_env *env, const MDBX_meta *meta,
- bool allow_volatile) {
- mdbx_assert(env, meta >= METAPAGE(env, 0) || meta < METAPAGE_END(env));
- txnid_t a = meta->mm_txnid_a;
- txnid_t b = meta->mm_txnid_b;
- if (allow_volatile)
- return (a == b) ? a : 0;
- mdbx_assert(env, a == b);
- return a;
-}
-
-static __inline txnid_t mdbx_meta_txnid_stable(const MDBX_env *env,
- const MDBX_meta *meta) {
- return meta_txnid(env, meta, false);
-}
-
-static __inline txnid_t mdbx_meta_txnid_fluid(const MDBX_env *env,
- const MDBX_meta *meta) {
- return meta_txnid(env, meta, true);
-}
-
-static __inline void mdbx_meta_update_begin(const MDBX_env *env,
- MDBX_meta *meta, txnid_t txnid) {
- mdbx_assert(env, meta >= METAPAGE(env, 0) || meta < METAPAGE_END(env));
- mdbx_assert(env, meta->mm_txnid_a < txnid && meta->mm_txnid_b < txnid);
- meta->mm_txnid_a = txnid;
- (void)env;
- mdbx_coherent_barrier();
-}
-
-static __inline void mdbx_meta_update_end(const MDBX_env *env, MDBX_meta *meta,
- txnid_t txnid) {
- mdbx_assert(env, meta >= METAPAGE(env, 0) || meta < METAPAGE_END(env));
- mdbx_assert(env, meta->mm_txnid_a == txnid);
- mdbx_assert(env, meta->mm_txnid_b < txnid);
-
- mdbx_jitter4testing(true);
- meta->mm_txnid_b = txnid;
- mdbx_coherent_barrier();
-}
-
-static __inline void mdbx_meta_set_txnid(const MDBX_env *env, MDBX_meta *meta,
- txnid_t txnid) {
- mdbx_assert(env, meta < METAPAGE(env, 0) || meta > METAPAGE_END(env));
- meta->mm_txnid_a = txnid;
- meta->mm_txnid_b = txnid;
-}
-
-static __inline uint64_t mdbx_meta_sign(const MDBX_meta *meta) {
- uint64_t sign = MDBX_DATASIGN_NONE;
-#if 0 /* TODO */
- sign = hippeus_hash64(...);
-#else
- (void)meta;
-#endif
- /* LY: newer returns MDBX_DATASIGN_NONE or MDBX_DATASIGN_WEAK */
- return (sign > MDBX_DATASIGN_WEAK) ? sign : ~sign;
-}
-
-enum meta_choise_mode { prefer_last, prefer_noweak, prefer_steady };
-
-static __inline bool mdbx_meta_ot(const enum meta_choise_mode mode,
- const MDBX_env *env, const MDBX_meta *a,
- const MDBX_meta *b) {
- mdbx_jitter4testing(true);
- txnid_t txnid_a = mdbx_meta_txnid_fluid(env, a);
- txnid_t txnid_b = mdbx_meta_txnid_fluid(env, b);
-
- mdbx_jitter4testing(true);
- switch (mode) {
- default:
- assert(false);
- __unreachable();
- /* fall through */
- __fallthrough;
- case prefer_steady:
- if (META_IS_STEADY(a) != META_IS_STEADY(b))
- return META_IS_STEADY(b);
- /* fall through */
- __fallthrough;
- case prefer_noweak:
- if (META_IS_WEAK(a) != META_IS_WEAK(b))
- return !META_IS_WEAK(b);
- /* fall through */
- __fallthrough;
- case prefer_last:
- mdbx_jitter4testing(true);
- if (txnid_a == txnid_b)
- return META_IS_STEADY(b) || (META_IS_WEAK(a) && !META_IS_WEAK(b));
- return txnid_a < txnid_b;
- }
-}
-
-static __inline bool mdbx_meta_eq(const MDBX_env *env, const MDBX_meta *a,
- const MDBX_meta *b) {
- mdbx_jitter4testing(true);
- const txnid_t txnid = mdbx_meta_txnid_fluid(env, a);
- if (!txnid || txnid != mdbx_meta_txnid_fluid(env, b))
- return false;
-
- mdbx_jitter4testing(true);
- if (META_IS_STEADY(a) != META_IS_STEADY(b))
- return false;
-
- mdbx_jitter4testing(true);
- return true;
-}
-
-static int mdbx_meta_eq_mask(const MDBX_env *env) {
- MDBX_meta *m0 = METAPAGE(env, 0);
- MDBX_meta *m1 = METAPAGE(env, 1);
- MDBX_meta *m2 = METAPAGE(env, 2);
-
- int rc = mdbx_meta_eq(env, m0, m1) ? 1 : 0;
- if (mdbx_meta_eq(env, m1, m2))
- rc += 2;
- if (mdbx_meta_eq(env, m2, m0))
- rc += 4;
- return rc;
-}
-
-static __inline MDBX_meta *mdbx_meta_recent(const enum meta_choise_mode mode,
- const MDBX_env *env, MDBX_meta *a,
- MDBX_meta *b) {
- const bool a_older_that_b = mdbx_meta_ot(mode, env, a, b);
- mdbx_assert(env, !mdbx_meta_eq(env, a, b));
- return a_older_that_b ? b : a;
-}
-
-static __inline MDBX_meta *mdbx_meta_ancient(const enum meta_choise_mode mode,
- const MDBX_env *env, MDBX_meta *a,
- MDBX_meta *b) {
- const bool a_older_that_b = mdbx_meta_ot(mode, env, a, b);
- mdbx_assert(env, !mdbx_meta_eq(env, a, b));
- return a_older_that_b ? a : b;
-}
-
-static __inline MDBX_meta *
-mdbx_meta_mostrecent(const enum meta_choise_mode mode, const MDBX_env *env) {
- MDBX_meta *m0 = METAPAGE(env, 0);
- MDBX_meta *m1 = METAPAGE(env, 1);
- MDBX_meta *m2 = METAPAGE(env, 2);
-
- MDBX_meta *head = mdbx_meta_recent(mode, env, m0, m1);
- head = mdbx_meta_recent(mode, env, head, m2);
- return head;
-}
-
-static __hot MDBX_meta *mdbx_meta_steady(const MDBX_env *env) {
- return mdbx_meta_mostrecent(prefer_steady, env);
-}
-
-static __hot MDBX_meta *mdbx_meta_head(const MDBX_env *env) {
- return mdbx_meta_mostrecent(prefer_last, env);
-}
-
-static __hot txnid_t mdbx_reclaiming_detent(const MDBX_env *env) {
- if (F_ISSET(env->me_flags, MDBX_UTTERLY_NOSYNC))
- return env->me_txn->mt_txnid - 1;
-
- return mdbx_meta_txnid_stable(env, mdbx_meta_steady(env));
-}
-
-static const char *mdbx_durable_str(const MDBX_meta *const meta) {
- if (META_IS_WEAK(meta))
- return "Weak";
- if (META_IS_STEADY(meta))
- return (meta->mm_datasync_sign == mdbx_meta_sign(meta)) ? "Steady"
- : "Tainted";
- return "Legacy";
-}
-
-/*----------------------------------------------------------------------------*/
-
-/* Find oldest txnid still referenced. */
-static txnid_t mdbx_find_oldest(MDBX_txn *txn) {
- mdbx_tassert(txn, (txn->mt_flags & MDBX_RDONLY) == 0);
- const MDBX_env *env = txn->mt_env;
- MDBX_lockinfo *const lck = env->me_lck;
-
- const txnid_t edge = mdbx_reclaiming_detent(env);
- mdbx_tassert(txn, edge <= txn->mt_txnid - 1);
- const txnid_t last_oldest = lck->mti_oldest;
- mdbx_tassert(txn, edge >= last_oldest);
- if (last_oldest == edge)
- return edge;
-
- const uint32_t nothing_changed = MDBX_STRING_TETRAD("None");
- const uint32_t snap_readers_refresh_flag = lck->mti_readers_refresh_flag;
- mdbx_jitter4testing(false);
- if (snap_readers_refresh_flag == nothing_changed)
- return last_oldest;
-
- txnid_t oldest = edge;
- lck->mti_readers_refresh_flag = nothing_changed;
- mdbx_coherent_barrier();
- const unsigned snap_nreaders = lck->mti_numreaders;
- for (unsigned i = 0; i < snap_nreaders; ++i) {
- if (lck->mti_readers[i].mr_pid) {
- /* mdbx_jitter4testing(true); */
- const txnid_t snap = lck->mti_readers[i].mr_txnid;
- if (oldest > snap && last_oldest <= /* ignore pending updates */ snap) {
- oldest = snap;
- if (oldest == last_oldest)
- return oldest;
- }
- }
- }
-
- if (oldest != last_oldest) {
- mdbx_notice("update oldest %" PRIaTXN " -> %" PRIaTXN, last_oldest, oldest);
- mdbx_tassert(txn, oldest >= lck->mti_oldest);
- lck->mti_oldest = oldest;
- }
- return oldest;
-}
-
-/* Add a page to the txn's dirty list */
-static void mdbx_page_dirty(MDBX_txn *txn, MDBX_page *mp) {
- MDBX_ID2 mid;
- int rc, (*insert)(MDBX_ID2L, MDBX_ID2 *);
-
- if (txn->mt_flags & MDBX_TXN_WRITEMAP) {
- insert = mdbx_mid2l_append;
- } else {
- insert = mdbx_mid2l_insert;
- }
- mid.mid = mp->mp_pgno;
- mid.mptr = mp;
- rc = insert(txn->mt_rw_dirtylist, &mid);
- mdbx_tassert(txn, rc == 0);
- txn->mt_dirtyroom--;
-}
-
-static int mdbx_mapresize(MDBX_env *env, const pgno_t size_pgno,
- const pgno_t limit_pgno) {
-#ifdef USE_VALGRIND
- const size_t prev_mapsize = env->me_mapsize;
- void *const prev_mapaddr = env->me_map;
-#endif
-
- const size_t limit_bytes = pgno_align2os_bytes(env, limit_pgno);
- const size_t size_bytes = pgno_align2os_bytes(env, size_pgno);
-
- mdbx_info("resize datafile/mapping: "
- "present %" PRIuPTR " -> %" PRIuPTR ", "
- "limit %" PRIuPTR " -> %" PRIuPTR,
- env->me_dbgeo.now, size_bytes, env->me_dbgeo.upper, limit_bytes);
-
- mdbx_assert(env, limit_bytes >= size_bytes);
- mdbx_assert(env, bytes2pgno(env, size_bytes) == size_pgno);
- mdbx_assert(env, bytes2pgno(env, limit_bytes) == limit_pgno);
- const int rc =
- mdbx_mresize(env->me_flags, &env->me_dxb_mmap, size_bytes, limit_bytes);
-
- if (rc == MDBX_SUCCESS) {
- env->me_dbgeo.now = size_bytes;
- env->me_dbgeo.upper = limit_bytes;
- } else if (rc != MDBX_RESULT_TRUE) {
- mdbx_error("failed resize datafile/mapping: "
- "present %" PRIuPTR " -> %" PRIuPTR ", "
- "limit %" PRIuPTR " -> %" PRIuPTR ", errcode %d",
- env->me_dbgeo.now, size_bytes, env->me_dbgeo.upper, limit_bytes,
- rc);
- return rc;
- } else {
- mdbx_notice("unable resize datafile/mapping: "
- "present %" PRIuPTR " -> %" PRIuPTR ", "
- "limit %" PRIuPTR " -> %" PRIuPTR ", errcode %d",
- env->me_dbgeo.now, size_bytes, env->me_dbgeo.upper, limit_bytes,
- rc);
- }
-
-#ifdef USE_VALGRIND
- if (prev_mapsize != env->me_mapsize || prev_mapaddr != env->me_map) {
- VALGRIND_DISCARD(env->me_valgrind_handle);
- env->me_valgrind_handle = 0;
- if (env->me_mapsize)
- env->me_valgrind_handle =
- VALGRIND_CREATE_BLOCK(env->me_map, env->me_mapsize, "mdbx");
- }
-#endif
-
- if (env->me_txn) {
- mdbx_tassert(env->me_txn, size_pgno >= env->me_txn->mt_next_pgno);
- env->me_txn->mt_end_pgno = size_pgno;
- }
- return MDBX_SUCCESS;
-}
-
-/* Allocate page numbers and memory for writing. Maintain me_last_reclaimed,
- * me_reclaimed_pglist and mt_next_pgno. Set MDBX_TXN_ERROR on failure.
- *
- * If there are free pages available from older transactions, they
- * are re-used first. Otherwise allocate a new page at mt_next_pgno.
- * Do not modify the freedB, just merge freeDB records into me_reclaimed_pglist
- * and move me_last_reclaimed to say which records were consumed. Only this
- * function can create me_reclaimed_pglist and move
- * me_last_reclaimed/mt_next_pgno.
- *
- * [in] mc cursor A cursor handle identifying the transaction and
- * database for which we are allocating.
- * [in] num the number of pages to allocate.
- * [out] mp Address of the allocated page(s). Requests for multiple pages
- * will always be satisfied by a single contiguous chunk of memory.
- *
- * Returns 0 on success, non-zero on failure.*/
-
-#define MDBX_ALLOC_CACHE 1
-#define MDBX_ALLOC_GC 2
-#define MDBX_ALLOC_NEW 4
-#define MDBX_ALLOC_KICK 8
-#define MDBX_ALLOC_ALL \
- (MDBX_ALLOC_CACHE | MDBX_ALLOC_GC | MDBX_ALLOC_NEW | MDBX_ALLOC_KICK)
-
-static int mdbx_page_alloc(MDBX_cursor *mc, unsigned num, MDBX_page **mp,
- int flags) {
- int rc;
- MDBX_txn *txn = mc->mc_txn;
- MDBX_env *env = txn->mt_env;
- MDBX_page *np;
-
- if (likely(flags & MDBX_ALLOC_GC)) {
- flags |= env->me_flags & (MDBX_COALESCE | MDBX_LIFORECLAIM);
- if (unlikely(mc->mc_flags & C_RECLAIMING)) {
- /* If mc is updating the freeDB, then the freelist cannot play
- * catch-up with itself by growing while trying to save it. */
- flags &=
- ~(MDBX_ALLOC_GC | MDBX_ALLOC_KICK | MDBX_COALESCE | MDBX_LIFORECLAIM);
- }
- }
-
- if (likely(flags & MDBX_ALLOC_CACHE)) {
- /* If there are any loose pages, just use them */
- assert(mp && num);
- if (likely(num == 1 && txn->mt_loose_pages)) {
- np = txn->mt_loose_pages;
- txn->mt_loose_pages = NEXT_LOOSE_PAGE(np);
- txn->mt_loose_count--;
- mdbx_debug("db %d use loose page %" PRIaPGNO, DDBI(mc), np->mp_pgno);
- ASAN_UNPOISON_MEMORY_REGION(np, env->me_psize);
- mdbx_tassert(txn, np->mp_pgno < txn->mt_next_pgno);
- mdbx_ensure(env, np->mp_pgno >= NUM_METAS);
- *mp = np;
- return MDBX_SUCCESS;
- }
- }
-
- mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist));
- pgno_t pgno, *repg_list = env->me_reclaimed_pglist;
- unsigned repg_pos = 0, repg_len = repg_list ? repg_list[0] : 0;
- txnid_t oldest = 0, last = 0;
- const unsigned wanna_range = num - 1;
-
- while (1) { /* oom-kick retry loop */
- /* If our dirty list is already full, we can't do anything */
- if (unlikely(txn->mt_dirtyroom == 0)) {
- rc = MDBX_TXN_FULL;
- goto fail;
- }
-
- MDBX_cursor recur;
- for (MDBX_cursor_op op = MDBX_FIRST;;
- op = (flags & MDBX_LIFORECLAIM) ? MDBX_PREV : MDBX_NEXT) {
- MDBX_val key, data;
-
- /* Seek a big enough contiguous page range.
- * Prefer pages with lower pgno. */
- mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist));
- if (likely(flags & MDBX_ALLOC_CACHE) && repg_len > wanna_range &&
- (!(flags & MDBX_COALESCE) || op == MDBX_FIRST)) {
-#if MDBX_PNL_ASCENDING
- for (repg_pos = 1; repg_pos <= repg_len - wanna_range; ++repg_pos) {
- pgno = repg_list[repg_pos];
- if (likely(repg_list[repg_pos + wanna_range - 1] ==
- pgno + wanna_range - 1))
- goto done;
- }
-#else
- repg_pos = repg_len;
- do {
- pgno = repg_list[repg_pos];
- if (likely(repg_list[repg_pos - wanna_range] == pgno + wanna_range))
- goto done;
- } while (--repg_pos > wanna_range);
-#endif /* MDBX_PNL sort-order */
- }
-
- if (op == MDBX_FIRST) { /* 1st iteration, setup cursor, etc */
- if (unlikely(!(flags & MDBX_ALLOC_GC)))
- break /* reclaiming is prohibited for now */;
-
- /* Prepare to fetch more and coalesce */
- oldest = (flags & MDBX_LIFORECLAIM) ? mdbx_find_oldest(txn)
- : env->me_oldest[0];
- mdbx_cursor_init(&recur, txn, FREE_DBI, NULL);
- if (flags & MDBX_LIFORECLAIM) {
- /* Begin from oldest reader if any */
- if (oldest > 2) {
- last = oldest - 1;
- op = MDBX_SET_RANGE;
- }
- } else if (env->me_last_reclaimed) {
- /* Continue lookup from env->me_last_reclaimed to oldest reader */
- last = env->me_last_reclaimed;
- op = MDBX_SET_RANGE;
- }
-
- key.iov_base = &last;
- key.iov_len = sizeof(last);
- }
-
- if (!(flags & MDBX_LIFORECLAIM)) {
- /* Do not try fetch more if the record will be too recent */
- if (op != MDBX_FIRST && ++last >= oldest) {
- oldest = mdbx_find_oldest(txn);
- if (oldest <= last)
- break;
- }
- }
-
- rc = mdbx_cursor_get(&recur, &key, NULL, op);
- if (rc == MDBX_NOTFOUND && (flags & MDBX_LIFORECLAIM)) {
- if (op == MDBX_SET_RANGE)
- continue;
- if (oldest < mdbx_find_oldest(txn)) {
- oldest = *env->me_oldest;
- last = oldest - 1;
- key.iov_base = &last;
- key.iov_len = sizeof(last);
- op = MDBX_SET_RANGE;
- rc = mdbx_cursor_get(&recur, &key, NULL, op);
- }
- }
- if (unlikely(rc)) {
- if (rc == MDBX_NOTFOUND)
- break;
- goto fail;
- }
-
- last = *(txnid_t *)key.iov_base;
- if (oldest <= last) {
- oldest = mdbx_find_oldest(txn);
- if (oldest <= last) {
- if (flags & MDBX_LIFORECLAIM)
- continue;
- break;
- }
- }
-
- if (flags & MDBX_LIFORECLAIM) {
- /* skip IDs of records that already reclaimed */
- if (txn->mt_lifo_reclaimed) {
- unsigned i;
- for (i = (unsigned)txn->mt_lifo_reclaimed[0]; i > 0; --i)
- if (txn->mt_lifo_reclaimed[i] == last)
- break;
- if (i)
- continue;
- }
- }
-
- /* Reading next FreeDB record */
- np = recur.mc_pg[recur.mc_top];
- MDBX_node *leaf = NODEPTR(np, recur.mc_ki[recur.mc_top]);
- if (unlikely((rc = mdbx_node_read(&recur, leaf, &data)) != MDBX_SUCCESS))
- goto fail;
-
- if ((flags & MDBX_LIFORECLAIM) && !txn->mt_lifo_reclaimed) {
- txn->mt_lifo_reclaimed = mdbx_txl_alloc();
- if (unlikely(!txn->mt_lifo_reclaimed)) {
- rc = MDBX_ENOMEM;
- goto fail;
- }
- }
-
- /* Append PNL from FreeDB record to me_reclaimed_pglist */
- pgno_t *re_pnl = (pgno_t *)data.iov_base;
- mdbx_tassert(txn, re_pnl[0] == 0 ||
- data.iov_len == (re_pnl[0] + 1) * sizeof(pgno_t));
- mdbx_tassert(txn, mdbx_pnl_check(re_pnl));
- repg_pos = re_pnl[0];
- if (!repg_list) {
- if (unlikely(!(env->me_reclaimed_pglist = repg_list =
- mdbx_pnl_alloc(repg_pos)))) {
- rc = MDBX_ENOMEM;
- goto fail;
- }
- } else {
- if (unlikely(
- (rc = mdbx_pnl_need(&env->me_reclaimed_pglist, repg_pos)) != 0))
- goto fail;
- repg_list = env->me_reclaimed_pglist;
- }
-
- /* Remember ID of FreeDB record */
- if (flags & MDBX_LIFORECLAIM) {
- if ((rc = mdbx_txl_append(&txn->mt_lifo_reclaimed, last)) != 0)
- goto fail;
- }
- env->me_last_reclaimed = last;
-
- if (mdbx_debug_enabled(MDBX_DBG_EXTRA)) {
- mdbx_debug_extra("PNL read txn %" PRIaTXN " root %" PRIaPGNO
- " num %u, PNL",
- last, txn->mt_dbs[FREE_DBI].md_root, repg_pos);
- unsigned i;
- for (i = repg_pos; i; i--)
- mdbx_debug_extra_print(" %" PRIaPGNO "", re_pnl[i]);
- mdbx_debug_extra_print("\n");
- }
-
- /* Merge in descending sorted order */
- mdbx_pnl_xmerge(repg_list, re_pnl);
- repg_len = repg_list[0];
- if (unlikely((flags & MDBX_ALLOC_CACHE) == 0)) {
- /* Done for a kick-reclaim mode, actually no page needed */
- return MDBX_SUCCESS;
- }
-
- mdbx_tassert(txn,
- repg_len == 0 || repg_list[repg_len] < txn->mt_next_pgno);
- if (repg_len) {
- /* Refund suitable pages into "unallocated" space */
- pgno_t tail = txn->mt_next_pgno;
- pgno_t *const begin = repg_list + 1;
- pgno_t *const end = begin + repg_len;
- pgno_t *higest;
-#if MDBX_PNL_ASCENDING
- for (higest = end; --higest >= begin;) {
-#else
- for (higest = begin; higest < end; ++higest) {
-#endif /* MDBX_PNL sort-order */
- mdbx_tassert(txn, *higest >= NUM_METAS && *higest < tail);
- if (*higest != tail - 1)
- break;
- tail -= 1;
- }
- if (tail != txn->mt_next_pgno) {
-#if MDBX_PNL_ASCENDING
- repg_len = (unsigned)(higest + 1 - begin);
-#else
- repg_len -= (unsigned)(higest - begin);
- for (pgno_t *move = begin; higest < end; ++move, ++higest)
- *move = *higest;
-#endif /* MDBX_PNL sort-order */
- repg_list[0] = repg_len;
- mdbx_info("refunded %" PRIaPGNO " pages: %" PRIaPGNO " -> %" PRIaPGNO,
- tail - txn->mt_next_pgno, tail, txn->mt_next_pgno);
- txn->mt_next_pgno = tail;
- mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist));
- }
- }
-
- /* Don't try to coalesce too much. */
- if (repg_len > MDBX_PNL_UM_SIZE / 2)
- break;
- if (flags & MDBX_COALESCE) {
- if (repg_len /* current size */ >= env->me_maxfree_1pg / 2 ||
- repg_pos /* prev size */ >= env->me_maxfree_1pg / 4)
- flags &= ~MDBX_COALESCE;
- }
- }
-
- if ((flags & (MDBX_COALESCE | MDBX_ALLOC_CACHE)) ==
- (MDBX_COALESCE | MDBX_ALLOC_CACHE) &&
- repg_len > wanna_range) {
-#if MDBX_PNL_ASCENDING
- for (repg_pos = 1; repg_pos <= repg_len - wanna_range; ++repg_pos) {
- pgno = repg_list[repg_pos];
- if (likely(repg_list[repg_pos + wanna_range - 1] ==
- pgno + wanna_range - 1))
- goto done;
- }
-#else
- repg_pos = repg_len;
- do {
- pgno = repg_list[repg_pos];
- if (likely(repg_list[repg_pos - wanna_range] == pgno + wanna_range))
- goto done;
- } while (--repg_pos > wanna_range);
-#endif /* MDBX_PNL sort-order */
- }
-
- /* Use new pages from the map when nothing suitable in the freeDB */
- repg_pos = 0;
- pgno = txn->mt_next_pgno;
- rc = MDBX_MAP_FULL;
- const pgno_t next = pgno_add(pgno, num);
- if (likely(next <= txn->mt_end_pgno)) {
- rc = MDBX_NOTFOUND;
- if (likely(flags & MDBX_ALLOC_NEW))
- goto done;
- }
-
- const MDBX_meta *head = mdbx_meta_head(env);
- if ((flags & MDBX_ALLOC_GC) &&
- ((flags & MDBX_ALLOC_KICK) || rc == MDBX_MAP_FULL)) {
- MDBX_meta *steady = mdbx_meta_steady(env);
-
- if (oldest == mdbx_meta_txnid_stable(env, steady) &&
- !META_IS_STEADY(head) && META_IS_STEADY(steady)) {
- /* LY: Here an oom was happened:
- * - all pages had allocated;
- * - reclaiming was stopped at the last steady-sync;
- * - the head-sync is weak.
- * Now we need make a sync to resume reclaiming. If both
- * MDBX_NOSYNC and MDBX_MAPASYNC flags are set, then assume that
- * utterly no-sync write mode was requested. In such case
- * don't make a steady-sync, but only a legacy-mode checkpoint,
- * just for resume reclaiming only, not for data consistency. */
-
- mdbx_debug("kick-gc: head %" PRIaTXN "-%s, tail %" PRIaTXN
- "-%s, oldest %" PRIaTXN "",
- mdbx_meta_txnid_stable(env, head), mdbx_durable_str(head),
- mdbx_meta_txnid_stable(env, steady),
- mdbx_durable_str(steady), oldest);
-
- const unsigned syncflags = F_ISSET(env->me_flags, MDBX_UTTERLY_NOSYNC)
- ? env->me_flags
- : env->me_flags & MDBX_WRITEMAP;
- MDBX_meta meta = *head;
- if (mdbx_sync_locked(env, syncflags, &meta) == MDBX_SUCCESS) {
- txnid_t snap = mdbx_find_oldest(txn);
- if (snap > oldest)
- continue;
- }
- }
-
- if (rc == MDBX_MAP_FULL && oldest < txn->mt_txnid - 1) {
- if (mdbx_oomkick(env, oldest) > oldest)
- continue;
- }
- }
-
- if (rc == MDBX_MAP_FULL && next < head->mm_geo.upper) {
- mdbx_assert(env, next > txn->mt_end_pgno);
- pgno_t aligned = pgno_align2os_pgno(
- env, pgno_add(next, head->mm_geo.grow - next % head->mm_geo.grow));
-
- if (aligned > head->mm_geo.upper)
- aligned = head->mm_geo.upper;
- mdbx_assert(env, aligned > txn->mt_end_pgno);
-
- mdbx_info("try growth datafile to %" PRIaPGNO " pages (+%" PRIaPGNO ")",
- aligned, aligned - txn->mt_end_pgno);
- rc = mdbx_mapresize(env, aligned, head->mm_geo.upper);
- if (rc == MDBX_SUCCESS) {
- mdbx_tassert(env->me_txn, txn->mt_end_pgno >= next);
- if (!mp)
- return rc;
- goto done;
- }
-
- mdbx_warning("unable growth datafile to %" PRIaPGNO "pages (+%" PRIaPGNO
- "), errcode %d",
- aligned, aligned - txn->mt_end_pgno, rc);
- }
-
- fail:
- mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist));
- if (mp) {
- *mp = NULL;
- txn->mt_flags |= MDBX_TXN_ERROR;
- }
- assert(rc);
- return rc;
- }
-
-done:
- mdbx_tassert(txn, mp && num);
- mdbx_ensure(env, pgno >= NUM_METAS);
- if (env->me_flags & MDBX_WRITEMAP) {
- np = pgno2page(env, pgno);
- /* LY: reset no-access flag from mdbx_kill_page() */
- VALGRIND_MAKE_MEM_UNDEFINED(np, pgno2bytes(env, num));
- ASAN_UNPOISON_MEMORY_REGION(np, pgno2bytes(env, num));
- } else {
- if (unlikely(!(np = mdbx_page_malloc(txn, num)))) {
- rc = MDBX_ENOMEM;
- goto fail;
- }
- }
-
- if (repg_pos) {
- mdbx_tassert(txn, pgno < txn->mt_next_pgno);
- mdbx_tassert(txn, pgno == repg_list[repg_pos]);
- /* Cutoff allocated pages from me_reclaimed_pglist */
- repg_list[0] = repg_len -= num;
- for (unsigned i = repg_pos - num; i < repg_len;)
- repg_list[++i] = repg_list[++repg_pos];
- mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist));
- } else {
- txn->mt_next_pgno = pgno + num;
- mdbx_assert(env, txn->mt_next_pgno <= txn->mt_end_pgno);
- }
-
- if (env->me_flags & MDBX_PAGEPERTURB)
- memset(np, 0x71 /* 'q', 113 */, pgno2bytes(env, num));
- VALGRIND_MAKE_MEM_UNDEFINED(np, pgno2bytes(env, num));
-
- np->mp_pgno = pgno;
- np->mp_leaf2_ksize = 0;
- np->mp_flags = 0;
- np->mp_pages = num;
- mdbx_page_dirty(txn, np);
- *mp = np;
-
- mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist));
- return MDBX_SUCCESS;
-}
-
-/* Copy the used portions of a non-overflow page.
- * [in] dst page to copy into
- * [in] src page to copy from
- * [in] psize size of a page */
-static void mdbx_page_copy(MDBX_page *dst, MDBX_page *src, unsigned psize) {
- STATIC_ASSERT(UINT16_MAX > MAX_PAGESIZE - PAGEHDRSZ);
- STATIC_ASSERT(MIN_PAGESIZE > PAGEHDRSZ + NODESIZE * 42);
- enum { Align = sizeof(pgno_t) };
- indx_t upper = src->mp_upper, lower = src->mp_lower, unused = upper - lower;
-
- /* If page isn't full, just copy the used portion. Adjust
- * alignment so memcpy may copy words instead of bytes. */
- if ((unused &= -Align) && !IS_LEAF2(src)) {
- upper = (upper + PAGEHDRSZ) & -Align;
- memcpy(dst, src, (lower + PAGEHDRSZ + (Align - 1)) & -Align);
- memcpy((pgno_t *)((char *)dst + upper), (pgno_t *)((char *)src + upper),
- psize - upper);
- } else {
- memcpy(dst, src, psize - unused);
- }
-}
-
-/* Pull a page off the txn's spill list, if present.
- *
- * If a page being referenced was spilled to disk in this txn, bring
- * it back and make it dirty/writable again.
- *
- * [in] txn the transaction handle.
- * [in] mp the page being referenced. It must not be dirty.
- * [out] ret the writable page, if any.
- * ret is unchanged if mp wasn't spilled. */
-static int mdbx_page_unspill(MDBX_txn *txn, MDBX_page *mp, MDBX_page **ret) {
- MDBX_env *env = txn->mt_env;
- const MDBX_txn *tx2;
- unsigned x;
- pgno_t pgno = mp->mp_pgno, pn = pgno << 1;
-
- for (tx2 = txn; tx2; tx2 = tx2->mt_parent) {
- if (!tx2->mt_spill_pages)
- continue;
- x = mdbx_pnl_search(tx2->mt_spill_pages, pn);
- if (x <= tx2->mt_spill_pages[0] && tx2->mt_spill_pages[x] == pn) {
- MDBX_page *np;
- int num;
- if (txn->mt_dirtyroom == 0)
- return MDBX_TXN_FULL;
- num = IS_OVERFLOW(mp) ? mp->mp_pages : 1;
- if (env->me_flags & MDBX_WRITEMAP) {
- np = mp;
- } else {
- np = mdbx_page_malloc(txn, num);
- if (unlikely(!np))
- return MDBX_ENOMEM;
- if (unlikely(num > 1))
- memcpy(np, mp, pgno2bytes(env, num));
- else
- mdbx_page_copy(np, mp, env->me_psize);
- }
- mdbx_debug("unspill page %" PRIaPGNO, mp->mp_pgno);
- if (tx2 == txn) {
- /* If in current txn, this page is no longer spilled.
- * If it happens to be the last page, truncate the spill list.
- * Otherwise mark it as deleted by setting the LSB. */
- if (x == txn->mt_spill_pages[0])
- txn->mt_spill_pages[0]--;
- else
- txn->mt_spill_pages[x] |= 1;
- } /* otherwise, if belonging to a parent txn, the
- * page remains spilled until child commits */
-
- mdbx_page_dirty(txn, np);
- np->mp_flags |= P_DIRTY;
- *ret = np;
- break;
- }
- }
- return MDBX_SUCCESS;
-}
-
-/* Touch a page: make it dirty and re-insert into tree with updated pgno.
- * Set MDBX_TXN_ERROR on failure.
- *
- * [in] mc cursor pointing to the page to be touched
- *
- * Returns 0 on success, non-zero on failure. */
-static int mdbx_page_touch(MDBX_cursor *mc) {
- MDBX_page *mp = mc->mc_pg[mc->mc_top], *np;
- MDBX_txn *txn = mc->mc_txn;
- MDBX_cursor *m2, *m3;
- pgno_t pgno;
- int rc;
-
- mdbx_cassert(mc, !IS_OVERFLOW(mp));
- if (!F_ISSET(mp->mp_flags, P_DIRTY)) {
- if (txn->mt_flags & MDBX_TXN_SPILLS) {
- np = NULL;
- rc = mdbx_page_unspill(txn, mp, &np);
- if (unlikely(rc))
- goto fail;
- if (likely(np))
- goto done;
- }
-
- if (unlikely((rc = mdbx_pnl_need(&txn->mt_befree_pages, 1)) ||
- (rc = mdbx_page_alloc(mc, 1, &np, MDBX_ALLOC_ALL))))
- goto fail;
- pgno = np->mp_pgno;
- mdbx_debug("touched db %d page %" PRIaPGNO " -> %" PRIaPGNO, DDBI(mc),
- mp->mp_pgno, pgno);
- mdbx_cassert(mc, mp->mp_pgno != pgno);
- mdbx_pnl_xappend(txn->mt_befree_pages, mp->mp_pgno);
- /* Update the parent page, if any, to point to the new page */
- if (mc->mc_top) {
- MDBX_page *parent = mc->mc_pg[mc->mc_top - 1];
- MDBX_node *node = NODEPTR(parent, mc->mc_ki[mc->mc_top - 1]);
- SETPGNO(node, pgno);
- } else {
- mc->mc_db->md_root = pgno;
- }
- } else if (txn->mt_parent && !IS_SUBP(mp)) {
- mdbx_tassert(txn, (txn->mt_env->me_flags & MDBX_WRITEMAP) == 0);
- MDBX_ID2 mid, *dl = txn->mt_rw_dirtylist;
- pgno = mp->mp_pgno;
- /* If txn has a parent, make sure the page is in our dirty list. */
- if (dl[0].mid) {
- unsigned x = mdbx_mid2l_search(dl, pgno);
- if (x <= dl[0].mid && dl[x].mid == pgno) {
- if (unlikely(mp != dl[x].mptr)) { /* bad cursor? */
- mdbx_error("wrong page 0x%p #%" PRIaPGNO
- " in the dirtylist[%d], expecting %p",
- dl[x].mptr, pgno, x, mp);
- mc->mc_flags &= ~(C_INITIALIZED | C_EOF);
- txn->mt_flags |= MDBX_TXN_ERROR;
- return MDBX_PROBLEM;
- }
- return MDBX_SUCCESS;
- }
- }
-
- mdbx_debug("clone db %d page %" PRIaPGNO, DDBI(mc), mp->mp_pgno);
- mdbx_cassert(mc, dl[0].mid < MDBX_PNL_UM_MAX);
- /* No - copy it */
- np = mdbx_page_malloc(txn, 1);
- if (unlikely(!np))
- return MDBX_ENOMEM;
- mid.mid = pgno;
- mid.mptr = np;
- rc = mdbx_mid2l_insert(dl, &mid);
- mdbx_cassert(mc, rc == 0);
- } else {
- return MDBX_SUCCESS;
- }
-
- mdbx_page_copy(np, mp, txn->mt_env->me_psize);
- np->mp_pgno = pgno;
- np->mp_flags |= P_DIRTY;
-
-done:
- /* Adjust cursors pointing to mp */
- mc->mc_pg[mc->mc_top] = np;
- m2 = txn->mt_cursors[mc->mc_dbi];
- if (mc->mc_flags & C_SUB) {
- for (; m2; m2 = m2->mc_next) {
- m3 = &m2->mc_xcursor->mx_cursor;
- if (m3->mc_snum < mc->mc_snum)
- continue;
- if (m3->mc_pg[mc->mc_top] == mp)
- m3->mc_pg[mc->mc_top] = np;
- }
- } else {
- for (; m2; m2 = m2->mc_next) {
- if (m2->mc_snum < mc->mc_snum)
- continue;
- if (m2 == mc)
- continue;
- if (m2->mc_pg[mc->mc_top] == mp) {
- m2->mc_pg[mc->mc_top] = np;
- if (XCURSOR_INITED(m2) && IS_LEAF(np))
- XCURSOR_REFRESH(m2, np, m2->mc_ki[mc->mc_top]);
- }
- }
- }
- return MDBX_SUCCESS;
-
-fail:
- txn->mt_flags |= MDBX_TXN_ERROR;
- return rc;
-}
-
-int mdbx_env_sync(MDBX_env *env, int force) {
- if (unlikely(!env))
- return MDBX_EINVAL;
-
- if (unlikely(env->me_signature != MDBX_ME_SIGNATURE))
- return MDBX_EBADSIGN;
-
- unsigned flags = env->me_flags & ~MDBX_NOMETASYNC;
- if (unlikely(flags & (MDBX_RDONLY | MDBX_FATAL_ERROR)))
- return MDBX_EACCESS;
-
- if (unlikely(!env->me_lck))
- return MDBX_PANIC;
-
- const bool outside_txn =
- (!env->me_txn0 || env->me_txn0->mt_owner != mdbx_thread_self());
-
- if (outside_txn) {
- int rc = mdbx_txn_lock(env, false);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
- }
-
- MDBX_meta *head = mdbx_meta_head(env);
- if (!META_IS_STEADY(head) || env->me_sync_pending) {
-
- if (force || (env->me_sync_threshold &&
- env->me_sync_pending >= env->me_sync_threshold))
- flags &= MDBX_WRITEMAP /* clear flags for full steady sync */;
-
- if (outside_txn &&
- env->me_sync_pending >
- pgno2bytes(env, 16 /* FIXME: define threshold */) &&
- (flags & MDBX_NOSYNC) == 0) {
- assert(((flags ^ env->me_flags) & MDBX_WRITEMAP) == 0);
- const size_t usedbytes = pgno_align2os_bytes(env, head->mm_geo.next);
-
- mdbx_txn_unlock(env);
-
- /* LY: pre-sync without holding lock to reduce latency for writer(s) */
- int rc = (flags & MDBX_WRITEMAP)
- ? mdbx_msync(&env->me_dxb_mmap, 0, usedbytes,
- flags & MDBX_MAPASYNC)
- : mdbx_filesync(env->me_fd, false);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
-
- rc = mdbx_txn_lock(env, false);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
-
- /* LY: head may be changed. */
- head = mdbx_meta_head(env);
- }
-
- if (!META_IS_STEADY(head) || env->me_sync_pending) {
- mdbx_debug("meta-head %" PRIaPGNO ", %s, sync_pending %" PRIuPTR,
- container_of(head, MDBX_page, mp_data)->mp_pgno,
- mdbx_durable_str(head), env->me_sync_pending);
- MDBX_meta meta = *head;
- int rc = mdbx_sync_locked(env, flags | MDBX_SHRINK_ALLOWED, &meta);
- if (unlikely(rc != MDBX_SUCCESS)) {
- if (outside_txn)
- mdbx_txn_unlock(env);
- return rc;
- }
- }
- }
-
- if (outside_txn)
- mdbx_txn_unlock(env);
- return MDBX_SUCCESS;
-}
-
-/* Back up parent txn's cursors, then grab the originals for tracking */
-static int mdbx_cursor_shadow(MDBX_txn *src, MDBX_txn *dst) {
- MDBX_cursor *mc, *bk;
- MDBX_xcursor *mx;
- size_t size;
- int i;
-
- for (i = src->mt_numdbs; --i >= 0;) {
- if ((mc = src->mt_cursors[i]) != NULL) {
- size = sizeof(MDBX_cursor);
- if (mc->mc_xcursor)
- size += sizeof(MDBX_xcursor);
- for (; mc; mc = bk->mc_next) {
- bk = malloc(size);
- if (unlikely(!bk))
- return MDBX_ENOMEM;
- *bk = *mc;
- mc->mc_backup = bk;
- mc->mc_db = &dst->mt_dbs[i];
- /* Kill pointers into src to reduce abuse: The
- * user may not use mc until dst ends. But we need a valid
- * txn pointer here for cursor fixups to keep working. */
- mc->mc_txn = dst;
- mc->mc_dbflag = &dst->mt_dbflags[i];
- if ((mx = mc->mc_xcursor) != NULL) {
- *(MDBX_xcursor *)(bk + 1) = *mx;
- mx->mx_cursor.mc_txn = dst;
- }
- mc->mc_next = dst->mt_cursors[i];
- dst->mt_cursors[i] = mc;
- }
- }
- }
- return MDBX_SUCCESS;
-}
-
-/* Close this write txn's cursors, give parent txn's cursors back to parent.
- *
- * [in] txn the transaction handle.
- * [in] merge true to keep changes to parent cursors, false to revert.
- *
- * Returns 0 on success, non-zero on failure. */
-static void mdbx_cursors_eot(MDBX_txn *txn, unsigned merge) {
- MDBX_cursor **cursors = txn->mt_cursors, *mc, *next, *bk;
- MDBX_xcursor *mx;
- int i;
-
- for (i = txn->mt_numdbs; --i >= 0;) {
- for (mc = cursors[i]; mc; mc = next) {
- unsigned stage = mc->mc_signature;
- mdbx_ensure(NULL,
- stage == MDBX_MC_SIGNATURE || stage == MDBX_MC_WAIT4EOT);
- next = mc->mc_next;
- if ((bk = mc->mc_backup) != NULL) {
- if (merge) {
- /* Commit changes to parent txn */
- mc->mc_next = bk->mc_next;
- mc->mc_backup = bk->mc_backup;
- mc->mc_txn = bk->mc_txn;
- mc->mc_db = bk->mc_db;
- mc->mc_dbflag = bk->mc_dbflag;
- if ((mx = mc->mc_xcursor) != NULL)
- mx->mx_cursor.mc_txn = bk->mc_txn;
- } else {
- /* Abort nested txn */
- *mc = *bk;
- if ((mx = mc->mc_xcursor) != NULL)
- *mx = *(MDBX_xcursor *)(bk + 1);
- }
- bk->mc_signature = 0;
- free(bk);
- }
- if (stage == MDBX_MC_WAIT4EOT) {
- mc->mc_signature = 0;
- free(mc);
- } else {
- mc->mc_signature = MDBX_MC_READY4CLOSE;
- mc->mc_flags = 0 /* reset C_UNTRACK */;
- }
- }
- cursors[i] = NULL;
- }
-}
-
-/* Common code for mdbx_txn_begin() and mdbx_txn_renew(). */
-static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) {
- MDBX_env *env = txn->mt_env;
- int rc;
-
- if (unlikely(env->me_pid != mdbx_getpid())) {
- env->me_flags |= MDBX_FATAL_ERROR;
- return MDBX_PANIC;
- }
-
- pgno_t upper_pgno = 0;
- if (flags & MDBX_TXN_RDONLY) {
- txn->mt_flags = MDBX_TXN_RDONLY;
- MDBX_reader *r = txn->mt_ro_reader;
- if (likely(env->me_flags & MDBX_ENV_TXKEY)) {
- mdbx_assert(env, !(env->me_flags & MDBX_NOTLS));
- r = mdbx_thread_rthc_get(env->me_txkey);
- if (likely(r)) {
- mdbx_assert(env, r->mr_pid == env->me_pid);
- mdbx_assert(env, r->mr_tid == mdbx_thread_self());
- }
- } else {
- mdbx_assert(env, !env->me_lck || (env->me_flags & MDBX_NOTLS));
- }
-
- if (likely(r)) {
- if (unlikely(r->mr_pid != env->me_pid || r->mr_txnid != ~(txnid_t)0))
- return MDBX_BAD_RSLOT;
- } else if (env->me_lck) {
- unsigned slot, nreaders;
- const mdbx_pid_t pid = env->me_pid;
- const mdbx_tid_t tid = mdbx_thread_self();
- mdbx_assert(env, env->me_lck->mti_magic_and_version == MDBX_LOCK_MAGIC);
- mdbx_assert(env, env->me_lck->mti_os_and_format == MDBX_LOCK_FORMAT);
-
- rc = mdbx_rdt_lock(env);
- if (unlikely(MDBX_IS_ERROR(rc)))
- return rc;
- rc = MDBX_SUCCESS;
-
- if (unlikely(env->me_live_reader != pid)) {
- rc = mdbx_rpid_set(env);
- if (unlikely(rc != MDBX_SUCCESS)) {
- mdbx_rdt_unlock(env);
- return rc;
- }
- env->me_live_reader = pid;
- }
-
- while (1) {
- nreaders = env->me_lck->mti_numreaders;
- for (slot = 0; slot < nreaders; slot++)
- if (env->me_lck->mti_readers[slot].mr_pid == 0)
- break;
-
- if (likely(slot < env->me_maxreaders))
- break;
-
- rc = mdbx_reader_check0(env, true, NULL);
- if (rc != MDBX_RESULT_TRUE) {
- mdbx_rdt_unlock(env);
- return (rc == MDBX_SUCCESS) ? MDBX_READERS_FULL : rc;
- }
- }
-
- STATIC_ASSERT(sizeof(MDBX_reader) == MDBX_CACHELINE_SIZE);
- STATIC_ASSERT(
- offsetof(MDBX_lockinfo, mti_readers) % MDBX_CACHELINE_SIZE == 0);
- r = &env->me_lck->mti_readers[slot];
- /* Claim the reader slot, carefully since other code
- * uses the reader table un-mutexed: First reset the
- * slot, next publish it in mtb.mti_numreaders. After
- * that, it is safe for mdbx_env_close() to touch it.
- * When it will be closed, we can finally claim it. */
- r->mr_pid = 0;
- r->mr_txnid = ~(txnid_t)0;
- r->mr_tid = tid;
- mdbx_coherent_barrier();
- if (slot == nreaders)
- env->me_lck->mti_numreaders = ++nreaders;
- if (env->me_close_readers < nreaders)
- env->me_close_readers = nreaders;
- r->mr_pid = pid;
- mdbx_rdt_unlock(env);
-
- if (likely(env->me_flags & MDBX_ENV_TXKEY))
- mdbx_thread_rthc_set(env->me_txkey, r);
- }
-
- while (1) {
- MDBX_meta *const meta = mdbx_meta_head(env);
- mdbx_jitter4testing(false);
- const txnid_t snap = mdbx_meta_txnid_fluid(env, meta);
- mdbx_jitter4testing(false);
- if (r) {
- r->mr_txnid = snap;
- mdbx_jitter4testing(false);
- mdbx_assert(env, r->mr_pid == mdbx_getpid());
- mdbx_assert(env, r->mr_txnid == snap);
- mdbx_coherent_barrier();
- env->me_lck->mti_readers_refresh_flag = true;
- }
- mdbx_jitter4testing(true);
-
- /* Snap the state from current meta-head */
- txn->mt_txnid = snap;
- txn->mt_next_pgno = meta->mm_geo.next;
- txn->mt_end_pgno = meta->mm_geo.now;
- upper_pgno = meta->mm_geo.upper;
- memcpy(txn->mt_dbs, meta->mm_dbs, CORE_DBS * sizeof(MDBX_db));
- txn->mt_canary = meta->mm_canary;
-
- /* LY: Retry on a race, ITS#7970. */
- mdbx_compiler_barrier();
- if (likely(meta == mdbx_meta_head(env) &&
- snap == mdbx_meta_txnid_fluid(env, meta) &&
- snap >= *env->me_oldest)) {
- mdbx_jitter4testing(false);
- break;
- }
- }
-
- if (unlikely(txn->mt_txnid == 0)) {
- mdbx_error("environment corrupted by died writer, must shutdown!");
- rc = MDBX_WANNA_RECOVERY;
- goto bailout;
- }
- mdbx_assert(env, txn->mt_txnid >= *env->me_oldest);
- txn->mt_ro_reader = r;
- txn->mt_dbxs = env->me_dbxs; /* mostly static anyway */
- } else {
- /* Not yet touching txn == env->me_txn0, it may be active */
- mdbx_jitter4testing(false);
- rc = mdbx_txn_lock(env, F_ISSET(flags, MDBX_TRYTXN));
- if (unlikely(rc))
- return rc;
-
- mdbx_jitter4testing(false);
- MDBX_meta *meta = mdbx_meta_head(env);
- mdbx_jitter4testing(false);
- txn->mt_canary = meta->mm_canary;
- const txnid_t snap = mdbx_meta_txnid_stable(env, meta);
- txn->mt_txnid = snap + 1;
- if (unlikely(txn->mt_txnid < snap)) {
- mdbx_debug("txnid overflow!");
- rc = MDBX_TXN_FULL;
- goto bailout;
- }
-
- txn->mt_flags = flags;
- txn->mt_child = NULL;
- txn->mt_loose_pages = NULL;
- txn->mt_loose_count = 0;
- txn->mt_dirtyroom = MDBX_PNL_UM_MAX;
- txn->mt_rw_dirtylist = env->me_dirtylist;
- txn->mt_rw_dirtylist[0].mid = 0;
- txn->mt_befree_pages = env->me_free_pgs;
- txn->mt_befree_pages[0] = 0;
- txn->mt_spill_pages = NULL;
- if (txn->mt_lifo_reclaimed)
- txn->mt_lifo_reclaimed[0] = 0;
- env->me_txn = txn;
- memcpy(txn->mt_dbiseqs, env->me_dbiseqs, env->me_maxdbs * sizeof(unsigned));
- /* Copy the DB info and flags */
- memcpy(txn->mt_dbs, meta->mm_dbs, CORE_DBS * sizeof(MDBX_db));
- /* Moved to here to avoid a data race in read TXNs */
- txn->mt_next_pgno = meta->mm_geo.next;
- txn->mt_end_pgno = meta->mm_geo.now;
- upper_pgno = meta->mm_geo.upper;
- }
-
- /* Setup db info */
- txn->mt_numdbs = env->me_numdbs;
- for (unsigned i = CORE_DBS; i < txn->mt_numdbs; i++) {
- unsigned x = env->me_dbflags[i];
- txn->mt_dbs[i].md_flags = x & PERSISTENT_FLAGS;
- txn->mt_dbflags[i] =
- (x & MDBX_VALID) ? DB_VALID | DB_USRVALID | DB_STALE : 0;
- }
- txn->mt_dbflags[MAIN_DBI] = DB_VALID | DB_USRVALID;
- txn->mt_dbflags[FREE_DBI] = DB_VALID;
-
- if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) {
- mdbx_warning("environment had fatal error, must shutdown!");
- rc = MDBX_PANIC;
- } else {
- const size_t size = pgno2bytes(env, txn->mt_end_pgno);
- if (unlikely(size > env->me_mapsize)) {
- if (upper_pgno > MAX_PAGENO ||
- bytes2pgno(env, pgno2bytes(env, upper_pgno)) != upper_pgno) {
- rc = MDBX_MAP_RESIZED;
- goto bailout;
- }
- rc = mdbx_mapresize(env, txn->mt_end_pgno, upper_pgno);
- if (rc != MDBX_SUCCESS)
- goto bailout;
- }
- txn->mt_owner = mdbx_thread_self();
- return MDBX_SUCCESS;
- }
-bailout:
- assert(rc != MDBX_SUCCESS);
- mdbx_txn_end(txn, MDBX_END_SLOT | MDBX_END_FAIL_BEGIN);
- return rc;
-}
-
-int mdbx_txn_renew(MDBX_txn *txn) {
- int rc;
-
- if (unlikely(!txn))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(!F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY | MDBX_TXN_FINISHED)))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_owner != 0))
- return MDBX_THREAD_MISMATCH;
-
- rc = mdbx_txn_renew0(txn, MDBX_TXN_RDONLY);
- if (rc == MDBX_SUCCESS) {
- txn->mt_owner = mdbx_thread_self();
- mdbx_debug("renew txn %" PRIaTXN "%c %p on env %p, root page %" PRIaPGNO
- "/%" PRIaPGNO,
- txn->mt_txnid, (txn->mt_flags & MDBX_TXN_RDONLY) ? 'r' : 'w',
- (void *)txn, (void *)txn->mt_env, txn->mt_dbs[MAIN_DBI].md_root,
- txn->mt_dbs[FREE_DBI].md_root);
- }
- return rc;
-}
-
-int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
- MDBX_txn **ret) {
- MDBX_txn *txn;
- MDBX_ntxn *ntxn;
- int rc, size, tsize;
-
- if (unlikely(!env || !ret))
- return MDBX_EINVAL;
-
- if (unlikely(env->me_signature != MDBX_ME_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(env->me_pid != mdbx_getpid())) {
- env->me_flags |= MDBX_FATAL_ERROR;
- return MDBX_PANIC;
- }
-
- if (unlikely(!env->me_map))
- return MDBX_EPERM;
-
- flags &= MDBX_TXN_BEGIN_FLAGS;
- flags |= env->me_flags & MDBX_WRITEMAP;
-
- if (unlikely(env->me_flags & MDBX_RDONLY &
- ~flags)) /* write txn in RDONLY env */
- return MDBX_EACCESS;
-
- if (parent) {
- if (unlikely(parent->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EINVAL;
-
- if (unlikely(parent->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- /* Nested transactions: Max 1 child, write txns only, no writemap */
- flags |= parent->mt_flags;
- if (unlikely(flags & (MDBX_RDONLY | MDBX_WRITEMAP | MDBX_TXN_BLOCKED))) {
- return (parent->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EINVAL : MDBX_BAD_TXN;
- }
- /* Child txns save MDBX_pgstate and use own copy of cursors */
- size = env->me_maxdbs * (sizeof(MDBX_db) + sizeof(MDBX_cursor *) + 1);
- size += tsize = sizeof(MDBX_ntxn);
- } else if (flags & MDBX_RDONLY) {
- size = env->me_maxdbs * (sizeof(MDBX_db) + 1);
- size += tsize = sizeof(MDBX_txn);
- } else {
- /* Reuse preallocated write txn. However, do not touch it until
- * mdbx_txn_renew0() succeeds, since it currently may be active. */
- txn = env->me_txn0;
- goto renew;
- }
- if (unlikely((txn = calloc(1, size)) == NULL)) {
- mdbx_debug("calloc: %s", "failed");
- return MDBX_ENOMEM;
- }
- txn->mt_dbxs = env->me_dbxs; /* static */
- txn->mt_dbs = (MDBX_db *)((char *)txn + tsize);
- txn->mt_dbflags = (uint8_t *)txn + size - env->me_maxdbs;
- txn->mt_flags = flags;
- txn->mt_env = env;
-
- if (parent) {
- unsigned i;
- txn->mt_cursors = (MDBX_cursor **)(txn->mt_dbs + env->me_maxdbs);
- txn->mt_dbiseqs = parent->mt_dbiseqs;
- txn->mt_rw_dirtylist = malloc(sizeof(MDBX_ID2) * MDBX_PNL_UM_SIZE);
- if (!txn->mt_rw_dirtylist ||
- !(txn->mt_befree_pages = mdbx_pnl_alloc(MDBX_PNL_UM_MAX))) {
- free(txn->mt_rw_dirtylist);
- free(txn);
- return MDBX_ENOMEM;
- }
- txn->mt_txnid = parent->mt_txnid;
- txn->mt_dirtyroom = parent->mt_dirtyroom;
- txn->mt_rw_dirtylist[0].mid = 0;
- txn->mt_spill_pages = NULL;
- txn->mt_next_pgno = parent->mt_next_pgno;
- txn->mt_end_pgno = parent->mt_end_pgno;
- parent->mt_flags |= MDBX_TXN_HAS_CHILD;
- parent->mt_child = txn;
- txn->mt_parent = parent;
- txn->mt_numdbs = parent->mt_numdbs;
- memcpy(txn->mt_dbs, parent->mt_dbs, txn->mt_numdbs * sizeof(MDBX_db));
- /* Copy parent's mt_dbflags, but clear DB_NEW */
- for (i = 0; i < txn->mt_numdbs; i++)
- txn->mt_dbflags[i] = parent->mt_dbflags[i] & ~DB_NEW;
- rc = 0;
- ntxn = (MDBX_ntxn *)txn;
- ntxn->mnt_pgstate =
- env->me_pgstate; /* save parent me_reclaimed_pglist & co */
- if (env->me_reclaimed_pglist) {
- size = MDBX_PNL_SIZEOF(env->me_reclaimed_pglist);
- env->me_reclaimed_pglist = mdbx_pnl_alloc(env->me_reclaimed_pglist[0]);
- if (likely(env->me_reclaimed_pglist))
- memcpy(env->me_reclaimed_pglist, ntxn->mnt_pgstate.mf_reclaimed_pglist,
- size);
- else
- rc = MDBX_ENOMEM;
- }
- if (likely(!rc))
- rc = mdbx_cursor_shadow(parent, txn);
- if (unlikely(rc))
- mdbx_txn_end(txn, MDBX_END_FAIL_BEGINCHILD);
- } else { /* MDBX_RDONLY */
- txn->mt_dbiseqs = env->me_dbiseqs;
- renew:
- rc = mdbx_txn_renew0(txn, flags);
- }
-
- if (unlikely(rc)) {
- if (txn != env->me_txn0)
- free(txn);
- } else {
- txn->mt_signature = MDBX_MT_SIGNATURE;
- *ret = txn;
- mdbx_debug("begin txn %" PRIaTXN "%c %p on env %p, root page %" PRIaPGNO
- "/%" PRIaPGNO,
- txn->mt_txnid, (flags & MDBX_RDONLY) ? 'r' : 'w', (void *)txn,
- (void *)env, txn->mt_dbs[MAIN_DBI].md_root,
- txn->mt_dbs[FREE_DBI].md_root);
- }
-
- return rc;
-}
-
-MDBX_env *mdbx_txn_env(MDBX_txn *txn) {
- if (unlikely(!txn || txn->mt_signature != MDBX_MT_SIGNATURE))
- return NULL;
- return txn->mt_env;
-}
-
-uint64_t mdbx_txn_id(MDBX_txn *txn) {
- if (unlikely(!txn || txn->mt_signature != MDBX_MT_SIGNATURE))
- return ~(txnid_t)0;
- return txn->mt_txnid;
-}
-
-/* Export or close DBI handles opened in this txn. */
-static void mdbx_dbis_update(MDBX_txn *txn, int keep) {
- MDBX_dbi n = txn->mt_numdbs;
- if (n) {
- MDBX_env *env = txn->mt_env;
- uint8_t *tdbflags = txn->mt_dbflags;
-
- for (unsigned i = n; --i >= CORE_DBS;) {
- if (tdbflags[i] & DB_NEW) {
- if (keep) {
- env->me_dbflags[i] = txn->mt_dbs[i].md_flags | MDBX_VALID;
- } else {
- char *ptr = env->me_dbxs[i].md_name.iov_base;
- if (ptr) {
- env->me_dbxs[i].md_name.iov_base = NULL;
- env->me_dbxs[i].md_name.iov_len = 0;
- env->me_dbflags[i] = 0;
- env->me_dbiseqs[i]++;
- free(ptr);
- }
- }
- }
- }
- if (keep && env->me_numdbs < n)
- env->me_numdbs = n;
- }
-}
-
-/* End a transaction, except successful commit of a nested transaction.
- * May be called twice for readonly txns: First reset it, then abort.
- * [in] txn the transaction handle to end
- * [in] mode why and how to end the transaction */
-static int mdbx_txn_end(MDBX_txn *txn, unsigned mode) {
- MDBX_env *env = txn->mt_env;
- static const char *const names[] = MDBX_END_NAMES;
-
- if (unlikely(txn->mt_env->me_pid != mdbx_getpid())) {
- env->me_flags |= MDBX_FATAL_ERROR;
- return MDBX_PANIC;
- }
-
- /* Export or close DBI handles opened in this txn */
- mdbx_dbis_update(txn, mode & MDBX_END_UPDATE);
-
- mdbx_debug("%s txn %" PRIaTXN "%c %p on mdbenv %p, root page %" PRIaPGNO
- "/%" PRIaPGNO,
- names[mode & MDBX_END_OPMASK], txn->mt_txnid,
- (txn->mt_flags & MDBX_TXN_RDONLY) ? 'r' : 'w', (void *)txn,
- (void *)env, txn->mt_dbs[MAIN_DBI].md_root,
- txn->mt_dbs[FREE_DBI].md_root);
-
- if (F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY)) {
- if (txn->mt_ro_reader) {
- txn->mt_ro_reader->mr_txnid = ~(txnid_t)0;
- env->me_lck->mti_readers_refresh_flag = true;
- if (mode & MDBX_END_SLOT) {
- if ((env->me_flags & MDBX_ENV_TXKEY) == 0)
- txn->mt_ro_reader->mr_pid = 0;
- txn->mt_ro_reader = NULL;
- }
- }
- mdbx_coherent_barrier();
- txn->mt_numdbs = 0; /* prevent further DBI activity */
- txn->mt_flags |= MDBX_TXN_FINISHED;
- txn->mt_owner = 0;
- } else if (!F_ISSET(txn->mt_flags, MDBX_TXN_FINISHED)) {
- pgno_t *pghead = env->me_reclaimed_pglist;
-
- if (!(mode & MDBX_END_EOTDONE)) /* !(already closed cursors) */
- mdbx_cursors_eot(txn, 0);
- if (!(env->me_flags & MDBX_WRITEMAP)) {
- mdbx_dlist_free(txn);
- }
-
- if (txn->mt_lifo_reclaimed) {
- txn->mt_lifo_reclaimed[0] = 0;
- if (txn != env->me_txn0) {
- mdbx_txl_free(txn->mt_lifo_reclaimed);
- txn->mt_lifo_reclaimed = NULL;
- }
- }
- txn->mt_numdbs = 0;
- txn->mt_flags = MDBX_TXN_FINISHED;
-
- if (!txn->mt_parent) {
- mdbx_pnl_shrink(&txn->mt_befree_pages);
- env->me_free_pgs = txn->mt_befree_pages;
- /* me_pgstate: */
- env->me_reclaimed_pglist = NULL;
- env->me_last_reclaimed = 0;
-
- env->me_txn = NULL;
- txn->mt_owner = 0;
- txn->mt_signature = 0;
- mode = 0; /* txn == env->me_txn0, do not free() it */
-
- /* The writer mutex was locked in mdbx_txn_begin. */
- mdbx_txn_unlock(env);
- } else {
- txn->mt_parent->mt_child = NULL;
- txn->mt_parent->mt_flags &= ~MDBX_TXN_HAS_CHILD;
- env->me_pgstate = ((MDBX_ntxn *)txn)->mnt_pgstate;
- mdbx_pnl_free(txn->mt_befree_pages);
- mdbx_pnl_free(txn->mt_spill_pages);
- free(txn->mt_rw_dirtylist);
- }
-
- mdbx_pnl_free(pghead);
- }
-
- if (mode & MDBX_END_FREE) {
- mdbx_ensure(env, txn != env->me_txn0);
- txn->mt_owner = 0;
- txn->mt_signature = 0;
- free(txn);
- }
-
- return MDBX_SUCCESS;
-}
-
-int mdbx_txn_reset(MDBX_txn *txn) {
- if (unlikely(!txn))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- /* This call is only valid for read-only txns */
- if (unlikely(!(txn->mt_flags & MDBX_TXN_RDONLY)))
- return MDBX_EINVAL;
-
- /* LY: don't close DBI-handles in MDBX mode */
- int rc = mdbx_txn_end(txn, MDBX_END_RESET | MDBX_END_UPDATE);
- if (rc == MDBX_SUCCESS) {
- assert(txn->mt_signature == MDBX_MT_SIGNATURE);
- assert(txn->mt_owner == 0);
- }
- return rc;
-}
-
-int mdbx_txn_abort(MDBX_txn *txn) {
- if (unlikely(!txn))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner !=
- ((txn->mt_flags & MDBX_TXN_FINISHED) ? 0 : mdbx_thread_self())))
- return MDBX_THREAD_MISMATCH;
-
- if (F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY))
- /* LY: don't close DBI-handles in MDBX mode */
- return mdbx_txn_end(txn, MDBX_END_ABORT | MDBX_END_UPDATE | MDBX_END_SLOT |
- MDBX_END_FREE);
-
- if (txn->mt_child)
- mdbx_txn_abort(txn->mt_child);
-
- return mdbx_txn_end(txn, MDBX_END_ABORT | MDBX_END_SLOT | MDBX_END_FREE);
-}
-
-static __inline int mdbx_backlog_size(MDBX_txn *txn) {
- int reclaimed = txn->mt_env->me_reclaimed_pglist
- ? txn->mt_env->me_reclaimed_pglist[0]
- : 0;
- return reclaimed + txn->mt_loose_count + txn->mt_end_pgno - txn->mt_next_pgno;
-}
-
-/* LY: Prepare a backlog of pages to modify FreeDB itself,
- * while reclaiming is prohibited. It should be enough to prevent search
- * in mdbx_page_alloc() during a deleting, when freeDB tree is unbalanced. */
-static int mdbx_prep_backlog(MDBX_txn *txn, MDBX_cursor *mc) {
- /* LY: extra page(s) for b-tree rebalancing */
- const int extra = (txn->mt_env->me_flags & MDBX_LIFORECLAIM) ? 2 : 1;
-
- if (mdbx_backlog_size(txn) < mc->mc_db->md_depth + extra) {
- int rc = mdbx_cursor_touch(mc);
- if (unlikely(rc))
- return rc;
-
- int backlog;
- while (unlikely((backlog = mdbx_backlog_size(txn)) < extra)) {
- rc = mdbx_page_alloc(mc, 1, NULL, MDBX_ALLOC_GC);
- if (unlikely(rc)) {
- if (unlikely(rc != MDBX_NOTFOUND))
- return rc;
- break;
- }
- }
- }
-
- return MDBX_SUCCESS;
-}
-
-/* Save the freelist as of this transaction to the freeDB.
- * This changes the freelist. Keep trying until it stabilizes. */
-static int mdbx_freelist_save(MDBX_txn *txn) {
- /* env->me_reclaimed_pglist[] can grow and shrink during this call.
- * env->me_last_reclaimed and txn->mt_free_pages[] can only grow.
- * Page numbers cannot disappear from txn->mt_free_pages[]. */
- MDBX_cursor mc;
- MDBX_env *env = txn->mt_env;
- int rc, more = 1;
- txnid_t cleanup_reclaimed_id = 0, head_id = 0;
- pgno_t befree_count = 0;
- intptr_t head_room = 0, total_room = 0;
- unsigned cleanup_reclaimed_pos = 0, refill_reclaimed_pos = 0;
- const bool lifo = (env->me_flags & MDBX_LIFORECLAIM) != 0;
-
- mdbx_cursor_init(&mc, txn, FREE_DBI, NULL);
-
- /* MDBX_RESERVE cancels meminit in ovpage malloc (when no WRITEMAP) */
- const intptr_t clean_limit =
- (env->me_flags & (MDBX_NOMEMINIT | MDBX_WRITEMAP)) ? SSIZE_MAX
- : env->me_maxfree_1pg;
-
- mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist));
-again_on_freelist_change:
- mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist));
- while (1) {
- /* Come back here after each Put() in case freelist changed */
- MDBX_val key, data;
-
- mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist));
- if (!lifo) {
- /* If using records from freeDB which we have not yet deleted,
- * now delete them and any we reserved for me_reclaimed_pglist. */
- while (cleanup_reclaimed_id < env->me_last_reclaimed) {
- rc = mdbx_cursor_first(&mc, &key, NULL);
- if (unlikely(rc))
- goto bailout;
- rc = mdbx_prep_backlog(txn, &mc);
- if (unlikely(rc))
- goto bailout;
- cleanup_reclaimed_id = head_id = *(txnid_t *)key.iov_base;
- total_room = head_room = 0;
- more = 1;
- mdbx_tassert(txn, cleanup_reclaimed_id <= env->me_last_reclaimed);
- mc.mc_flags |= C_RECLAIMING;
- rc = mdbx_cursor_del(&mc, 0);
- mc.mc_flags ^= C_RECLAIMING;
- if (unlikely(rc))
- goto bailout;
- }
- } else if (txn->mt_lifo_reclaimed) {
- /* LY: cleanup reclaimed records. */
- while (cleanup_reclaimed_pos < txn->mt_lifo_reclaimed[0]) {
- cleanup_reclaimed_id = txn->mt_lifo_reclaimed[++cleanup_reclaimed_pos];
- key.iov_base = &cleanup_reclaimed_id;
- key.iov_len = sizeof(cleanup_reclaimed_id);
- rc = mdbx_cursor_get(&mc, &key, NULL, MDBX_SET);
- if (likely(rc != MDBX_NOTFOUND)) {
- if (unlikely(rc))
- goto bailout;
- rc = mdbx_prep_backlog(txn, &mc);
- if (unlikely(rc))
- goto bailout;
- mc.mc_flags |= C_RECLAIMING;
- rc = mdbx_cursor_del(&mc, 0);
- mc.mc_flags ^= C_RECLAIMING;
- if (unlikely(rc))
- goto bailout;
- }
- }
- }
-
- mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist));
- if (txn->mt_loose_pages) {
- /* Return loose page numbers to me_reclaimed_pglist,
- * though usually none are left at this point.
- * The pages themselves remain in dirtylist. */
- if (unlikely(!env->me_reclaimed_pglist) &&
- !(lifo && env->me_last_reclaimed > 1)) {
- /* Put loose page numbers in mt_free_pages,
- * since unable to return them to me_reclaimed_pglist. */
- if (unlikely((rc = mdbx_pnl_need(&txn->mt_befree_pages,
- txn->mt_loose_count)) != 0))
- return rc;
- for (MDBX_page *mp = txn->mt_loose_pages; mp; mp = NEXT_LOOSE_PAGE(mp))
- mdbx_pnl_xappend(txn->mt_befree_pages, mp->mp_pgno);
- } else {
- /* Room for loose pages + temp PNL with same */
- if ((rc = mdbx_pnl_need(&env->me_reclaimed_pglist,
- 2 * txn->mt_loose_count + 1)) != 0)
- goto bailout;
- MDBX_PNL loose = env->me_reclaimed_pglist +
- MDBX_PNL_ALLOCLEN(env->me_reclaimed_pglist) -
- txn->mt_loose_count;
- unsigned count = 0;
- for (MDBX_page *mp = txn->mt_loose_pages; mp; mp = NEXT_LOOSE_PAGE(mp))
- loose[++count] = mp->mp_pgno;
- loose[0] = count;
- mdbx_pnl_sort(loose);
- mdbx_pnl_xmerge(env->me_reclaimed_pglist, loose);
- }
-
- MDBX_ID2L dl = txn->mt_rw_dirtylist;
- for (MDBX_page *mp = txn->mt_loose_pages; mp;) {
- mdbx_tassert(txn, mp->mp_pgno < txn->mt_next_pgno);
- mdbx_ensure(env, mp->mp_pgno >= NUM_METAS);
-
- unsigned s, d;
- for (s = d = 0; ++s <= dl[0].mid;)
- if (dl[s].mid != mp->mp_pgno)
- dl[++d] = dl[s];
-
- dl[0].mid -= 1;
- mdbx_tassert(txn, dl[0].mid == d);
-
- MDBX_page *dp = mp;
- mp = NEXT_LOOSE_PAGE(mp);
- if ((env->me_flags & MDBX_WRITEMAP) == 0)
- mdbx_dpage_free(env, dp);
- }
-
- txn->mt_loose_pages = NULL;
- txn->mt_loose_count = 0;
- }
-
- mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist));
- if (env->me_reclaimed_pglist) {
- /* Refund suitable pages into "unallocated" space */
- pgno_t tail = txn->mt_next_pgno;
- pgno_t *const begin = env->me_reclaimed_pglist + 1;
- pgno_t *const end = begin + env->me_reclaimed_pglist[0];
- pgno_t *higest;
-#if MDBX_PNL_ASCENDING
- for (higest = end; --higest >= begin;) {
-#else
- for (higest = begin; higest < end; ++higest) {
-#endif /* MDBX_PNL sort-order */
- mdbx_tassert(txn, *higest >= NUM_METAS && *higest < tail);
- if (*higest != tail - 1)
- break;
- tail -= 1;
- }
- if (tail != txn->mt_next_pgno) {
-#if MDBX_PNL_ASCENDING
- env->me_reclaimed_pglist[0] = (unsigned)(higest + 1 - begin);
-#else
- env->me_reclaimed_pglist[0] -= (unsigned)(higest - begin);
- for (pgno_t *move = begin; higest < end; ++move, ++higest)
- *move = *higest;
-#endif /* MDBX_PNL sort-order */
- mdbx_info("refunded %" PRIaPGNO " pages: %" PRIaPGNO " -> %" PRIaPGNO,
- tail - txn->mt_next_pgno, tail, txn->mt_next_pgno);
- txn->mt_next_pgno = tail;
- mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist));
- }
- }
-
- /* Save the PNL of pages freed by this txn, to a single record */
- if (befree_count < txn->mt_befree_pages[0]) {
- if (unlikely(!befree_count)) {
- /* Make sure last page of freeDB is touched and on freelist */
- rc = mdbx_page_search(&mc, NULL, MDBX_PS_LAST | MDBX_PS_MODIFY);
- if (unlikely(rc && rc != MDBX_NOTFOUND))
- goto bailout;
- }
- pgno_t *befree_pages = txn->mt_befree_pages;
- /* Write to last page of freeDB */
- key.iov_len = sizeof(txn->mt_txnid);
- key.iov_base = &txn->mt_txnid;
- do {
- befree_count = befree_pages[0];
- data.iov_len = MDBX_PNL_SIZEOF(befree_pages);
- rc = mdbx_cursor_put(&mc, &key, &data, MDBX_RESERVE);
- if (unlikely(rc))
- goto bailout;
- /* Retry if mt_free_pages[] grew during the Put() */
- befree_pages = txn->mt_befree_pages;
- } while (befree_count < befree_pages[0]);
-
- mdbx_pnl_sort(befree_pages);
- memcpy(data.iov_base, befree_pages, data.iov_len);
-
- if (mdbx_debug_enabled(MDBX_DBG_EXTRA)) {
- unsigned i = (unsigned)befree_pages[0];
- mdbx_debug_extra("PNL write txn %" PRIaTXN " root %" PRIaPGNO
- " num %u, PNL",
- txn->mt_txnid, txn->mt_dbs[FREE_DBI].md_root, i);
- for (; i; i--)
- mdbx_debug_extra_print(" %" PRIaPGNO "", befree_pages[i]);
- mdbx_debug_extra_print("\n");
- }
- continue;
- }
-
- mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist));
- const intptr_t rpl_len =
- (env->me_reclaimed_pglist ? env->me_reclaimed_pglist[0] : 0) +
- txn->mt_loose_count;
- if (rpl_len && refill_reclaimed_pos == 0)
- refill_reclaimed_pos = 1;
-
- /* Reserve records for me_reclaimed_pglist[]. Split it if multi-page,
- * to avoid searching freeDB for a page range. Use keys in
- * range [1,me_last_reclaimed]: Smaller than txnid of oldest reader. */
- if (total_room >= rpl_len) {
- if (total_room == rpl_len || --more < 0)
- break;
- } else if (head_room >= (intptr_t)env->me_maxfree_1pg && head_id > 1) {
- /* Keep current record (overflow page), add a new one */
- head_id--;
- refill_reclaimed_pos++;
- head_room = 0;
- }
-
- if (lifo) {
- if (refill_reclaimed_pos >
- (txn->mt_lifo_reclaimed ? txn->mt_lifo_reclaimed[0] : 0)) {
- /* LY: need just a txn-id for save page list. */
- rc = mdbx_page_alloc(&mc, 0, NULL, MDBX_ALLOC_GC | MDBX_ALLOC_KICK);
- if (likely(rc == 0))
- /* LY: ok, reclaimed from freedb. */
- continue;
- if (unlikely(rc != MDBX_NOTFOUND))
- /* LY: other troubles... */
- goto bailout;
-
- /* LY: freedb is empty, will look any free txn-id in high2low order. */
- if (unlikely(env->me_last_reclaimed < 1)) {
- /* LY: not any txn in the past of freedb. */
- rc = MDBX_MAP_FULL;
- goto bailout;
- }
-
- if (unlikely(!txn->mt_lifo_reclaimed)) {
- txn->mt_lifo_reclaimed = mdbx_txl_alloc();
- if (unlikely(!txn->mt_lifo_reclaimed)) {
- rc = MDBX_ENOMEM;
- goto bailout;
- }
- }
- /* LY: append the list. */
- rc = mdbx_txl_append(&txn->mt_lifo_reclaimed,
- env->me_last_reclaimed - 1);
- if (unlikely(rc))
- goto bailout;
- --env->me_last_reclaimed;
- /* LY: note that freeDB cleanup is not needed. */
- ++cleanup_reclaimed_pos;
- }
- mdbx_tassert(txn, txn->mt_lifo_reclaimed != NULL);
- head_id = txn->mt_lifo_reclaimed[refill_reclaimed_pos];
- } else {
- mdbx_tassert(txn, txn->mt_lifo_reclaimed == NULL);
- }
-
- /* (Re)write {key = head_id, PNL length = head_room} */
- total_room -= head_room;
- head_room = rpl_len - total_room;
- if (head_room > (intptr_t)env->me_maxfree_1pg && head_id > 1) {
- /* Overflow multi-page for part of me_reclaimed_pglist */
- head_room /= (head_id < INT16_MAX) ? (pgno_t)head_id
- : INT16_MAX; /* amortize page sizes */
- head_room += env->me_maxfree_1pg - head_room % (env->me_maxfree_1pg + 1);
- } else if (head_room < 0) {
- /* Rare case, not bothering to delete this record */
- head_room = 0;
- continue;
- }
- key.iov_len = sizeof(head_id);
- key.iov_base = &head_id;
- data.iov_len = (head_room + 1) * sizeof(pgno_t);
- rc = mdbx_cursor_put(&mc, &key, &data, MDBX_RESERVE);
- mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist));
- if (unlikely(rc))
- goto bailout;
-
- /* PNL is initially empty, zero out at least the length */
- pgno_t *pgs = (pgno_t *)data.iov_base;
- intptr_t i = head_room > clean_limit ? head_room : 0;
- do {
- pgs[i] = 0;
- } while (--i >= 0);
- total_room += head_room;
- continue;
- }
-
- mdbx_tassert(txn,
- cleanup_reclaimed_pos ==
- (txn->mt_lifo_reclaimed ? txn->mt_lifo_reclaimed[0] : 0));
-
- /* Fill in the reserved me_reclaimed_pglist records */
- rc = MDBX_SUCCESS;
- mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist));
- if (env->me_reclaimed_pglist && env->me_reclaimed_pglist[0]) {
- MDBX_val key, data;
- key.iov_len = data.iov_len = 0; /* avoid MSVC warning */
- key.iov_base = data.iov_base = NULL;
-
- size_t rpl_left = env->me_reclaimed_pglist[0];
- pgno_t *rpl_end = env->me_reclaimed_pglist + rpl_left;
- if (txn->mt_lifo_reclaimed == 0) {
- mdbx_tassert(txn, lifo == 0);
- rc = mdbx_cursor_first(&mc, &key, &data);
- if (unlikely(rc))
- goto bailout;
- } else {
- mdbx_tassert(txn, lifo != 0);
- }
-
- while (1) {
- txnid_t id;
- if (txn->mt_lifo_reclaimed == 0) {
- mdbx_tassert(txn, lifo == 0);
- id = *(txnid_t *)key.iov_base;
- mdbx_tassert(txn, id <= env->me_last_reclaimed);
- } else {
- mdbx_tassert(txn, lifo != 0);
- mdbx_tassert(txn,
- refill_reclaimed_pos > 0 &&
- refill_reclaimed_pos <= txn->mt_lifo_reclaimed[0]);
- id = txn->mt_lifo_reclaimed[refill_reclaimed_pos--];
- key.iov_base = &id;
- key.iov_len = sizeof(id);
- rc = mdbx_cursor_get(&mc, &key, &data, MDBX_SET);
- if (unlikely(rc))
- goto bailout;
- }
- mdbx_tassert(
- txn, cleanup_reclaimed_pos ==
- (txn->mt_lifo_reclaimed ? txn->mt_lifo_reclaimed[0] : 0));
-
- mdbx_tassert(txn, data.iov_len >= sizeof(pgno_t) * 2);
- size_t chunk_len = (data.iov_len / sizeof(pgno_t)) - 1;
- if (chunk_len > rpl_left)
- chunk_len = rpl_left;
- data.iov_len = (chunk_len + 1) * sizeof(pgno_t);
- key.iov_base = &id;
- key.iov_len = sizeof(id);
-
- rpl_end -= chunk_len;
- data.iov_base = rpl_end;
- pgno_t save = rpl_end[0];
- rpl_end[0] = (pgno_t)chunk_len;
- mdbx_tassert(txn, mdbx_pnl_check(rpl_end));
- mc.mc_flags |= C_RECLAIMING;
- rc = mdbx_cursor_put(&mc, &key, &data, MDBX_CURRENT);
- mc.mc_flags ^= C_RECLAIMING;
- mdbx_tassert(txn, mdbx_pnl_check(rpl_end));
- mdbx_tassert(
- txn, cleanup_reclaimed_pos ==
- (txn->mt_lifo_reclaimed ? txn->mt_lifo_reclaimed[0] : 0));
- rpl_end[0] = save;
- if (unlikely(rc))
- goto bailout;
-
- rpl_left -= chunk_len;
- if (rpl_left == 0)
- break;
-
- if (!lifo) {
- rc = mdbx_cursor_next(&mc, &key, &data, MDBX_NEXT);
- if (unlikely(rc))
- goto bailout;
- }
- }
- }
-
-bailout:
- if (txn->mt_lifo_reclaimed) {
- mdbx_tassert(txn, rc || cleanup_reclaimed_pos == txn->mt_lifo_reclaimed[0]);
- if (rc == MDBX_SUCCESS &&
- cleanup_reclaimed_pos != txn->mt_lifo_reclaimed[0]) {
- mdbx_tassert(txn, cleanup_reclaimed_pos < txn->mt_lifo_reclaimed[0]);
- /* LY: zeroed cleanup_idx to force cleanup
- * and refill created freeDB records. */
- cleanup_reclaimed_pos = 0;
- /* LY: restart filling */
- total_room = head_room = refill_reclaimed_pos = 0;
- more = 1;
- goto again_on_freelist_change;
- }
- txn->mt_lifo_reclaimed[0] = 0;
- if (txn != env->me_txn0) {
- mdbx_txl_free(txn->mt_lifo_reclaimed);
- txn->mt_lifo_reclaimed = NULL;
- }
- }
-
- return rc;
-}
-
-/* Flush (some) dirty pages to the map, after clearing their dirty flag.
- * [in] txn the transaction that's being committed
- * [in] keep number of initial pages in dirtylist to keep dirty.
- * Returns 0 on success, non-zero on failure. */
-static int mdbx_page_flush(MDBX_txn *txn, pgno_t keep) {
- MDBX_env *env = txn->mt_env;
- MDBX_ID2L dl = txn->mt_rw_dirtylist;
- unsigned i, j, pagecount = dl[0].mid;
- int rc;
- size_t size = 0, pos = 0;
- pgno_t pgno = 0;
- MDBX_page *dp = NULL;
- struct iovec iov[MDBX_COMMIT_PAGES];
- intptr_t wpos = 0, wsize = 0;
- size_t next_pos = 1; /* impossible pos, so pos != next_pos */
- int n = 0;
-
- j = i = keep;
-
- if (env->me_flags & MDBX_WRITEMAP) {
- /* Clear dirty flags */
- while (++i <= pagecount) {
- dp = dl[i].mptr;
- /* Don't flush this page yet */
- if (dp->mp_flags & (P_LOOSE | P_KEEP)) {
- dp->mp_flags &= ~P_KEEP;
- dl[++j] = dl[i];
- continue;
- }
- dp->mp_flags &= ~P_DIRTY;
- dp->mp_validator = 0 /* TODO */;
- env->me_sync_pending +=
- IS_OVERFLOW(dp) ? pgno2bytes(env, dp->mp_pages) : env->me_psize;
- }
- goto done;
- }
-
- /* Write the pages */
- for (;;) {
- if (++i <= pagecount) {
- dp = dl[i].mptr;
- /* Don't flush this page yet */
- if (dp->mp_flags & (P_LOOSE | P_KEEP)) {
- dp->mp_flags &= ~P_KEEP;
- dl[i].mid = 0;
- continue;
- }
- pgno = dl[i].mid;
- /* clear dirty flag */
- dp->mp_flags &= ~P_DIRTY;
- dp->mp_validator = 0 /* TODO */;
- pos = pgno2bytes(env, pgno);
- size = IS_OVERFLOW(dp) ? pgno2bytes(env, dp->mp_pages) : env->me_psize;
- env->me_sync_pending += size;
- }
- /* Write up to MDBX_COMMIT_PAGES dirty pages at a time. */
- if (pos != next_pos || n == MDBX_COMMIT_PAGES || wsize + size > MAX_WRITE) {
- if (n) {
- /* Write previous page(s) */
- rc = mdbx_pwritev(env->me_fd, iov, n, wpos, wsize);
- if (unlikely(rc != MDBX_SUCCESS)) {
- mdbx_debug("Write error: %s", strerror(rc));
- return rc;
- }
- n = 0;
- }
- if (i > pagecount)
- break;
- wpos = pos;
- wsize = 0;
- }
- mdbx_debug("committing page %" PRIaPGNO "", pgno);
- next_pos = pos + size;
- iov[n].iov_len = size;
- iov[n].iov_base = (char *)dp;
- wsize += size;
- n++;
- }
-
- mdbx_invalidate_cache(env->me_map, pgno2bytes(env, txn->mt_next_pgno));
-
- for (i = keep; ++i <= pagecount;) {
- dp = dl[i].mptr;
- /* This is a page we skipped above */
- if (!dl[i].mid) {
- dl[++j] = dl[i];
- dl[j].mid = dp->mp_pgno;
- continue;
- }
- mdbx_dpage_free(env, dp);
- }
-
-done:
- i--;
- txn->mt_dirtyroom += i - j;
- dl[0].mid = j;
- return MDBX_SUCCESS;
-}
-
-int mdbx_txn_commit(MDBX_txn *txn) {
- int rc;
-
- if (unlikely(txn == NULL))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- MDBX_env *env = txn->mt_env;
- if (unlikely(env->me_pid != mdbx_getpid())) {
- env->me_flags |= MDBX_FATAL_ERROR;
- return MDBX_PANIC;
- }
-
- if (txn->mt_child) {
- rc = mdbx_txn_commit(txn->mt_child);
- txn->mt_child = NULL;
- if (unlikely(rc != MDBX_SUCCESS))
- goto fail;
- }
-
- /* mdbx_txn_end() mode for a commit which writes nothing */
- unsigned end_mode =
- MDBX_END_EMPTY_COMMIT | MDBX_END_UPDATE | MDBX_END_SLOT | MDBX_END_FREE;
- if (unlikely(F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY)))
- goto done;
-
- if (unlikely(txn->mt_flags & (MDBX_TXN_FINISHED | MDBX_TXN_ERROR))) {
- mdbx_debug("error flag is set, can't commit");
- if (txn->mt_parent)
- txn->mt_parent->mt_flags |= MDBX_TXN_ERROR;
- rc = MDBX_BAD_TXN;
- goto fail;
- }
-
- if (txn->mt_parent) {
- MDBX_txn *parent = txn->mt_parent;
- MDBX_page **lp;
- MDBX_ID2L dst, src;
- MDBX_PNL pspill;
- unsigned i, x, y, len, ps_len;
-
- /* Append our reclaim list to parent's */
- if (txn->mt_lifo_reclaimed) {
- if (parent->mt_lifo_reclaimed) {
- rc = mdbx_txl_append_list(&parent->mt_lifo_reclaimed,
- txn->mt_lifo_reclaimed);
- if (unlikely(rc != MDBX_SUCCESS))
- goto fail;
- mdbx_txl_free(txn->mt_lifo_reclaimed);
- } else
- parent->mt_lifo_reclaimed = txn->mt_lifo_reclaimed;
- txn->mt_lifo_reclaimed = NULL;
- }
-
- /* Append our free list to parent's */
- rc = mdbx_pnl_append_list(&parent->mt_befree_pages, txn->mt_befree_pages);
- if (unlikely(rc != MDBX_SUCCESS))
- goto fail;
- mdbx_pnl_free(txn->mt_befree_pages);
- /* Failures after this must either undo the changes
- * to the parent or set MDBX_TXN_ERROR in the parent. */
-
- parent->mt_next_pgno = txn->mt_next_pgno;
- parent->mt_end_pgno = txn->mt_end_pgno;
- parent->mt_flags = txn->mt_flags;
-
- /* Merge our cursors into parent's and close them */
- mdbx_cursors_eot(txn, 1);
-
- /* Update parent's DB table. */
- memcpy(parent->mt_dbs, txn->mt_dbs, txn->mt_numdbs * sizeof(MDBX_db));
- parent->mt_numdbs = txn->mt_numdbs;
- parent->mt_dbflags[FREE_DBI] = txn->mt_dbflags[FREE_DBI];
- parent->mt_dbflags[MAIN_DBI] = txn->mt_dbflags[MAIN_DBI];
- for (i = CORE_DBS; i < txn->mt_numdbs; i++) {
- /* preserve parent's DB_NEW status */
- parent->mt_dbflags[i] =
- txn->mt_dbflags[i] | (parent->mt_dbflags[i] & DB_NEW);
- }
-
- dst = parent->mt_rw_dirtylist;
- src = txn->mt_rw_dirtylist;
- /* Remove anything in our dirty list from parent's spill list */
- if ((pspill = parent->mt_spill_pages) && (ps_len = pspill[0])) {
- x = y = ps_len;
- pspill[0] = (pgno_t)-1;
- /* Mark our dirty pages as deleted in parent spill list */
- for (i = 0, len = src[0].mid; ++i <= len;) {
- pgno_t pn = src[i].mid << 1;
- while (pn > pspill[x])
- x--;
- if (pn == pspill[x]) {
- pspill[x] = 1;
- y = --x;
- }
- }
- /* Squash deleted pagenums if we deleted any */
- for (x = y; ++x <= ps_len;)
- if (!(pspill[x] & 1))
- pspill[++y] = pspill[x];
- pspill[0] = y;
- }
-
- /* Remove anything in our spill list from parent's dirty list */
- if (txn->mt_spill_pages && txn->mt_spill_pages[0]) {
- for (i = 1; i <= txn->mt_spill_pages[0]; i++) {
- pgno_t pn = txn->mt_spill_pages[i];
- if (pn & 1)
- continue; /* deleted spillpg */
- pn >>= 1;
- y = mdbx_mid2l_search(dst, pn);
- if (y <= dst[0].mid && dst[y].mid == pn) {
- free(dst[y].mptr);
- while (y < dst[0].mid) {
- dst[y] = dst[y + 1];
- y++;
- }
- dst[0].mid--;
- }
- }
- }
-
- /* Find len = length of merging our dirty list with parent's */
- x = dst[0].mid;
- dst[0].mid = 0; /* simplify loops */
- if (parent->mt_parent) {
- len = x + src[0].mid;
- y = mdbx_mid2l_search(src, dst[x].mid + 1) - 1;
- for (i = x; y && i; y--) {
- pgno_t yp = src[y].mid;
- while (yp < dst[i].mid)
- i--;
- if (yp == dst[i].mid) {
- i--;
- len--;
- }
- }
- } else { /* Simplify the above for single-ancestor case */
- len = MDBX_PNL_UM_MAX - txn->mt_dirtyroom;
- }
- /* Merge our dirty list with parent's */
- y = src[0].mid;
- for (i = len; y; dst[i--] = src[y--]) {
- pgno_t yp = src[y].mid;
- while (yp < dst[x].mid)
- dst[i--] = dst[x--];
- if (yp == dst[x].mid)
- free(dst[x--].mptr);
- }
- mdbx_tassert(txn, i == x);
- dst[0].mid = len;
- free(txn->mt_rw_dirtylist);
- parent->mt_dirtyroom = txn->mt_dirtyroom;
- if (txn->mt_spill_pages) {
- if (parent->mt_spill_pages) {
- /* TODO: Prevent failure here, so parent does not fail */
- rc = mdbx_pnl_append_list(&parent->mt_spill_pages, txn->mt_spill_pages);
- if (unlikely(rc != MDBX_SUCCESS))
- parent->mt_flags |= MDBX_TXN_ERROR;
- mdbx_pnl_free(txn->mt_spill_pages);
- mdbx_pnl_sort(parent->mt_spill_pages);
- } else {
- parent->mt_spill_pages = txn->mt_spill_pages;
- }
- }
-
- /* Append our loose page list to parent's */
- for (lp = &parent->mt_loose_pages; *lp; lp = &NEXT_LOOSE_PAGE(*lp))
- ;
- *lp = txn->mt_loose_pages;
- parent->mt_loose_count += txn->mt_loose_count;
-
- parent->mt_child = NULL;
- mdbx_pnl_free(((MDBX_ntxn *)txn)->mnt_pgstate.mf_reclaimed_pglist);
- txn->mt_signature = 0;
- free(txn);
- return rc;
- }
-
- if (unlikely(txn != env->me_txn)) {
- mdbx_debug("attempt to commit unknown transaction");
- rc = MDBX_EINVAL;
- goto fail;
- }
-
- mdbx_cursors_eot(txn, 0);
- end_mode |= MDBX_END_EOTDONE;
-
- if (!txn->mt_rw_dirtylist[0].mid &&
- !(txn->mt_flags & (MDBX_TXN_DIRTY | MDBX_TXN_SPILLS)))
- goto done;
-
- mdbx_debug("committing txn %" PRIaTXN " %p on mdbenv %p, root page %" PRIaPGNO
- "/%" PRIaPGNO,
- txn->mt_txnid, (void *)txn, (void *)env,
- txn->mt_dbs[MAIN_DBI].md_root, txn->mt_dbs[FREE_DBI].md_root);
-
- /* Update DB root pointers */
- if (txn->mt_numdbs > CORE_DBS) {
- MDBX_cursor mc;
- MDBX_dbi i;
- MDBX_val data;
- data.iov_len = sizeof(MDBX_db);
-
- mdbx_cursor_init(&mc, txn, MAIN_DBI, NULL);
- for (i = CORE_DBS; i < txn->mt_numdbs; i++) {
- if (txn->mt_dbflags[i] & DB_DIRTY) {
- if (unlikely(TXN_DBI_CHANGED(txn, i))) {
- rc = MDBX_BAD_DBI;
- goto fail;
- }
- data.iov_base = &txn->mt_dbs[i];
- rc = mdbx_cursor_put(&mc, &txn->mt_dbxs[i].md_name, &data, F_SUBDATA);
- if (unlikely(rc != MDBX_SUCCESS))
- goto fail;
- }
- }
- }
-
- rc = mdbx_freelist_save(txn);
- if (unlikely(rc != MDBX_SUCCESS))
- goto fail;
-
- mdbx_pnl_free(env->me_reclaimed_pglist);
- env->me_reclaimed_pglist = NULL;
- mdbx_pnl_shrink(&txn->mt_befree_pages);
-
- if (mdbx_audit_enabled())
- mdbx_audit(txn);
-
- rc = mdbx_page_flush(txn, 0);
- if (likely(rc == MDBX_SUCCESS)) {
- MDBX_meta meta, *head = mdbx_meta_head(env);
-
- meta.mm_magic_and_version = head->mm_magic_and_version;
- meta.mm_extra_flags = head->mm_extra_flags;
- meta.mm_validator_id = head->mm_validator_id;
- meta.mm_extra_pagehdr = head->mm_extra_pagehdr;
-
- meta.mm_geo = head->mm_geo;
- meta.mm_geo.next = txn->mt_next_pgno;
- meta.mm_geo.now = txn->mt_end_pgno;
- meta.mm_dbs[FREE_DBI] = txn->mt_dbs[FREE_DBI];
- meta.mm_dbs[MAIN_DBI] = txn->mt_dbs[MAIN_DBI];
- meta.mm_canary = txn->mt_canary;
- mdbx_meta_set_txnid(env, &meta, txn->mt_txnid);
-
- rc = mdbx_sync_locked(
- env, env->me_flags | txn->mt_flags | MDBX_SHRINK_ALLOWED, &meta);
- }
- if (unlikely(rc != MDBX_SUCCESS))
- goto fail;
- env->me_lck->mti_readers_refresh_flag = false;
- end_mode = MDBX_END_COMMITTED | MDBX_END_UPDATE | MDBX_END_EOTDONE;
-
-done:
- return mdbx_txn_end(txn, end_mode);
-
-fail:
- mdbx_txn_abort(txn);
- return rc;
-}
-
-/* Read the environment parameters of a DB environment
- * before mapping it into memory. */
-static int __cold mdbx_read_header(MDBX_env *env, MDBX_meta *meta) {
- assert(offsetof(MDBX_page, mp_meta) == PAGEHDRSZ);
- memset(meta, 0, sizeof(MDBX_meta));
- meta->mm_datasync_sign = MDBX_DATASIGN_WEAK;
- int rc = MDBX_CORRUPTED;
-
- /* Read twice all meta pages so we can find the latest one. */
- unsigned loop_limit = NUM_METAS * 2;
- for (unsigned loop_count = 0; loop_count < loop_limit; ++loop_count) {
- MDBX_page page;
-
- /* We don't know the page size on first time.
- * So, just guess it. */
- unsigned guess_pagesize = meta->mm_psize;
- if (guess_pagesize == 0)
- guess_pagesize =
- (loop_count > NUM_METAS) ? env->me_psize : env->me_os_psize;
-
- const unsigned meta_number = loop_count % NUM_METAS;
- const unsigned offset = guess_pagesize * meta_number;
-
- unsigned retryleft = 42;
- while (1) {
- int err = mdbx_pread(env->me_fd, &page, sizeof(page), offset);
- if (err != MDBX_SUCCESS) {
- mdbx_error("read meta[%u,%u]: %i, %s", offset, (unsigned)sizeof(page),
- err, mdbx_strerror(err));
- return err;
- }
-
- MDBX_page again;
- err = mdbx_pread(env->me_fd, &again, sizeof(again), offset);
- if (err != MDBX_SUCCESS) {
- mdbx_error("read meta[%u,%u]: %i, %s", offset, (unsigned)sizeof(again),
- err, mdbx_strerror(err));
- return err;
- }
-
- if (memcmp(&page, &again, sizeof(page)) == 0 || --retryleft == 0)
- break;
-
- mdbx_info("meta[%u] was updated, re-read it", meta_number);
- }
-
- if (!retryleft) {
- mdbx_error("meta[%u] is too volatile, skip it", meta_number);
- continue;
- }
-
- if (page.mp_pgno != meta_number) {
- mdbx_error("meta[%u] has invalid pageno %" PRIaPGNO, meta_number,
- page.mp_pgno);
- return MDBX_INVALID;
- }
-
- if (!F_ISSET(page.mp_flags, P_META)) {
- mdbx_error("page #%u not a meta-page", meta_number);
- return MDBX_INVALID;
- }
-
- if (page.mp_meta.mm_magic_and_version != MDBX_DATA_MAGIC) {
- mdbx_error("meta[%u] has invalid magic/version MDBX_DEVEL=%d",
- meta_number, MDBX_DEVEL);
- return ((page.mp_meta.mm_magic_and_version >> 8) != MDBX_MAGIC)
- ? MDBX_INVALID
- : MDBX_VERSION_MISMATCH;
- }
-
- if (page.mp_meta.mm_txnid_a != page.mp_meta.mm_txnid_b) {
- mdbx_warning("meta[%u] not completely updated, skip it", meta_number);
- continue;
- }
-
- /* LY: check signature as a checksum */
- if (META_IS_STEADY(&page.mp_meta) &&
- page.mp_meta.mm_datasync_sign != mdbx_meta_sign(&page.mp_meta)) {
- mdbx_notice("meta[%u] has invalid steady-checksum (0x%" PRIx64
- " != 0x%" PRIx64 "), skip it",
- meta_number, page.mp_meta.mm_datasync_sign,
- mdbx_meta_sign(&page.mp_meta));
- continue;
- }
-
- /* LY: check pagesize */
- if (!mdbx_is_power2(page.mp_meta.mm_psize) ||
- page.mp_meta.mm_psize < MIN_PAGESIZE ||
- page.mp_meta.mm_psize > MAX_PAGESIZE) {
- mdbx_notice("meta[%u] has invalid pagesize (%u), skip it", meta_number,
- page.mp_meta.mm_psize);
- rc = MDBX_VERSION_MISMATCH;
- continue;
- }
-
- mdbx_debug("read meta%" PRIaPGNO " = root %" PRIaPGNO "/%" PRIaPGNO
- ", geo %" PRIaPGNO "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO
- " +%u -%u, txn_id %" PRIaTXN ", %s",
- page.mp_pgno, page.mp_meta.mm_dbs[MAIN_DBI].md_root,
- page.mp_meta.mm_dbs[FREE_DBI].md_root, page.mp_meta.mm_geo.lower,
- page.mp_meta.mm_geo.next, page.mp_meta.mm_geo.now,
- page.mp_meta.mm_geo.upper, page.mp_meta.mm_geo.grow,
- page.mp_meta.mm_geo.shrink, page.mp_meta.mm_txnid_a,
- mdbx_durable_str(&page.mp_meta));
-
- /* LY: check min-pages value */
- if (page.mp_meta.mm_geo.lower < MIN_PAGENO ||
- page.mp_meta.mm_geo.lower > MAX_PAGENO) {
- mdbx_notice("meta[%u] has invalid min-pages (%" PRIaPGNO "), skip it",
- meta_number, page.mp_meta.mm_geo.lower);
- rc = MDBX_INVALID;
- continue;
- }
-
- /* LY: check max-pages value */
- if (page.mp_meta.mm_geo.upper < MIN_PAGENO ||
- page.mp_meta.mm_geo.upper > MAX_PAGENO ||
- page.mp_meta.mm_geo.upper < page.mp_meta.mm_geo.lower) {
- mdbx_notice("meta[%u] has invalid max-pages (%" PRIaPGNO "), skip it",
- meta_number, page.mp_meta.mm_geo.upper);
- rc = MDBX_INVALID;
- continue;
- }
-
- /* LY: check mapsize limits */
- const uint64_t mapsize_min =
- page.mp_meta.mm_geo.lower * (uint64_t)page.mp_meta.mm_psize;
- const uint64_t mapsize_max =
- page.mp_meta.mm_geo.upper * (uint64_t)page.mp_meta.mm_psize;
- STATIC_ASSERT(MAX_MAPSIZE < SSIZE_MAX - MAX_PAGESIZE);
- STATIC_ASSERT(MIN_MAPSIZE < MAX_MAPSIZE);
- if (mapsize_min < MIN_MAPSIZE || mapsize_max > MAX_MAPSIZE) {
- mdbx_notice("meta[%u] has invalid min-mapsize (%" PRIu64 "), skip it",
- meta_number, mapsize_min);
- rc = MDBX_VERSION_MISMATCH;
- continue;
- }
-
- STATIC_ASSERT(MIN_MAPSIZE < MAX_MAPSIZE);
- if (mapsize_max > MAX_MAPSIZE ||
- MAX_PAGENO < mdbx_roundup2((size_t)mapsize_max, env->me_os_psize) /
- (uint64_t)page.mp_meta.mm_psize) {
- mdbx_notice("meta[%u] has too large max-mapsize (%" PRIu64 "), skip it",
- meta_number, mapsize_max);
- rc = MDBX_TOO_LARGE;
- continue;
- }
-
- /* LY: check end_pgno */
- if (page.mp_meta.mm_geo.now < page.mp_meta.mm_geo.lower ||
- page.mp_meta.mm_geo.now > page.mp_meta.mm_geo.upper) {
- mdbx_notice("meta[%u] has invalid end-pageno (%" PRIaPGNO "), skip it",
- meta_number, page.mp_meta.mm_geo.now);
- rc = MDBX_CORRUPTED;
- continue;
- }
-
- /* LY: check last_pgno */
- if (page.mp_meta.mm_geo.next < MIN_PAGENO ||
- page.mp_meta.mm_geo.next - 1 > MAX_PAGENO) {
- mdbx_notice("meta[%u] has invalid next-pageno (%" PRIaPGNO "), skip it",
- meta_number, page.mp_meta.mm_geo.next);
- rc = MDBX_CORRUPTED;
- continue;
- }
-
- if (page.mp_meta.mm_geo.next > page.mp_meta.mm_geo.now) {
- mdbx_notice("meta[%u] next-pageno (%" PRIaPGNO
- ") is beyond end-pgno (%" PRIaPGNO "), skip it",
- meta_number, page.mp_meta.mm_geo.next,
- page.mp_meta.mm_geo.now);
- rc = MDBX_CORRUPTED;
- continue;
- }
-
- /* LY: FreeDB root */
- if (page.mp_meta.mm_dbs[FREE_DBI].md_root == P_INVALID) {
- if (page.mp_meta.mm_dbs[FREE_DBI].md_branch_pages ||
- page.mp_meta.mm_dbs[FREE_DBI].md_depth ||
- page.mp_meta.mm_dbs[FREE_DBI].md_entries ||
- page.mp_meta.mm_dbs[FREE_DBI].md_leaf_pages ||
- page.mp_meta.mm_dbs[FREE_DBI].md_overflow_pages) {
- mdbx_notice("meta[%u] has false-empty freedb, skip it", meta_number);
- rc = MDBX_CORRUPTED;
- continue;
- }
- } else if (page.mp_meta.mm_dbs[FREE_DBI].md_root >=
- page.mp_meta.mm_geo.next) {
- mdbx_notice("meta[%u] has invalid freedb-root %" PRIaPGNO ", skip it",
- meta_number, page.mp_meta.mm_dbs[FREE_DBI].md_root);
- rc = MDBX_CORRUPTED;
- continue;
- }
-
- /* LY: MainDB root */
- if (page.mp_meta.mm_dbs[MAIN_DBI].md_root == P_INVALID) {
- if (page.mp_meta.mm_dbs[MAIN_DBI].md_branch_pages ||
- page.mp_meta.mm_dbs[MAIN_DBI].md_depth ||
- page.mp_meta.mm_dbs[MAIN_DBI].md_entries ||
- page.mp_meta.mm_dbs[MAIN_DBI].md_leaf_pages ||
- page.mp_meta.mm_dbs[MAIN_DBI].md_overflow_pages) {
- mdbx_notice("meta[%u] has false-empty maindb", meta_number);
- rc = MDBX_CORRUPTED;
- continue;
- }
- } else if (page.mp_meta.mm_dbs[MAIN_DBI].md_root >=
- page.mp_meta.mm_geo.next) {
- mdbx_notice("meta[%u] has invalid maindb-root %" PRIaPGNO ", skip it",
- meta_number, page.mp_meta.mm_dbs[MAIN_DBI].md_root);
- rc = MDBX_CORRUPTED;
- continue;
- }
-
- if (page.mp_meta.mm_txnid_a == 0) {
- mdbx_warning("meta[%u] has zero txnid, skip it", meta_number);
- continue;
- }
-
- if (mdbx_meta_ot(prefer_noweak, env, meta, &page.mp_meta)) {
- *meta = page.mp_meta;
- if (META_IS_WEAK(meta))
- loop_limit += 1; /* LY: should re-read to hush race with update */
- mdbx_info("latch meta[%u]", meta_number);
- }
- }
-
- if (META_IS_WEAK(meta)) {
- mdbx_error("no usable meta-pages, database is corrupted");
- return rc;
- }
-
- return MDBX_SUCCESS;
-}
-
-static MDBX_page *__cold mdbx_meta_model(const MDBX_env *env, MDBX_page *model,
- unsigned num) {
-
- mdbx_ensure(env, mdbx_is_power2(env->me_psize));
- mdbx_ensure(env, env->me_psize >= MIN_PAGESIZE);
- mdbx_ensure(env, env->me_psize <= MAX_PAGESIZE);
- mdbx_ensure(env, env->me_dbgeo.lower >= MIN_MAPSIZE);
- mdbx_ensure(env, env->me_dbgeo.upper <= MAX_MAPSIZE);
- mdbx_ensure(env, env->me_dbgeo.now >= env->me_dbgeo.lower);
- mdbx_ensure(env, env->me_dbgeo.now <= env->me_dbgeo.upper);
-
- memset(model, 0, sizeof(*model));
- model->mp_pgno = num;
- model->mp_flags = P_META;
- model->mp_meta.mm_magic_and_version = MDBX_DATA_MAGIC;
-
- model->mp_meta.mm_geo.lower = bytes2pgno(env, env->me_dbgeo.lower);
- model->mp_meta.mm_geo.upper = bytes2pgno(env, env->me_dbgeo.upper);
- model->mp_meta.mm_geo.grow = (uint16_t)bytes2pgno(env, env->me_dbgeo.grow);
- model->mp_meta.mm_geo.shrink =
- (uint16_t)bytes2pgno(env, env->me_dbgeo.shrink);
- model->mp_meta.mm_geo.now = bytes2pgno(env, env->me_dbgeo.now);
- model->mp_meta.mm_geo.next = NUM_METAS;
-
- mdbx_ensure(env, model->mp_meta.mm_geo.lower >= MIN_PAGENO);
- mdbx_ensure(env, model->mp_meta.mm_geo.upper <= MAX_PAGENO);
- mdbx_ensure(env, model->mp_meta.mm_geo.now >= model->mp_meta.mm_geo.lower);
- mdbx_ensure(env, model->mp_meta.mm_geo.now <= model->mp_meta.mm_geo.upper);
- mdbx_ensure(env, model->mp_meta.mm_geo.next >= MIN_PAGENO);
- mdbx_ensure(env, model->mp_meta.mm_geo.next <= model->mp_meta.mm_geo.now);
- mdbx_ensure(env, model->mp_meta.mm_geo.grow ==
- bytes2pgno(env, env->me_dbgeo.grow));
- mdbx_ensure(env, model->mp_meta.mm_geo.shrink ==
- bytes2pgno(env, env->me_dbgeo.shrink));
-
- model->mp_meta.mm_psize = env->me_psize;
- model->mp_meta.mm_flags = (uint16_t)env->me_flags;
- model->mp_meta.mm_flags |=
- MDBX_INTEGERKEY; /* this is mm_dbs[FREE_DBI].md_flags */
- model->mp_meta.mm_dbs[FREE_DBI].md_root = P_INVALID;
- model->mp_meta.mm_dbs[MAIN_DBI].md_root = P_INVALID;
- mdbx_meta_set_txnid(env, &model->mp_meta, MIN_TXNID + num);
- model->mp_meta.mm_datasync_sign = mdbx_meta_sign(&model->mp_meta);
- return (MDBX_page *)((uint8_t *)model + env->me_psize);
-}
-
-/* Fill in most of the zeroed meta-pages for an empty database environment.
- * Return pointer to recenly (head) meta-page. */
-static MDBX_page *__cold mdbx_init_metas(const MDBX_env *env, void *buffer) {
- MDBX_page *page0 = (MDBX_page *)buffer;
- MDBX_page *page1 = mdbx_meta_model(env, page0, 0);
- MDBX_page *page2 = mdbx_meta_model(env, page1, 1);
- mdbx_meta_model(env, page2, 2);
- page2->mp_meta.mm_datasync_sign = MDBX_DATASIGN_WEAK;
- mdbx_assert(env, !mdbx_meta_eq(env, &page0->mp_meta, &page1->mp_meta));
- mdbx_assert(env, !mdbx_meta_eq(env, &page1->mp_meta, &page2->mp_meta));
- mdbx_assert(env, !mdbx_meta_eq(env, &page2->mp_meta, &page0->mp_meta));
- return page1;
-}
-
-static int mdbx_sync_locked(MDBX_env *env, unsigned flags,
- MDBX_meta *const pending) {
- mdbx_assert(env, ((env->me_flags ^ flags) & MDBX_WRITEMAP) == 0);
- MDBX_meta *const meta0 = METAPAGE(env, 0);
- MDBX_meta *const meta1 = METAPAGE(env, 1);
- MDBX_meta *const meta2 = METAPAGE(env, 2);
- MDBX_meta *const head = mdbx_meta_head(env);
-
- mdbx_assert(env, mdbx_meta_eq_mask(env) == 0);
- mdbx_assert(env,
- pending < METAPAGE(env, 0) || pending > METAPAGE(env, NUM_METAS));
- mdbx_assert(env, (env->me_flags & (MDBX_RDONLY | MDBX_FATAL_ERROR)) == 0);
- mdbx_assert(env, !META_IS_STEADY(head) || env->me_sync_pending != 0);
- mdbx_assert(env, pending->mm_geo.next <= pending->mm_geo.now);
-
- const size_t usedbytes = pgno_align2os_bytes(env, pending->mm_geo.next);
- if (env->me_sync_threshold && env->me_sync_pending >= env->me_sync_threshold)
- flags &= MDBX_WRITEMAP | MDBX_SHRINK_ALLOWED;
-
- /* LY: step#1 - sync previously written/updated data-pages */
- int rc = MDBX_RESULT_TRUE;
- if (env->me_sync_pending && (flags & MDBX_NOSYNC) == 0) {
- mdbx_assert(env, ((flags ^ env->me_flags) & MDBX_WRITEMAP) == 0);
- MDBX_meta *const steady = mdbx_meta_steady(env);
- if (flags & MDBX_WRITEMAP) {
- rc = mdbx_msync(&env->me_dxb_mmap, 0, usedbytes, flags & MDBX_MAPASYNC);
- if (unlikely(rc != MDBX_SUCCESS))
- goto fail;
- if ((flags & MDBX_MAPASYNC) == 0) {
- if (unlikely(pending->mm_geo.next > steady->mm_geo.now)) {
- rc = mdbx_filesize_sync(env->me_fd);
- if (unlikely(rc != MDBX_SUCCESS))
- goto fail;
- }
- env->me_sync_pending = 0;
- }
- } else {
- rc = mdbx_filesync(env->me_fd, pending->mm_geo.next > steady->mm_geo.now);
- if (unlikely(rc != MDBX_SUCCESS))
- goto fail;
- env->me_sync_pending = 0;
- }
- }
-
-#if defined(_WIN32) || defined(_WIN64)
-/* Windows is unable shrinking a mapped file */
-#else
- /* LY: check conditions to shrink datafile */
- pgno_t shrink = 0;
- if ((flags & MDBX_SHRINK_ALLOWED) && pending->mm_geo.shrink &&
- pending->mm_geo.now - pending->mm_geo.next > pending->mm_geo.shrink) {
- const pgno_t aligner =
- pending->mm_geo.grow ? pending->mm_geo.grow : pending->mm_geo.shrink;
- const pgno_t aligned = pgno_align2os_pgno(
- env, pending->mm_geo.next + aligner - pending->mm_geo.next % aligner);
- const pgno_t bottom =
- (aligned > pending->mm_geo.lower) ? aligned : pending->mm_geo.lower;
- if (pending->mm_geo.now > bottom) {
- shrink = pending->mm_geo.now - bottom;
- pending->mm_geo.now = bottom;
- if (mdbx_meta_txnid_stable(env, head) == pending->mm_txnid_a)
- mdbx_meta_set_txnid(env, pending, pending->mm_txnid_a + 1);
- }
- }
-#endif /* not a Windows */
-
- /* Steady or Weak */
- if (env->me_sync_pending == 0) {
- pending->mm_datasync_sign = mdbx_meta_sign(pending);
- } else {
- pending->mm_datasync_sign =
- (flags & MDBX_UTTERLY_NOSYNC) == MDBX_UTTERLY_NOSYNC
- ? MDBX_DATASIGN_NONE
- : MDBX_DATASIGN_WEAK;
- }
-
- MDBX_meta *target = nullptr;
- if (mdbx_meta_txnid_stable(env, head) == pending->mm_txnid_a) {
- mdbx_assert(env, memcmp(&head->mm_dbs, &pending->mm_dbs,
- sizeof(head->mm_dbs)) == 0);
- mdbx_assert(env, memcmp(&head->mm_canary, &pending->mm_canary,
- sizeof(head->mm_canary)) == 0);
- mdbx_assert(env, memcmp(&head->mm_geo, &pending->mm_geo,
- sizeof(pending->mm_geo)) == 0);
- if (!META_IS_STEADY(head) && META_IS_STEADY(pending))
- target = head;
- else {
- mdbx_ensure(env, mdbx_meta_eq(env, head, pending));
- mdbx_debug("skip update meta");
- return MDBX_SUCCESS;
- }
- } else if (head == meta0)
- target = mdbx_meta_ancient(prefer_steady, env, meta1, meta2);
- else if (head == meta1)
- target = mdbx_meta_ancient(prefer_steady, env, meta0, meta2);
- else {
- mdbx_assert(env, head == meta2);
- target = mdbx_meta_ancient(prefer_steady, env, meta0, meta1);
- }
-
- /* LY: step#2 - update meta-page. */
- mdbx_debug("writing meta%" PRIaPGNO " = root %" PRIaPGNO "/%" PRIaPGNO
- ", geo %" PRIaPGNO "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO
- " +%u -%u, txn_id %" PRIaTXN ", %s",
- container_of(target, MDBX_page, mp_data)->mp_pgno,
- pending->mm_dbs[MAIN_DBI].md_root,
- pending->mm_dbs[FREE_DBI].md_root, pending->mm_geo.lower,
- pending->mm_geo.next, pending->mm_geo.now, pending->mm_geo.upper,
- pending->mm_geo.grow, pending->mm_geo.shrink, pending->mm_txnid_a,
- mdbx_durable_str(pending));
-
- mdbx_debug("meta0: %s, %s, txn_id %" PRIaTXN ", root %" PRIaPGNO
- "/%" PRIaPGNO,
- (meta0 == head) ? "head" : (meta0 == target) ? "tail" : "stay",
- mdbx_durable_str(meta0), mdbx_meta_txnid_fluid(env, meta0),
- meta0->mm_dbs[MAIN_DBI].md_root, meta0->mm_dbs[FREE_DBI].md_root);
- mdbx_debug("meta1: %s, %s, txn_id %" PRIaTXN ", root %" PRIaPGNO
- "/%" PRIaPGNO,
- (meta1 == head) ? "head" : (meta1 == target) ? "tail" : "stay",
- mdbx_durable_str(meta1), mdbx_meta_txnid_fluid(env, meta1),
- meta1->mm_dbs[MAIN_DBI].md_root, meta1->mm_dbs[FREE_DBI].md_root);
- mdbx_debug("meta2: %s, %s, txn_id %" PRIaTXN ", root %" PRIaPGNO
- "/%" PRIaPGNO,
- (meta2 == head) ? "head" : (meta2 == target) ? "tail" : "stay",
- mdbx_durable_str(meta2), mdbx_meta_txnid_fluid(env, meta2),
- meta2->mm_dbs[MAIN_DBI].md_root, meta2->mm_dbs[FREE_DBI].md_root);
-
- mdbx_assert(env, !mdbx_meta_eq(env, pending, meta0));
- mdbx_assert(env, !mdbx_meta_eq(env, pending, meta1));
- mdbx_assert(env, !mdbx_meta_eq(env, pending, meta2));
-
- mdbx_assert(env, ((env->me_flags ^ flags) & MDBX_WRITEMAP) == 0);
- mdbx_ensure(env,
- target == head ||
- mdbx_meta_txnid_stable(env, target) < pending->mm_txnid_a);
- if (env->me_flags & MDBX_WRITEMAP) {
- mdbx_jitter4testing(true);
- if (likely(target != head)) {
- /* LY: 'invalidate' the meta. */
- target->mm_datasync_sign = MDBX_DATASIGN_WEAK;
- mdbx_meta_update_begin(env, target, pending->mm_txnid_a);
-#ifndef NDEBUG
- /* debug: provoke failure to catch a violators */
- memset(target->mm_dbs, 0xCC,
- sizeof(target->mm_dbs) + sizeof(target->mm_canary));
- mdbx_jitter4testing(false);
-#endif
-
- /* LY: update info */
- target->mm_geo = pending->mm_geo;
- target->mm_dbs[FREE_DBI] = pending->mm_dbs[FREE_DBI];
- target->mm_dbs[MAIN_DBI] = pending->mm_dbs[MAIN_DBI];
- target->mm_canary = pending->mm_canary;
- mdbx_jitter4testing(true);
- mdbx_coherent_barrier();
-
- /* LY: 'commit' the meta */
- mdbx_meta_update_end(env, target, pending->mm_txnid_b);
- mdbx_jitter4testing(true);
- } else {
- /* dangerous case (target == head), only mm_datasync_sign could
- * me updated, check assertions once again */
- mdbx_ensure(env,
- mdbx_meta_txnid_stable(env, head) == pending->mm_txnid_a &&
- !META_IS_STEADY(head) && META_IS_STEADY(pending));
- mdbx_ensure(env, memcmp(&head->mm_geo, &pending->mm_geo,
- sizeof(head->mm_geo)) == 0);
- mdbx_ensure(env, memcmp(&head->mm_dbs, &pending->mm_dbs,
- sizeof(head->mm_dbs)) == 0);
- mdbx_ensure(env, memcmp(&head->mm_canary, &pending->mm_canary,
- sizeof(head->mm_canary)) == 0);
- }
- target->mm_datasync_sign = pending->mm_datasync_sign;
- mdbx_coherent_barrier();
- mdbx_jitter4testing(true);
- } else {
- rc = mdbx_pwrite(env->me_fd, pending, sizeof(MDBX_meta),
- (uint8_t *)target - env->me_map);
- if (unlikely(rc != MDBX_SUCCESS)) {
- undo:
- mdbx_debug("write failed, disk error?");
- /* On a failure, the pagecache still contains the new data.
- * Try write some old data back, to prevent it from being used. */
- mdbx_pwrite(env->me_fd, (void *)target, sizeof(MDBX_meta),
- (uint8_t *)target - env->me_map);
- goto fail;
- }
- mdbx_invalidate_cache(target, sizeof(MDBX_meta));
- }
-
- /* LY: step#3 - sync meta-pages. */
- mdbx_assert(env, ((env->me_flags ^ flags) & MDBX_WRITEMAP) == 0);
- if ((flags & (MDBX_NOSYNC | MDBX_NOMETASYNC)) == 0) {
- mdbx_assert(env, ((flags ^ env->me_flags) & MDBX_WRITEMAP) == 0);
- if (flags & MDBX_WRITEMAP) {
- const size_t offset =
- ((uint8_t *)container_of(head, MDBX_page, mp_meta)) -
- env->me_dxb_mmap.dxb;
- const size_t paged_offset = offset & ~(env->me_os_psize - 1);
- const size_t paged_length = mdbx_roundup2(
- env->me_psize + offset - paged_offset, env->me_os_psize);
- rc = mdbx_msync(&env->me_dxb_mmap, paged_offset, paged_length,
- flags & MDBX_MAPASYNC);
- if (unlikely(rc != MDBX_SUCCESS))
- goto fail;
- } else {
- rc = mdbx_filesync(env->me_fd, false);
- if (rc != MDBX_SUCCESS)
- goto undo;
- }
- }
-
-#if defined(_WIN32) || defined(_WIN64)
-/* Windows is unable shrinking a mapped file */
-#else
- /* LY: shrink datafile if needed */
- if (unlikely(shrink)) {
- mdbx_info("shrink to %" PRIaPGNO " pages (-%" PRIaPGNO ")",
- pending->mm_geo.now, shrink);
- rc = mdbx_mapresize(env, pending->mm_geo.now, pending->mm_geo.upper);
- if (MDBX_IS_ERROR(rc))
- goto fail;
- }
-#endif /* not a Windows */
-
- return MDBX_SUCCESS;
-
-fail:
- env->me_flags |= MDBX_FATAL_ERROR;
- return rc;
-}
-
-int __cold mdbx_env_get_maxkeysize(MDBX_env *env) {
- if (!env || env->me_signature != MDBX_ME_SIGNATURE || !env->me_maxkey_limit)
- return -MDBX_EINVAL;
- return env->me_maxkey_limit;
-}
-
-#define mdbx_nodemax(pagesize) \
- (((((pagesize)-PAGEHDRSZ) / MDBX_MINKEYS) & -(intptr_t)2) - sizeof(indx_t))
-
-#define mdbx_maxkey(nodemax) ((nodemax) - (NODESIZE + sizeof(MDBX_db)))
-
-#define mdbx_maxfree1pg(pagesize) (((pagesize)-PAGEHDRSZ) / sizeof(pgno_t) - 1)
-
-int mdbx_get_maxkeysize(size_t pagesize) {
- if (pagesize == 0)
- pagesize = mdbx_syspagesize();
-
- intptr_t nodemax = mdbx_nodemax(pagesize);
- if (nodemax < 0)
- return -MDBX_EINVAL;
-
- intptr_t maxkey = mdbx_maxkey(nodemax);
- return (maxkey > 0 && maxkey < INT_MAX) ? (int)maxkey : -MDBX_EINVAL;
-}
-
-static void __cold mdbx_setup_pagesize(MDBX_env *env, const size_t pagesize) {
- STATIC_ASSERT(SSIZE_MAX > MAX_MAPSIZE);
- STATIC_ASSERT(MIN_PAGESIZE > sizeof(MDBX_page));
- mdbx_ensure(env, mdbx_is_power2(pagesize));
- mdbx_ensure(env, pagesize >= MIN_PAGESIZE);
- mdbx_ensure(env, pagesize <= MAX_PAGESIZE);
- env->me_psize = (unsigned)pagesize;
-
- STATIC_ASSERT(mdbx_maxfree1pg(MIN_PAGESIZE) > 42);
- STATIC_ASSERT(mdbx_maxfree1pg(MAX_PAGESIZE) < MDBX_PNL_DB_MAX);
- const intptr_t maxfree_1pg = (pagesize - PAGEHDRSZ) / sizeof(pgno_t) - 1;
- mdbx_ensure(env, maxfree_1pg > 42 && maxfree_1pg < MDBX_PNL_DB_MAX);
- env->me_maxfree_1pg = (unsigned)maxfree_1pg;
-
- STATIC_ASSERT(mdbx_nodemax(MIN_PAGESIZE) > 42);
- STATIC_ASSERT(mdbx_nodemax(MAX_PAGESIZE) < UINT16_MAX);
- const intptr_t nodemax = mdbx_nodemax(pagesize);
- mdbx_ensure(env, nodemax > 42 && nodemax < UINT16_MAX);
- env->me_nodemax = (unsigned)nodemax;
-
- STATIC_ASSERT(mdbx_maxkey(MIN_PAGESIZE) > 42);
- STATIC_ASSERT(mdbx_maxkey(MIN_PAGESIZE) < MIN_PAGESIZE);
- STATIC_ASSERT(mdbx_maxkey(MAX_PAGESIZE) > 42);
- STATIC_ASSERT(mdbx_maxkey(MAX_PAGESIZE) < MAX_PAGESIZE);
- const intptr_t maxkey_limit = mdbx_maxkey(env->me_nodemax);
- mdbx_ensure(env, maxkey_limit > 42 && (size_t)maxkey_limit < pagesize);
- env->me_maxkey_limit = (unsigned)maxkey_limit;
-
- env->me_psize2log = mdbx_log2(pagesize);
- mdbx_assert(env, pgno2bytes(env, 1) == pagesize);
- mdbx_assert(env, bytes2pgno(env, pagesize + pagesize) == 2);
-}
-
-int __cold mdbx_env_create(MDBX_env **penv) {
- MDBX_env *env = calloc(1, sizeof(MDBX_env));
- if (!env)
- return MDBX_ENOMEM;
-
- env->me_maxreaders = DEFAULT_READERS;
- env->me_maxdbs = env->me_numdbs = CORE_DBS;
- env->me_fd = INVALID_HANDLE_VALUE;
- env->me_lfd = INVALID_HANDLE_VALUE;
- env->me_pid = mdbx_getpid();
-
- int rc;
- const size_t os_psize = mdbx_syspagesize();
- if (!mdbx_is_power2(os_psize) || os_psize < MIN_PAGESIZE) {
- mdbx_error("unsuitable system pagesize %" PRIuPTR, os_psize);
- rc = MDBX_INCOMPATIBLE;
- goto bailout;
- }
- env->me_os_psize = (unsigned)os_psize;
- mdbx_setup_pagesize(env, env->me_os_psize);
-
- rc = mdbx_fastmutex_init(&env->me_dbi_lock);
- if (unlikely(rc != MDBX_SUCCESS))
- goto bailout;
-
- VALGRIND_CREATE_MEMPOOL(env, 0, 0);
- env->me_signature = MDBX_ME_SIGNATURE;
- *penv = env;
- return MDBX_SUCCESS;
-
-bailout:
- free(env);
- *penv = nullptr;
- return rc;
-}
-
-static int __cold mdbx_env_map(MDBX_env *env, size_t usedsize) {
- int rc = mdbx_mmap(env->me_flags, &env->me_dxb_mmap, env->me_dbgeo.now,
- env->me_dbgeo.upper);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
-
-#ifdef MADV_DONTFORK
- if (madvise(env->me_map, env->me_mapsize, MADV_DONTFORK))
- return errno;
-#endif
-
-#ifdef MADV_NOHUGEPAGE
- (void)madvise(env->me_map, env->me_mapsize, MADV_NOHUGEPAGE);
-#endif
-
-#if defined(MADV_DODUMP) && defined(MADV_DONTDUMP)
- const size_t meta_length = pgno2bytes(env, NUM_METAS);
- (void)madvise(env->me_map, meta_length, MADV_DODUMP);
- if (!(env->me_flags & MDBX_PAGEPERTURB))
- (void)madvise(env->me_map + meta_length, env->me_mapsize - meta_length,
- MADV_DONTDUMP);
-#endif
-
-#ifdef MADV_REMOVE
- if (usedsize && (env->me_flags & MDBX_WRITEMAP)) {
- (void)madvise(env->me_map + usedsize, env->me_mapsize - usedsize,
- MADV_REMOVE);
- }
-#else
- (void)usedsize;
-#endif
-
-#if defined(MADV_RANDOM) && defined(MADV_WILLNEED)
- /* Turn on/off readahead. It's harmful when the DB is larger than RAM. */
- if (madvise(env->me_map, env->me_mapsize,
- (env->me_flags & MDBX_NORDAHEAD) ? MADV_RANDOM : MADV_WILLNEED))
- return errno;
-#endif
-
-#ifdef USE_VALGRIND
- env->me_valgrind_handle =
- VALGRIND_CREATE_BLOCK(env->me_map, env->me_mapsize, "mdbx");
-#endif
-
- return MDBX_SUCCESS;
-}
-
-LIBMDBX_API int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower,
- intptr_t size_now, intptr_t size_upper,
- intptr_t growth_step,
- intptr_t shrink_threshold,
- intptr_t pagesize) {
- if (unlikely(!env))
- return MDBX_EINVAL;
-
- if (unlikely(env->me_signature != MDBX_ME_SIGNATURE))
- return MDBX_EBADSIGN;
-
- const bool outside_txn =
- (!env->me_txn0 || env->me_txn0->mt_owner != mdbx_thread_self());
-
-#if MDBX_DEBUG
- if (growth_step < 0)
- growth_step = 1;
- if (shrink_threshold < 0)
- shrink_threshold = 1;
-#endif
-
- int rc = MDBX_PROBLEM;
- if (env->me_map) {
- /* env already mapped */
- if (!env->me_lck || (env->me_flags & MDBX_RDONLY))
- return MDBX_EACCESS;
-
- if (outside_txn) {
- int err = mdbx_txn_lock(env, false);
- if (unlikely(err != MDBX_SUCCESS))
- return err;
- }
- MDBX_meta *head = mdbx_meta_head(env);
-
- if (pagesize < 0)
- pagesize = env->me_psize;
- if (pagesize != (intptr_t)env->me_psize) {
- rc = MDBX_EINVAL;
- goto bailout;
- }
-
- if (size_lower < 0)
- size_lower = pgno2bytes(env, head->mm_geo.lower);
- if (size_now < 0)
- size_now = pgno2bytes(env, head->mm_geo.now);
- if (size_upper < 0)
- size_upper = pgno2bytes(env, head->mm_geo.upper);
- if (growth_step < 0)
- growth_step = pgno2bytes(env, head->mm_geo.grow);
- if (shrink_threshold < 0)
- shrink_threshold = pgno2bytes(env, head->mm_geo.shrink);
-
- const size_t usedbytes = pgno2bytes(env, head->mm_geo.next);
- if ((size_t)size_upper < usedbytes) {
- rc = MDBX_MAP_FULL;
- goto bailout;
- }
- if ((size_t)size_now < usedbytes)
- size_now = usedbytes;
-#if defined(_WIN32) || defined(_WIN64)
- if ((size_t)size_now < env->me_dbgeo.now ||
- (size_t)size_upper < env->me_dbgeo.upper) {
- /* Windows is unable shrinking a mapped file */
- return ERROR_USER_MAPPED_FILE;
- }
-#endif /* Windows */
- } else {
- /* env NOT yet mapped */
- if (!outside_txn) {
- rc = MDBX_PANIC;
- goto bailout;
- }
-
- if (pagesize < 0) {
- pagesize = env->me_os_psize;
- if (pagesize > MAX_PAGESIZE)
- pagesize = MAX_PAGESIZE;
- mdbx_assert(env, pagesize >= MIN_PAGESIZE);
- }
- }
-
- if (pagesize < MIN_PAGESIZE || pagesize > MAX_PAGESIZE ||
- !mdbx_is_power2(pagesize)) {
- rc = MDBX_EINVAL;
- goto bailout;
- }
-
- if (size_lower < 0) {
- size_lower = MIN_MAPSIZE;
- if (MIN_MAPSIZE / pagesize < MIN_PAGENO)
- size_lower = MIN_PAGENO * pagesize;
- }
-
- if (size_now < 0) {
- size_now = DEFAULT_MAPSIZE;
- if (size_now < size_lower)
- size_now = size_lower;
- }
-
- if (size_upper < 0) {
- if ((size_t)size_now >= MAX_MAPSIZE / 2)
- size_upper = MAX_MAPSIZE;
- else if (MAX_MAPSIZE != MAX_MAPSIZE32 &&
- (size_t)size_now >= MAX_MAPSIZE32 / 2 &&
- (size_t)size_now <= MAX_MAPSIZE32 / 4 * 3)
- size_upper = MAX_MAPSIZE32;
- else {
- size_upper = size_now + size_now;
- if ((size_t)size_upper < DEFAULT_MAPSIZE * 2)
- size_upper = DEFAULT_MAPSIZE * 2;
- }
- if ((size_t)size_upper / pagesize > MAX_PAGENO)
- size_upper = pagesize * MAX_PAGENO;
- }
-
- if (unlikely(size_lower < MIN_MAPSIZE || size_lower > size_upper)) {
- rc = MDBX_EINVAL;
- goto bailout;
- }
-
- if ((uint64_t)size_lower / pagesize < MIN_PAGENO) {
- rc = MDBX_EINVAL;
- goto bailout;
- }
-
- if (unlikely((size_t)size_upper > MAX_MAPSIZE ||
- (uint64_t)size_upper / pagesize > MAX_PAGENO)) {
- rc = MDBX_TOO_LARGE;
- goto bailout;
- }
-
- size_lower = mdbx_roundup2(size_lower, env->me_os_psize);
- size_upper = mdbx_roundup2(size_upper, env->me_os_psize);
- size_now = mdbx_roundup2(size_now, env->me_os_psize);
-
- /* LY: подбираем значение size_upper:
- * - кратное размеру ÑиÑтемной Ñтраницы
- * - без Ð½Ð°Ñ€ÑƒÑˆÐµÐ½Ð¸Ñ MAX_MAPSIZE или MAX_PAGENO */
- while (unlikely((size_t)size_upper > MAX_MAPSIZE ||
- (uint64_t)size_upper / pagesize > MAX_PAGENO)) {
- if ((size_t)size_upper < env->me_os_psize + MIN_MAPSIZE ||
- (size_t)size_upper < env->me_os_psize * (MIN_PAGENO + 1)) {
- /* паранойа на Ñлучай Ð¿ÐµÑ€ÐµÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸ невероÑтных значениÑÑ… */
- rc = MDBX_EINVAL;
- goto bailout;
- }
- size_upper -= env->me_os_psize;
- if ((size_t)size_upper > (size_t)size_lower)
- size_lower = size_upper;
- }
- mdbx_assert(env, (size_upper - size_lower) % env->me_os_psize == 0);
-
- if (size_now < size_lower)
- size_now = size_lower;
- if (size_now > size_upper)
- size_now = size_upper;
-
- if (growth_step < 0) {
- growth_step = ((size_t)(size_upper - size_lower)) / 42;
- if (growth_step > size_lower)
- growth_step = size_lower;
- if (growth_step < 65536)
- growth_step = 65536;
- if ((size_t)growth_step > MEGABYTE * 16)
- growth_step = MEGABYTE * 16;
- }
- growth_step = mdbx_roundup2(growth_step, env->me_os_psize);
- if (bytes2pgno(env, growth_step) > UINT16_MAX)
- growth_step = pgno2bytes(env, UINT16_MAX);
-
- if (shrink_threshold < 0) {
- shrink_threshold = growth_step + growth_step;
- if (shrink_threshold < growth_step)
- shrink_threshold = growth_step;
- }
- shrink_threshold = mdbx_roundup2(shrink_threshold, env->me_os_psize);
- if (bytes2pgno(env, shrink_threshold) > UINT16_MAX)
- shrink_threshold = pgno2bytes(env, UINT16_MAX);
-
- /* save user's geo-params for future open/create */
- env->me_dbgeo.lower = size_lower;
- env->me_dbgeo.now = size_now;
- env->me_dbgeo.upper = size_upper;
- env->me_dbgeo.grow = growth_step;
- env->me_dbgeo.shrink = shrink_threshold;
- rc = MDBX_SUCCESS;
-
- if (env->me_map) {
- /* apply new params */
- mdbx_assert(env, pagesize == (intptr_t)env->me_psize);
-
- MDBX_meta *head = mdbx_meta_head(env);
- MDBX_meta meta = *head;
- meta.mm_geo.lower = bytes2pgno(env, env->me_dbgeo.lower);
- meta.mm_geo.now = bytes2pgno(env, env->me_dbgeo.now);
- meta.mm_geo.upper = bytes2pgno(env, env->me_dbgeo.upper);
- meta.mm_geo.grow = (uint16_t)bytes2pgno(env, env->me_dbgeo.grow);
- meta.mm_geo.shrink = (uint16_t)bytes2pgno(env, env->me_dbgeo.shrink);
-
- mdbx_assert(env, env->me_dbgeo.lower >= MIN_MAPSIZE);
- mdbx_assert(env, meta.mm_geo.lower >= MIN_PAGENO);
- mdbx_assert(env, env->me_dbgeo.upper <= MAX_MAPSIZE);
- mdbx_assert(env, meta.mm_geo.upper <= MAX_PAGENO);
- mdbx_assert(env, meta.mm_geo.now >= meta.mm_geo.next);
- mdbx_assert(env, env->me_dbgeo.upper >= env->me_dbgeo.lower);
- mdbx_assert(env, meta.mm_geo.upper >= meta.mm_geo.now);
- mdbx_assert(env, meta.mm_geo.now >= meta.mm_geo.lower);
- mdbx_assert(env, meta.mm_geo.grow == bytes2pgno(env, env->me_dbgeo.grow));
- mdbx_assert(env,
- meta.mm_geo.shrink == bytes2pgno(env, env->me_dbgeo.shrink));
-
- if (memcmp(&meta.mm_geo, &head->mm_geo, sizeof(meta.mm_geo))) {
- if (meta.mm_geo.now != head->mm_geo.now ||
- meta.mm_geo.upper != head->mm_geo.upper) {
- rc = mdbx_mapresize(env, meta.mm_geo.now, meta.mm_geo.upper);
- if (unlikely(rc != MDBX_SUCCESS))
- goto bailout;
- }
- mdbx_meta_set_txnid(env, &meta, mdbx_meta_txnid_stable(env, head) + 1);
- rc = mdbx_sync_locked(env, env->me_flags, &meta);
- }
- } else if (pagesize != (intptr_t)env->me_psize) {
- mdbx_setup_pagesize(env, pagesize);
- }
-
-bailout:
- if (env->me_map && outside_txn)
- mdbx_txn_unlock(env);
- return rc;
-}
-
-int __cold mdbx_env_set_mapsize(MDBX_env *env, size_t size) {
- return mdbx_env_set_geometry(env, -1, size, -1, -1, -1, -1);
-}
-
-int __cold mdbx_env_set_maxdbs(MDBX_env *env, MDBX_dbi dbs) {
- if (unlikely(dbs > MAX_DBI))
- return MDBX_EINVAL;
-
- if (unlikely(!env))
- return MDBX_EINVAL;
-
- if (unlikely(env->me_signature != MDBX_ME_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(env->me_map))
- return MDBX_EPERM;
-
- env->me_maxdbs = dbs + CORE_DBS;
- return MDBX_SUCCESS;
-}
-
-int __cold mdbx_env_set_maxreaders(MDBX_env *env, unsigned readers) {
- if (unlikely(readers < 1 || readers > INT16_MAX))
- return MDBX_EINVAL;
-
- if (unlikely(!env))
- return MDBX_EINVAL;
-
- if (unlikely(env->me_signature != MDBX_ME_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(env->me_map))
- return MDBX_EPERM;
-
- env->me_maxreaders = readers;
- return MDBX_SUCCESS;
-}
-
-int __cold mdbx_env_get_maxreaders(MDBX_env *env, unsigned *readers) {
- if (!env || !readers)
- return MDBX_EINVAL;
-
- if (unlikely(env->me_signature != MDBX_ME_SIGNATURE))
- return MDBX_EBADSIGN;
-
- *readers = env->me_maxreaders;
- return MDBX_SUCCESS;
-}
-
-/* Further setup required for opening an MDBX environment */
-static int __cold mdbx_setup_dxb(MDBX_env *env, int lck_rc) {
- MDBX_meta meta;
- int rc = MDBX_RESULT_FALSE;
- int err = mdbx_read_header(env, &meta);
- if (unlikely(err != MDBX_SUCCESS)) {
- if (lck_rc != /* lck exclusive */ MDBX_RESULT_TRUE || err != MDBX_ENODATA ||
- (env->me_flags & MDBX_RDONLY) != 0)
- return err;
-
- mdbx_debug("create new database");
- rc = /* new database */ MDBX_RESULT_TRUE;
-
- if (!env->me_dbgeo.now) {
- /* set defaults if not configured */
- err = mdbx_env_set_mapsize(env, DEFAULT_MAPSIZE);
- if (unlikely(err != MDBX_SUCCESS))
- return err;
- }
-
- void *buffer = calloc(NUM_METAS, env->me_psize);
- if (!buffer)
- return MDBX_ENOMEM;
-
- meta = mdbx_init_metas(env, buffer)->mp_meta;
- err = mdbx_pwrite(env->me_fd, buffer, env->me_psize * NUM_METAS, 0);
- free(buffer);
- if (unlikely(err != MDBX_SUCCESS))
- return err;
-
- err = mdbx_ftruncate(env->me_fd, env->me_dbgeo.now);
- if (unlikely(err != MDBX_SUCCESS))
- return err;
-
-#ifndef NDEBUG /* just for checking */
- err = mdbx_read_header(env, &meta);
- if (unlikely(err != MDBX_SUCCESS))
- return err;
-#endif
- }
-
- mdbx_info("header: root %" PRIaPGNO "/%" PRIaPGNO ", geo %" PRIaPGNO
- "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO
- " +%u -%u, txn_id %" PRIaTXN ", %s",
- meta.mm_dbs[MAIN_DBI].md_root, meta.mm_dbs[FREE_DBI].md_root,
- meta.mm_geo.lower, meta.mm_geo.next, meta.mm_geo.now,
- meta.mm_geo.upper, meta.mm_geo.grow, meta.mm_geo.shrink,
- meta.mm_txnid_a, mdbx_durable_str(&meta));
-
- mdbx_setup_pagesize(env, meta.mm_psize);
- if ((env->me_flags & MDBX_RDONLY) /* readonly */
- || lck_rc != MDBX_RESULT_TRUE /* not exclusive */) {
- /* use present params from db */
- err = mdbx_env_set_geometry(
- env, meta.mm_geo.lower * (uint64_t)meta.mm_psize,
- meta.mm_geo.now * (uint64_t)meta.mm_psize,
- meta.mm_geo.upper * (uint64_t)meta.mm_psize,
- meta.mm_geo.grow * (uint64_t)meta.mm_psize,
- meta.mm_geo.shrink * (uint64_t)meta.mm_psize, meta.mm_psize);
- if (unlikely(err != MDBX_SUCCESS)) {
- mdbx_error("could not use present dbsize-params from db");
- return MDBX_INCOMPATIBLE;
- }
- } else if (env->me_dbgeo.now) {
- /* silently growth to last used page */
- const size_t used_bytes = pgno2bytes(env, meta.mm_geo.next);
- if (env->me_dbgeo.lower < used_bytes)
- env->me_dbgeo.lower = used_bytes;
- if (env->me_dbgeo.now < used_bytes)
- env->me_dbgeo.now = used_bytes;
- if (env->me_dbgeo.upper < used_bytes)
- env->me_dbgeo.upper = used_bytes;
-
- /* apply preconfigured params, but only if substantial changes:
- * - upper or lower limit changes
- * - shrink theshold or growth step
- * But ignore just chagne just a 'now/current' size. */
- if (bytes_align2os_bytes(env, env->me_dbgeo.upper) !=
- pgno_align2os_bytes(env, meta.mm_geo.upper) ||
- bytes_align2os_bytes(env, env->me_dbgeo.lower) !=
- pgno_align2os_bytes(env, meta.mm_geo.lower) ||
- bytes_align2os_bytes(env, env->me_dbgeo.shrink) !=
- pgno_align2os_bytes(env, meta.mm_geo.shrink) ||
- bytes_align2os_bytes(env, env->me_dbgeo.grow) !=
- pgno_align2os_bytes(env, meta.mm_geo.grow)) {
-
- if (env->me_dbgeo.shrink && env->me_dbgeo.now > used_bytes)
- /* pre-shrink if enabled */
- env->me_dbgeo.now = used_bytes + env->me_dbgeo.shrink -
- used_bytes % env->me_dbgeo.shrink;
-
- err = mdbx_env_set_geometry(env, env->me_dbgeo.lower, env->me_dbgeo.now,
- env->me_dbgeo.upper, env->me_dbgeo.grow,
- env->me_dbgeo.shrink, meta.mm_psize);
- if (unlikely(err != MDBX_SUCCESS)) {
- mdbx_error("could not apply preconfigured dbsize-params to db");
- return MDBX_INCOMPATIBLE;
- }
-
- /* update meta fields */
- meta.mm_geo.now = bytes2pgno(env, env->me_dbgeo.now);
- meta.mm_geo.lower = bytes2pgno(env, env->me_dbgeo.lower);
- meta.mm_geo.upper = bytes2pgno(env, env->me_dbgeo.upper);
- meta.mm_geo.grow = (uint16_t)bytes2pgno(env, env->me_dbgeo.grow);
- meta.mm_geo.shrink = (uint16_t)bytes2pgno(env, env->me_dbgeo.shrink);
-
- mdbx_info("amended: root %" PRIaPGNO "/%" PRIaPGNO ", geo %" PRIaPGNO
- "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO
- " +%u -%u, txn_id %" PRIaTXN ", %s",
- meta.mm_dbs[MAIN_DBI].md_root, meta.mm_dbs[FREE_DBI].md_root,
- meta.mm_geo.lower, meta.mm_geo.next, meta.mm_geo.now,
- meta.mm_geo.upper, meta.mm_geo.grow, meta.mm_geo.shrink,
- meta.mm_txnid_a, mdbx_durable_str(&meta));
- }
- mdbx_ensure(env, meta.mm_geo.now >= meta.mm_geo.next);
- } else {
- /* geo-params not pre-configured by user,
- * get current values from a meta. */
- env->me_dbgeo.now = pgno2bytes(env, meta.mm_geo.now);
- env->me_dbgeo.lower = pgno2bytes(env, meta.mm_geo.lower);
- env->me_dbgeo.upper = pgno2bytes(env, meta.mm_geo.upper);
- env->me_dbgeo.grow = pgno2bytes(env, meta.mm_geo.grow);
- env->me_dbgeo.shrink = pgno2bytes(env, meta.mm_geo.shrink);
- }
-
- uint64_t filesize_before_mmap;
- err = mdbx_filesize(env->me_fd, &filesize_before_mmap);
- if (unlikely(err != MDBX_SUCCESS))
- return err;
-
- const size_t expected_bytes =
- mdbx_roundup2(pgno2bytes(env, meta.mm_geo.now), env->me_os_psize);
- const size_t used_bytes = pgno2bytes(env, meta.mm_geo.next);
- mdbx_ensure(env, expected_bytes >= used_bytes);
- if (filesize_before_mmap != expected_bytes) {
- if (lck_rc != /* lck exclusive */ MDBX_RESULT_TRUE) {
- mdbx_info("filesize mismatch (expect %" PRIuPTR "/%" PRIaPGNO
- ", have %" PRIu64 "/%" PRIaPGNO "), "
- "assume collision in non-exclusive mode",
- expected_bytes, bytes2pgno(env, expected_bytes),
- filesize_before_mmap,
- bytes2pgno(env, (size_t)filesize_before_mmap));
- } else {
- mdbx_notice("filesize mismatch (expect %" PRIuPTR "/%" PRIaPGNO
- ", have %" PRIu64 "/%" PRIaPGNO ")",
- expected_bytes, bytes2pgno(env, expected_bytes),
- filesize_before_mmap,
- bytes2pgno(env, (size_t)filesize_before_mmap));
- if (filesize_before_mmap < used_bytes) {
- mdbx_error("last-page beyond end-of-file (last %" PRIaPGNO
- ", have %" PRIaPGNO ")",
- meta.mm_geo.next,
- bytes2pgno(env, (size_t)filesize_before_mmap));
- return MDBX_CORRUPTED;
- }
-
- if (env->me_flags & MDBX_RDONLY) {
- mdbx_notice("ignore filesize mismatch in readonly-mode");
- } else {
- mdbx_info("resize datafile to %" PRIu64 " bytes, %" PRIaPGNO " pages",
- expected_bytes, bytes2pgno(env, expected_bytes));
- err = mdbx_ftruncate(env->me_fd, expected_bytes);
- if (unlikely(err != MDBX_SUCCESS)) {
- mdbx_error("error %d, while resize datafile to %" PRIu64
- " bytes, %" PRIaPGNO " pages",
- rc, expected_bytes, bytes2pgno(env, expected_bytes));
- return err;
- }
- filesize_before_mmap = expected_bytes;
- }
- }
- }
-
- err = mdbx_env_map(env, (lck_rc != /* lck exclusive */ MDBX_RESULT_TRUE)
- ? 0
- : expected_bytes);
- if (err != MDBX_SUCCESS)
- return err;
-
- const unsigned meta_clash_mask = mdbx_meta_eq_mask(env);
- if (meta_clash_mask) {
- mdbx_error("meta-pages are clashed: mask 0x%d", meta_clash_mask);
- return MDBX_WANNA_RECOVERY;
- }
-
- while (1) {
- MDBX_meta *head = mdbx_meta_head(env);
- const txnid_t head_txnid = mdbx_meta_txnid_fluid(env, head);
- if (head_txnid == meta.mm_txnid_a)
- break;
-
- if (lck_rc == /* lck exclusive */ MDBX_RESULT_TRUE) {
- assert(META_IS_STEADY(&meta) && !META_IS_STEADY(head));
- if (env->me_flags & MDBX_RDONLY) {
- mdbx_error("rollback needed: (from head %" PRIaTXN
- " to steady %" PRIaTXN "), but unable in read-only mode",
- head_txnid, meta.mm_txnid_a);
- return MDBX_WANNA_RECOVERY /* LY: could not recovery/rollback */;
- }
-
- /* LY: rollback weak checkpoint */
- mdbx_trace("rollback: from %" PRIaTXN ", to %" PRIaTXN, head_txnid,
- meta.mm_txnid_a);
- mdbx_ensure(env, head_txnid == mdbx_meta_txnid_stable(env, head));
-
- if (env->me_flags & MDBX_WRITEMAP) {
- head->mm_txnid_a = 0;
- head->mm_datasync_sign = MDBX_DATASIGN_WEAK;
- head->mm_txnid_b = 0;
- const size_t offset =
- ((uint8_t *)container_of(head, MDBX_page, mp_meta)) -
- env->me_dxb_mmap.dxb;
- const size_t paged_offset = offset & ~(env->me_os_psize - 1);
- const size_t paged_length = mdbx_roundup2(
- env->me_psize + offset - paged_offset, env->me_os_psize);
- err = mdbx_msync(&env->me_dxb_mmap, paged_offset, paged_length, false);
- } else {
- MDBX_meta rollback = *head;
- mdbx_meta_set_txnid(env, &rollback, 0);
- rollback.mm_datasync_sign = MDBX_DATASIGN_WEAK;
- err = mdbx_pwrite(env->me_fd, &rollback, sizeof(MDBX_meta),
- (uint8_t *)head - (uint8_t *)env->me_map);
- }
- if (err)
- return err;
-
- mdbx_invalidate_cache(env->me_map, pgno2bytes(env, NUM_METAS));
- mdbx_ensure(env, 0 == mdbx_meta_txnid_fluid(env, head));
- mdbx_ensure(env, 0 == mdbx_meta_eq_mask(env));
- continue;
- }
-
- if (!env->me_lck) {
- /* LY: without-lck (read-only) mode, so it is imposible that other
- * process made weak checkpoint. */
- mdbx_error("without-lck, unable recovery/rollback");
- return MDBX_WANNA_RECOVERY;
- }
-
- /* LY: assume just have a collision with other running process,
- * or someone make a weak checkpoint */
- mdbx_info("assume collision or online weak checkpoint");
- break;
- }
-
- const MDBX_meta *head = mdbx_meta_head(env);
- if (lck_rc == /* lck exclusive */ MDBX_RESULT_TRUE) {
- /* re-check file size after mmap */
- uint64_t filesize_after_mmap;
- err = mdbx_filesize(env->me_fd, &filesize_after_mmap);
- if (unlikely(err != MDBX_SUCCESS))
- return err;
- if (filesize_after_mmap != expected_bytes) {
- if (filesize_after_mmap != filesize_before_mmap)
- mdbx_info("datafile resized by system to %" PRIu64 " bytes",
- filesize_after_mmap);
- if (filesize_after_mmap % env->me_os_psize ||
- filesize_after_mmap > env->me_dbgeo.upper ||
- filesize_after_mmap < used_bytes) {
- mdbx_info("unacceptable/unexpected datafile size %" PRIu64,
- filesize_after_mmap);
- return MDBX_PROBLEM;
- }
- if ((env->me_flags & MDBX_RDONLY) == 0) {
- meta.mm_geo.now =
- bytes2pgno(env, env->me_dbgeo.now = (size_t)filesize_after_mmap);
- mdbx_info("update meta-geo to filesize %" PRIuPTR " bytes, %" PRIaPGNO
- " pages",
- env->me_dbgeo.now, meta.mm_geo.now);
- }
- }
-
- if (memcmp(&meta.mm_geo, &head->mm_geo, sizeof(meta.mm_geo))) {
- const txnid_t txnid = mdbx_meta_txnid_stable(env, head);
- mdbx_info("updating meta.geo: "
- "from l%" PRIaPGNO "-n%" PRIaPGNO "-u%" PRIaPGNO
- "/s%u-g%u (txn#%" PRIaTXN "), "
- "to l%" PRIaPGNO "-n%" PRIaPGNO "-u%" PRIaPGNO
- "/s%u-g%u (txn#%" PRIaTXN ")",
- head->mm_geo.lower, head->mm_geo.now, head->mm_geo.upper,
- head->mm_geo.shrink, head->mm_geo.grow, txnid,
- meta.mm_geo.lower, meta.mm_geo.now, meta.mm_geo.upper,
- meta.mm_geo.shrink, meta.mm_geo.grow, txnid + 1);
-
- mdbx_ensure(env, mdbx_meta_eq(env, &meta, head));
- mdbx_meta_set_txnid(env, &meta, txnid + 1);
- env->me_sync_pending += env->me_psize;
- err = mdbx_sync_locked(env, env->me_flags | MDBX_SHRINK_ALLOWED, &meta);
- if (err) {
- mdbx_info("error %d, while updating meta.geo: "
- "from l%" PRIaPGNO "-n%" PRIaPGNO "-u%" PRIaPGNO
- "/s%u-g%u (txn#%" PRIaTXN "), "
- "to l%" PRIaPGNO "-n%" PRIaPGNO "-u%" PRIaPGNO
- "/s%u-g%u (txn#%" PRIaTXN ")",
- err, head->mm_geo.lower, head->mm_geo.now, head->mm_geo.upper,
- head->mm_geo.shrink, head->mm_geo.grow, txnid,
- meta.mm_geo.lower, meta.mm_geo.now, meta.mm_geo.upper,
- meta.mm_geo.shrink, meta.mm_geo.grow, txnid + 1);
- return err;
- }
- }
- }
-
- return rc;
-}
-
-/****************************************************************************/
-
-/* Open and/or initialize the lock region for the environment. */
-static int __cold mdbx_setup_lck(MDBX_env *env, char *lck_pathname,
- mode_t mode) {
- assert(env->me_fd != INVALID_HANDLE_VALUE);
- assert(env->me_lfd == INVALID_HANDLE_VALUE);
-
- int err = mdbx_openfile(lck_pathname, O_RDWR | O_CREAT, mode, &env->me_lfd);
- if (err != MDBX_SUCCESS) {
- if (err != MDBX_EROFS || (env->me_flags & MDBX_RDONLY) == 0)
- return err;
- /* LY: without-lck mode (e.g. on read-only filesystem) */
- env->me_lfd = INVALID_HANDLE_VALUE;
- env->me_oldest = &env->me_oldest_stub;
- env->me_maxreaders = UINT_MAX;
- mdbx_debug("lck-setup: %s ", "lockless mode (readonly)");
- return MDBX_SUCCESS;
- }
-
- /* Try to get exclusive lock. If we succeed, then
- * nobody is using the lock region and we should initialize it. */
- const int rc = mdbx_lck_seize(env);
- if (MDBX_IS_ERROR(rc))
- return rc;
-
- mdbx_debug("lck-setup: %s ",
- (rc == MDBX_RESULT_TRUE) ? "exclusive" : "shared");
-
- uint64_t size;
- err = mdbx_filesize(env->me_lfd, &size);
- if (unlikely(err != MDBX_SUCCESS))
- return err;
-
- if (rc == MDBX_RESULT_TRUE) {
- uint64_t wanna = mdbx_roundup2(
- (env->me_maxreaders - 1) * sizeof(MDBX_reader) + sizeof(MDBX_lockinfo),
- env->me_os_psize);
-#ifndef NDEBUG
- err = mdbx_ftruncate(env->me_lfd, size = 0);
- if (unlikely(err != MDBX_SUCCESS))
- return err;
-#endif
- mdbx_jitter4testing(false);
-
- if (size != wanna) {
- err = mdbx_ftruncate(env->me_lfd, wanna);
- if (unlikely(err != MDBX_SUCCESS))
- return err;
- size = wanna;
- }
- } else if (size > SSIZE_MAX || (size & (env->me_os_psize - 1)) ||
- size < env->me_os_psize) {
- mdbx_notice("lck-file has invalid size %" PRIu64 " bytes", size);
- return MDBX_PROBLEM;
- }
-
- const size_t maxreaders =
- ((size_t)size - sizeof(MDBX_lockinfo)) / sizeof(MDBX_reader) + 1;
- if (maxreaders > UINT16_MAX) {
- mdbx_error("lck-size too big (up to %" PRIuPTR " readers)", maxreaders);
- return MDBX_PROBLEM;
- }
- env->me_maxreaders = (unsigned)maxreaders;
-
- err = mdbx_mmap(MDBX_WRITEMAP, &env->me_lck_mmap, (size_t)size, (size_t)size);
- if (unlikely(err != MDBX_SUCCESS))
- return err;
-
-#ifdef MADV_DODUMP
- (void)madvise(env->me_lck, size, MADV_DODUMP);
-#endif
-
-#ifdef MADV_DONTFORK
- if (madvise(env->me_lck, size, MADV_DONTFORK) < 0)
- return errno;
-#endif
-
-#ifdef MADV_WILLNEED
- if (madvise(env->me_lck, size, MADV_WILLNEED) < 0)
- return errno;
-#endif
-
-#ifdef MADV_RANDOM
- if (madvise(env->me_lck, size, MADV_RANDOM) < 0)
- return errno;
-#endif
-
- if (rc == MDBX_RESULT_TRUE) {
- /* LY: exlcusive mode, init lck */
- memset(env->me_lck, 0, (size_t)size);
- err = mdbx_lck_init(env);
- if (err)
- return err;
-
- env->me_lck->mti_magic_and_version = MDBX_LOCK_MAGIC;
- env->me_lck->mti_os_and_format = MDBX_LOCK_FORMAT;
- } else {
- if (env->me_lck->mti_magic_and_version != MDBX_LOCK_MAGIC) {
- mdbx_error("lock region has invalid magic/version");
- return ((env->me_lck->mti_magic_and_version >> 8) != MDBX_MAGIC)
- ? MDBX_INVALID
- : MDBX_VERSION_MISMATCH;
- }
- if (env->me_lck->mti_os_and_format != MDBX_LOCK_FORMAT) {
- mdbx_error("lock region has os/format 0x%" PRIx32 ", expected 0x%" PRIx32,
- env->me_lck->mti_os_and_format, MDBX_LOCK_FORMAT);
- return MDBX_VERSION_MISMATCH;
- }
- }
-
- mdbx_assert(env, !MDBX_IS_ERROR(rc));
- env->me_oldest = &env->me_lck->mti_oldest;
- return rc;
-}
-
-/* Only a subset of the mdbx_env flags can be changed
- * at runtime. Changing other flags requires closing the
- * environment and re-opening it with the new flags. */
-#define CHANGEABLE \
- (MDBX_NOSYNC | MDBX_NOMETASYNC | MDBX_MAPASYNC | MDBX_NOMEMINIT | \
- MDBX_COALESCE | MDBX_PAGEPERTURB)
-#define CHANGELESS \
- (MDBX_NOSUBDIR | MDBX_RDONLY | MDBX_WRITEMAP | MDBX_NOTLS | MDBX_NORDAHEAD | \
- MDBX_LIFORECLAIM)
-
-#if VALID_FLAGS & PERSISTENT_FLAGS & (CHANGEABLE | CHANGELESS)
-#error "Persistent DB flags & env flags overlap, but both go in mm_flags"
-#endif
-
-int __cold mdbx_env_open_ex(MDBX_env *env, const char *path, unsigned flags,
- mode_t mode, int *exclusive) {
- if (unlikely(!env || !path))
- return MDBX_EINVAL;
-
- if (unlikely(env->me_signature != MDBX_ME_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (env->me_fd != INVALID_HANDLE_VALUE ||
- (flags & ~(CHANGEABLE | CHANGELESS)))
- return MDBX_EINVAL;
-
- size_t len_full, len = strlen(path);
- if (flags & MDBX_NOSUBDIR) {
- len_full = len + sizeof(MDBX_LOCK_SUFFIX) + len + 1;
- } else {
- len_full = len + sizeof(MDBX_LOCKNAME) + len + sizeof(MDBX_DATANAME);
- }
- char *lck_pathname = malloc(len_full);
- if (!lck_pathname)
- return MDBX_ENOMEM;
-
- char *dxb_pathname;
- if (flags & MDBX_NOSUBDIR) {
- dxb_pathname = lck_pathname + len + sizeof(MDBX_LOCK_SUFFIX);
- sprintf(lck_pathname, "%s" MDBX_LOCK_SUFFIX, path);
- strcpy(dxb_pathname, path);
- } else {
- dxb_pathname = lck_pathname + len + sizeof(MDBX_LOCKNAME);
- sprintf(lck_pathname, "%s" MDBX_LOCKNAME, path);
- sprintf(dxb_pathname, "%s" MDBX_DATANAME, path);
- }
-
- int rc = MDBX_SUCCESS;
- flags |= env->me_flags;
- if (flags & MDBX_RDONLY) {
- /* LY: silently ignore irrelevant flags when
- * we're only getting read access */
- flags &= ~(MDBX_WRITEMAP | MDBX_MAPASYNC | MDBX_NOSYNC | MDBX_NOMETASYNC |
- MDBX_COALESCE | MDBX_LIFORECLAIM | MDBX_NOMEMINIT);
- } else {
- if (!((env->me_free_pgs = mdbx_pnl_alloc(MDBX_PNL_UM_MAX)) &&
- (env->me_dirtylist = calloc(MDBX_PNL_UM_SIZE, sizeof(MDBX_ID2)))))
- rc = MDBX_ENOMEM;
- }
- env->me_flags = flags |= MDBX_ENV_ACTIVE;
- if (rc)
- goto bailout;
-
- env->me_path = mdbx_strdup(path);
- env->me_dbxs = calloc(env->me_maxdbs, sizeof(MDBX_dbx));
- env->me_dbflags = calloc(env->me_maxdbs, sizeof(uint16_t));
- env->me_dbiseqs = calloc(env->me_maxdbs, sizeof(unsigned));
- if (!(env->me_dbxs && env->me_path && env->me_dbflags && env->me_dbiseqs)) {
- rc = MDBX_ENOMEM;
- goto bailout;
- }
- env->me_dbxs[FREE_DBI].md_cmp = mdbx_cmp_int_ai; /* aligned MDBX_INTEGERKEY */
-
- int oflags;
- if (F_ISSET(flags, MDBX_RDONLY))
- oflags = O_RDONLY;
- else
- oflags = O_RDWR | O_CREAT;
-
- rc = mdbx_openfile(dxb_pathname, oflags, mode, &env->me_fd);
- if (rc != MDBX_SUCCESS)
- goto bailout;
-
- const int lck_rc = mdbx_setup_lck(env, lck_pathname, mode);
- if (MDBX_IS_ERROR(lck_rc)) {
- rc = lck_rc;
- goto bailout;
- }
-
- const int dxb_rc = mdbx_setup_dxb(env, lck_rc);
- if (MDBX_IS_ERROR(dxb_rc)) {
- rc = dxb_rc;
- goto bailout;
- }
-
- mdbx_debug("opened dbenv %p", (void *)env);
- const unsigned mode_flags =
- MDBX_WRITEMAP | MDBX_NOSYNC | MDBX_NOMETASYNC | MDBX_MAPASYNC;
- if (lck_rc == MDBX_RESULT_TRUE) {
- env->me_lck->mti_envmode = env->me_flags & (mode_flags | MDBX_RDONLY);
- if (exclusive == NULL || *exclusive < 2) {
- /* LY: downgrade lock only if exclusive access not requested.
- * in case exclusive==1, just leave value as is. */
- rc = mdbx_lck_downgrade(env, true);
- mdbx_debug("lck-downgrade-full: rc %i ", rc);
- } else {
- rc = mdbx_lck_downgrade(env, false);
- mdbx_debug("lck-downgrade-partial: rc %i ", rc);
- }
- if (rc != MDBX_SUCCESS)
- goto bailout;
- } else {
- if (exclusive) {
- /* LY: just indicate that is not an exclusive access. */
- *exclusive = 0;
- }
- if ((env->me_flags & MDBX_RDONLY) == 0) {
- while (env->me_lck->mti_envmode == MDBX_RDONLY) {
- if (mdbx_atomic_compare_and_swap32(&env->me_lck->mti_envmode,
- MDBX_RDONLY,
- env->me_flags & mode_flags))
- break;
- /* TODO: yield/relax cpu */
- }
- if ((env->me_lck->mti_envmode ^ env->me_flags) & mode_flags) {
- mdbx_error("current mode/flags incompatible with requested");
- rc = MDBX_INCOMPATIBLE;
- goto bailout;
- }
- }
- }
-
- if (env->me_lck && (env->me_flags & MDBX_NOTLS) == 0) {
- rc = mdbx_rthc_alloc(&env->me_txkey, &env->me_lck->mti_readers[0],
- &env->me_lck->mti_readers[env->me_maxreaders]);
- if (unlikely(rc != MDBX_SUCCESS))
- goto bailout;
- env->me_flags |= MDBX_ENV_TXKEY;
- }
-
- if ((flags & MDBX_RDONLY) == 0) {
- MDBX_txn *txn;
- int tsize = sizeof(MDBX_txn),
- size = tsize +
- env->me_maxdbs * (sizeof(MDBX_db) + sizeof(MDBX_cursor *) +
- sizeof(unsigned) + 1);
- if ((env->me_pbuf = calloc(1, env->me_psize)) && (txn = calloc(1, size))) {
- txn->mt_dbs = (MDBX_db *)((char *)txn + tsize);
- txn->mt_cursors = (MDBX_cursor **)(txn->mt_dbs + env->me_maxdbs);
- txn->mt_dbiseqs = (unsigned *)(txn->mt_cursors + env->me_maxdbs);
- txn->mt_dbflags = (uint8_t *)(txn->mt_dbiseqs + env->me_maxdbs);
- txn->mt_env = env;
- txn->mt_dbxs = env->me_dbxs;
- txn->mt_flags = MDBX_TXN_FINISHED;
- env->me_txn0 = txn;
- } else {
- rc = MDBX_ENOMEM;
- }
- }
-
-#if MDBX_DEBUG
- if (rc == MDBX_SUCCESS) {
- MDBX_meta *meta = mdbx_meta_head(env);
- MDBX_db *db = &meta->mm_dbs[MAIN_DBI];
-
- mdbx_debug("opened database version %u, pagesize %u",
- (uint8_t)meta->mm_magic_and_version, env->me_psize);
- mdbx_debug("using meta page %" PRIaPGNO ", txn %" PRIaTXN "",
- container_of(meta, MDBX_page, mp_data)->mp_pgno,
- mdbx_meta_txnid_fluid(env, meta));
- mdbx_debug("depth: %u", db->md_depth);
- mdbx_debug("entries: %" PRIu64 "", db->md_entries);
- mdbx_debug("branch pages: %" PRIaPGNO "", db->md_branch_pages);
- mdbx_debug("leaf pages: %" PRIaPGNO "", db->md_leaf_pages);
- mdbx_debug("overflow pages: %" PRIaPGNO "", db->md_overflow_pages);
- mdbx_debug("root: %" PRIaPGNO "", db->md_root);
- }
-#endif
-
-bailout:
- if (rc)
- mdbx_env_close0(env);
- free(lck_pathname);
- return rc;
-}
-
-int __cold mdbx_env_open(MDBX_env *env, const char *path, unsigned flags,
- mode_t mode) {
- return mdbx_env_open_ex(env, path, flags, mode, NULL);
-}
-
-/* Destroy resources from mdbx_env_open(), clear our readers & DBIs */
-static void __cold mdbx_env_close0(MDBX_env *env) {
- if (!(env->me_flags & MDBX_ENV_ACTIVE))
- return;
- env->me_flags &= ~MDBX_ENV_ACTIVE;
-
- /* Doing this here since me_dbxs may not exist during mdbx_env_close */
- if (env->me_dbxs) {
- for (unsigned i = env->me_maxdbs; --i >= CORE_DBS;)
- free(env->me_dbxs[i].md_name.iov_base);
- free(env->me_dbxs);
- }
-
- free(env->me_pbuf);
- free(env->me_dbiseqs);
- free(env->me_dbflags);
- free(env->me_path);
- free(env->me_dirtylist);
- if (env->me_txn0) {
- mdbx_txl_free(env->me_txn0->mt_lifo_reclaimed);
- free(env->me_txn0);
- }
- mdbx_pnl_free(env->me_free_pgs);
-
- if (env->me_flags & MDBX_ENV_TXKEY) {
- mdbx_rthc_remove(env->me_txkey);
- env->me_flags &= ~MDBX_ENV_TXKEY;
- }
-
- if (env->me_map) {
- mdbx_munmap(&env->me_dxb_mmap);
-#ifdef USE_VALGRIND
- VALGRIND_DISCARD(env->me_valgrind_handle);
- env->me_valgrind_handle = -1;
-#endif
- }
- if (env->me_fd != INVALID_HANDLE_VALUE) {
- (void)mdbx_closefile(env->me_fd);
- env->me_fd = INVALID_HANDLE_VALUE;
- }
-
- if (env->me_lck)
- mdbx_munmap(&env->me_lck_mmap);
- env->me_pid = 0;
- env->me_oldest = nullptr;
-
- mdbx_lck_destroy(env);
- if (env->me_lfd != INVALID_HANDLE_VALUE) {
- (void)mdbx_closefile(env->me_lfd);
- env->me_lfd = INVALID_HANDLE_VALUE;
- }
-}
-
-int __cold mdbx_env_close_ex(MDBX_env *env, int dont_sync) {
- MDBX_page *dp;
- int rc = MDBX_SUCCESS;
-
- if (unlikely(!env))
- return MDBX_EINVAL;
- if (unlikely(env->me_signature != MDBX_ME_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (!dont_sync && !(env->me_flags & MDBX_RDONLY))
- rc = mdbx_env_sync(env, true);
-
- VALGRIND_DESTROY_MEMPOOL(env);
- while ((dp = env->me_dpages) != NULL) {
- ASAN_UNPOISON_MEMORY_REGION(&dp->mp_next, sizeof(dp->mp_next));
- VALGRIND_MAKE_MEM_DEFINED(&dp->mp_next, sizeof(dp->mp_next));
- env->me_dpages = dp->mp_next;
- free(dp);
- }
-
- mdbx_env_close0(env);
- mdbx_ensure(env, mdbx_fastmutex_destroy(&env->me_dbi_lock) == MDBX_SUCCESS);
- env->me_signature = 0;
- free(env);
-
- return rc;
-}
-
-void __cold mdbx_env_close(MDBX_env *env) { mdbx_env_close_ex(env, 0); }
-
-/* Compare two items pointing at aligned unsigned int's. */
-static int __hot mdbx_cmp_int_ai(const MDBX_val *a, const MDBX_val *b) {
- mdbx_assert(NULL, a->iov_len == b->iov_len);
- mdbx_assert(NULL, 0 == (uintptr_t)a->iov_base % sizeof(int) &&
- 0 == (uintptr_t)b->iov_base % sizeof(int));
- switch (a->iov_len) {
- case 4:
- return mdbx_cmp2int(*(uint32_t *)a->iov_base, *(uint32_t *)b->iov_base);
- case 8:
- return mdbx_cmp2int(*(uint64_t *)a->iov_base, *(uint64_t *)b->iov_base);
- default:
- mdbx_assert_fail(NULL, "invalid size for INTEGERKEY/INTEGERDUP", mdbx_func_,
- __LINE__);
- return 0;
- }
-}
-
-/* Compare two items pointing at 2-byte aligned unsigned int's. */
-static int __hot mdbx_cmp_int_a2(const MDBX_val *a, const MDBX_val *b) {
- mdbx_assert(NULL, a->iov_len == b->iov_len);
- mdbx_assert(NULL, 0 == (uintptr_t)a->iov_base % sizeof(uint16_t) &&
- 0 == (uintptr_t)b->iov_base % sizeof(uint16_t));
-#if UNALIGNED_OK
- switch (a->iov_len) {
- case 4:
- return mdbx_cmp2int(*(uint32_t *)a->iov_base, *(uint32_t *)b->iov_base);
- case 8:
- return mdbx_cmp2int(*(uint64_t *)a->iov_base, *(uint64_t *)b->iov_base);
- default:
- mdbx_assert_fail(NULL, "invalid size for INTEGERKEY/INTEGERDUP", mdbx_func_,
- __LINE__);
- return 0;
- }
-#else
- mdbx_assert(NULL, 0 == a->iov_len % sizeof(uint16_t));
- {
- int diff;
- const uint16_t *pa, *pb, *end;
-
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- end = (const uint16_t *)a->iov_base;
- pa = (const uint16_t *)((char *)a->iov_base + a->iov_len);
- pb = (const uint16_t *)((char *)b->iov_base + a->iov_len);
- do {
- diff = *--pa - *--pb;
-#else /* __BYTE_ORDER__ */
- end = (const uint16_t *)((char *)a->iov_base + a->iov_len);
- pa = (const uint16_t *)a->iov_base;
- pb = (const uint16_t *)b->iov_base;
- do {
- diff = *pa++ - *pb++;
-#endif /* __BYTE_ORDER__ */
- if (likely(diff != 0))
- break;
- } while (pa != end);
- return diff;
- }
-#endif /* UNALIGNED_OK */
-}
-
-/* Compare two items pointing at unsigneds of unknown alignment.
- *
- * This is also set as MDBX_INTEGERDUP|MDBX_DUPFIXED's MDBX_dbx.md_dcmp. */
-static int __hot mdbx_cmp_int_ua(const MDBX_val *a, const MDBX_val *b) {
- mdbx_assert(NULL, a->iov_len == b->iov_len);
-#if UNALIGNED_OK
- switch (a->iov_len) {
- case 4:
- return mdbx_cmp2int(*(uint32_t *)a->iov_base, *(uint32_t *)b->iov_base);
- case 8:
- return mdbx_cmp2int(*(uint64_t *)a->iov_base, *(uint64_t *)b->iov_base);
- default:
- mdbx_assert_fail(NULL, "invalid size for INTEGERKEY/INTEGERDUP", mdbx_func_,
- __LINE__);
- return 0;
- }
-#else
- mdbx_assert(NULL, a->iov_len == sizeof(int) || a->iov_len == sizeof(size_t));
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- {
- int diff;
- const uint8_t *pa, *pb;
-
- pa = (const uint8_t *)a->iov_base + a->iov_len;
- pb = (const uint8_t *)b->iov_base + a->iov_len;
-
- do {
- diff = *--pa - *--pb;
- if (likely(diff != 0))
- break;
- } while (pa != a->iov_base);
- return diff;
- }
-#else /* __BYTE_ORDER__ */
- return memcmp(a->iov_base, b->iov_base, a->iov_len);
-#endif /* __BYTE_ORDER__ */
-#endif /* UNALIGNED_OK */
-}
-
-/* Compare two items lexically */
-static int __hot mdbx_cmp_memn(const MDBX_val *a, const MDBX_val *b) {
-/* LY: assumes that length of keys are NOT equal for most cases,
- * if no then branch-prediction should mitigate the problem */
-#if 0
- /* LY: without branch instructions on x86,
- * but isn't best for equal length of keys */
- int diff_len = mdbx_cmp2int(a->iov_len, b->iov_len);
-#else
- /* LY: best when length of keys are equal,
- * but got a branch-penalty otherwise */
- if (likely(a->iov_len == b->iov_len))
- return memcmp(a->iov_base, b->iov_base, a->iov_len);
- int diff_len = (a->iov_len < b->iov_len) ? -1 : 1;
-#endif
- size_t shortest = (a->iov_len < b->iov_len) ? a->iov_len : b->iov_len;
- int diff_data = memcmp(a->iov_base, b->iov_base, shortest);
- return likely(diff_data) ? diff_data : diff_len;
-}
-
-/* Compare two items in reverse byte order */
-static int __hot mdbx_cmp_memnr(const MDBX_val *a, const MDBX_val *b) {
- const uint8_t *pa, *pb, *end;
-
- pa = (const uint8_t *)a->iov_base + a->iov_len;
- pb = (const uint8_t *)b->iov_base + b->iov_len;
- size_t minlen = (a->iov_len < b->iov_len) ? a->iov_len : b->iov_len;
- end = pa - minlen;
-
- while (pa != end) {
- int diff = *--pa - *--pb;
- if (likely(diff))
- return diff;
- }
- return mdbx_cmp2int(a->iov_len, b->iov_len);
-}
-
-/* Search for key within a page, using binary search.
- * Returns the smallest entry larger or equal to the key.
- * If exactp is non-null, stores whether the found entry was an exact match
- * in *exactp (1 or 0).
- * Updates the cursor index with the index of the found entry.
- * If no entry larger or equal to the key is found, returns NULL. */
-static MDBX_node *__hot mdbx_node_search(MDBX_cursor *mc, MDBX_val *key,
- int *exactp) {
- unsigned i = 0, nkeys;
- int low, high;
- int rc = 0;
- MDBX_page *mp = mc->mc_pg[mc->mc_top];
- MDBX_node *node = NULL;
- MDBX_val nodekey;
- MDBX_cmp_func *cmp;
- DKBUF;
-
- nkeys = NUMKEYS(mp);
-
- mdbx_debug("searching %u keys in %s %spage %" PRIaPGNO "", nkeys,
- IS_LEAF(mp) ? "leaf" : "branch", IS_SUBP(mp) ? "sub-" : "",
- mp->mp_pgno);
-
- low = IS_LEAF(mp) ? 0 : 1;
- high = nkeys - 1;
- cmp = mc->mc_dbx->md_cmp;
-
- /* Branch pages have no data, so if using integer keys,
- * alignment is guaranteed. Use faster mdbx_cmp_int_ai.
- */
- if (cmp == mdbx_cmp_int_a2 && IS_BRANCH(mp))
- cmp = mdbx_cmp_int_ai;
-
- if (IS_LEAF2(mp)) {
- nodekey.iov_len = mc->mc_db->md_xsize;
- node = NODEPTR(mp, 0); /* fake */
- while (low <= high) {
- i = (low + high) >> 1;
- nodekey.iov_base = LEAF2KEY(mp, i, nodekey.iov_len);
- rc = cmp(key, &nodekey);
- mdbx_debug("found leaf index %u [%s], rc = %i", i, DKEY(&nodekey), rc);
- if (rc == 0)
- break;
- if (rc > 0)
- low = i + 1;
- else
- high = i - 1;
- }
- } else {
- while (low <= high) {
- i = (low + high) >> 1;
-
- node = NODEPTR(mp, i);
- nodekey.iov_len = NODEKSZ(node);
- nodekey.iov_base = NODEKEY(node);
-
- rc = cmp(key, &nodekey);
- if (IS_LEAF(mp))
- mdbx_debug("found leaf index %u [%s], rc = %i", i, DKEY(&nodekey), rc);
- else
- mdbx_debug("found branch index %u [%s -> %" PRIaPGNO "], rc = %i", i,
- DKEY(&nodekey), NODEPGNO(node), rc);
- if (rc == 0)
- break;
- if (rc > 0)
- low = i + 1;
- else
- high = i - 1;
- }
- }
-
- if (rc > 0) /* Found entry is less than the key. */
- i++; /* Skip to get the smallest entry larger than key. */
-
- if (exactp)
- *exactp = (rc == 0 && nkeys > 0);
- /* store the key index */
- mdbx_cassert(mc, i <= UINT16_MAX);
- mc->mc_ki[mc->mc_top] = (indx_t)i;
- if (i >= nkeys)
- /* There is no entry larger or equal to the key. */
- return NULL;
-
- /* nodeptr is fake for LEAF2 */
- return IS_LEAF2(mp) ? node : NODEPTR(mp, i);
-}
-
-#if 0 /* unused for now */
-static void mdbx_cursor_adjust(MDBX_cursor *mc, func) {
- MDBX_cursor *m2;
-
- for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2 = m2->mc_next) {
- if (m2->mc_pg[m2->mc_top] == mc->mc_pg[mc->mc_top]) {
- func(mc, m2);
- }
- }
-}
-#endif
-
-/* Pop a page off the top of the cursor's stack. */
-static void mdbx_cursor_pop(MDBX_cursor *mc) {
- if (mc->mc_snum) {
- mdbx_debug("popped page %" PRIaPGNO " off db %d cursor %p",
- mc->mc_pg[mc->mc_top]->mp_pgno, DDBI(mc), (void *)mc);
-
- mc->mc_snum--;
- if (mc->mc_snum) {
- mc->mc_top--;
- } else {
- mc->mc_flags &= ~C_INITIALIZED;
- }
- }
-}
-
-/* Push a page onto the top of the cursor's stack.
- * Set MDBX_TXN_ERROR on failure. */
-static int mdbx_cursor_push(MDBX_cursor *mc, MDBX_page *mp) {
- mdbx_debug("pushing page %" PRIaPGNO " on db %d cursor %p", mp->mp_pgno,
- DDBI(mc), (void *)mc);
-
- if (unlikely(mc->mc_snum >= CURSOR_STACK)) {
- mc->mc_txn->mt_flags |= MDBX_TXN_ERROR;
- return MDBX_CURSOR_FULL;
- }
-
- mdbx_cassert(mc, mc->mc_snum < UINT16_MAX);
- mc->mc_top = mc->mc_snum++;
- mc->mc_pg[mc->mc_top] = mp;
- mc->mc_ki[mc->mc_top] = 0;
-
- return MDBX_SUCCESS;
-}
-
-/* Find the address of the page corresponding to a given page number.
- * Set MDBX_TXN_ERROR on failure.
- *
- * [in] mc the cursor accessing the page.
- * [in] pgno the page number for the page to retrieve.
- * [out] ret address of a pointer where the page's address will be
- * stored.
- * [out] lvl dirtylist inheritance level of found page. 1=current txn,
- * 0=mapped page.
- *
- * Returns 0 on success, non-zero on failure. */
-static int mdbx_page_get(MDBX_cursor *mc, pgno_t pgno, MDBX_page **ret,
- int *lvl) {
- MDBX_txn *txn = mc->mc_txn;
- MDBX_env *env = txn->mt_env;
- MDBX_page *p = NULL;
- int level;
-
- if (!(txn->mt_flags & (MDBX_TXN_RDONLY | MDBX_TXN_WRITEMAP))) {
- MDBX_txn *tx2 = txn;
- level = 1;
- do {
- MDBX_ID2L dl = tx2->mt_rw_dirtylist;
- unsigned x;
- /* Spilled pages were dirtied in this txn and flushed
- * because the dirty list got full. Bring this page
- * back in from the map (but don't unspill it here,
- * leave that unless page_touch happens again). */
- if (tx2->mt_spill_pages) {
- pgno_t pn = pgno << 1;
- x = mdbx_pnl_search(tx2->mt_spill_pages, pn);
- if (x <= tx2->mt_spill_pages[0] && tx2->mt_spill_pages[x] == pn)
- goto mapped;
- }
- if (dl[0].mid) {
- unsigned y = mdbx_mid2l_search(dl, pgno);
- if (y <= dl[0].mid && dl[y].mid == pgno) {
- p = dl[y].mptr;
- goto done;
- }
- }
- level++;
- } while ((tx2 = tx2->mt_parent) != NULL);
- }
-
- if (unlikely(pgno >= txn->mt_next_pgno)) {
- mdbx_debug("page %" PRIaPGNO " not found", pgno);
- txn->mt_flags |= MDBX_TXN_ERROR;
- return MDBX_PAGE_NOTFOUND;
- }
- level = 0;
-
-mapped:
- p = pgno2page(env, pgno);
-/* TODO: check p->mp_validator here */
-
-done:
- *ret = p;
- if (lvl)
- *lvl = level;
- return MDBX_SUCCESS;
-}
-
-/* Finish mdbx_page_search() / mdbx_page_search_lowest().
- * The cursor is at the root page, set up the rest of it. */
-static int mdbx_page_search_root(MDBX_cursor *mc, MDBX_val *key, int flags) {
- MDBX_page *mp = mc->mc_pg[mc->mc_top];
- int rc;
- DKBUF;
-
- while (IS_BRANCH(mp)) {
- MDBX_node *node;
- indx_t i;
-
- mdbx_debug("branch page %" PRIaPGNO " has %u keys", mp->mp_pgno,
- NUMKEYS(mp));
- /* Don't assert on branch pages in the FreeDB. We can get here
- * while in the process of rebalancing a FreeDB branch page; we must
- * let that proceed. ITS#8336 */
- mdbx_cassert(mc, !mc->mc_dbi || NUMKEYS(mp) > 1);
- mdbx_debug("found index 0 to page %" PRIaPGNO "", NODEPGNO(NODEPTR(mp, 0)));
-
- if (flags & (MDBX_PS_FIRST | MDBX_PS_LAST)) {
- i = 0;
- if (flags & MDBX_PS_LAST) {
- i = NUMKEYS(mp) - 1;
- /* if already init'd, see if we're already in right place */
- if (mc->mc_flags & C_INITIALIZED) {
- if (mc->mc_ki[mc->mc_top] == i) {
- mc->mc_top = mc->mc_snum++;
- mp = mc->mc_pg[mc->mc_top];
- goto ready;
- }
- }
- }
- } else {
- int exact;
- node = mdbx_node_search(mc, key, &exact);
- if (node == NULL)
- i = NUMKEYS(mp) - 1;
- else {
- i = mc->mc_ki[mc->mc_top];
- if (!exact) {
- mdbx_cassert(mc, i > 0);
- i--;
- }
- }
- mdbx_debug("following index %u for key [%s]", i, DKEY(key));
- }
-
- mdbx_cassert(mc, i < NUMKEYS(mp));
- node = NODEPTR(mp, i);
-
- if (unlikely((rc = mdbx_page_get(mc, NODEPGNO(node), &mp, NULL)) != 0))
- return rc;
-
- mc->mc_ki[mc->mc_top] = i;
- if (unlikely(rc = mdbx_cursor_push(mc, mp)))
- return rc;
-
- ready:
- if (flags & MDBX_PS_MODIFY) {
- if (unlikely((rc = mdbx_page_touch(mc)) != 0))
- return rc;
- mp = mc->mc_pg[mc->mc_top];
- }
- }
-
- if (unlikely(!IS_LEAF(mp))) {
- mdbx_debug("internal error, index points to a page with 0x%02x flags!?",
- mp->mp_flags);
- mc->mc_txn->mt_flags |= MDBX_TXN_ERROR;
- return MDBX_CORRUPTED;
- }
-
- mdbx_debug("found leaf page %" PRIaPGNO " for key [%s]", mp->mp_pgno,
- DKEY(key));
- mc->mc_flags |= C_INITIALIZED;
- mc->mc_flags &= ~C_EOF;
-
- return MDBX_SUCCESS;
-}
-
-/* Search for the lowest key under the current branch page.
- * This just bypasses a NUMKEYS check in the current page
- * before calling mdbx_page_search_root(), because the callers
- * are all in situations where the current page is known to
- * be underfilled. */
-static int mdbx_page_search_lowest(MDBX_cursor *mc) {
- MDBX_page *mp = mc->mc_pg[mc->mc_top];
- MDBX_node *node = NODEPTR(mp, 0);
- int rc;
-
- if (unlikely((rc = mdbx_page_get(mc, NODEPGNO(node), &mp, NULL)) != 0))
- return rc;
-
- mc->mc_ki[mc->mc_top] = 0;
- if (unlikely(rc = mdbx_cursor_push(mc, mp)))
- return rc;
- return mdbx_page_search_root(mc, NULL, MDBX_PS_FIRST);
-}
-
-/* Search for the page a given key should be in.
- * Push it and its parent pages on the cursor stack.
- *
- * [in,out] mc the cursor for this operation.
- * [in] key the key to search for, or NULL for first/last page.
- * [in] flags If MDBX_PS_MODIFY is set, visited pages in the DB
- * are touched (updated with new page numbers).
- * If MDBX_PS_FIRST or MDBX_PS_LAST is set, find first or last
- * leaf.
- * This is used by mdbx_cursor_first() and mdbx_cursor_last().
- * If MDBX_PS_ROOTONLY set, just fetch root node, no further
- * lookups.
- *
- * Returns 0 on success, non-zero on failure. */
-static int mdbx_page_search(MDBX_cursor *mc, MDBX_val *key, int flags) {
- int rc;
- pgno_t root;
-
- /* Make sure the txn is still viable, then find the root from
- * the txn's db table and set it as the root of the cursor's stack. */
- if (unlikely(mc->mc_txn->mt_flags & MDBX_TXN_BLOCKED)) {
- mdbx_debug("transaction has failed, must abort");
- return MDBX_BAD_TXN;
- }
-
- mdbx_cassert(mc, mc->mc_txn->mt_txnid >= mc->mc_txn->mt_env->me_oldest[0]);
- /* Make sure we're using an up-to-date root */
- if (unlikely(*mc->mc_dbflag & DB_STALE)) {
- MDBX_cursor mc2;
- if (unlikely(TXN_DBI_CHANGED(mc->mc_txn, mc->mc_dbi)))
- return MDBX_BAD_DBI;
- mdbx_cursor_init(&mc2, mc->mc_txn, MAIN_DBI, NULL);
- rc = mdbx_page_search(&mc2, &mc->mc_dbx->md_name, 0);
- if (rc)
- return rc;
- {
- MDBX_val data;
- int exact = 0;
- MDBX_node *leaf = mdbx_node_search(&mc2, &mc->mc_dbx->md_name, &exact);
- if (!exact)
- return MDBX_NOTFOUND;
- if (unlikely((leaf->mn_flags & (F_DUPDATA | F_SUBDATA)) != F_SUBDATA))
- return MDBX_INCOMPATIBLE; /* not a named DB */
- rc = mdbx_node_read(&mc2, leaf, &data);
- if (rc)
- return rc;
-
- uint16_t md_flags;
- memcpy(&md_flags, ((char *)data.iov_base + offsetof(MDBX_db, md_flags)),
- sizeof(uint16_t));
- /* The txn may not know this DBI, or another process may
- * have dropped and recreated the DB with other flags. */
- if (unlikely((mc->mc_db->md_flags & PERSISTENT_FLAGS) != md_flags))
- return MDBX_INCOMPATIBLE;
- memcpy(mc->mc_db, data.iov_base, sizeof(MDBX_db));
- }
- *mc->mc_dbflag &= ~DB_STALE;
- }
- root = mc->mc_db->md_root;
-
- if (unlikely(root == P_INVALID)) { /* Tree is empty. */
- mdbx_debug("tree is empty");
- return MDBX_NOTFOUND;
- }
-
- mdbx_cassert(mc, mc->mc_txn->mt_txnid >= mc->mc_txn->mt_env->me_oldest[0]);
- mdbx_cassert(mc, root >= NUM_METAS);
- if (!mc->mc_pg[0] || mc->mc_pg[0]->mp_pgno != root)
- if (unlikely((rc = mdbx_page_get(mc, root, &mc->mc_pg[0], NULL)) != 0))
- return rc;
-
- mc->mc_snum = 1;
- mc->mc_top = 0;
-
- mdbx_debug("db %d root page %" PRIaPGNO " has flags 0x%X", DDBI(mc), root,
- mc->mc_pg[0]->mp_flags);
-
- if (flags & MDBX_PS_MODIFY) {
- if (unlikely(rc = mdbx_page_touch(mc)))
- return rc;
- }
-
- if (flags & MDBX_PS_ROOTONLY)
- return MDBX_SUCCESS;
-
- return mdbx_page_search_root(mc, key, flags);
-}
-
-static int mdbx_ovpage_free(MDBX_cursor *mc, MDBX_page *mp) {
- MDBX_txn *txn = mc->mc_txn;
- pgno_t pg = mp->mp_pgno;
- unsigned x = 0, ovpages = mp->mp_pages;
- MDBX_env *env = txn->mt_env;
- MDBX_PNL sl = txn->mt_spill_pages;
- pgno_t pn = pg << 1;
- int rc;
-
- mdbx_debug("free ov page %" PRIaPGNO " (%u)", pg, ovpages);
- /* If the page is dirty or on the spill list we just acquired it,
- * so we should give it back to our current free list, if any.
- * Otherwise put it onto the list of pages we freed in this txn.
- *
- * Won't create me_reclaimed_pglist: me_last_reclaimed must be inited along
- * with it.
- * Unsupported in nested txns: They would need to hide the page
- * range in ancestor txns' dirty and spilled lists. */
- if (env->me_reclaimed_pglist && !txn->mt_parent &&
- ((mp->mp_flags & P_DIRTY) ||
- (sl && (x = mdbx_pnl_search(sl, pn)) <= sl[0] && sl[x] == pn))) {
- unsigned i, j;
- pgno_t *mop;
- MDBX_ID2 *dl, ix, iy;
- rc = mdbx_pnl_need(&env->me_reclaimed_pglist, ovpages);
- if (unlikely(rc))
- return rc;
- if (!(mp->mp_flags & P_DIRTY)) {
- /* This page is no longer spilled */
- if (x == sl[0])
- sl[0]--;
- else
- sl[x] |= 1;
- goto release;
- }
- /* Remove from dirty list */
- dl = txn->mt_rw_dirtylist;
- x = dl[0].mid--;
- for (ix = dl[x]; ix.mptr != mp; ix = iy) {
- if (likely(x > 1)) {
- x--;
- iy = dl[x];
- dl[x] = ix;
- } else {
- mdbx_cassert(mc, x > 1);
- mdbx_error("not found page 0x%p #%" PRIaPGNO " in the dirtylist", mp,
- mp->mp_pgno);
- j = ++(dl[0].mid);
- dl[j] = ix; /* Unsorted. OK when MDBX_TXN_ERROR. */
- txn->mt_flags |= MDBX_TXN_ERROR;
- return MDBX_PROBLEM;
- }
- }
- txn->mt_dirtyroom++;
- if (!(env->me_flags & MDBX_WRITEMAP))
- mdbx_dpage_free(env, mp);
- release:
- /* Insert in me_reclaimed_pglist */
- mop = env->me_reclaimed_pglist;
- j = mop[0] + ovpages;
- for (i = mop[0]; i && mop[i] < pg; i--)
- mop[j--] = mop[i];
- while (j > i)
- mop[j--] = pg++;
- mop[0] += ovpages;
- } else {
- rc = mdbx_pnl_append_range(&txn->mt_befree_pages, pg, ovpages);
- if (unlikely(rc))
- return rc;
- }
- mc->mc_db->md_overflow_pages -= ovpages;
- return 0;
-}
-
-/* Return the data associated with a given node.
- *
- * [in] mc The cursor for this operation.
- * [in] leaf The node being read.
- * [out] data Updated to point to the node's data.
- *
- * Returns 0 on success, non-zero on failure. */
-static __inline int mdbx_node_read(MDBX_cursor *mc, MDBX_node *leaf,
- MDBX_val *data) {
- MDBX_page *omp; /* overflow page */
- pgno_t pgno;
- int rc;
-
- mdbx_cassert(mc, mc->mc_txn->mt_txnid >= mc->mc_txn->mt_env->me_oldest[0]);
- if (!F_ISSET(leaf->mn_flags, F_BIGDATA)) {
- data->iov_len = NODEDSZ(leaf);
- data->iov_base = NODEDATA(leaf);
- return MDBX_SUCCESS;
- }
-
- /* Read overflow data. */
- data->iov_len = NODEDSZ(leaf);
- memcpy(&pgno, NODEDATA(leaf), sizeof(pgno));
- if (unlikely((rc = mdbx_page_get(mc, pgno, &omp, NULL)) != 0)) {
- mdbx_debug("read overflow page %" PRIaPGNO " failed", pgno);
- return rc;
- }
- data->iov_base = PAGEDATA(omp);
-
- return MDBX_SUCCESS;
-}
-
-int mdbx_get(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data) {
- MDBX_cursor mc;
- MDBX_xcursor mx;
- int exact = 0;
- DKBUF;
-
- mdbx_debug("===> get db %u key [%s]", dbi, DKEY(key));
-
- if (unlikely(!key || !data || !txn))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED))
- return MDBX_BAD_TXN;
-
- mdbx_cursor_init(&mc, txn, dbi, &mx);
- return mdbx_cursor_set(&mc, key, data, MDBX_SET, &exact);
-}
-
-/* Find a sibling for a page.
- * Replaces the page at the top of the cursor's stack with the specified
- * sibling, if one exists.
- *
- * [in] mc The cursor for this operation.
- * [in] move_right Non-zero if the right sibling is requested,
- * otherwise the left sibling.
- *
- * Returns 0 on success, non-zero on failure. */
-static int mdbx_cursor_sibling(MDBX_cursor *mc, int move_right) {
- int rc;
- MDBX_node *indx;
- MDBX_page *mp;
-
- mdbx_cassert(mc, mc->mc_txn->mt_txnid >= mc->mc_txn->mt_env->me_oldest[0]);
- if (unlikely(mc->mc_snum < 2)) {
- return MDBX_NOTFOUND; /* root has no siblings */
- }
-
- mdbx_cursor_pop(mc);
- mdbx_debug("parent page is page %" PRIaPGNO ", index %u",
- mc->mc_pg[mc->mc_top]->mp_pgno, mc->mc_ki[mc->mc_top]);
-
- if (move_right
- ? (mc->mc_ki[mc->mc_top] + 1u >= NUMKEYS(mc->mc_pg[mc->mc_top]))
- : (mc->mc_ki[mc->mc_top] == 0)) {
- mdbx_debug("no more keys left, moving to %s sibling",
- move_right ? "right" : "left");
- if (unlikely((rc = mdbx_cursor_sibling(mc, move_right)) != MDBX_SUCCESS)) {
- /* undo cursor_pop before returning */
- mc->mc_top++;
- mc->mc_snum++;
- return rc;
- }
- } else {
- if (move_right)
- mc->mc_ki[mc->mc_top]++;
- else
- mc->mc_ki[mc->mc_top]--;
- mdbx_debug("just moving to %s index key %u", move_right ? "right" : "left",
- mc->mc_ki[mc->mc_top]);
- }
- mdbx_cassert(mc, IS_BRANCH(mc->mc_pg[mc->mc_top]));
-
- indx = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
- if (unlikely((rc = mdbx_page_get(mc, NODEPGNO(indx), &mp, NULL)) != 0)) {
- /* mc will be inconsistent if caller does mc_snum++ as above */
- mc->mc_flags &= ~(C_INITIALIZED | C_EOF);
- return rc;
- }
-
- mdbx_cursor_push(mc, mp);
- if (!move_right)
- mc->mc_ki[mc->mc_top] = NUMKEYS(mp) - 1;
-
- return MDBX_SUCCESS;
-}
-
-/* Move the cursor to the next data item. */
-static int mdbx_cursor_next(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
- MDBX_cursor_op op) {
- MDBX_page *mp;
- MDBX_node *leaf;
- int rc;
-
- if ((mc->mc_flags & C_DEL) && op == MDBX_NEXT_DUP)
- return MDBX_NOTFOUND;
-
- if (!(mc->mc_flags & C_INITIALIZED))
- return mdbx_cursor_first(mc, key, data);
-
- mp = mc->mc_pg[mc->mc_top];
- if (mc->mc_flags & C_EOF) {
- if (mc->mc_ki[mc->mc_top] + 1u >= NUMKEYS(mp))
- return MDBX_NOTFOUND;
- mc->mc_flags ^= C_EOF;
- }
-
- if (mc->mc_db->md_flags & MDBX_DUPSORT) {
- leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
- if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- if (op == MDBX_NEXT || op == MDBX_NEXT_DUP) {
- rc =
- mdbx_cursor_next(&mc->mc_xcursor->mx_cursor, data, NULL, MDBX_NEXT);
- if (op != MDBX_NEXT || rc != MDBX_NOTFOUND) {
- if (likely(rc == MDBX_SUCCESS))
- MDBX_GET_KEY(leaf, key);
- return rc;
- }
- }
- } else {
- mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF);
- if (op == MDBX_NEXT_DUP)
- return MDBX_NOTFOUND;
- }
- }
-
- mdbx_debug("cursor_next: top page is %" PRIaPGNO " in cursor %p", mp->mp_pgno,
- (void *)mc);
- if (mc->mc_flags & C_DEL) {
- mc->mc_flags ^= C_DEL;
- goto skip;
- }
-
- if (mc->mc_ki[mc->mc_top] + 1u >= NUMKEYS(mp)) {
- mdbx_debug("=====> move to next sibling page");
- if (unlikely((rc = mdbx_cursor_sibling(mc, 1)) != MDBX_SUCCESS)) {
- mc->mc_flags |= C_EOF;
- return rc;
- }
- mp = mc->mc_pg[mc->mc_top];
- mdbx_debug("next page is %" PRIaPGNO ", key index %u", mp->mp_pgno,
- mc->mc_ki[mc->mc_top]);
- } else
- mc->mc_ki[mc->mc_top]++;
-
-skip:
- mdbx_debug("==> cursor points to page %" PRIaPGNO
- " with %u keys, key index %u",
- mp->mp_pgno, NUMKEYS(mp), mc->mc_ki[mc->mc_top]);
-
- if (IS_LEAF2(mp)) {
- key->iov_len = mc->mc_db->md_xsize;
- key->iov_base = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->iov_len);
- return MDBX_SUCCESS;
- }
-
- mdbx_cassert(mc, IS_LEAF(mp));
- leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
-
- if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- mdbx_xcursor_init1(mc, leaf);
- }
- if (data) {
- if (unlikely((rc = mdbx_node_read(mc, leaf, data)) != MDBX_SUCCESS))
- return rc;
-
- if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- rc = mdbx_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
- }
- }
-
- MDBX_GET_KEY(leaf, key);
- return MDBX_SUCCESS;
-}
-
-/* Move the cursor to the previous data item. */
-static int mdbx_cursor_prev(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
- MDBX_cursor_op op) {
- MDBX_page *mp;
- MDBX_node *leaf;
- int rc;
-
- if ((mc->mc_flags & C_DEL) && op == MDBX_PREV_DUP)
- return MDBX_NOTFOUND;
-
- if (!(mc->mc_flags & C_INITIALIZED)) {
- rc = mdbx_cursor_last(mc, key, data);
- if (unlikely(rc))
- return rc;
- mc->mc_ki[mc->mc_top]++;
- }
-
- mp = mc->mc_pg[mc->mc_top];
- if ((mc->mc_db->md_flags & MDBX_DUPSORT) &&
- mc->mc_ki[mc->mc_top] < NUMKEYS(mp)) {
- leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
- if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- if (op == MDBX_PREV || op == MDBX_PREV_DUP) {
- rc =
- mdbx_cursor_prev(&mc->mc_xcursor->mx_cursor, data, NULL, MDBX_PREV);
- if (op != MDBX_PREV || rc != MDBX_NOTFOUND) {
- if (likely(rc == MDBX_SUCCESS)) {
- MDBX_GET_KEY(leaf, key);
- mc->mc_flags &= ~C_EOF;
- }
- return rc;
- }
- }
- } else {
- mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF);
- if (op == MDBX_PREV_DUP)
- return MDBX_NOTFOUND;
- }
- }
-
- mdbx_debug("cursor_prev: top page is %" PRIaPGNO " in cursor %p", mp->mp_pgno,
- (void *)mc);
-
- mc->mc_flags &= ~(C_EOF | C_DEL);
-
- if (mc->mc_ki[mc->mc_top] == 0) {
- mdbx_debug("=====> move to prev sibling page");
- if ((rc = mdbx_cursor_sibling(mc, 0)) != MDBX_SUCCESS) {
- return rc;
- }
- mp = mc->mc_pg[mc->mc_top];
- mc->mc_ki[mc->mc_top] = NUMKEYS(mp) - 1;
- mdbx_debug("prev page is %" PRIaPGNO ", key index %u", mp->mp_pgno,
- mc->mc_ki[mc->mc_top]);
- } else
- mc->mc_ki[mc->mc_top]--;
-
- mdbx_debug("==> cursor points to page %" PRIaPGNO
- " with %u keys, key index %u",
- mp->mp_pgno, NUMKEYS(mp), mc->mc_ki[mc->mc_top]);
-
- if (IS_LEAF2(mp)) {
- key->iov_len = mc->mc_db->md_xsize;
- key->iov_base = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->iov_len);
- return MDBX_SUCCESS;
- }
-
- mdbx_cassert(mc, IS_LEAF(mp));
- leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
-
- if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- mdbx_xcursor_init1(mc, leaf);
- }
- if (data) {
- if (unlikely((rc = mdbx_node_read(mc, leaf, data)) != MDBX_SUCCESS))
- return rc;
-
- if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- rc = mdbx_cursor_last(&mc->mc_xcursor->mx_cursor, data, NULL);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
- }
- }
-
- MDBX_GET_KEY(leaf, key);
- return MDBX_SUCCESS;
-}
-
-/* Set the cursor on a specific data item. */
-static int mdbx_cursor_set(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
- MDBX_cursor_op op, int *exactp) {
- int rc;
- MDBX_page *mp;
- MDBX_node *leaf = NULL;
- DKBUF;
-
- mdbx_cassert(mc, mc->mc_txn->mt_txnid >= mc->mc_txn->mt_env->me_oldest[0]);
- if ((mc->mc_db->md_flags & MDBX_INTEGERKEY) &&
- unlikely(key->iov_len != sizeof(uint32_t) &&
- key->iov_len != sizeof(uint64_t))) {
- mdbx_cassert(mc, !"key-size is invalid for MDBX_INTEGERKEY");
- return MDBX_BAD_VALSIZE;
- }
-
- if (mc->mc_xcursor)
- mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF);
-
- /* See if we're already on the right page */
- if (mc->mc_flags & C_INITIALIZED) {
- MDBX_val nodekey;
-
- mp = mc->mc_pg[mc->mc_top];
- if (!NUMKEYS(mp)) {
- mc->mc_ki[mc->mc_top] = 0;
- return MDBX_NOTFOUND;
- }
- if (mp->mp_flags & P_LEAF2) {
- nodekey.iov_len = mc->mc_db->md_xsize;
- nodekey.iov_base = LEAF2KEY(mp, 0, nodekey.iov_len);
- } else {
- leaf = NODEPTR(mp, 0);
- MDBX_GET_KEY2(leaf, nodekey);
- }
- rc = mc->mc_dbx->md_cmp(key, &nodekey);
- if (rc == 0) {
- /* Probably happens rarely, but first node on the page
- * was the one we wanted.
- */
- mc->mc_ki[mc->mc_top] = 0;
- if (exactp)
- *exactp = 1;
- goto set1;
- }
- if (rc > 0) {
- unsigned i;
- unsigned nkeys = NUMKEYS(mp);
- if (nkeys > 1) {
- if (mp->mp_flags & P_LEAF2) {
- nodekey.iov_base = LEAF2KEY(mp, nkeys - 1, nodekey.iov_len);
- } else {
- leaf = NODEPTR(mp, nkeys - 1);
- MDBX_GET_KEY2(leaf, nodekey);
- }
- rc = mc->mc_dbx->md_cmp(key, &nodekey);
- if (rc == 0) {
- /* last node was the one we wanted */
- mdbx_cassert(mc, nkeys >= 1 && nkeys <= UINT16_MAX + 1);
- mc->mc_ki[mc->mc_top] = (indx_t)(nkeys - 1);
- if (exactp)
- *exactp = 1;
- goto set1;
- }
- if (rc < 0) {
- if (mc->mc_ki[mc->mc_top] < NUMKEYS(mp)) {
- /* This is definitely the right page, skip search_page */
- if (mp->mp_flags & P_LEAF2) {
- nodekey.iov_base =
- LEAF2KEY(mp, mc->mc_ki[mc->mc_top], nodekey.iov_len);
- } else {
- leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
- MDBX_GET_KEY2(leaf, nodekey);
- }
- rc = mc->mc_dbx->md_cmp(key, &nodekey);
- if (rc == 0) {
- /* current node was the one we wanted */
- if (exactp)
- *exactp = 1;
- goto set1;
- }
- }
- rc = 0;
- mc->mc_flags &= ~C_EOF;
- goto set2;
- }
- }
- /* If any parents have right-sibs, search.
- * Otherwise, there's nothing further. */
- for (i = 0; i < mc->mc_top; i++)
- if (mc->mc_ki[i] < NUMKEYS(mc->mc_pg[i]) - 1)
- break;
- if (i == mc->mc_top) {
- /* There are no other pages */
- mdbx_cassert(mc, nkeys <= UINT16_MAX);
- mc->mc_ki[mc->mc_top] = (uint16_t)nkeys;
- return MDBX_NOTFOUND;
- }
- }
- if (!mc->mc_top) {
- /* There are no other pages */
- mc->mc_ki[mc->mc_top] = 0;
- if (op == MDBX_SET_RANGE && !exactp) {
- rc = 0;
- goto set1;
- } else
- return MDBX_NOTFOUND;
- }
- } else {
- mc->mc_pg[0] = 0;
- }
-
- rc = mdbx_page_search(mc, key, 0);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
-
- mp = mc->mc_pg[mc->mc_top];
- mdbx_cassert(mc, IS_LEAF(mp));
-
-set2:
- leaf = mdbx_node_search(mc, key, exactp);
- if (exactp != NULL && !*exactp) {
- /* MDBX_SET specified and not an exact match. */
- return MDBX_NOTFOUND;
- }
-
- if (leaf == NULL) {
- mdbx_debug("===> inexact leaf not found, goto sibling");
- if (unlikely((rc = mdbx_cursor_sibling(mc, 1)) != MDBX_SUCCESS)) {
- mc->mc_flags |= C_EOF;
- return rc; /* no entries matched */
- }
- mp = mc->mc_pg[mc->mc_top];
- mdbx_cassert(mc, IS_LEAF(mp));
- leaf = NODEPTR(mp, 0);
- }
-
-set1:
- mc->mc_flags |= C_INITIALIZED;
- mc->mc_flags &= ~C_EOF;
-
- if (IS_LEAF2(mp)) {
- if (op == MDBX_SET_RANGE || op == MDBX_SET_KEY) {
- key->iov_len = mc->mc_db->md_xsize;
- key->iov_base = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->iov_len);
- }
- return MDBX_SUCCESS;
- }
-
- if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- mdbx_xcursor_init1(mc, leaf);
- }
- if (likely(data)) {
- if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- if (op == MDBX_SET || op == MDBX_SET_KEY || op == MDBX_SET_RANGE) {
- rc = mdbx_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL);
- } else {
- int ex2, *ex2p;
- if (op == MDBX_GET_BOTH) {
- ex2p = &ex2;
- ex2 = 0;
- } else {
- ex2p = NULL;
- }
- rc = mdbx_cursor_set(&mc->mc_xcursor->mx_cursor, data, NULL,
- MDBX_SET_RANGE, ex2p);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
- }
- } else if (op == MDBX_GET_BOTH || op == MDBX_GET_BOTH_RANGE) {
- MDBX_val olddata;
- if (unlikely((rc = mdbx_node_read(mc, leaf, &olddata)) != MDBX_SUCCESS))
- return rc;
- rc = mc->mc_dbx->md_dcmp(data, &olddata);
- if (rc) {
- if (op == MDBX_GET_BOTH || rc > 0)
- return MDBX_NOTFOUND;
- rc = 0;
- }
- *data = olddata;
- } else {
- if (mc->mc_xcursor)
- mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF);
- if (unlikely((rc = mdbx_node_read(mc, leaf, data)) != MDBX_SUCCESS))
- return rc;
- }
- }
-
- /* The key already matches in all other cases */
- if (op == MDBX_SET_RANGE || op == MDBX_SET_KEY)
- MDBX_GET_KEY(leaf, key);
-
- mdbx_debug("==> cursor placed on key [%s], data [%s]", DKEY(key), DVAL(data));
- return rc;
-}
-
-/* Move the cursor to the first item in the database. */
-static int mdbx_cursor_first(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data) {
- int rc;
- MDBX_node *leaf;
-
- if (mc->mc_xcursor)
- mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF);
-
- if (!(mc->mc_flags & C_INITIALIZED) || mc->mc_top) {
- rc = mdbx_page_search(mc, NULL, MDBX_PS_FIRST);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
- }
- mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]));
-
- leaf = NODEPTR(mc->mc_pg[mc->mc_top], 0);
- mc->mc_flags |= C_INITIALIZED;
- mc->mc_flags &= ~C_EOF;
-
- mc->mc_ki[mc->mc_top] = 0;
-
- if (IS_LEAF2(mc->mc_pg[mc->mc_top])) {
- key->iov_len = mc->mc_db->md_xsize;
- key->iov_base = LEAF2KEY(mc->mc_pg[mc->mc_top], 0, key->iov_len);
- return MDBX_SUCCESS;
- }
-
- if (likely(data)) {
- if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- mdbx_cassert(mc, mc->mc_xcursor != nullptr);
- mdbx_xcursor_init1(mc, leaf);
- rc = mdbx_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL);
- if (unlikely(rc))
- return rc;
- } else {
- if (unlikely((rc = mdbx_node_read(mc, leaf, data)) != MDBX_SUCCESS))
- return rc;
- }
- }
- MDBX_GET_KEY(leaf, key);
- return MDBX_SUCCESS;
-}
-
-/* Move the cursor to the last item in the database. */
-static int mdbx_cursor_last(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data) {
- int rc;
- MDBX_node *leaf;
-
- if (mc->mc_xcursor)
- mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF);
-
- if (likely((mc->mc_flags & (C_EOF | C_DEL)) != C_EOF)) {
- if (!(mc->mc_flags & C_INITIALIZED) || mc->mc_top) {
- rc = mdbx_page_search(mc, NULL, MDBX_PS_LAST);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
- }
- mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]));
- }
-
- mc->mc_ki[mc->mc_top] = NUMKEYS(mc->mc_pg[mc->mc_top]) - 1;
- mc->mc_flags |= C_INITIALIZED | C_EOF;
- leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
-
- if (IS_LEAF2(mc->mc_pg[mc->mc_top])) {
- key->iov_len = mc->mc_db->md_xsize;
- key->iov_base =
- LEAF2KEY(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], key->iov_len);
- return MDBX_SUCCESS;
- }
-
- if (likely(data)) {
- if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- mdbx_cassert(mc, mc->mc_xcursor != nullptr);
- mdbx_xcursor_init1(mc, leaf);
- rc = mdbx_cursor_last(&mc->mc_xcursor->mx_cursor, data, NULL);
- if (unlikely(rc))
- return rc;
- } else {
- if (unlikely((rc = mdbx_node_read(mc, leaf, data)) != MDBX_SUCCESS))
- return rc;
- }
- }
-
- MDBX_GET_KEY(leaf, key);
- return MDBX_SUCCESS;
-}
-
-int mdbx_cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
- MDBX_cursor_op op) {
- int rc;
- int exact = 0;
- int (*mfunc)(MDBX_cursor * mc, MDBX_val * key, MDBX_val * data);
-
- if (unlikely(mc == NULL))
- return MDBX_EINVAL;
-
- if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(mc->mc_txn->mt_flags & MDBX_TXN_BLOCKED))
- return MDBX_BAD_TXN;
-
- mdbx_cassert(mc, mc->mc_txn->mt_txnid >= mc->mc_txn->mt_env->me_oldest[0]);
- switch (op) {
- case MDBX_GET_CURRENT: {
- if (unlikely(!(mc->mc_flags & C_INITIALIZED)))
- return MDBX_EINVAL;
- MDBX_page *mp = mc->mc_pg[mc->mc_top];
- unsigned nkeys = NUMKEYS(mp);
- if (mc->mc_ki[mc->mc_top] >= nkeys) {
- mdbx_cassert(mc, nkeys <= UINT16_MAX);
- mc->mc_ki[mc->mc_top] = (uint16_t)nkeys;
- return MDBX_NOTFOUND;
- }
- assert(nkeys > 0);
-
- rc = MDBX_SUCCESS;
- if (IS_LEAF2(mp)) {
- key->iov_len = mc->mc_db->md_xsize;
- key->iov_base = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->iov_len);
- } else {
- MDBX_node *leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
- MDBX_GET_KEY(leaf, key);
- if (data) {
- if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- if (unlikely(!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED))) {
- mdbx_xcursor_init1(mc, leaf);
- rc = mdbx_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL);
- if (unlikely(rc))
- return rc;
- }
- rc = mdbx_cursor_get(&mc->mc_xcursor->mx_cursor, data, NULL,
- MDBX_GET_CURRENT);
- } else {
- rc = mdbx_node_read(mc, leaf, data);
- }
- if (unlikely(rc))
- return rc;
- }
- }
- break;
- }
- case MDBX_GET_BOTH:
- case MDBX_GET_BOTH_RANGE:
- if (unlikely(data == NULL))
- return MDBX_EINVAL;
- if (unlikely(mc->mc_xcursor == NULL))
- return MDBX_INCOMPATIBLE;
- /* FALLTHRU */
- case MDBX_SET:
- case MDBX_SET_KEY:
- case MDBX_SET_RANGE:
- if (unlikely(key == NULL))
- return MDBX_EINVAL;
- rc = mdbx_cursor_set(mc, key, data, op,
- op == MDBX_SET_RANGE ? NULL : &exact);
- break;
- case MDBX_GET_MULTIPLE:
- if (unlikely(data == NULL || !(mc->mc_flags & C_INITIALIZED)))
- return MDBX_EINVAL;
- if (unlikely(!(mc->mc_db->md_flags & MDBX_DUPFIXED)))
- return MDBX_INCOMPATIBLE;
- rc = MDBX_SUCCESS;
- if (!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) ||
- (mc->mc_xcursor->mx_cursor.mc_flags & C_EOF))
- break;
- goto fetchm;
- case MDBX_NEXT_MULTIPLE:
- if (unlikely(data == NULL))
- return MDBX_EINVAL;
- if (unlikely(!(mc->mc_db->md_flags & MDBX_DUPFIXED)))
- return MDBX_INCOMPATIBLE;
- rc = mdbx_cursor_next(mc, key, data, MDBX_NEXT_DUP);
- if (rc == MDBX_SUCCESS) {
- if (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) {
- MDBX_cursor *mx;
- fetchm:
- mx = &mc->mc_xcursor->mx_cursor;
- data->iov_len = NUMKEYS(mx->mc_pg[mx->mc_top]) * mx->mc_db->md_xsize;
- data->iov_base = PAGEDATA(mx->mc_pg[mx->mc_top]);
- mx->mc_ki[mx->mc_top] = NUMKEYS(mx->mc_pg[mx->mc_top]) - 1;
- } else {
- rc = MDBX_NOTFOUND;
- }
- }
- break;
- case MDBX_PREV_MULTIPLE:
- if (data == NULL)
- return MDBX_EINVAL;
- if (!(mc->mc_db->md_flags & MDBX_DUPFIXED))
- return MDBX_INCOMPATIBLE;
- rc = MDBX_SUCCESS;
- if (!(mc->mc_flags & C_INITIALIZED))
- rc = mdbx_cursor_last(mc, key, data);
- if (rc == MDBX_SUCCESS) {
- MDBX_cursor *mx = &mc->mc_xcursor->mx_cursor;
- if (mx->mc_flags & C_INITIALIZED) {
- rc = mdbx_cursor_sibling(mx, 0);
- if (rc == MDBX_SUCCESS)
- goto fetchm;
- } else {
- rc = MDBX_NOTFOUND;
- }
- }
- break;
- case MDBX_NEXT:
- case MDBX_NEXT_DUP:
- case MDBX_NEXT_NODUP:
- rc = mdbx_cursor_next(mc, key, data, op);
- break;
- case MDBX_PREV:
- case MDBX_PREV_DUP:
- case MDBX_PREV_NODUP:
- rc = mdbx_cursor_prev(mc, key, data, op);
- break;
- case MDBX_FIRST:
- rc = mdbx_cursor_first(mc, key, data);
- break;
- case MDBX_FIRST_DUP:
- mfunc = mdbx_cursor_first;
- mmove:
- if (unlikely(data == NULL || !(mc->mc_flags & C_INITIALIZED)))
- return MDBX_EINVAL;
- if (unlikely(mc->mc_xcursor == NULL))
- return MDBX_INCOMPATIBLE;
- if (mc->mc_ki[mc->mc_top] >= NUMKEYS(mc->mc_pg[mc->mc_top])) {
- mc->mc_ki[mc->mc_top] = NUMKEYS(mc->mc_pg[mc->mc_top]);
- return MDBX_NOTFOUND;
- }
- {
- MDBX_node *leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
- if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- MDBX_GET_KEY(leaf, key);
- rc = mdbx_node_read(mc, leaf, data);
- break;
- }
- }
- if (unlikely(!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)))
- return MDBX_EINVAL;
- rc = mfunc(&mc->mc_xcursor->mx_cursor, data, NULL);
- break;
- case MDBX_LAST:
- rc = mdbx_cursor_last(mc, key, data);
- break;
- case MDBX_LAST_DUP:
- mfunc = mdbx_cursor_last;
- goto mmove;
- default:
- mdbx_debug("unhandled/unimplemented cursor operation %u", op);
- return MDBX_EINVAL;
- }
-
- mc->mc_flags &= ~C_DEL;
- return rc;
-}
-
-/* Touch all the pages in the cursor stack. Set mc_top.
- * Makes sure all the pages are writable, before attempting a write operation.
- * [in] mc The cursor to operate on. */
-static int mdbx_cursor_touch(MDBX_cursor *mc) {
- int rc = MDBX_SUCCESS;
-
- if (mc->mc_dbi >= CORE_DBS && !(*mc->mc_dbflag & (DB_DIRTY | DB_DUPDATA))) {
- /* Touch DB record of named DB */
- MDBX_cursor mc2;
- MDBX_xcursor mcx;
- if (TXN_DBI_CHANGED(mc->mc_txn, mc->mc_dbi))
- return MDBX_BAD_DBI;
- mdbx_cursor_init(&mc2, mc->mc_txn, MAIN_DBI, &mcx);
- rc = mdbx_page_search(&mc2, &mc->mc_dbx->md_name, MDBX_PS_MODIFY);
- if (unlikely(rc))
- return rc;
- *mc->mc_dbflag |= DB_DIRTY;
- }
- mc->mc_top = 0;
- if (mc->mc_snum) {
- do {
- rc = mdbx_page_touch(mc);
- } while (!rc && ++(mc->mc_top) < mc->mc_snum);
- mc->mc_top = mc->mc_snum - 1;
- }
- return rc;
-}
-
-/* Do not spill pages to disk if txn is getting full, may fail instead */
-#define MDBX_NOSPILL 0x8000
-
-int mdbx_cursor_put(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
- unsigned flags) {
- MDBX_env *env;
- MDBX_page *fp, *sub_root = NULL;
- uint16_t fp_flags;
- MDBX_val xdata, *rdata, dkey, olddata;
- MDBX_db dummy;
- unsigned mcount = 0, dcount = 0, nospill;
- size_t nsize;
- int rc = MDBX_SUCCESS, rc2;
- unsigned nflags;
- DKBUF;
-
- if (unlikely(mc == NULL || key == NULL))
- return MDBX_EINVAL;
-
- if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE))
- return MDBX_EBADSIGN;
-
- env = mc->mc_txn->mt_env;
-
- /* Check this first so counter will always be zero on any early failures. */
- if (flags & MDBX_MULTIPLE) {
- if (unlikely(!F_ISSET(mc->mc_db->md_flags, MDBX_DUPFIXED)))
- return MDBX_INCOMPATIBLE;
- if (unlikely(data[1].iov_len >= INT_MAX))
- return MDBX_EINVAL;
- dcount = (unsigned)data[1].iov_len;
- data[1].iov_len = 0;
- }
-
- if (flags & MDBX_RESERVE) {
- if (unlikely(mc->mc_db->md_flags & (MDBX_DUPSORT | MDBX_REVERSEDUP)))
- return MDBX_INCOMPATIBLE;
- data->iov_base = nullptr;
- }
-
- nospill = flags & MDBX_NOSPILL;
- flags &= ~MDBX_NOSPILL;
-
- if (unlikely(mc->mc_txn->mt_flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED)))
- return (mc->mc_txn->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EACCESS
- : MDBX_BAD_TXN;
-
- if (unlikely(key->iov_len > env->me_maxkey_limit))
- return MDBX_BAD_VALSIZE;
-
- if (unlikely(data->iov_len > ((mc->mc_db->md_flags & MDBX_DUPSORT)
- ? env->me_maxkey_limit
- : MDBX_MAXDATASIZE)))
- return MDBX_BAD_VALSIZE;
-
- if ((mc->mc_db->md_flags & MDBX_INTEGERKEY) &&
- unlikely(key->iov_len != sizeof(uint32_t) &&
- key->iov_len != sizeof(uint64_t))) {
- mdbx_cassert(mc, !"key-size is invalid for MDBX_INTEGERKEY");
- return MDBX_BAD_VALSIZE;
- }
-
- if ((mc->mc_db->md_flags & MDBX_INTEGERDUP) &&
- unlikely(data->iov_len != sizeof(uint32_t) &&
- data->iov_len != sizeof(uint64_t))) {
- mdbx_cassert(mc, !"data-size is invalid MDBX_INTEGERDUP");
- return MDBX_BAD_VALSIZE;
- }
-
- mdbx_debug("==> put db %d key [%s], size %" PRIuPTR
- ", data [%s] size %" PRIuPTR,
- DDBI(mc), DKEY(key), key ? key->iov_len : 0,
- DVAL((flags & MDBX_RESERVE) ? nullptr : data), data->iov_len);
-
- int dupdata_flag = 0;
- if (flags & MDBX_CURRENT) {
- /* ÐžÐ¿Ñ†Ð¸Ñ MDBX_CURRENT означает, что запрошено обновление текущей запиÑи,
- * на которой ÑÐµÐ¹Ñ‡Ð°Ñ Ñтоит курÑор. ПроверÑем что переданный ключ Ñовпадает
- * Ñо значением в текущей позиции курÑора.
- * ЗдеÑÑŒ проще вызвать mdbx_cursor_get(), так как Ð´Ð»Ñ Ð¾Ð±ÑÐ»ÑƒÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†
- * Ñ MDBX_DUPSORT также требуетÑÑ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ð¹ размер данных. */
- MDBX_val current_key, current_data;
- rc = mdbx_cursor_get(mc, &current_key, &current_data, MDBX_GET_CURRENT);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
- if (mc->mc_dbx->md_cmp(key, &current_key) != 0)
- return MDBX_EKEYMISMATCH;
-
- if (F_ISSET(mc->mc_db->md_flags, MDBX_DUPSORT)) {
- MDBX_node *leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
- if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- mdbx_cassert(mc,
- mc->mc_xcursor != NULL &&
- (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED));
- /* ЕÑли за ключом более одного значениÑ, либо еÑли размер данных
- * отличаетÑÑ, то вмеÑто inplace Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ÑÑ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ðµ и
- * поÑÐ»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ð²Ñтавка. */
- if (mc->mc_xcursor->mx_db.md_entries > 1 ||
- current_data.iov_len != data->iov_len) {
- rc = mdbx_cursor_del(mc, 0);
- if (rc != MDBX_SUCCESS)
- return rc;
- flags -= MDBX_CURRENT;
- }
- }
- }
- }
-
- if (mc->mc_db->md_root == P_INVALID) {
- /* new database, cursor has nothing to point to */
- mc->mc_snum = 0;
- mc->mc_top = 0;
- mc->mc_flags &= ~C_INITIALIZED;
- rc = MDBX_NO_ROOT;
- } else if ((flags & MDBX_CURRENT) == 0) {
- int exact = 0;
- MDBX_val d2;
- if (flags & MDBX_APPEND) {
- MDBX_val k2;
- rc = mdbx_cursor_last(mc, &k2, &d2);
- if (rc == 0) {
- rc = mc->mc_dbx->md_cmp(key, &k2);
- if (rc > 0) {
- rc = MDBX_NOTFOUND;
- mc->mc_ki[mc->mc_top]++;
- } else {
- /* new key is <= last key */
- rc = MDBX_EKEYMISMATCH;
- }
- }
- } else {
- rc = mdbx_cursor_set(mc, key, &d2, MDBX_SET, &exact);
- }
- if ((flags & MDBX_NOOVERWRITE) && rc == 0) {
- mdbx_debug("duplicate key [%s]", DKEY(key));
- *data = d2;
- return MDBX_KEYEXIST;
- }
- if (rc && unlikely(rc != MDBX_NOTFOUND))
- return rc;
- }
-
- mc->mc_flags &= ~C_DEL;
-
- /* Cursor is positioned, check for room in the dirty list */
- if (!nospill) {
- if (flags & MDBX_MULTIPLE) {
- rdata = &xdata;
- xdata.iov_len = data->iov_len * dcount;
- } else {
- rdata = data;
- }
- if (unlikely(rc2 = mdbx_page_spill(mc, key, rdata)))
- return rc2;
- }
-
- if (rc == MDBX_NO_ROOT) {
- MDBX_page *np;
- /* new database, write a root leaf page */
- mdbx_debug("allocating new root leaf page");
- if (unlikely(rc2 = mdbx_page_new(mc, P_LEAF, 1, &np))) {
- return rc2;
- }
- assert(np->mp_flags & P_LEAF);
- mdbx_cursor_push(mc, np);
- mc->mc_db->md_root = np->mp_pgno;
- mc->mc_db->md_depth++;
- *mc->mc_dbflag |= DB_DIRTY;
- if ((mc->mc_db->md_flags & (MDBX_DUPSORT | MDBX_DUPFIXED)) == MDBX_DUPFIXED)
- np->mp_flags |= P_LEAF2;
- mc->mc_flags |= C_INITIALIZED;
- } else {
- /* make sure all cursor pages are writable */
- rc2 = mdbx_cursor_touch(mc);
- if (unlikely(rc2))
- return rc2;
- }
-
- bool insert_key, insert_data, do_sub = false;
- insert_key = insert_data = (rc != MDBX_SUCCESS);
- if (insert_key) {
- /* The key does not exist */
- mdbx_debug("inserting key at index %i", mc->mc_ki[mc->mc_top]);
- if ((mc->mc_db->md_flags & MDBX_DUPSORT) &&
- LEAFSIZE(key, data) > env->me_nodemax) {
- /* Too big for a node, insert in sub-DB. Set up an empty
- * "old sub-page" for prep_subDB to expand to a full page. */
- fp_flags = P_LEAF | P_DIRTY;
- fp = env->me_pbuf;
- fp->mp_leaf2_ksize = (uint16_t)data->iov_len; /* used if MDBX_DUPFIXED */
- fp->mp_lower = fp->mp_upper = 0;
- olddata.iov_len = PAGEHDRSZ;
- goto prep_subDB;
- }
- } else {
- /* there's only a key anyway, so this is a no-op */
- if (IS_LEAF2(mc->mc_pg[mc->mc_top])) {
- char *ptr;
- unsigned ksize = mc->mc_db->md_xsize;
- if (key->iov_len != ksize)
- return MDBX_BAD_VALSIZE;
- ptr = LEAF2KEY(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], ksize);
- memcpy(ptr, key->iov_base, ksize);
- fix_parent:
- /* if overwriting slot 0 of leaf, need to
- * update branch key if there is a parent page */
- if (mc->mc_top && !mc->mc_ki[mc->mc_top]) {
- unsigned dtop = 1;
- mc->mc_top--;
- /* slot 0 is always an empty key, find real slot */
- while (mc->mc_top && !mc->mc_ki[mc->mc_top]) {
- mc->mc_top--;
- dtop++;
- }
- if (mc->mc_ki[mc->mc_top])
- rc2 = mdbx_update_key(mc, key);
- else
- rc2 = MDBX_SUCCESS;
- mdbx_cassert(mc, mc->mc_top + dtop < UINT16_MAX);
- mc->mc_top += (uint16_t)dtop;
- if (rc2)
- return rc2;
- }
- return MDBX_SUCCESS;
- }
-
- more:;
- MDBX_node *leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
- olddata.iov_len = NODEDSZ(leaf);
- olddata.iov_base = NODEDATA(leaf);
-
- /* DB has dups? */
- if (F_ISSET(mc->mc_db->md_flags, MDBX_DUPSORT)) {
- /* Prepare (sub-)page/sub-DB to accept the new item, if needed.
- * fp: old sub-page or a header faking it.
- * mp: new (sub-)page. offset: growth in page size.
- * xdata: node data with new page or DB. */
- unsigned i, offset = 0;
- MDBX_page *mp = fp = xdata.iov_base = env->me_pbuf;
- mp->mp_pgno = mc->mc_pg[mc->mc_top]->mp_pgno;
-
- /* Was a single item before, must convert now */
- if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) {
-
- /* does data match? */
- if (!mc->mc_dbx->md_dcmp(data, &olddata)) {
- if (unlikely(flags & (MDBX_NODUPDATA | MDBX_APPENDDUP)))
- return MDBX_KEYEXIST;
- /* overwrite it */
- goto current;
- }
-
- /* Just overwrite the current item */
- if (flags & MDBX_CURRENT)
- goto current;
-
- /* Back up original data item */
- dupdata_flag = 1;
- dkey.iov_len = olddata.iov_len;
- dkey.iov_base = memcpy(fp + 1, olddata.iov_base, olddata.iov_len);
-
- /* Make sub-page header for the dup items, with dummy body */
- fp->mp_flags = P_LEAF | P_DIRTY | P_SUBP;
- fp->mp_lower = 0;
- xdata.iov_len = PAGEHDRSZ + dkey.iov_len + data->iov_len;
- if (mc->mc_db->md_flags & MDBX_DUPFIXED) {
- fp->mp_flags |= P_LEAF2;
- fp->mp_leaf2_ksize = (uint16_t)data->iov_len;
- xdata.iov_len += 2 * data->iov_len; /* leave space for 2 more */
- } else {
- xdata.iov_len += 2 * (sizeof(indx_t) + NODESIZE) +
- (dkey.iov_len & 1) + (data->iov_len & 1);
- }
- fp->mp_upper = (uint16_t)(xdata.iov_len - PAGEHDRSZ);
- olddata.iov_len = xdata.iov_len; /* pretend olddata is fp */
- } else if (leaf->mn_flags & F_SUBDATA) {
- /* Data is on sub-DB, just store it */
- flags |= F_DUPDATA | F_SUBDATA;
- goto put_sub;
- } else {
- /* Data is on sub-page */
- fp = olddata.iov_base;
- switch (flags) {
- default:
- if (!(mc->mc_db->md_flags & MDBX_DUPFIXED)) {
- offset = EVEN(NODESIZE + sizeof(indx_t) + data->iov_len);
- break;
- }
- offset = fp->mp_leaf2_ksize;
- if (SIZELEFT(fp) < offset) {
- offset *= 4; /* space for 4 more */
- break;
- }
- /* FALLTHRU: Big enough MDBX_DUPFIXaED sub-page */
- __fallthrough;
- case MDBX_CURRENT | MDBX_NODUPDATA:
- case MDBX_CURRENT:
- fp->mp_flags |= P_DIRTY;
- fp->mp_pgno = mp->mp_pgno;
- mc->mc_xcursor->mx_cursor.mc_pg[0] = fp;
- flags |= F_DUPDATA;
- goto put_sub;
- }
- xdata.iov_len = olddata.iov_len + offset;
- }
-
- fp_flags = fp->mp_flags;
- if (NODESIZE + NODEKSZ(leaf) + xdata.iov_len > env->me_nodemax) {
- /* Too big for a sub-page, convert to sub-DB */
- fp_flags &= ~P_SUBP;
- prep_subDB:
- dummy.md_xsize = 0;
- dummy.md_flags = 0;
- if (mc->mc_db->md_flags & MDBX_DUPFIXED) {
- fp_flags |= P_LEAF2;
- dummy.md_xsize = fp->mp_leaf2_ksize;
- dummy.md_flags = MDBX_DUPFIXED;
- if (mc->mc_db->md_flags & MDBX_INTEGERDUP)
- dummy.md_flags |= MDBX_INTEGERKEY;
- }
- dummy.md_depth = 1;
- dummy.md_branch_pages = 0;
- dummy.md_leaf_pages = 1;
- dummy.md_overflow_pages = 0;
- dummy.md_entries = NUMKEYS(fp);
- xdata.iov_len = sizeof(MDBX_db);
- xdata.iov_base = &dummy;
- if ((rc = mdbx_page_alloc(mc, 1, &mp, MDBX_ALLOC_ALL)))
- return rc;
- mdbx_cassert(mc, env->me_psize > olddata.iov_len);
- offset = env->me_psize - (unsigned)olddata.iov_len;
- flags |= F_DUPDATA | F_SUBDATA;
- dummy.md_root = mp->mp_pgno;
- sub_root = mp;
- }
- if (mp != fp) {
- mp->mp_flags = fp_flags | P_DIRTY;
- mp->mp_leaf2_ksize = fp->mp_leaf2_ksize;
- mp->mp_lower = fp->mp_lower;
- mdbx_cassert(mc, fp->mp_upper + offset <= UINT16_MAX);
- mp->mp_upper = (indx_t)(fp->mp_upper + offset);
- if (fp_flags & P_LEAF2) {
- memcpy(PAGEDATA(mp), PAGEDATA(fp), NUMKEYS(fp) * fp->mp_leaf2_ksize);
- } else {
- memcpy((char *)mp + mp->mp_upper + PAGEHDRSZ,
- (char *)fp + fp->mp_upper + PAGEHDRSZ,
- olddata.iov_len - fp->mp_upper - PAGEHDRSZ);
- for (i = 0; i < NUMKEYS(fp); i++) {
- mdbx_cassert(mc, fp->mp_ptrs[i] + offset <= UINT16_MAX);
- mp->mp_ptrs[i] = (indx_t)(fp->mp_ptrs[i] + offset);
- }
- }
- }
-
- rdata = &xdata;
- flags |= F_DUPDATA;
- do_sub = true;
- if (!insert_key)
- mdbx_node_del(mc, 0);
- goto new_sub;
- }
- current:
- /* MDBX passes F_SUBDATA in 'flags' to write a DB record */
- if (unlikely((leaf->mn_flags ^ flags) & F_SUBDATA))
- return MDBX_INCOMPATIBLE;
- /* overflow page overwrites need special handling */
- if (F_ISSET(leaf->mn_flags, F_BIGDATA)) {
- MDBX_page *omp;
- pgno_t pg;
- int level, ovpages, dpages = OVPAGES(env, data->iov_len);
-
- memcpy(&pg, olddata.iov_base, sizeof(pg));
- if (unlikely((rc2 = mdbx_page_get(mc, pg, &omp, &level)) != 0))
- return rc2;
- ovpages = omp->mp_pages;
-
- /* Is the ov page large enough? */
- if (ovpages >= dpages) {
- if (!(omp->mp_flags & P_DIRTY) &&
- (level || (env->me_flags & MDBX_WRITEMAP))) {
- rc = mdbx_page_unspill(mc->mc_txn, omp, &omp);
- if (unlikely(rc))
- return rc;
- level = 0; /* dirty in this txn or clean */
- }
- /* Is it dirty? */
- if (omp->mp_flags & P_DIRTY) {
- /* yes, overwrite it. Note in this case we don't
- * bother to try shrinking the page if the new data
- * is smaller than the overflow threshold. */
- if (unlikely(level > 1)) {
- /* It is writable only in a parent txn */
- MDBX_page *np = mdbx_page_malloc(mc->mc_txn, ovpages);
- MDBX_ID2 id2;
- if (unlikely(!np))
- return MDBX_ENOMEM;
- id2.mid = pg;
- id2.mptr = np;
- /* Note - this page is already counted in parent's dirtyroom */
- rc2 = mdbx_mid2l_insert(mc->mc_txn->mt_rw_dirtylist, &id2);
- mdbx_cassert(mc, rc2 == 0);
-
- /* Currently we make the page look as with put() in the
- * parent txn, in case the user peeks at MDBX_RESERVEd
- * or unused parts. Some users treat ovpages specially. */
- const size_t whole = pgno2bytes(env, ovpages);
- /* Skip the part where MDBX will put *data.
- * Copy end of page, adjusting alignment so
- * compiler may copy words instead of bytes. */
- const size_t off =
- (PAGEHDRSZ + data->iov_len) & -(intptr_t)sizeof(size_t);
- memcpy((size_t *)((char *)np + off), (size_t *)((char *)omp + off),
- whole - off);
- memcpy(np, omp, PAGEHDRSZ); /* Copy header of page */
- omp = np;
- }
- SETDSZ(leaf, data->iov_len);
- if (F_ISSET(flags, MDBX_RESERVE))
- data->iov_base = PAGEDATA(omp);
- else
- memcpy(PAGEDATA(omp), data->iov_base, data->iov_len);
- return MDBX_SUCCESS;
- }
- }
- if ((rc2 = mdbx_ovpage_free(mc, omp)) != MDBX_SUCCESS)
- return rc2;
- } else if (data->iov_len == olddata.iov_len) {
- assert(EVEN(key->iov_len) == EVEN(leaf->mn_ksize));
- /* same size, just replace it. Note that we could
- * also reuse this node if the new data is smaller,
- * but instead we opt to shrink the node in that case. */
- if (F_ISSET(flags, MDBX_RESERVE))
- data->iov_base = olddata.iov_base;
- else if (!(mc->mc_flags & C_SUB))
- memcpy(olddata.iov_base, data->iov_base, data->iov_len);
- else {
- mdbx_cassert(mc, NUMKEYS(mc->mc_pg[mc->mc_top]) == 1);
- mdbx_cassert(mc, mc->mc_pg[mc->mc_top]->mp_upper ==
- mc->mc_pg[mc->mc_top]->mp_lower);
- mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]) &&
- !IS_LEAF2(mc->mc_pg[mc->mc_top]));
- mdbx_cassert(mc, NODEDSZ(leaf) == 0);
- mdbx_cassert(mc, leaf->mn_flags == 0);
- mdbx_cassert(mc, key->iov_len < UINT16_MAX);
- leaf->mn_ksize = (uint16_t)key->iov_len;
- memcpy(NODEKEY(leaf), key->iov_base, key->iov_len);
- assert((char *)NODEDATA(leaf) + NODEDSZ(leaf) <
- (char *)(mc->mc_pg[mc->mc_top]) + env->me_psize);
- goto fix_parent;
- }
- return MDBX_SUCCESS;
- }
- mdbx_node_del(mc, 0);
- }
-
- rdata = data;
-
-new_sub:
- nflags = flags & NODE_ADD_FLAGS;
- nsize = IS_LEAF2(mc->mc_pg[mc->mc_top]) ? key->iov_len
- : mdbx_leaf_size(env, key, rdata);
- if (SIZELEFT(mc->mc_pg[mc->mc_top]) < nsize) {
- if ((flags & (F_DUPDATA | F_SUBDATA)) == F_DUPDATA)
- nflags &= ~MDBX_APPEND; /* sub-page may need room to grow */
- if (!insert_key)
- nflags |= MDBX_SPLIT_REPLACE;
- rc = mdbx_page_split(mc, key, rdata, P_INVALID, nflags);
- } else {
- /* There is room already in this leaf page. */
- rc = mdbx_node_add(mc, mc->mc_ki[mc->mc_top], key, rdata, 0, nflags);
- if (likely(rc == 0)) {
- /* Adjust other cursors pointing to mp */
- MDBX_cursor *m2, *m3;
- MDBX_dbi dbi = mc->mc_dbi;
- unsigned i = mc->mc_top;
- MDBX_page *mp = mc->mc_pg[i];
-
- for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) {
- if (mc->mc_flags & C_SUB)
- m3 = &m2->mc_xcursor->mx_cursor;
- else
- m3 = m2;
- if (m3 == mc || m3->mc_snum < mc->mc_snum || m3->mc_pg[i] != mp)
- continue;
- if (m3->mc_ki[i] >= mc->mc_ki[i] && insert_key) {
- m3->mc_ki[i]++;
- }
- if (XCURSOR_INITED(m3))
- XCURSOR_REFRESH(m3, mp, m3->mc_ki[i]);
- }
- }
- }
-
- if (likely(rc == MDBX_SUCCESS)) {
- /* Now store the actual data in the child DB. Note that we're
- * storing the user data in the keys field, so there are strict
- * size limits on dupdata. The actual data fields of the child
- * DB are all zero size. */
- if (do_sub) {
- int xflags;
- size_t ecount;
- put_sub:
- xdata.iov_len = 0;
- xdata.iov_base = "";
- MDBX_node *leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
- if (flags & MDBX_CURRENT) {
- xflags = (flags & MDBX_NODUPDATA)
- ? MDBX_CURRENT | MDBX_NOOVERWRITE | MDBX_NOSPILL
- : MDBX_CURRENT | MDBX_NOSPILL;
- } else {
- mdbx_xcursor_init1(mc, leaf);
- xflags = (flags & MDBX_NODUPDATA) ? MDBX_NOOVERWRITE | MDBX_NOSPILL
- : MDBX_NOSPILL;
- }
- if (sub_root)
- mc->mc_xcursor->mx_cursor.mc_pg[0] = sub_root;
- /* converted, write the original data first */
- if (dupdata_flag) {
- rc = mdbx_cursor_put(&mc->mc_xcursor->mx_cursor, &dkey, &xdata, xflags);
- if (unlikely(rc))
- goto bad_sub;
- /* we've done our job */
- dkey.iov_len = 0;
- }
- if (!(leaf->mn_flags & F_SUBDATA) || sub_root) {
- /* Adjust other cursors pointing to mp */
- MDBX_cursor *m2;
- MDBX_xcursor *mx = mc->mc_xcursor;
- unsigned i = mc->mc_top;
- MDBX_page *mp = mc->mc_pg[i];
- int nkeys = NUMKEYS(mp);
-
- for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2 = m2->mc_next) {
- if (m2 == mc || m2->mc_snum < mc->mc_snum)
- continue;
- if (!(m2->mc_flags & C_INITIALIZED))
- continue;
- if (m2->mc_pg[i] == mp) {
- if (m2->mc_ki[i] == mc->mc_ki[i]) {
- mdbx_xcursor_init2(m2, mx, dupdata_flag);
- } else if (!insert_key && m2->mc_ki[i] < nkeys) {
- XCURSOR_REFRESH(m2, mp, m2->mc_ki[i]);
- }
- }
- }
- }
- mdbx_cassert(mc, mc->mc_xcursor->mx_db.md_entries < SIZE_MAX);
- ecount = (size_t)mc->mc_xcursor->mx_db.md_entries;
- if (flags & MDBX_APPENDDUP)
- xflags |= MDBX_APPEND;
- rc = mdbx_cursor_put(&mc->mc_xcursor->mx_cursor, data, &xdata, xflags);
- if (flags & F_SUBDATA) {
- void *db = NODEDATA(leaf);
- memcpy(db, &mc->mc_xcursor->mx_db, sizeof(MDBX_db));
- }
- insert_data = (ecount != (size_t)mc->mc_xcursor->mx_db.md_entries);
- }
- /* Increment count unless we just replaced an existing item. */
- if (insert_data)
- mc->mc_db->md_entries++;
- if (insert_key) {
- /* Invalidate txn if we created an empty sub-DB */
- if (unlikely(rc))
- goto bad_sub;
- /* If we succeeded and the key didn't exist before,
- * make sure the cursor is marked valid. */
- mc->mc_flags |= C_INITIALIZED;
- }
- if (flags & MDBX_MULTIPLE) {
- if (!rc) {
- mcount++;
- /* let caller know how many succeeded, if any */
- data[1].iov_len = mcount;
- if (mcount < dcount) {
- data[0].iov_base = (char *)data[0].iov_base + data[0].iov_len;
- insert_key = insert_data = false;
- goto more;
- }
- }
- }
- return rc;
- bad_sub:
- if (unlikely(rc == MDBX_KEYEXIST))
- mdbx_error("unexpected %s", "MDBX_KEYEXIST");
- /* should not happen, we deleted that item */
- rc = MDBX_PROBLEM;
- }
- mc->mc_txn->mt_flags |= MDBX_TXN_ERROR;
- return rc;
-}
-
-int mdbx_cursor_del(MDBX_cursor *mc, unsigned flags) {
- MDBX_node *leaf;
- MDBX_page *mp;
- int rc;
-
- if (unlikely(!mc))
- return MDBX_EINVAL;
-
- if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(mc->mc_txn->mt_flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED)))
- return (mc->mc_txn->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EACCESS
- : MDBX_BAD_TXN;
-
- if (unlikely(!(mc->mc_flags & C_INITIALIZED)))
- return MDBX_EINVAL;
-
- if (unlikely(mc->mc_ki[mc->mc_top] >= NUMKEYS(mc->mc_pg[mc->mc_top])))
- return MDBX_NOTFOUND;
-
- if (unlikely(!(flags & MDBX_NOSPILL) &&
- (rc = mdbx_page_spill(mc, NULL, NULL))))
- return rc;
-
- rc = mdbx_cursor_touch(mc);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
-
- mp = mc->mc_pg[mc->mc_top];
- if (IS_LEAF2(mp))
- goto del_key;
- leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
-
- if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- if (flags & MDBX_NODUPDATA) {
- /* mdbx_cursor_del0() will subtract the final entry */
- mc->mc_db->md_entries -= mc->mc_xcursor->mx_db.md_entries - 1;
- mc->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED;
- } else {
- if (!F_ISSET(leaf->mn_flags, F_SUBDATA)) {
- mc->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf);
- }
- rc = mdbx_cursor_del(&mc->mc_xcursor->mx_cursor, MDBX_NOSPILL);
- if (unlikely(rc))
- return rc;
- /* If sub-DB still has entries, we're done */
- if (mc->mc_xcursor->mx_db.md_entries) {
- if (leaf->mn_flags & F_SUBDATA) {
- /* update subDB info */
- void *db = NODEDATA(leaf);
- memcpy(db, &mc->mc_xcursor->mx_db, sizeof(MDBX_db));
- } else {
- MDBX_cursor *m2;
- /* shrink fake page */
- mdbx_node_shrink(mp, mc->mc_ki[mc->mc_top]);
- leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
- mc->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf);
- /* fix other sub-DB cursors pointed at fake pages on this page */
- for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2 = m2->mc_next) {
- if (m2 == mc || m2->mc_snum < mc->mc_snum)
- continue;
- if (!(m2->mc_flags & C_INITIALIZED))
- continue;
- if (m2->mc_pg[mc->mc_top] == mp) {
- MDBX_node *n2 = leaf;
- if (m2->mc_ki[mc->mc_top] >= NUMKEYS(mp))
- continue;
- if (m2->mc_ki[mc->mc_top] != mc->mc_ki[mc->mc_top]) {
- n2 = NODEPTR(mp, m2->mc_ki[mc->mc_top]);
- if (n2->mn_flags & F_SUBDATA)
- continue;
- }
- m2->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(n2);
- }
- }
- }
- mc->mc_db->md_entries--;
- return rc;
- } else {
- mc->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED;
- }
- /* otherwise fall thru and delete the sub-DB */
- }
-
- if (leaf->mn_flags & F_SUBDATA) {
- /* add all the child DB's pages to the free list */
- rc = mdbx_drop0(&mc->mc_xcursor->mx_cursor, 0);
- if (unlikely(rc))
- goto fail;
- }
- }
- /* MDBX passes F_SUBDATA in 'flags' to delete a DB record */
- else if (unlikely((leaf->mn_flags ^ flags) & F_SUBDATA)) {
- rc = MDBX_INCOMPATIBLE;
- goto fail;
- }
-
- /* add overflow pages to free list */
- if (F_ISSET(leaf->mn_flags, F_BIGDATA)) {
- MDBX_page *omp;
- pgno_t pg;
-
- memcpy(&pg, NODEDATA(leaf), sizeof(pg));
- if (unlikely((rc = mdbx_page_get(mc, pg, &omp, NULL)) ||
- (rc = mdbx_ovpage_free(mc, omp))))
- goto fail;
- }
-
-del_key:
- return mdbx_cursor_del0(mc);
-
-fail:
- mc->mc_txn->mt_flags |= MDBX_TXN_ERROR;
- return rc;
-}
-
-/* Allocate and initialize new pages for a database.
- * Set MDBX_TXN_ERROR on failure.
- *
- * [in] mc a cursor on the database being added to.
- * [in] flags flags defining what type of page is being allocated.
- * [in] num the number of pages to allocate. This is usually 1,
- * unless allocating overflow pages for a large record.
- * [out] mp Address of a page, or NULL on failure.
- *
- * Returns 0 on success, non-zero on failure. */
-static int mdbx_page_new(MDBX_cursor *mc, unsigned flags, unsigned num,
- MDBX_page **mp) {
- MDBX_page *np;
- int rc;
-
- if (unlikely((rc = mdbx_page_alloc(mc, num, &np, MDBX_ALLOC_ALL))))
- return rc;
- mdbx_debug("allocated new page #%" PRIaPGNO ", size %u", np->mp_pgno,
- mc->mc_txn->mt_env->me_psize);
- np->mp_flags = (uint16_t)(flags | P_DIRTY);
- np->mp_lower = 0;
- np->mp_upper = (indx_t)(mc->mc_txn->mt_env->me_psize - PAGEHDRSZ);
-
- if (IS_BRANCH(np))
- mc->mc_db->md_branch_pages++;
- else if (IS_LEAF(np))
- mc->mc_db->md_leaf_pages++;
- else if (IS_OVERFLOW(np)) {
- mc->mc_db->md_overflow_pages += num;
- np->mp_pages = num;
- }
- *mp = np;
-
- return MDBX_SUCCESS;
-}
-
-/* Calculate the size of a leaf node.
- *
- * The size depends on the environment's page size; if a data item
- * is too large it will be put onto an overflow page and the node
- * size will only include the key and not the data. Sizes are always
- * rounded up to an even number of bytes, to guarantee 2-byte alignment
- * of the MDBX_node headers.
- *
- * [in] env The environment handle.
- * [in] key The key for the node.
- * [in] data The data for the node.
- *
- * Returns The number of bytes needed to store the node. */
-static __inline size_t mdbx_leaf_size(MDBX_env *env, MDBX_val *key,
- MDBX_val *data) {
- size_t sz;
-
- sz = LEAFSIZE(key, data);
- if (sz > env->me_nodemax) {
- /* put on overflow page */
- sz -= data->iov_len - sizeof(pgno_t);
- }
-
- return EVEN(sz + sizeof(indx_t));
-}
-
-/* Calculate the size of a branch node.
- *
- * The size should depend on the environment's page size but since
- * we currently don't support spilling large keys onto overflow
- * pages, it's simply the size of the MDBX_node header plus the
- * size of the key. Sizes are always rounded up to an even number
- * of bytes, to guarantee 2-byte alignment of the MDBX_node headers.
- *
- * [in] env The environment handle.
- * [in] key The key for the node.
- *
- * Returns The number of bytes needed to store the node. */
-static __inline size_t mdbx_branch_size(MDBX_env *env, MDBX_val *key) {
- size_t sz;
-
- sz = INDXSIZE(key);
- if (unlikely(sz > env->me_nodemax)) {
- /* put on overflow page */
- /* not implemented */
- mdbx_assert_fail(env, "INDXSIZE(key) <= env->me_nodemax", __FUNCTION__,
- __LINE__);
- sz -= key->iov_len - sizeof(pgno_t);
- }
-
- return sz + sizeof(indx_t);
-}
-
-/* Add a node to the page pointed to by the cursor.
- * Set MDBX_TXN_ERROR on failure.
- *
- * [in] mc The cursor for this operation.
- * [in] indx The index on the page where the new node should be added.
- * [in] key The key for the new node.
- * [in] data The data for the new node, if any.
- * [in] pgno The page number, if adding a branch node.
- * [in] flags Flags for the node.
- *
- * Returns 0 on success, non-zero on failure. Possible errors are:
- *
- * MDBX_ENOMEM - failed to allocate overflow pages for the node.
- * MDBX_PAGE_FULL - there is insufficient room in the page. This error
- * should never happen since all callers already calculate
- * the page's free space before calling this function. */
-static int mdbx_node_add(MDBX_cursor *mc, unsigned indx, MDBX_val *key,
- MDBX_val *data, pgno_t pgno, unsigned flags) {
- unsigned i;
- size_t node_size = NODESIZE;
- intptr_t room;
- MDBX_node *node;
- MDBX_page *mp = mc->mc_pg[mc->mc_top];
- MDBX_page *ofp = NULL; /* overflow page */
- void *ndata;
- DKBUF;
-
- mdbx_cassert(mc, mp->mp_upper >= mp->mp_lower);
-
- mdbx_debug("add to %s %spage %" PRIaPGNO " index %i, data size %" PRIuPTR
- " key size %" PRIuPTR " [%s]",
- IS_LEAF(mp) ? "leaf" : "branch", IS_SUBP(mp) ? "sub-" : "",
- mp->mp_pgno, indx, data ? data->iov_len : 0,
- key ? key->iov_len : 0, DKEY(key));
-
- if (IS_LEAF2(mp)) {
- mdbx_cassert(mc, key);
- /* Move higher keys up one slot. */
- const int ksize = mc->mc_db->md_xsize;
- char *const ptr = LEAF2KEY(mp, indx, ksize);
- const int diff = NUMKEYS(mp) - indx;
- if (diff > 0)
- memmove(ptr + ksize, ptr, diff * ksize);
- /* insert new key */
- memcpy(ptr, key->iov_base, ksize);
-
- /* Just using these for counting */
- mdbx_cassert(mc, UINT16_MAX - mp->mp_lower >= (int)sizeof(indx_t));
- mp->mp_lower += sizeof(indx_t);
- mdbx_cassert(mc, mp->mp_upper >= ksize - sizeof(indx_t));
- mp->mp_upper -= (indx_t)(ksize - sizeof(indx_t));
- return MDBX_SUCCESS;
- }
-
- room = (intptr_t)SIZELEFT(mp) - (intptr_t)sizeof(indx_t);
- if (key != NULL)
- node_size += key->iov_len;
- if (IS_LEAF(mp)) {
- mdbx_cassert(mc, key && data);
- if (unlikely(F_ISSET(flags, F_BIGDATA))) {
- /* Data already on overflow page. */
- node_size += sizeof(pgno_t);
- } else if (unlikely(node_size + data->iov_len >
- mc->mc_txn->mt_env->me_nodemax)) {
- pgno_t ovpages = OVPAGES(mc->mc_txn->mt_env, data->iov_len);
- int rc;
- /* Put data on overflow page. */
- mdbx_debug("data size is %" PRIuPTR ", node would be %" PRIuPTR
- ", put data on overflow page",
- data->iov_len, node_size + data->iov_len);
- node_size = EVEN(node_size + sizeof(pgno_t));
- if ((intptr_t)node_size > room)
- goto full;
- if ((rc = mdbx_page_new(mc, P_OVERFLOW, ovpages, &ofp)))
- return rc;
- mdbx_debug("allocated overflow page %" PRIaPGNO "", ofp->mp_pgno);
- flags |= F_BIGDATA;
- goto update;
- } else {
- node_size += data->iov_len;
- }
- }
- node_size = EVEN(node_size);
- if (unlikely((intptr_t)node_size > room))
- goto full;
-
-update:
- /* Move higher pointers up one slot. */
- for (i = NUMKEYS(mp); i > indx; i--)
- mp->mp_ptrs[i] = mp->mp_ptrs[i - 1];
-
- /* Adjust free space offsets. */
- size_t ofs = mp->mp_upper - node_size;
- mdbx_cassert(mc, ofs >= mp->mp_lower + sizeof(indx_t));
- mdbx_cassert(mc, ofs <= UINT16_MAX);
- mp->mp_ptrs[indx] = (uint16_t)ofs;
- mp->mp_upper = (uint16_t)ofs;
- mp->mp_lower += sizeof(indx_t);
-
- /* Write the node data. */
- node = NODEPTR(mp, indx);
- node->mn_ksize = (key == NULL) ? 0 : (uint16_t)key->iov_len;
- node->mn_flags = (uint16_t)flags;
- if (IS_LEAF(mp))
- SETDSZ(node, data->iov_len);
- else
- SETPGNO(node, pgno);
-
- if (key)
- memcpy(NODEKEY(node), key->iov_base, key->iov_len);
-
- if (IS_LEAF(mp)) {
- ndata = NODEDATA(node);
- if (unlikely(ofp == NULL)) {
- if (unlikely(F_ISSET(flags, F_BIGDATA)))
- memcpy(ndata, data->iov_base, sizeof(pgno_t));
- else if (F_ISSET(flags, MDBX_RESERVE))
- data->iov_base = ndata;
- else if (likely(ndata != data->iov_base))
- memcpy(ndata, data->iov_base, data->iov_len);
- } else {
- memcpy(ndata, &ofp->mp_pgno, sizeof(pgno_t));
- ndata = PAGEDATA(ofp);
- if (F_ISSET(flags, MDBX_RESERVE))
- data->iov_base = ndata;
- else if (likely(ndata != data->iov_base))
- memcpy(ndata, data->iov_base, data->iov_len);
- }
- }
-
- return MDBX_SUCCESS;
-
-full:
- mdbx_debug("not enough room in page %" PRIaPGNO ", got %u ptrs", mp->mp_pgno,
- NUMKEYS(mp));
- mdbx_debug("upper-lower = %u - %u = %" PRIiPTR "", mp->mp_upper, mp->mp_lower,
- room);
- mdbx_debug("node size = %" PRIuPTR "", node_size);
- mc->mc_txn->mt_flags |= MDBX_TXN_ERROR;
- return MDBX_PAGE_FULL;
-}
-
-/* Delete the specified node from a page.
- * [in] mc Cursor pointing to the node to delete.
- * [in] ksize The size of a node. Only used if the page is
- * part of a MDBX_DUPFIXED database. */
-static void mdbx_node_del(MDBX_cursor *mc, size_t ksize) {
- MDBX_page *mp = mc->mc_pg[mc->mc_top];
- indx_t indx = mc->mc_ki[mc->mc_top];
- indx_t i, j, numkeys, ptr;
- MDBX_node *node;
- char *base;
-
- mdbx_debug("delete node %u on %s page %" PRIaPGNO "", indx,
- IS_LEAF(mp) ? "leaf" : "branch", mp->mp_pgno);
- numkeys = NUMKEYS(mp);
- mdbx_cassert(mc, indx < numkeys);
-
- if (IS_LEAF2(mp)) {
- mdbx_cassert(mc, ksize >= sizeof(indx_t));
- unsigned diff = numkeys - 1 - indx;
- base = LEAF2KEY(mp, indx, ksize);
- if (diff)
- memmove(base, base + ksize, diff * ksize);
- mdbx_cassert(mc, mp->mp_lower >= sizeof(indx_t));
- mp->mp_lower -= sizeof(indx_t);
- mdbx_cassert(mc,
- (size_t)UINT16_MAX - mp->mp_upper >= ksize - sizeof(indx_t));
- mp->mp_upper += (indx_t)(ksize - sizeof(indx_t));
- return;
- }
-
- node = NODEPTR(mp, indx);
- size_t sz = NODESIZE + node->mn_ksize;
- if (IS_LEAF(mp)) {
- if (F_ISSET(node->mn_flags, F_BIGDATA))
- sz += sizeof(pgno_t);
- else
- sz += NODEDSZ(node);
- }
- sz = EVEN(sz);
-
- ptr = mp->mp_ptrs[indx];
- for (i = j = 0; i < numkeys; i++) {
- if (i != indx) {
- mp->mp_ptrs[j] = mp->mp_ptrs[i];
- if (mp->mp_ptrs[i] < ptr) {
- mdbx_cassert(mc, (size_t)UINT16_MAX - mp->mp_ptrs[j] >= sz);
- mp->mp_ptrs[j] += (indx_t)sz;
- }
- j++;
- }
- }
-
- base = (char *)mp + mp->mp_upper + PAGEHDRSZ;
- memmove(base + sz, base, ptr - mp->mp_upper);
-
- mdbx_cassert(mc, mp->mp_lower >= sizeof(indx_t));
- mp->mp_lower -= sizeof(indx_t);
- mdbx_cassert(mc, (size_t)UINT16_MAX - mp->mp_upper >= sz);
- mp->mp_upper += (indx_t)sz;
-}
-
-/* Compact the main page after deleting a node on a subpage.
- * [in] mp The main page to operate on.
- * [in] indx The index of the subpage on the main page. */
-static void mdbx_node_shrink(MDBX_page *mp, unsigned indx) {
- MDBX_node *node;
- MDBX_page *sp, *xp;
- char *base;
- size_t nsize, delta, len, ptr;
- int i;
-
- node = NODEPTR(mp, indx);
- sp = (MDBX_page *)NODEDATA(node);
- delta = SIZELEFT(sp);
- nsize = NODEDSZ(node) - delta;
-
- /* Prepare to shift upward, set len = length(subpage part to shift) */
- if (IS_LEAF2(sp)) {
- len = nsize;
- if (nsize & 1)
- return; /* do not make the node uneven-sized */
- } else {
- xp = (MDBX_page *)((char *)sp + delta); /* destination subpage */
- for (i = NUMKEYS(sp); --i >= 0;) {
- assert(sp->mp_ptrs[i] >= delta);
- xp->mp_ptrs[i] = (indx_t)(sp->mp_ptrs[i] - delta);
- }
- len = PAGEHDRSZ;
- }
- sp->mp_upper = sp->mp_lower;
- sp->mp_pgno = mp->mp_pgno;
- SETDSZ(node, nsize);
-
- /* Shift <lower nodes...initial part of subpage> upward */
- base = (char *)mp + mp->mp_upper + PAGEHDRSZ;
- memmove(base + delta, base, (char *)sp + len - base);
-
- ptr = mp->mp_ptrs[indx];
- for (i = NUMKEYS(mp); --i >= 0;) {
- if (mp->mp_ptrs[i] <= ptr) {
- assert((size_t)UINT16_MAX - mp->mp_ptrs[i] >= delta);
- mp->mp_ptrs[i] += (indx_t)delta;
- }
- }
- assert((size_t)UINT16_MAX - mp->mp_upper >= delta);
- mp->mp_upper += (indx_t)delta;
-}
-
-/* Initial setup of a sorted-dups cursor.
- *
- * Sorted duplicates are implemented as a sub-database for the given key.
- * The duplicate data items are actually keys of the sub-database.
- * Operations on the duplicate data items are performed using a sub-cursor
- * initialized when the sub-database is first accessed. This function does
- * the preliminary setup of the sub-cursor, filling in the fields that
- * depend only on the parent DB.
- *
- * [in] mc The main cursor whose sorted-dups cursor is to be initialized. */
-static void mdbx_xcursor_init0(MDBX_cursor *mc) {
- MDBX_xcursor *mx = mc->mc_xcursor;
-
- mx->mx_cursor.mc_xcursor = NULL;
- mx->mx_cursor.mc_txn = mc->mc_txn;
- mx->mx_cursor.mc_db = &mx->mx_db;
- mx->mx_cursor.mc_dbx = &mx->mx_dbx;
- mx->mx_cursor.mc_dbi = mc->mc_dbi;
- mx->mx_cursor.mc_dbflag = &mx->mx_dbflag;
- mx->mx_cursor.mc_snum = 0;
- mx->mx_cursor.mc_top = 0;
- mx->mx_cursor.mc_flags = C_SUB;
- mx->mx_dbx.md_name.iov_len = 0;
- mx->mx_dbx.md_name.iov_base = NULL;
- mx->mx_dbx.md_cmp = mc->mc_dbx->md_dcmp;
- mx->mx_dbx.md_dcmp = NULL;
-}
-
-/* Final setup of a sorted-dups cursor.
- * Sets up the fields that depend on the data from the main cursor.
- * [in] mc The main cursor whose sorted-dups cursor is to be initialized.
- * [in] node The data containing the MDBX_db record for the sorted-dup database.
- */
-static void mdbx_xcursor_init1(MDBX_cursor *mc, MDBX_node *node) {
- MDBX_xcursor *mx = mc->mc_xcursor;
-
- mdbx_cassert(mc, mc->mc_txn->mt_txnid >= mc->mc_txn->mt_env->me_oldest[0]);
- if (node->mn_flags & F_SUBDATA) {
- memcpy(&mx->mx_db, NODEDATA(node), sizeof(MDBX_db));
- mx->mx_cursor.mc_pg[0] = 0;
- mx->mx_cursor.mc_snum = 0;
- mx->mx_cursor.mc_top = 0;
- mx->mx_cursor.mc_flags = C_SUB;
- } else {
- MDBX_page *fp = NODEDATA(node);
- mx->mx_db.md_xsize = 0;
- mx->mx_db.md_flags = 0;
- mx->mx_db.md_depth = 1;
- mx->mx_db.md_branch_pages = 0;
- mx->mx_db.md_leaf_pages = 1;
- mx->mx_db.md_overflow_pages = 0;
- mx->mx_db.md_entries = NUMKEYS(fp);
- mx->mx_db.md_root = fp->mp_pgno;
- mx->mx_cursor.mc_snum = 1;
- mx->mx_cursor.mc_top = 0;
- mx->mx_cursor.mc_flags = C_INITIALIZED | C_SUB;
- mx->mx_cursor.mc_pg[0] = fp;
- mx->mx_cursor.mc_ki[0] = 0;
- if (mc->mc_db->md_flags & MDBX_DUPFIXED) {
- mx->mx_db.md_flags = MDBX_DUPFIXED;
- mx->mx_db.md_xsize = fp->mp_leaf2_ksize;
- if (mc->mc_db->md_flags & MDBX_INTEGERDUP)
- mx->mx_db.md_flags |= MDBX_INTEGERKEY;
- }
- }
- mdbx_debug("Sub-db -%u root page %" PRIaPGNO "", mx->mx_cursor.mc_dbi,
- mx->mx_db.md_root);
- mx->mx_dbflag = DB_VALID | DB_USRVALID | DB_DUPDATA;
- /* FIXME: #if UINT_MAX < SIZE_MAX
- if (mx->mx_dbx.md_cmp == mdbx_cmp_int && mx->mx_db.md_pad ==
- sizeof(size_t))
- mx->mx_dbx.md_cmp = mdbx_cmp_clong;
- #endif */
-}
-
-/* Fixup a sorted-dups cursor due to underlying update.
- * Sets up some fields that depend on the data from the main cursor.
- * Almost the same as init1, but skips initialization steps if the
- * xcursor had already been used.
- * [in] mc The main cursor whose sorted-dups cursor is to be fixed up.
- * [in] src_mx The xcursor of an up-to-date cursor.
- * [in] new_dupdata True if converting from a non-F_DUPDATA item. */
-static void mdbx_xcursor_init2(MDBX_cursor *mc, MDBX_xcursor *src_mx,
- int new_dupdata) {
- MDBX_xcursor *mx = mc->mc_xcursor;
-
- mdbx_cassert(mc, mc->mc_txn->mt_txnid >= mc->mc_txn->mt_env->me_oldest[0]);
- if (new_dupdata) {
- mx->mx_cursor.mc_snum = 1;
- mx->mx_cursor.mc_top = 0;
- mx->mx_cursor.mc_flags |= C_INITIALIZED;
- mx->mx_cursor.mc_ki[0] = 0;
- mx->mx_dbflag = DB_VALID | DB_USRVALID | DB_DUPDATA;
- mx->mx_dbx.md_cmp = src_mx->mx_dbx.md_cmp;
- } else if (!(mx->mx_cursor.mc_flags & C_INITIALIZED)) {
- return;
- }
- mx->mx_db = src_mx->mx_db;
- mx->mx_cursor.mc_pg[0] = src_mx->mx_cursor.mc_pg[0];
- mdbx_debug("Sub-db -%u root page %" PRIaPGNO "", mx->mx_cursor.mc_dbi,
- mx->mx_db.md_root);
-}
-
-/* Initialize a cursor for a given transaction and database. */
-static void mdbx_cursor_init(MDBX_cursor *mc, MDBX_txn *txn, MDBX_dbi dbi,
- MDBX_xcursor *mx) {
- mc->mc_signature = MDBX_MC_SIGNATURE;
- mc->mc_next = NULL;
- mc->mc_backup = NULL;
- mc->mc_dbi = dbi;
- mc->mc_txn = txn;
- mc->mc_db = &txn->mt_dbs[dbi];
- mc->mc_dbx = &txn->mt_dbxs[dbi];
- mc->mc_dbflag = &txn->mt_dbflags[dbi];
- mc->mc_snum = 0;
- mc->mc_top = 0;
- mc->mc_pg[0] = 0;
- mc->mc_flags = 0;
- mc->mc_ki[0] = 0;
- mc->mc_xcursor = NULL;
- if (txn->mt_dbs[dbi].md_flags & MDBX_DUPSORT) {
- mdbx_tassert(txn, mx != NULL);
- mx->mx_cursor.mc_signature = MDBX_MC_SIGNATURE;
- mc->mc_xcursor = mx;
- mdbx_xcursor_init0(mc);
- }
- mdbx_cassert(mc, mc->mc_txn->mt_txnid >= mc->mc_txn->mt_env->me_oldest[0]);
- if (unlikely(*mc->mc_dbflag & DB_STALE)) {
- mdbx_page_search(mc, NULL, MDBX_PS_ROOTONLY);
- }
-}
-
-int mdbx_cursor_open(MDBX_txn *txn, MDBX_dbi dbi, MDBX_cursor **ret) {
- MDBX_cursor *mc;
- size_t size = sizeof(MDBX_cursor);
-
- if (unlikely(!ret || !txn))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_VALID)))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED))
- return MDBX_BAD_TXN;
-
- if (unlikely(dbi == FREE_DBI && !F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY)))
- return MDBX_EINVAL;
-
- if (txn->mt_dbs[dbi].md_flags & MDBX_DUPSORT)
- size += sizeof(MDBX_xcursor);
-
- if (likely((mc = malloc(size)) != NULL)) {
- mdbx_cursor_init(mc, txn, dbi, (MDBX_xcursor *)(mc + 1));
- if (txn->mt_cursors) {
- mc->mc_next = txn->mt_cursors[dbi];
- txn->mt_cursors[dbi] = mc;
- mc->mc_flags |= C_UNTRACK;
- }
- } else {
- return MDBX_ENOMEM;
- }
-
- *ret = mc;
-
- return MDBX_SUCCESS;
-}
-
-int mdbx_cursor_renew(MDBX_txn *txn, MDBX_cursor *mc) {
- if (unlikely(!mc || !txn))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE &&
- mc->mc_signature != MDBX_MC_READY4CLOSE))
- return MDBX_EINVAL;
-
- if (unlikely(!TXN_DBI_EXIST(txn, mc->mc_dbi, DB_VALID)))
- return MDBX_EINVAL;
-
- if (unlikely(mc->mc_backup))
- return MDBX_EINVAL;
-
- if (unlikely((mc->mc_flags & C_UNTRACK) || txn->mt_cursors)) {
- MDBX_cursor **prev = &mc->mc_txn->mt_cursors[mc->mc_dbi];
- while (*prev && *prev != mc)
- prev = &(*prev)->mc_next;
- if (*prev == mc)
- *prev = mc->mc_next;
- mc->mc_signature = MDBX_MC_READY4CLOSE;
- }
-
- if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED))
- return MDBX_BAD_TXN;
-
- mdbx_cursor_init(mc, txn, mc->mc_dbi, mc->mc_xcursor);
- return MDBX_SUCCESS;
-}
-
-/* Return the count of duplicate data items for the current key */
-int mdbx_cursor_count(MDBX_cursor *mc, size_t *countp) {
- if (unlikely(mc == NULL || countp == NULL))
- return MDBX_EINVAL;
-
- if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(mc->mc_txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- if (unlikely(mc->mc_txn->mt_flags & MDBX_TXN_BLOCKED))
- return MDBX_BAD_TXN;
-
- if (unlikely(!(mc->mc_flags & C_INITIALIZED)))
- return MDBX_EINVAL;
-
- if (!mc->mc_snum) {
- *countp = 0;
- return MDBX_NOTFOUND;
- }
-
- MDBX_page *mp = mc->mc_pg[mc->mc_top];
- if ((mc->mc_flags & C_EOF) && mc->mc_ki[mc->mc_top] >= NUMKEYS(mp)) {
- *countp = 0;
- return MDBX_NOTFOUND;
- }
-
- *countp = 1;
- if (mc->mc_xcursor != NULL) {
- MDBX_node *leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
- if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- mdbx_cassert(mc, mc->mc_xcursor && (mc->mc_xcursor->mx_cursor.mc_flags &
- C_INITIALIZED));
- *countp = unlikely(mc->mc_xcursor->mx_db.md_entries > SIZE_MAX)
- ? SIZE_MAX
- : (size_t)mc->mc_xcursor->mx_db.md_entries;
- }
- }
- return MDBX_SUCCESS;
-}
-
-void mdbx_cursor_close(MDBX_cursor *mc) {
- if (mc) {
- mdbx_ensure(NULL, mc->mc_signature == MDBX_MC_SIGNATURE ||
- mc->mc_signature == MDBX_MC_READY4CLOSE);
- if (!mc->mc_backup) {
- /* Remove from txn, if tracked.
- * A read-only txn (!C_UNTRACK) may have been freed already,
- * so do not peek inside it. Only write txns track cursors. */
- if ((mc->mc_flags & C_UNTRACK) && mc->mc_txn->mt_cursors) {
- MDBX_cursor **prev = &mc->mc_txn->mt_cursors[mc->mc_dbi];
- while (*prev && *prev != mc)
- prev = &(*prev)->mc_next;
- if (*prev == mc)
- *prev = mc->mc_next;
- }
- mc->mc_signature = 0;
- free(mc);
- } else {
- /* cursor closed before nested txn ends */
- mdbx_cassert(mc, mc->mc_signature == MDBX_MC_SIGNATURE);
- mc->mc_signature = MDBX_MC_WAIT4EOT;
- }
- }
-}
-
-MDBX_txn *mdbx_cursor_txn(MDBX_cursor *mc) {
- if (unlikely(!mc || mc->mc_signature != MDBX_MC_SIGNATURE))
- return NULL;
- return mc->mc_txn;
-}
-
-MDBX_dbi mdbx_cursor_dbi(MDBX_cursor *mc) {
- if (unlikely(!mc || mc->mc_signature != MDBX_MC_SIGNATURE))
- return UINT_MAX;
- return mc->mc_dbi;
-}
-
-/* Replace the key for a branch node with a new key.
- * Set MDBX_TXN_ERROR on failure.
- * [in] mc Cursor pointing to the node to operate on.
- * [in] key The new key to use.
- * Returns 0 on success, non-zero on failure. */
-static int mdbx_update_key(MDBX_cursor *mc, MDBX_val *key) {
- MDBX_page *mp;
- MDBX_node *node;
- char *base;
- size_t len;
- int delta, ksize, oksize;
- indx_t ptr, i, numkeys, indx;
- DKBUF;
-
- indx = mc->mc_ki[mc->mc_top];
- mp = mc->mc_pg[mc->mc_top];
- node = NODEPTR(mp, indx);
- ptr = mp->mp_ptrs[indx];
- if (MDBX_DEBUG) {
- MDBX_val k2;
- char kbuf2[DKBUF_MAXKEYSIZE * 2 + 1];
- k2.iov_base = NODEKEY(node);
- k2.iov_len = node->mn_ksize;
- mdbx_debug("update key %u (ofs %u) [%s] to [%s] on page %" PRIaPGNO "",
- indx, ptr, mdbx_dkey(&k2, kbuf2, sizeof(kbuf2)), DKEY(key),
- mp->mp_pgno);
- }
-
- /* Sizes must be 2-byte aligned. */
- ksize = EVEN(key->iov_len);
- oksize = EVEN(node->mn_ksize);
- delta = ksize - oksize;
-
- /* Shift node contents if EVEN(key length) changed. */
- if (delta) {
- if (delta > 0 && SIZELEFT(mp) < delta) {
- pgno_t pgno;
- /* not enough space left, do a delete and split */
- mdbx_debug("Not enough room, delta = %d, splitting...", delta);
- pgno = NODEPGNO(node);
- mdbx_node_del(mc, 0);
- return mdbx_page_split(mc, key, NULL, pgno, MDBX_SPLIT_REPLACE);
- }
-
- numkeys = NUMKEYS(mp);
- for (i = 0; i < numkeys; i++) {
- if (mp->mp_ptrs[i] <= ptr) {
- mdbx_cassert(mc, mp->mp_ptrs[i] >= delta);
- mp->mp_ptrs[i] -= (indx_t)delta;
- }
- }
-
- base = (char *)mp + mp->mp_upper + PAGEHDRSZ;
- len = ptr - mp->mp_upper + NODESIZE;
- memmove(base - delta, base, len);
- mdbx_cassert(mc, mp->mp_upper >= delta);
- mp->mp_upper -= (indx_t)delta;
-
- node = NODEPTR(mp, indx);
- }
-
- /* But even if no shift was needed, update ksize */
- if (node->mn_ksize != key->iov_len)
- node->mn_ksize = (uint16_t)key->iov_len;
-
- if (key->iov_len)
- memcpy(NODEKEY(node), key->iov_base, key->iov_len);
-
- return MDBX_SUCCESS;
-}
-
-static void mdbx_cursor_copy(const MDBX_cursor *csrc, MDBX_cursor *cdst);
-
-/* Perform act while tracking temporary cursor mn */
-#define WITH_CURSOR_TRACKING(mn, act) \
- do { \
- mdbx_cassert(&(mn), \
- mn.mc_txn->mt_cursors != NULL /* must be not rdonly txt */); \
- MDBX_cursor mc_dummy, *tracked, \
- **tp = &(mn).mc_txn->mt_cursors[mn.mc_dbi]; \
- if ((mn).mc_flags & C_SUB) { \
- mc_dummy.mc_flags = C_INITIALIZED; \
- mc_dummy.mc_xcursor = (MDBX_xcursor *)&(mn); \
- tracked = &mc_dummy; \
- } else { \
- tracked = &(mn); \
- } \
- tracked->mc_next = *tp; \
- *tp = tracked; \
- { act; } \
- *tp = tracked->mc_next; \
- } while (0)
-
-/* Move a node from csrc to cdst. */
-static int mdbx_node_move(MDBX_cursor *csrc, MDBX_cursor *cdst, int fromleft) {
- MDBX_node *srcnode;
- MDBX_val key, data;
- pgno_t srcpg;
- MDBX_cursor mn;
- int rc;
- unsigned flags;
-
- DKBUF;
-
- /* Mark src and dst as dirty. */
- if (unlikely((rc = mdbx_page_touch(csrc)) || (rc = mdbx_page_touch(cdst))))
- return rc;
-
- if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
- key.iov_len = csrc->mc_db->md_xsize;
- key.iov_base = LEAF2KEY(csrc->mc_pg[csrc->mc_top],
- csrc->mc_ki[csrc->mc_top], key.iov_len);
- data.iov_len = 0;
- data.iov_base = NULL;
- srcpg = 0;
- flags = 0;
- } else {
- srcnode = NODEPTR(csrc->mc_pg[csrc->mc_top], csrc->mc_ki[csrc->mc_top]);
- mdbx_cassert(csrc, !((size_t)srcnode & 1));
- srcpg = NODEPGNO(srcnode);
- flags = srcnode->mn_flags;
- if (csrc->mc_ki[csrc->mc_top] == 0 &&
- IS_BRANCH(csrc->mc_pg[csrc->mc_top])) {
- unsigned snum = csrc->mc_snum;
- MDBX_node *s2;
- /* must find the lowest key below src */
- rc = mdbx_page_search_lowest(csrc);
- if (unlikely(rc))
- return rc;
- if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
- key.iov_len = csrc->mc_db->md_xsize;
- key.iov_base = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.iov_len);
- } else {
- s2 = NODEPTR(csrc->mc_pg[csrc->mc_top], 0);
- key.iov_len = NODEKSZ(s2);
- key.iov_base = NODEKEY(s2);
- }
- mdbx_cassert(csrc, snum >= 1 && snum <= UINT16_MAX);
- csrc->mc_snum = (uint16_t)snum--;
- csrc->mc_top = (uint16_t)snum;
- } else {
- key.iov_len = NODEKSZ(srcnode);
- key.iov_base = NODEKEY(srcnode);
- }
- data.iov_len = NODEDSZ(srcnode);
- data.iov_base = NODEDATA(srcnode);
- }
- mn.mc_xcursor = NULL;
- if (IS_BRANCH(cdst->mc_pg[cdst->mc_top]) && cdst->mc_ki[cdst->mc_top] == 0) {
- unsigned snum = cdst->mc_snum;
- MDBX_node *s2;
- MDBX_val bkey;
- /* must find the lowest key below dst */
- mdbx_cursor_copy(cdst, &mn);
- rc = mdbx_page_search_lowest(&mn);
- if (unlikely(rc))
- return rc;
- if (IS_LEAF2(mn.mc_pg[mn.mc_top])) {
- bkey.iov_len = mn.mc_db->md_xsize;
- bkey.iov_base = LEAF2KEY(mn.mc_pg[mn.mc_top], 0, bkey.iov_len);
- } else {
- s2 = NODEPTR(mn.mc_pg[mn.mc_top], 0);
- bkey.iov_len = NODEKSZ(s2);
- bkey.iov_base = NODEKEY(s2);
- }
- mdbx_cassert(csrc, snum >= 1 && snum <= UINT16_MAX);
- mn.mc_snum = (uint16_t)snum--;
- mn.mc_top = (uint16_t)snum;
- mn.mc_ki[snum] = 0;
- rc = mdbx_update_key(&mn, &bkey);
- if (unlikely(rc))
- return rc;
- }
-
- mdbx_debug("moving %s node %u [%s] on page %" PRIaPGNO
- " to node %u on page %" PRIaPGNO "",
- IS_LEAF(csrc->mc_pg[csrc->mc_top]) ? "leaf" : "branch",
- csrc->mc_ki[csrc->mc_top], DKEY(&key),
- csrc->mc_pg[csrc->mc_top]->mp_pgno, cdst->mc_ki[cdst->mc_top],
- cdst->mc_pg[cdst->mc_top]->mp_pgno);
-
- /* Add the node to the destination page. */
- rc =
- mdbx_node_add(cdst, cdst->mc_ki[cdst->mc_top], &key, &data, srcpg, flags);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
-
- /* Delete the node from the source page. */
- mdbx_node_del(csrc, key.iov_len);
-
- {
- /* Adjust other cursors pointing to mp */
- MDBX_cursor *m2, *m3;
- MDBX_dbi dbi = csrc->mc_dbi;
- MDBX_page *mpd, *mps;
-
- mps = csrc->mc_pg[csrc->mc_top];
- /* If we're adding on the left, bump others up */
- if (fromleft) {
- mpd = cdst->mc_pg[csrc->mc_top];
- for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) {
- if (csrc->mc_flags & C_SUB)
- m3 = &m2->mc_xcursor->mx_cursor;
- else
- m3 = m2;
- if (!(m3->mc_flags & C_INITIALIZED) || m3->mc_top < csrc->mc_top)
- continue;
- if (m3 != cdst && m3->mc_pg[csrc->mc_top] == mpd &&
- m3->mc_ki[csrc->mc_top] >= cdst->mc_ki[csrc->mc_top]) {
- m3->mc_ki[csrc->mc_top]++;
- }
- if (m3 != csrc && m3->mc_pg[csrc->mc_top] == mps &&
- m3->mc_ki[csrc->mc_top] == csrc->mc_ki[csrc->mc_top]) {
- m3->mc_pg[csrc->mc_top] = cdst->mc_pg[cdst->mc_top];
- m3->mc_ki[csrc->mc_top] = cdst->mc_ki[cdst->mc_top];
- m3->mc_ki[csrc->mc_top - 1]++;
- }
- if (XCURSOR_INITED(m3) && IS_LEAF(mps))
- XCURSOR_REFRESH(m3, m3->mc_pg[csrc->mc_top], m3->mc_ki[csrc->mc_top]);
- }
- } else
- /* Adding on the right, bump others down */
- {
- for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) {
- if (csrc->mc_flags & C_SUB)
- m3 = &m2->mc_xcursor->mx_cursor;
- else
- m3 = m2;
- if (m3 == csrc)
- continue;
- if (!(m3->mc_flags & C_INITIALIZED) || m3->mc_top < csrc->mc_top)
- continue;
- if (m3->mc_pg[csrc->mc_top] == mps) {
- if (!m3->mc_ki[csrc->mc_top]) {
- m3->mc_pg[csrc->mc_top] = cdst->mc_pg[cdst->mc_top];
- m3->mc_ki[csrc->mc_top] = cdst->mc_ki[cdst->mc_top];
- m3->mc_ki[csrc->mc_top - 1]--;
- } else {
- m3->mc_ki[csrc->mc_top]--;
- }
- if (XCURSOR_INITED(m3) && IS_LEAF(mps))
- XCURSOR_REFRESH(m3, m3->mc_pg[csrc->mc_top],
- m3->mc_ki[csrc->mc_top]);
- }
- }
- }
- }
-
- /* Update the parent separators. */
- if (csrc->mc_ki[csrc->mc_top] == 0) {
- if (csrc->mc_ki[csrc->mc_top - 1] != 0) {
- if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
- key.iov_base = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.iov_len);
- } else {
- srcnode = NODEPTR(csrc->mc_pg[csrc->mc_top], 0);
- key.iov_len = NODEKSZ(srcnode);
- key.iov_base = NODEKEY(srcnode);
- }
- mdbx_debug("update separator for source page %" PRIaPGNO " to [%s]",
- csrc->mc_pg[csrc->mc_top]->mp_pgno, DKEY(&key));
- mdbx_cursor_copy(csrc, &mn);
- mn.mc_snum--;
- mn.mc_top--;
- /* We want mdbx_rebalance to find mn when doing fixups */
- WITH_CURSOR_TRACKING(mn, rc = mdbx_update_key(&mn, &key));
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
- }
- if (IS_BRANCH(csrc->mc_pg[csrc->mc_top])) {
- MDBX_val nullkey;
- indx_t ix = csrc->mc_ki[csrc->mc_top];
- nullkey.iov_len = 0;
- csrc->mc_ki[csrc->mc_top] = 0;
- rc = mdbx_update_key(csrc, &nullkey);
- csrc->mc_ki[csrc->mc_top] = ix;
- mdbx_cassert(csrc, rc == MDBX_SUCCESS);
- }
- }
-
- if (cdst->mc_ki[cdst->mc_top] == 0) {
- if (cdst->mc_ki[cdst->mc_top - 1] != 0) {
- if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
- key.iov_base = LEAF2KEY(cdst->mc_pg[cdst->mc_top], 0, key.iov_len);
- } else {
- srcnode = NODEPTR(cdst->mc_pg[cdst->mc_top], 0);
- key.iov_len = NODEKSZ(srcnode);
- key.iov_base = NODEKEY(srcnode);
- }
- mdbx_debug("update separator for destination page %" PRIaPGNO " to [%s]",
- cdst->mc_pg[cdst->mc_top]->mp_pgno, DKEY(&key));
- mdbx_cursor_copy(cdst, &mn);
- mn.mc_snum--;
- mn.mc_top--;
- /* We want mdbx_rebalance to find mn when doing fixups */
- WITH_CURSOR_TRACKING(mn, rc = mdbx_update_key(&mn, &key));
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
- }
- if (IS_BRANCH(cdst->mc_pg[cdst->mc_top])) {
- MDBX_val nullkey;
- indx_t ix = cdst->mc_ki[cdst->mc_top];
- nullkey.iov_len = 0;
- cdst->mc_ki[cdst->mc_top] = 0;
- rc = mdbx_update_key(cdst, &nullkey);
- cdst->mc_ki[cdst->mc_top] = ix;
- mdbx_cassert(cdst, rc == MDBX_SUCCESS);
- }
- }
-
- return MDBX_SUCCESS;
-}
-
-/* Merge one page into another.
- *
- * The nodes from the page pointed to by csrc will be copied to the page
- * pointed to by cdst and then the csrc page will be freed.
- *
- * [in] csrc Cursor pointing to the source page.
- * [in] cdst Cursor pointing to the destination page.
- *
- * Returns 0 on success, non-zero on failure. */
-static int mdbx_page_merge(MDBX_cursor *csrc, MDBX_cursor *cdst) {
- MDBX_page *psrc, *pdst;
- MDBX_node *srcnode;
- MDBX_val key, data;
- unsigned nkeys;
- int rc;
- unsigned i, j;
-
- psrc = csrc->mc_pg[csrc->mc_top];
- pdst = cdst->mc_pg[cdst->mc_top];
-
- mdbx_debug("merging page %" PRIaPGNO " into %" PRIaPGNO "", psrc->mp_pgno,
- pdst->mp_pgno);
-
- mdbx_cassert(csrc, csrc->mc_snum > 1); /* can't merge root page */
- mdbx_cassert(csrc, cdst->mc_snum > 1);
-
- /* Mark dst as dirty. */
- if (unlikely(rc = mdbx_page_touch(cdst)))
- return rc;
-
- /* get dst page again now that we've touched it. */
- pdst = cdst->mc_pg[cdst->mc_top];
-
- /* Move all nodes from src to dst. */
- j = nkeys = NUMKEYS(pdst);
- if (IS_LEAF2(psrc)) {
- key.iov_len = csrc->mc_db->md_xsize;
- key.iov_base = PAGEDATA(psrc);
- for (i = 0; i < NUMKEYS(psrc); i++, j++) {
- rc = mdbx_node_add(cdst, j, &key, NULL, 0, 0);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
- key.iov_base = (char *)key.iov_base + key.iov_len;
- }
- } else {
- for (i = 0; i < NUMKEYS(psrc); i++, j++) {
- srcnode = NODEPTR(psrc, i);
- if (i == 0 && IS_BRANCH(psrc)) {
- MDBX_cursor mn;
- MDBX_node *s2;
- mdbx_cursor_copy(csrc, &mn);
- mn.mc_xcursor = NULL;
- /* must find the lowest key below src */
- rc = mdbx_page_search_lowest(&mn);
- if (unlikely(rc))
- return rc;
- if (IS_LEAF2(mn.mc_pg[mn.mc_top])) {
- key.iov_len = mn.mc_db->md_xsize;
- key.iov_base = LEAF2KEY(mn.mc_pg[mn.mc_top], 0, key.iov_len);
- } else {
- s2 = NODEPTR(mn.mc_pg[mn.mc_top], 0);
- key.iov_len = NODEKSZ(s2);
- key.iov_base = NODEKEY(s2);
- }
- } else {
- key.iov_len = srcnode->mn_ksize;
- key.iov_base = NODEKEY(srcnode);
- }
-
- data.iov_len = NODEDSZ(srcnode);
- data.iov_base = NODEDATA(srcnode);
- rc = mdbx_node_add(cdst, j, &key, &data, NODEPGNO(srcnode),
- srcnode->mn_flags);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
- }
- }
-
- mdbx_debug("dst page %" PRIaPGNO " now has %u keys (%.1f%% filled)",
- pdst->mp_pgno, NUMKEYS(pdst),
- (float)PAGEFILL(cdst->mc_txn->mt_env, pdst) / 10);
-
- /* Unlink the src page from parent and add to free list. */
- csrc->mc_top--;
- mdbx_node_del(csrc, 0);
- if (csrc->mc_ki[csrc->mc_top] == 0) {
- key.iov_len = 0;
- rc = mdbx_update_key(csrc, &key);
- if (unlikely(rc)) {
- csrc->mc_top++;
- return rc;
- }
- }
- csrc->mc_top++;
-
- psrc = csrc->mc_pg[csrc->mc_top];
- /* If not operating on FreeDB, allow this page to be reused
- * in this txn. Otherwise just add to free list. */
- rc = mdbx_page_loose(csrc, psrc);
- if (unlikely(rc))
- return rc;
- if (IS_LEAF(psrc))
- csrc->mc_db->md_leaf_pages--;
- else
- csrc->mc_db->md_branch_pages--;
- {
- /* Adjust other cursors pointing to mp */
- MDBX_cursor *m2, *m3;
- MDBX_dbi dbi = csrc->mc_dbi;
- unsigned top = csrc->mc_top;
-
- for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) {
- if (csrc->mc_flags & C_SUB)
- m3 = &m2->mc_xcursor->mx_cursor;
- else
- m3 = m2;
- if (m3 == csrc)
- continue;
- if (m3->mc_snum < csrc->mc_snum)
- continue;
- if (m3->mc_pg[top] == psrc) {
- m3->mc_pg[top] = pdst;
- mdbx_cassert(m3, nkeys + m3->mc_ki[top] <= UINT16_MAX);
- m3->mc_ki[top] += (indx_t)nkeys;
- m3->mc_ki[top - 1] = cdst->mc_ki[top - 1];
- } else if (m3->mc_pg[top - 1] == csrc->mc_pg[top - 1] &&
- m3->mc_ki[top - 1] > csrc->mc_ki[top - 1]) {
- m3->mc_ki[top - 1]--;
- }
- if (XCURSOR_INITED(m3) && IS_LEAF(psrc))
- XCURSOR_REFRESH(m3, m3->mc_pg[top], m3->mc_ki[top]);
- }
- }
- {
- unsigned snum = cdst->mc_snum;
- uint16_t depth = cdst->mc_db->md_depth;
- mdbx_cursor_pop(cdst);
- rc = mdbx_rebalance(cdst);
- /* Did the tree height change? */
- if (depth != cdst->mc_db->md_depth)
- snum += cdst->mc_db->md_depth - depth;
- mdbx_cassert(cdst, snum >= 1 && snum <= UINT16_MAX);
- cdst->mc_snum = (uint16_t)snum;
- cdst->mc_top = (uint16_t)(snum - 1);
- }
- return rc;
-}
-
-/* Copy the contents of a cursor.
- * [in] csrc The cursor to copy from.
- * [out] cdst The cursor to copy to. */
-static void mdbx_cursor_copy(const MDBX_cursor *csrc, MDBX_cursor *cdst) {
- unsigned i;
-
- mdbx_cassert(csrc,
- csrc->mc_txn->mt_txnid >= csrc->mc_txn->mt_env->me_oldest[0]);
- cdst->mc_txn = csrc->mc_txn;
- cdst->mc_dbi = csrc->mc_dbi;
- cdst->mc_db = csrc->mc_db;
- cdst->mc_dbx = csrc->mc_dbx;
- cdst->mc_snum = csrc->mc_snum;
- cdst->mc_top = csrc->mc_top;
- cdst->mc_flags = csrc->mc_flags;
-
- for (i = 0; i < csrc->mc_snum; i++) {
- cdst->mc_pg[i] = csrc->mc_pg[i];
- cdst->mc_ki[i] = csrc->mc_ki[i];
- }
-}
-
-/* Rebalance the tree after a delete operation.
- * [in] mc Cursor pointing to the page where rebalancing should begin.
- * Returns 0 on success, non-zero on failure. */
-static int mdbx_rebalance(MDBX_cursor *mc) {
- MDBX_node *node;
- int rc, fromleft;
- unsigned ptop, minkeys, thresh;
- MDBX_cursor mn;
- indx_t oldki;
-
- if (IS_BRANCH(mc->mc_pg[mc->mc_top])) {
- minkeys = 2;
- thresh = 1;
- } else {
- minkeys = 1;
- thresh = FILL_THRESHOLD;
- }
- mdbx_debug("rebalancing %s page %" PRIaPGNO " (has %u keys, %.1f%% full)",
- IS_LEAF(mc->mc_pg[mc->mc_top]) ? "leaf" : "branch",
- mc->mc_pg[mc->mc_top]->mp_pgno, NUMKEYS(mc->mc_pg[mc->mc_top]),
- (float)PAGEFILL(mc->mc_txn->mt_env, mc->mc_pg[mc->mc_top]) / 10);
-
- if (PAGEFILL(mc->mc_txn->mt_env, mc->mc_pg[mc->mc_top]) >= thresh &&
- NUMKEYS(mc->mc_pg[mc->mc_top]) >= minkeys) {
- mdbx_debug("no need to rebalance page %" PRIaPGNO ", above fill threshold",
- mc->mc_pg[mc->mc_top]->mp_pgno);
- return MDBX_SUCCESS;
- }
-
- if (mc->mc_snum < 2) {
- MDBX_page *mp = mc->mc_pg[0];
- unsigned nkeys = NUMKEYS(mp);
- if (IS_SUBP(mp)) {
- mdbx_debug("Can't rebalance a subpage, ignoring");
- return MDBX_SUCCESS;
- }
- if (nkeys == 0) {
- mdbx_debug("tree is completely empty");
- mc->mc_db->md_root = P_INVALID;
- mc->mc_db->md_depth = 0;
- mc->mc_db->md_leaf_pages = 0;
- rc = mdbx_pnl_append(&mc->mc_txn->mt_befree_pages, mp->mp_pgno);
- if (unlikely(rc))
- return rc;
- /* Adjust cursors pointing to mp */
- mc->mc_snum = 0;
- mc->mc_top = 0;
- mc->mc_flags &= ~C_INITIALIZED;
- {
- MDBX_cursor *m2, *m3;
- MDBX_dbi dbi = mc->mc_dbi;
-
- for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) {
- if (mc->mc_flags & C_SUB)
- m3 = &m2->mc_xcursor->mx_cursor;
- else
- m3 = m2;
- if (!(m3->mc_flags & C_INITIALIZED) || (m3->mc_snum < mc->mc_snum))
- continue;
- if (m3->mc_pg[0] == mp) {
- m3->mc_snum = 0;
- m3->mc_top = 0;
- m3->mc_flags &= ~C_INITIALIZED;
- }
- }
- }
- } else if (IS_BRANCH(mp) && NUMKEYS(mp) == 1) {
- int i;
- mdbx_debug("collapsing root page!");
- rc = mdbx_pnl_append(&mc->mc_txn->mt_befree_pages, mp->mp_pgno);
- if (unlikely(rc))
- return rc;
- mc->mc_db->md_root = NODEPGNO(NODEPTR(mp, 0));
- rc = mdbx_page_get(mc, mc->mc_db->md_root, &mc->mc_pg[0], NULL);
- if (unlikely(rc))
- return rc;
- mc->mc_db->md_depth--;
- mc->mc_db->md_branch_pages--;
- mc->mc_ki[0] = mc->mc_ki[1];
- for (i = 1; i < mc->mc_db->md_depth; i++) {
- mc->mc_pg[i] = mc->mc_pg[i + 1];
- mc->mc_ki[i] = mc->mc_ki[i + 1];
- }
- {
- /* Adjust other cursors pointing to mp */
- MDBX_cursor *m2, *m3;
- MDBX_dbi dbi = mc->mc_dbi;
-
- for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) {
- if (mc->mc_flags & C_SUB)
- m3 = &m2->mc_xcursor->mx_cursor;
- else
- m3 = m2;
- if (m3 == mc)
- continue;
- if (!(m3->mc_flags & C_INITIALIZED))
- continue;
- if (m3->mc_pg[0] == mp) {
- for (i = 0; i < mc->mc_db->md_depth; i++) {
- m3->mc_pg[i] = m3->mc_pg[i + 1];
- m3->mc_ki[i] = m3->mc_ki[i + 1];
- }
- m3->mc_snum--;
- m3->mc_top--;
- }
- }
- }
- } else {
- mdbx_debug("root page %" PRIaPGNO
- " doesn't need rebalancing (flags 0x%x)",
- mp->mp_pgno, mp->mp_flags);
- }
- return MDBX_SUCCESS;
- }
-
- /* The parent (branch page) must have at least 2 pointers,
- * otherwise the tree is invalid. */
- ptop = mc->mc_top - 1;
- mdbx_cassert(mc, NUMKEYS(mc->mc_pg[ptop]) > 1);
-
- /* Leaf page fill factor is below the threshold.
- * Try to move keys from left or right neighbor, or
- * merge with a neighbor page. */
-
- /* Find neighbors. */
- mdbx_cursor_copy(mc, &mn);
- mn.mc_xcursor = NULL;
-
- oldki = mc->mc_ki[mc->mc_top];
- if (mc->mc_ki[ptop] == 0) {
- /* We're the leftmost leaf in our parent. */
- mdbx_debug("reading right neighbor");
- mn.mc_ki[ptop]++;
- node = NODEPTR(mc->mc_pg[ptop], mn.mc_ki[ptop]);
- rc = mdbx_page_get(mc, NODEPGNO(node), &mn.mc_pg[mn.mc_top], NULL);
- if (unlikely(rc))
- return rc;
- mn.mc_ki[mn.mc_top] = 0;
- mc->mc_ki[mc->mc_top] = NUMKEYS(mc->mc_pg[mc->mc_top]);
- fromleft = 0;
- } else {
- /* There is at least one neighbor to the left. */
- mdbx_debug("reading left neighbor");
- mn.mc_ki[ptop]--;
- node = NODEPTR(mc->mc_pg[ptop], mn.mc_ki[ptop]);
- rc = mdbx_page_get(mc, NODEPGNO(node), &mn.mc_pg[mn.mc_top], NULL);
- if (unlikely(rc))
- return rc;
- mn.mc_ki[mn.mc_top] = NUMKEYS(mn.mc_pg[mn.mc_top]) - 1;
- mc->mc_ki[mc->mc_top] = 0;
- fromleft = 1;
- }
-
- mdbx_debug("found neighbor page %" PRIaPGNO " (%u keys, %.1f%% full)",
- mn.mc_pg[mn.mc_top]->mp_pgno, NUMKEYS(mn.mc_pg[mn.mc_top]),
- (float)PAGEFILL(mc->mc_txn->mt_env, mn.mc_pg[mn.mc_top]) / 10);
-
- /* If the neighbor page is above threshold and has enough keys,
- * move one key from it. Otherwise we should try to merge them.
- * (A branch page must never have less than 2 keys.) */
- if (PAGEFILL(mc->mc_txn->mt_env, mn.mc_pg[mn.mc_top]) >= thresh &&
- NUMKEYS(mn.mc_pg[mn.mc_top]) > minkeys) {
- rc = mdbx_node_move(&mn, mc, fromleft);
- if (fromleft) {
- /* if we inserted on left, bump position up */
- oldki++;
- }
- } else {
- if (!fromleft) {
- rc = mdbx_page_merge(&mn, mc);
- } else {
- oldki += NUMKEYS(mn.mc_pg[mn.mc_top]);
- mn.mc_ki[mn.mc_top] += mc->mc_ki[mn.mc_top] + 1;
- /* We want mdbx_rebalance to find mn when doing fixups */
- WITH_CURSOR_TRACKING(mn, rc = mdbx_page_merge(mc, &mn));
- mdbx_cursor_copy(&mn, mc);
- }
- mc->mc_flags &= ~C_EOF;
- }
- mc->mc_ki[mc->mc_top] = oldki;
- return rc;
-}
-
-/* Complete a delete operation started by mdbx_cursor_del(). */
-static int mdbx_cursor_del0(MDBX_cursor *mc) {
- int rc;
- MDBX_page *mp;
- indx_t ki;
- unsigned nkeys;
- MDBX_cursor *m2, *m3;
- MDBX_dbi dbi = mc->mc_dbi;
-
- ki = mc->mc_ki[mc->mc_top];
- mp = mc->mc_pg[mc->mc_top];
- mdbx_node_del(mc, mc->mc_db->md_xsize);
- mc->mc_db->md_entries--;
- {
- /* Adjust other cursors pointing to mp */
- for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) {
- m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2;
- if (!(m2->mc_flags & m3->mc_flags & C_INITIALIZED))
- continue;
- if (m3 == mc || m3->mc_snum < mc->mc_snum)
- continue;
- if (m3->mc_pg[mc->mc_top] == mp) {
- if (m3->mc_ki[mc->mc_top] == ki) {
- m3->mc_flags |= C_DEL;
- if (mc->mc_db->md_flags & MDBX_DUPSORT) {
- /* Sub-cursor referred into dataset which is gone */
- m3->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF);
- }
- continue;
- } else if (m3->mc_ki[mc->mc_top] > ki) {
- m3->mc_ki[mc->mc_top]--;
- }
- if (XCURSOR_INITED(m3))
- XCURSOR_REFRESH(m3, m3->mc_pg[mc->mc_top], m3->mc_ki[mc->mc_top]);
- }
- }
- }
- rc = mdbx_rebalance(mc);
-
- if (likely(rc == MDBX_SUCCESS)) {
- /* DB is totally empty now, just bail out.
- * Other cursors adjustments were already done
- * by mdbx_rebalance and aren't needed here. */
- if (!mc->mc_snum) {
- mc->mc_flags |= C_DEL | C_EOF;
- return rc;
- }
-
- mp = mc->mc_pg[mc->mc_top];
- nkeys = NUMKEYS(mp);
-
- /* Adjust other cursors pointing to mp */
- for (m2 = mc->mc_txn->mt_cursors[dbi]; !rc && m2; m2 = m2->mc_next) {
- m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2;
- if (!(m2->mc_flags & m3->mc_flags & C_INITIALIZED))
- continue;
- if (m3->mc_snum < mc->mc_snum)
- continue;
- if (m3->mc_pg[mc->mc_top] == mp) {
- /* if m3 points past last node in page, find next sibling */
- if (m3->mc_ki[mc->mc_top] >= mc->mc_ki[mc->mc_top]) {
- if (m3->mc_ki[mc->mc_top] >= nkeys) {
- rc = mdbx_cursor_sibling(m3, 1);
- if (rc == MDBX_NOTFOUND) {
- m3->mc_flags |= C_EOF;
- rc = MDBX_SUCCESS;
- continue;
- }
- }
- if (mc->mc_db->md_flags & MDBX_DUPSORT) {
- MDBX_node *node =
- NODEPTR(m3->mc_pg[m3->mc_top], m3->mc_ki[m3->mc_top]);
- /* If this node has dupdata, it may need to be reinited
- * because its data has moved.
- * If the xcursor was not initd it must be reinited.
- * Else if node points to a subDB, nothing is needed. */
- if (node->mn_flags & F_DUPDATA) {
- if (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) {
- if (!(node->mn_flags & F_SUBDATA))
- m3->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(node);
- } else {
- mdbx_xcursor_init1(m3, node);
- m3->mc_xcursor->mx_cursor.mc_flags |= C_DEL;
- }
- }
- }
- }
- }
- }
- mc->mc_flags |= C_DEL;
- }
-
- if (unlikely(rc))
- mc->mc_txn->mt_flags |= MDBX_TXN_ERROR;
- return rc;
-}
-
-int mdbx_del(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data) {
- if (unlikely(!key || !txn))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED)))
- return (txn->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EACCESS : MDBX_BAD_TXN;
-
- return mdbx_del0(txn, dbi, key, data, 0);
-}
-
-static int mdbx_del0(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data,
- unsigned flags) {
- MDBX_cursor mc;
- MDBX_xcursor mx;
- MDBX_cursor_op op;
- MDBX_val rdata;
- int rc, exact = 0;
- DKBUF;
-
- mdbx_debug("====> delete db %u key [%s], data [%s]", dbi, DKEY(key),
- DVAL(data));
-
- mdbx_cursor_init(&mc, txn, dbi, &mx);
-
- if (data) {
- op = MDBX_GET_BOTH;
- rdata = *data;
- data = &rdata;
- } else {
- op = MDBX_SET;
- flags |= MDBX_NODUPDATA;
- }
- rc = mdbx_cursor_set(&mc, key, data, op, &exact);
- if (likely(rc == MDBX_SUCCESS)) {
- /* let mdbx_page_split know about this cursor if needed:
- * delete will trigger a rebalance; if it needs to move
- * a node from one page to another, it will have to
- * update the parent's separator key(s). If the new sepkey
- * is larger than the current one, the parent page may
- * run out of space, triggering a split. We need this
- * cursor to be consistent until the end of the rebalance. */
- mc.mc_next = txn->mt_cursors[dbi];
- txn->mt_cursors[dbi] = &mc;
- rc = mdbx_cursor_del(&mc, flags);
- txn->mt_cursors[dbi] = mc.mc_next;
- }
- return rc;
-}
-
-/* Split a page and insert a new node.
- * Set MDBX_TXN_ERROR on failure.
- * [in,out] mc Cursor pointing to the page and desired insertion index.
- * The cursor will be updated to point to the actual page and index where
- * the node got inserted after the split.
- * [in] newkey The key for the newly inserted node.
- * [in] newdata The data for the newly inserted node.
- * [in] newpgno The page number, if the new node is a branch node.
- * [in] nflags The NODE_ADD_FLAGS for the new node.
- * Returns 0 on success, non-zero on failure. */
-static int mdbx_page_split(MDBX_cursor *mc, MDBX_val *newkey, MDBX_val *newdata,
- pgno_t newpgno, unsigned nflags) {
- unsigned flags;
- int rc = MDBX_SUCCESS, new_root = 0, did_split = 0;
- pgno_t pgno = 0;
- unsigned i, ptop;
- MDBX_env *env = mc->mc_txn->mt_env;
- MDBX_node *node;
- MDBX_val sepkey, rkey, xdata, *rdata = &xdata;
- MDBX_page *copy = NULL;
- MDBX_page *rp, *pp;
- MDBX_cursor mn;
- DKBUF;
-
- MDBX_page *mp = mc->mc_pg[mc->mc_top];
- unsigned newindx = mc->mc_ki[mc->mc_top];
- unsigned nkeys = NUMKEYS(mp);
-
- mdbx_debug("-----> splitting %s page %" PRIaPGNO
- " and adding [%s] at index %i/%i",
- IS_LEAF(mp) ? "leaf" : "branch", mp->mp_pgno, DKEY(newkey),
- mc->mc_ki[mc->mc_top], nkeys);
-
- /* Create a right sibling. */
- if ((rc = mdbx_page_new(mc, mp->mp_flags, 1, &rp)))
- return rc;
- rp->mp_leaf2_ksize = mp->mp_leaf2_ksize;
- mdbx_debug("new right sibling: page %" PRIaPGNO "", rp->mp_pgno);
-
- /* Usually when splitting the root page, the cursor
- * height is 1. But when called from mdbx_update_key,
- * the cursor height may be greater because it walks
- * up the stack while finding the branch slot to update. */
- if (mc->mc_top < 1) {
- if ((rc = mdbx_page_new(mc, P_BRANCH, 1, &pp)))
- goto done;
- /* shift current top to make room for new parent */
- for (i = mc->mc_snum; i > 0; i--) {
- mc->mc_pg[i] = mc->mc_pg[i - 1];
- mc->mc_ki[i] = mc->mc_ki[i - 1];
- }
- mc->mc_pg[0] = pp;
- mc->mc_ki[0] = 0;
- mc->mc_db->md_root = pp->mp_pgno;
- mdbx_debug("root split! new root = %" PRIaPGNO "", pp->mp_pgno);
- new_root = mc->mc_db->md_depth++;
-
- /* Add left (implicit) pointer. */
- if (unlikely((rc = mdbx_node_add(mc, 0, NULL, NULL, mp->mp_pgno, 0)) !=
- MDBX_SUCCESS)) {
- /* undo the pre-push */
- mc->mc_pg[0] = mc->mc_pg[1];
- mc->mc_ki[0] = mc->mc_ki[1];
- mc->mc_db->md_root = mp->mp_pgno;
- mc->mc_db->md_depth--;
- goto done;
- }
- mc->mc_snum++;
- mc->mc_top++;
- ptop = 0;
- } else {
- ptop = mc->mc_top - 1;
- mdbx_debug("parent branch page is %" PRIaPGNO "", mc->mc_pg[ptop]->mp_pgno);
- }
-
- mdbx_cursor_copy(mc, &mn);
- mn.mc_xcursor = NULL;
- mn.mc_pg[mn.mc_top] = rp;
- mn.mc_ki[ptop] = mc->mc_ki[ptop] + 1;
-
- unsigned split_indx;
- if (nflags & MDBX_APPEND) {
- mn.mc_ki[mn.mc_top] = 0;
- sepkey = *newkey;
- split_indx = newindx;
- nkeys = 0;
- } else {
- split_indx = (nkeys + 1) / 2;
-
- if (IS_LEAF2(rp)) {
- char *split, *ins;
- int x;
- unsigned lsize, rsize, ksize;
- /* Move half of the keys to the right sibling */
- x = mc->mc_ki[mc->mc_top] - split_indx;
- ksize = mc->mc_db->md_xsize;
- split = LEAF2KEY(mp, split_indx, ksize);
- rsize = (nkeys - split_indx) * ksize;
- lsize = (nkeys - split_indx) * sizeof(indx_t);
- mdbx_cassert(mc, mp->mp_lower >= lsize);
- mp->mp_lower -= (indx_t)lsize;
- mdbx_cassert(mc, rp->mp_lower + lsize <= UINT16_MAX);
- rp->mp_lower += (indx_t)lsize;
- mdbx_cassert(mc, mp->mp_upper + rsize - lsize <= UINT16_MAX);
- mp->mp_upper += (indx_t)(rsize - lsize);
- mdbx_cassert(mc, rp->mp_upper >= rsize - lsize);
- rp->mp_upper -= (indx_t)(rsize - lsize);
- sepkey.iov_len = ksize;
- if (newindx == split_indx) {
- sepkey.iov_base = newkey->iov_base;
- } else {
- sepkey.iov_base = split;
- }
- if (x < 0) {
- mdbx_cassert(mc, ksize >= sizeof(indx_t));
- ins = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], ksize);
- memcpy(rp->mp_ptrs, split, rsize);
- sepkey.iov_base = rp->mp_ptrs;
- memmove(ins + ksize, ins, (split_indx - mc->mc_ki[mc->mc_top]) * ksize);
- memcpy(ins, newkey->iov_base, ksize);
- mdbx_cassert(mc, UINT16_MAX - mp->mp_lower >= (int)sizeof(indx_t));
- mp->mp_lower += sizeof(indx_t);
- mdbx_cassert(mc, mp->mp_upper >= ksize - sizeof(indx_t));
- mp->mp_upper -= (indx_t)(ksize - sizeof(indx_t));
- } else {
- if (x)
- memcpy(rp->mp_ptrs, split, x * ksize);
- ins = LEAF2KEY(rp, x, ksize);
- memcpy(ins, newkey->iov_base, ksize);
- memcpy(ins + ksize, split + x * ksize, rsize - x * ksize);
- mdbx_cassert(mc, UINT16_MAX - rp->mp_lower >= (int)sizeof(indx_t));
- rp->mp_lower += sizeof(indx_t);
- mdbx_cassert(mc, rp->mp_upper >= ksize - sizeof(indx_t));
- rp->mp_upper -= (indx_t)(ksize - sizeof(indx_t));
- mdbx_cassert(mc, x <= UINT16_MAX);
- mc->mc_ki[mc->mc_top] = (indx_t)x;
- }
- } else {
- size_t psize, nsize, k;
- /* Maximum free space in an empty page */
- unsigned pmax = env->me_psize - PAGEHDRSZ;
- if (IS_LEAF(mp))
- nsize = mdbx_leaf_size(env, newkey, newdata);
- else
- nsize = mdbx_branch_size(env, newkey);
- nsize = EVEN(nsize);
-
- /* grab a page to hold a temporary copy */
- copy = mdbx_page_malloc(mc->mc_txn, 1);
- if (unlikely(copy == NULL)) {
- rc = MDBX_ENOMEM;
- goto done;
- }
- copy->mp_pgno = mp->mp_pgno;
- copy->mp_flags = mp->mp_flags;
- copy->mp_lower = 0;
- mdbx_cassert(mc, env->me_psize - PAGEHDRSZ <= UINT16_MAX);
- copy->mp_upper = (indx_t)(env->me_psize - PAGEHDRSZ);
-
- /* prepare to insert */
- for (unsigned j = i = 0; i < nkeys; i++) {
- if (i == newindx)
- copy->mp_ptrs[j++] = 0;
- copy->mp_ptrs[j++] = mp->mp_ptrs[i];
- }
-
- /* When items are relatively large the split point needs
- * to be checked, because being off-by-one will make the
- * difference between success or failure in mdbx_node_add.
- *
- * It's also relevant if a page happens to be laid out
- * such that one half of its nodes are all "small" and
- * the other half of its nodes are "large." If the new
- * item is also "large" and falls on the half with
- * "large" nodes, it also may not fit.
- *
- * As a final tweak, if the new item goes on the last
- * spot on the page (and thus, onto the new page), bias
- * the split so the new page is emptier than the old page.
- * This yields better packing during sequential inserts.
- */
- int dir;
- if (nkeys < 20 || nsize > pmax / 16 || newindx >= nkeys) {
- /* Find split point */
- psize = 0;
- if (newindx <= split_indx || newindx >= nkeys) {
- i = 0;
- dir = 1;
- k = (newindx >= nkeys) ? nkeys : split_indx + 1 + IS_LEAF(mp);
- } else {
- i = nkeys;
- dir = -1;
- k = split_indx - 1;
- }
- for (; i != k; i += dir) {
- if (i == newindx) {
- psize += nsize;
- node = NULL;
- } else {
- node = (MDBX_node *)((char *)mp + copy->mp_ptrs[i] + PAGEHDRSZ);
- psize += NODESIZE + NODEKSZ(node) + sizeof(indx_t);
- if (IS_LEAF(mp)) {
- if (F_ISSET(node->mn_flags, F_BIGDATA))
- psize += sizeof(pgno_t);
- else
- psize += NODEDSZ(node);
- }
- psize = EVEN(psize);
- }
- if (psize > pmax || i == k - dir) {
- split_indx = i + (dir < 0);
- break;
- }
- }
- }
- if (split_indx == newindx) {
- sepkey.iov_len = newkey->iov_len;
- sepkey.iov_base = newkey->iov_base;
- } else {
- node =
- (MDBX_node *)((char *)mp + copy->mp_ptrs[split_indx] + PAGEHDRSZ);
- sepkey.iov_len = node->mn_ksize;
- sepkey.iov_base = NODEKEY(node);
- }
- }
- }
-
- mdbx_debug("separator is %d [%s]", split_indx, DKEY(&sepkey));
-
- /* Copy separator key to the parent. */
- if (SIZELEFT(mn.mc_pg[ptop]) < mdbx_branch_size(env, &sepkey)) {
- int snum = mc->mc_snum;
- mn.mc_snum--;
- mn.mc_top--;
- did_split = 1;
- /* We want other splits to find mn when doing fixups */
- WITH_CURSOR_TRACKING(
- mn, rc = mdbx_page_split(&mn, &sepkey, NULL, rp->mp_pgno, 0));
- if (unlikely(rc != MDBX_SUCCESS))
- goto done;
-
- /* root split? */
- if (mc->mc_snum > snum)
- ptop++;
-
- /* Right page might now have changed parent.
- * Check if left page also changed parent. */
- if (mn.mc_pg[ptop] != mc->mc_pg[ptop] &&
- mc->mc_ki[ptop] >= NUMKEYS(mc->mc_pg[ptop])) {
- for (i = 0; i < ptop; i++) {
- mc->mc_pg[i] = mn.mc_pg[i];
- mc->mc_ki[i] = mn.mc_ki[i];
- }
- mc->mc_pg[ptop] = mn.mc_pg[ptop];
- if (mn.mc_ki[ptop]) {
- mc->mc_ki[ptop] = mn.mc_ki[ptop] - 1;
- } else {
- /* find right page's left sibling */
- mc->mc_ki[ptop] = mn.mc_ki[ptop];
- rc = mdbx_cursor_sibling(mc, 0);
- }
- }
- } else {
- mn.mc_top--;
- rc = mdbx_node_add(&mn, mn.mc_ki[ptop], &sepkey, NULL, rp->mp_pgno, 0);
- mn.mc_top++;
- }
- if (unlikely(rc != MDBX_SUCCESS)) {
- if (rc == MDBX_NOTFOUND) /* improper mdbx_cursor_sibling() result */ {
- mdbx_error("unexpected %s", "MDBX_NOTFOUND");
- rc = MDBX_PROBLEM;
- }
- goto done;
- }
- if (nflags & MDBX_APPEND) {
- mc->mc_pg[mc->mc_top] = rp;
- mc->mc_ki[mc->mc_top] = 0;
- rc = mdbx_node_add(mc, 0, newkey, newdata, newpgno, nflags);
- if (rc)
- goto done;
- for (i = 0; i < mc->mc_top; i++)
- mc->mc_ki[i] = mn.mc_ki[i];
- } else if (!IS_LEAF2(mp)) {
- /* Move nodes */
- mc->mc_pg[mc->mc_top] = rp;
- i = split_indx;
- indx_t n = 0;
- do {
- if (i == newindx) {
- rkey.iov_base = newkey->iov_base;
- rkey.iov_len = newkey->iov_len;
- if (IS_LEAF(mp)) {
- rdata = newdata;
- } else
- pgno = newpgno;
- flags = nflags;
- /* Update index for the new key. */
- mc->mc_ki[mc->mc_top] = n;
- } else {
- node = (MDBX_node *)((char *)mp + copy->mp_ptrs[i] + PAGEHDRSZ);
- rkey.iov_base = NODEKEY(node);
- rkey.iov_len = node->mn_ksize;
- if (IS_LEAF(mp)) {
- xdata.iov_base = NODEDATA(node);
- xdata.iov_len = NODEDSZ(node);
- rdata = &xdata;
- } else
- pgno = NODEPGNO(node);
- flags = node->mn_flags;
- }
-
- if (!IS_LEAF(mp) && n == 0) {
- /* First branch index doesn't need key data. */
- rkey.iov_len = 0;
- }
-
- rc = mdbx_node_add(mc, n, &rkey, rdata, pgno, flags);
- if (rc)
- goto done;
- if (i == nkeys) {
- i = 0;
- n = 0;
- mc->mc_pg[mc->mc_top] = copy;
- } else {
- i++;
- n++;
- }
- } while (i != split_indx);
-
- nkeys = NUMKEYS(copy);
- for (i = 0; i < nkeys; i++)
- mp->mp_ptrs[i] = copy->mp_ptrs[i];
- mp->mp_lower = copy->mp_lower;
- mp->mp_upper = copy->mp_upper;
- memcpy(NODEPTR(mp, nkeys - 1), NODEPTR(copy, nkeys - 1),
- env->me_psize - copy->mp_upper - PAGEHDRSZ);
-
- /* reset back to original page */
- if (newindx < split_indx) {
- mc->mc_pg[mc->mc_top] = mp;
- } else {
- mc->mc_pg[mc->mc_top] = rp;
- mc->mc_ki[ptop]++;
- /* Make sure mc_ki is still valid. */
- if (mn.mc_pg[ptop] != mc->mc_pg[ptop] &&
- mc->mc_ki[ptop] >= NUMKEYS(mc->mc_pg[ptop])) {
- for (i = 0; i <= ptop; i++) {
- mc->mc_pg[i] = mn.mc_pg[i];
- mc->mc_ki[i] = mn.mc_ki[i];
- }
- }
- }
- if (nflags & MDBX_RESERVE) {
- node = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
- if (!(node->mn_flags & F_BIGDATA))
- newdata->iov_base = NODEDATA(node);
- }
- } else {
- if (newindx >= split_indx) {
- mc->mc_pg[mc->mc_top] = rp;
- mc->mc_ki[ptop]++;
- /* Make sure mc_ki is still valid. */
- if (mn.mc_pg[ptop] != mc->mc_pg[ptop] &&
- mc->mc_ki[ptop] >= NUMKEYS(mc->mc_pg[ptop])) {
- for (i = 0; i <= ptop; i++) {
- mc->mc_pg[i] = mn.mc_pg[i];
- mc->mc_ki[i] = mn.mc_ki[i];
- }
- }
- }
- }
-
- {
- /* Adjust other cursors pointing to mp */
- MDBX_cursor *m2, *m3;
- MDBX_dbi dbi = mc->mc_dbi;
- nkeys = NUMKEYS(mp);
-
- for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) {
- if (mc->mc_flags & C_SUB)
- m3 = &m2->mc_xcursor->mx_cursor;
- else
- m3 = m2;
- if (m3 == mc)
- continue;
- if (!(m2->mc_flags & m3->mc_flags & C_INITIALIZED))
- continue;
- if (new_root) {
- int k;
- /* sub cursors may be on different DB */
- if (m3->mc_pg[0] != mp)
- continue;
- /* root split */
- for (k = new_root; k >= 0; k--) {
- m3->mc_ki[k + 1] = m3->mc_ki[k];
- m3->mc_pg[k + 1] = m3->mc_pg[k];
- }
- if (m3->mc_ki[0] >= nkeys) {
- m3->mc_ki[0] = 1;
- } else {
- m3->mc_ki[0] = 0;
- }
- m3->mc_pg[0] = mc->mc_pg[0];
- m3->mc_snum++;
- m3->mc_top++;
- }
- if (m3->mc_top >= mc->mc_top && m3->mc_pg[mc->mc_top] == mp) {
- if (m3->mc_ki[mc->mc_top] >= newindx && !(nflags & MDBX_SPLIT_REPLACE))
- m3->mc_ki[mc->mc_top]++;
- if (m3->mc_ki[mc->mc_top] >= nkeys) {
- m3->mc_pg[mc->mc_top] = rp;
- mdbx_cassert(mc, m3->mc_ki[mc->mc_top] >= nkeys);
- m3->mc_ki[mc->mc_top] -= (indx_t)nkeys;
- for (i = 0; i < mc->mc_top; i++) {
- m3->mc_ki[i] = mn.mc_ki[i];
- m3->mc_pg[i] = mn.mc_pg[i];
- }
- }
- } else if (!did_split && m3->mc_top >= ptop &&
- m3->mc_pg[ptop] == mc->mc_pg[ptop] &&
- m3->mc_ki[ptop] >= mc->mc_ki[ptop]) {
- m3->mc_ki[ptop]++;
- }
- if (XCURSOR_INITED(m3) && IS_LEAF(mp))
- XCURSOR_REFRESH(m3, m3->mc_pg[mc->mc_top], m3->mc_ki[mc->mc_top]);
- }
- }
- mdbx_debug("mp left: %d, rp left: %d", SIZELEFT(mp), SIZELEFT(rp));
-
-done:
- if (copy) /* tmp page */
- mdbx_page_free(env, copy);
- if (unlikely(rc))
- mc->mc_txn->mt_flags |= MDBX_TXN_ERROR;
- return rc;
-}
-
-int mdbx_put(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data,
- unsigned flags) {
- MDBX_cursor mc;
- MDBX_xcursor mx;
-
- if (unlikely(!key || !data || !txn))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
- return MDBX_EINVAL;
-
- if (unlikely(flags &
- ~(MDBX_NOOVERWRITE | MDBX_NODUPDATA | MDBX_RESERVE |
- MDBX_APPEND | MDBX_APPENDDUP | MDBX_CURRENT)))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED)))
- return (txn->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EACCESS : MDBX_BAD_TXN;
-
- mdbx_cursor_init(&mc, txn, dbi, &mx);
- mc.mc_next = txn->mt_cursors[dbi];
- txn->mt_cursors[dbi] = &mc;
-
- int rc = MDBX_SUCCESS;
- /* LY: support for update (explicit overwrite) */
- if (flags & MDBX_CURRENT) {
- rc = mdbx_cursor_get(&mc, key, NULL, MDBX_SET);
- if (likely(rc == MDBX_SUCCESS) &&
- (txn->mt_dbs[dbi].md_flags & MDBX_DUPSORT)) {
- /* LY: allows update (explicit overwrite) only for unique keys */
- MDBX_node *leaf = NODEPTR(mc.mc_pg[mc.mc_top], mc.mc_ki[mc.mc_top]);
- if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- mdbx_tassert(txn, XCURSOR_INITED(&mc) &&
- mc.mc_xcursor->mx_db.md_entries > 1);
- rc = MDBX_EMULTIVAL;
- }
- }
- }
-
- if (likely(rc == MDBX_SUCCESS))
- rc = mdbx_cursor_put(&mc, key, data, flags);
- txn->mt_cursors[dbi] = mc.mc_next;
-
- return rc;
-}
-
-#ifndef MDBX_WBUF
-#define MDBX_WBUF (1024 * 1024)
-#endif
-#define MDBX_EOF 0x10 /* mdbx_env_copyfd1() is done reading */
-
-/* State needed for a double-buffering compacting copy. */
-typedef struct mdbx_copy {
- MDBX_env *mc_env;
- MDBX_txn *mc_txn;
- mdbx_condmutex_t mc_condmutex;
- char *mc_wbuf[2];
- char *mc_over[2];
- size_t mc_wlen[2];
- size_t mc_olen[2];
- mdbx_filehandle_t mc_fd;
- volatile int mc_error;
- pgno_t mc_next_pgno;
- short mc_toggle; /* Buffer number in provider */
- short mc_new; /* (0-2 buffers to write) | (MDBX_EOF at end) */
- /* Error code. Never cleared if set. Both threads can set nonzero
- * to fail the copy. Not mutex-protected, MDBX expects atomic int. */
-} mdbx_copy;
-
-/* Dedicated writer thread for compacting copy. */
-static THREAD_RESULT __cold THREAD_CALL mdbx_env_copythr(void *arg) {
- mdbx_copy *my = arg;
- char *ptr;
- int toggle = 0;
- int rc;
-
-#if defined(F_SETNOSIGPIPE)
- /* OS X delivers SIGPIPE to the whole process, not the thread that caused it.
- * Disable SIGPIPE using platform specific fcntl. */
- int enabled = 1;
- if (fcntl(my->mc_fd, F_SETNOSIGPIPE, &enabled))
- my->mc_error = errno;
-#endif
-
-#if defined(SIGPIPE) && !defined(_WIN32) && !defined(_WIN64)
- sigset_t set;
- sigemptyset(&set);
- sigaddset(&set, SIGPIPE);
- rc = pthread_sigmask(SIG_BLOCK, &set, NULL);
- if (rc != 0)
- my->mc_error = rc;
-#endif
-
- mdbx_condmutex_lock(&my->mc_condmutex);
- while (!my->mc_error) {
- while (!my->mc_new)
- mdbx_condmutex_wait(&my->mc_condmutex);
- if (my->mc_new == 0 + MDBX_EOF) /* 0 buffers, just EOF */
- break;
- size_t wsize = my->mc_wlen[toggle];
- ptr = my->mc_wbuf[toggle];
- again:
- if (wsize > 0 && !my->mc_error) {
- rc = mdbx_write(my->mc_fd, ptr, wsize);
- if (rc != MDBX_SUCCESS) {
-#if defined(SIGPIPE) && !defined(_WIN32) && !defined(_WIN64)
- if (rc == EPIPE) {
- /* Collect the pending SIGPIPE, otherwise (at least OS X)
- * gives it to the process on thread-exit (ITS#8504). */
- int tmp;
- sigwait(&set, &tmp);
- }
-#endif
- my->mc_error = rc;
- }
- }
-
- /* If there's an overflow page tail, write it too */
- if (my->mc_olen[toggle]) {
- wsize = my->mc_olen[toggle];
- ptr = my->mc_over[toggle];
- my->mc_olen[toggle] = 0;
- goto again;
- }
- my->mc_wlen[toggle] = 0;
- toggle ^= 1;
- /* Return the empty buffer to provider */
- my->mc_new--;
- mdbx_condmutex_signal(&my->mc_condmutex);
- }
- mdbx_condmutex_unlock(&my->mc_condmutex);
- return (THREAD_RESULT)0;
-}
-
-/* Give buffer and/or MDBX_EOF to writer thread, await unused buffer.
- *
- * [in] my control structure.
- * [in] adjust (1 to hand off 1 buffer) | (MDBX_EOF when ending). */
-static int __cold mdbx_env_cthr_toggle(mdbx_copy *my, int adjust) {
- mdbx_condmutex_lock(&my->mc_condmutex);
- my->mc_new += (short)adjust;
- mdbx_condmutex_signal(&my->mc_condmutex);
- while (my->mc_new & 2) /* both buffers in use */
- mdbx_condmutex_wait(&my->mc_condmutex);
- mdbx_condmutex_unlock(&my->mc_condmutex);
-
- my->mc_toggle ^= (adjust & 1);
- /* Both threads reset mc_wlen, to be safe from threading errors */
- my->mc_wlen[my->mc_toggle] = 0;
- return my->mc_error;
-}
-
-/* Depth-first tree traversal for compacting copy.
- * [in] my control structure.
- * [in,out] pg database root.
- * [in] flags includes F_DUPDATA if it is a sorted-duplicate sub-DB. */
-static int __cold mdbx_env_cwalk(mdbx_copy *my, pgno_t *pg, int flags) {
- MDBX_cursor mc;
- MDBX_node *ni;
- MDBX_page *mo, *mp, *leaf;
- char *buf, *ptr;
- int rc, toggle;
- unsigned i;
-
- /* Empty DB, nothing to do */
- if (*pg == P_INVALID)
- return MDBX_SUCCESS;
-
- memset(&mc, 0, sizeof(mc));
- mc.mc_snum = 1;
- mc.mc_txn = my->mc_txn;
-
- rc = mdbx_page_get(&mc, *pg, &mc.mc_pg[0], NULL);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
- rc = mdbx_page_search_root(&mc, NULL, MDBX_PS_FIRST);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
-
- /* Make cursor pages writable */
- buf = ptr = malloc(pgno2bytes(my->mc_env, mc.mc_snum));
- if (buf == NULL)
- return MDBX_ENOMEM;
-
- for (i = 0; i < mc.mc_top; i++) {
- mdbx_page_copy((MDBX_page *)ptr, mc.mc_pg[i], my->mc_env->me_psize);
- mc.mc_pg[i] = (MDBX_page *)ptr;
- ptr += my->mc_env->me_psize;
- }
-
- /* This is writable space for a leaf page. Usually not needed. */
- leaf = (MDBX_page *)ptr;
-
- toggle = my->mc_toggle;
- while (mc.mc_snum > 0) {
- unsigned n;
- mp = mc.mc_pg[mc.mc_top];
- n = NUMKEYS(mp);
-
- if (IS_LEAF(mp)) {
- if (!IS_LEAF2(mp) && !(flags & F_DUPDATA)) {
- for (i = 0; i < n; i++) {
- ni = NODEPTR(mp, i);
- if (ni->mn_flags & F_BIGDATA) {
- MDBX_page *omp;
-
- /* Need writable leaf */
- if (mp != leaf) {
- mc.mc_pg[mc.mc_top] = leaf;
- mdbx_page_copy(leaf, mp, my->mc_env->me_psize);
- mp = leaf;
- ni = NODEPTR(mp, i);
- }
-
- pgno_t pgno;
- memcpy(&pgno, NODEDATA(ni), sizeof(pgno));
- memcpy(NODEDATA(ni), &my->mc_next_pgno, sizeof(pgno_t));
- rc = mdbx_page_get(&mc, pgno, &omp, NULL);
- if (unlikely(rc != MDBX_SUCCESS))
- goto done;
- if (my->mc_wlen[toggle] >= MDBX_WBUF) {
- rc = mdbx_env_cthr_toggle(my, 1);
- if (unlikely(rc != MDBX_SUCCESS))
- goto done;
- toggle = my->mc_toggle;
- }
- mo = (MDBX_page *)(my->mc_wbuf[toggle] + my->mc_wlen[toggle]);
- memcpy(mo, omp, my->mc_env->me_psize);
- mo->mp_pgno = my->mc_next_pgno;
- my->mc_next_pgno += omp->mp_pages;
- my->mc_wlen[toggle] += my->mc_env->me_psize;
- if (omp->mp_pages > 1) {
- my->mc_olen[toggle] = pgno2bytes(my->mc_env, omp->mp_pages - 1);
- my->mc_over[toggle] = (char *)omp + my->mc_env->me_psize;
- rc = mdbx_env_cthr_toggle(my, 1);
- if (unlikely(rc != MDBX_SUCCESS))
- goto done;
- toggle = my->mc_toggle;
- }
- } else if (ni->mn_flags & F_SUBDATA) {
- MDBX_db db;
-
- /* Need writable leaf */
- if (mp != leaf) {
- mc.mc_pg[mc.mc_top] = leaf;
- mdbx_page_copy(leaf, mp, my->mc_env->me_psize);
- mp = leaf;
- ni = NODEPTR(mp, i);
- }
-
- memcpy(&db, NODEDATA(ni), sizeof(db));
- my->mc_toggle = (short)toggle;
- rc = mdbx_env_cwalk(my, &db.md_root, ni->mn_flags & F_DUPDATA);
- if (rc)
- goto done;
- toggle = my->mc_toggle;
- memcpy(NODEDATA(ni), &db, sizeof(db));
- }
- }
- }
- } else {
- mc.mc_ki[mc.mc_top]++;
- if (mc.mc_ki[mc.mc_top] < n) {
- pgno_t pgno;
- again:
- ni = NODEPTR(mp, mc.mc_ki[mc.mc_top]);
- pgno = NODEPGNO(ni);
- rc = mdbx_page_get(&mc, pgno, &mp, NULL);
- if (unlikely(rc != MDBX_SUCCESS))
- goto done;
- mc.mc_top++;
- mc.mc_snum++;
- mc.mc_ki[mc.mc_top] = 0;
- if (IS_BRANCH(mp)) {
- /* Whenever we advance to a sibling branch page,
- * we must proceed all the way down to its first leaf. */
- mdbx_page_copy(mc.mc_pg[mc.mc_top], mp, my->mc_env->me_psize);
- goto again;
- } else
- mc.mc_pg[mc.mc_top] = mp;
- continue;
- }
- }
- if (my->mc_wlen[toggle] >= MDBX_WBUF) {
- rc = mdbx_env_cthr_toggle(my, 1);
- if (unlikely(rc != MDBX_SUCCESS))
- goto done;
- toggle = my->mc_toggle;
- }
- mo = (MDBX_page *)(my->mc_wbuf[toggle] + my->mc_wlen[toggle]);
- mdbx_page_copy(mo, mp, my->mc_env->me_psize);
- mo->mp_pgno = my->mc_next_pgno++;
- my->mc_wlen[toggle] += my->mc_env->me_psize;
- if (mc.mc_top) {
- /* Update parent if there is one */
- ni = NODEPTR(mc.mc_pg[mc.mc_top - 1], mc.mc_ki[mc.mc_top - 1]);
- SETPGNO(ni, mo->mp_pgno);
- mdbx_cursor_pop(&mc);
- } else {
- /* Otherwise we're done */
- *pg = mo->mp_pgno;
- break;
- }
- }
-done:
- free(buf);
- return rc;
-}
-
-/* Copy environment with compaction. */
-static int __cold mdbx_env_compact(MDBX_env *env, mdbx_filehandle_t fd) {
- MDBX_txn *txn = NULL;
- mdbx_thread_t thr;
- mdbx_copy my;
- memset(&my, 0, sizeof(my));
-
- int rc = mdbx_condmutex_init(&my.mc_condmutex);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
- rc = mdbx_memalign_alloc(env->me_os_psize, MDBX_WBUF * 2,
- (void **)&my.mc_wbuf[0]);
- if (unlikely(rc != MDBX_SUCCESS))
- goto done;
-
- memset(my.mc_wbuf[0], 0, MDBX_WBUF * 2);
- my.mc_wbuf[1] = my.mc_wbuf[0] + MDBX_WBUF;
- my.mc_next_pgno = NUM_METAS;
- my.mc_env = env;
- my.mc_fd = fd;
- rc = mdbx_thread_create(&thr, mdbx_env_copythr, &my);
- if (unlikely(rc != MDBX_SUCCESS))
- goto done;
-
- rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn);
- if (unlikely(rc != MDBX_SUCCESS))
- goto finish;
-
- MDBX_page *meta = mdbx_init_metas(env, my.mc_wbuf[0]);
-
- /* Set metapage 1 with current main DB */
- pgno_t new_root, root = txn->mt_dbs[MAIN_DBI].md_root;
- if ((new_root = root) != P_INVALID) {
- /* Count free pages + freeDB pages. Subtract from last_pg
- * to find the new last_pg, which also becomes the new root. */
- pgno_t freecount = 0;
- MDBX_cursor mc;
- MDBX_val key, data;
-
- mdbx_cursor_init(&mc, txn, FREE_DBI, NULL);
- while ((rc = mdbx_cursor_get(&mc, &key, &data, MDBX_NEXT)) == 0)
- freecount += *(pgno_t *)data.iov_base;
- if (unlikely(rc != MDBX_NOTFOUND))
- goto finish;
-
- freecount += txn->mt_dbs[FREE_DBI].md_branch_pages +
- txn->mt_dbs[FREE_DBI].md_leaf_pages +
- txn->mt_dbs[FREE_DBI].md_overflow_pages;
-
- new_root = txn->mt_next_pgno - 1 - freecount;
- meta->mp_meta.mm_geo.next = meta->mp_meta.mm_geo.now = new_root + 1;
- meta->mp_meta.mm_dbs[MAIN_DBI] = txn->mt_dbs[MAIN_DBI];
- meta->mp_meta.mm_dbs[MAIN_DBI].md_root = new_root;
- } else {
- /* When the DB is empty, handle it specially to
- * fix any breakage like page leaks from ITS#8174. */
- meta->mp_meta.mm_dbs[MAIN_DBI].md_flags = txn->mt_dbs[MAIN_DBI].md_flags;
- }
-
- /* copy canary sequenses if present */
- if (txn->mt_canary.v) {
- meta->mp_meta.mm_canary = txn->mt_canary;
- meta->mp_meta.mm_canary.v = mdbx_meta_txnid_stable(env, &meta->mp_meta);
- }
-
- /* update signature */
- meta->mp_meta.mm_datasync_sign = mdbx_meta_sign(&meta->mp_meta);
-
- my.mc_wlen[0] = pgno2bytes(env, NUM_METAS);
- my.mc_txn = txn;
- rc = mdbx_env_cwalk(&my, &root, 0);
- if (rc == MDBX_SUCCESS && root != new_root) {
- mdbx_error("unexpected root %" PRIaPGNO " (%" PRIaPGNO ")", root, new_root);
- rc = MDBX_PROBLEM; /* page leak or corrupt DB */
- }
-
-finish:
- if (rc != MDBX_SUCCESS)
- my.mc_error = rc;
- mdbx_env_cthr_toggle(&my, 1 | MDBX_EOF);
- rc = mdbx_thread_join(thr);
- mdbx_txn_abort(txn);
-
-done:
- mdbx_memalign_free(my.mc_wbuf[0]);
- mdbx_condmutex_destroy(&my.mc_condmutex);
- return rc ? rc : my.mc_error;
-}
-
-/* Copy environment as-is. */
-static int __cold mdbx_env_copy_asis(MDBX_env *env, mdbx_filehandle_t fd) {
- MDBX_txn *txn = NULL;
-
- /* Do the lock/unlock of the reader mutex before starting the
- * write txn. Otherwise other read txns could block writers. */
- int rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
-
- /* We must start the actual read txn after blocking writers */
- rc = mdbx_txn_end(txn, MDBX_END_RESET_TMP);
- if (unlikely(rc != MDBX_SUCCESS))
- goto bailout; /* FIXME: or just return? */
-
- /* Temporarily block writers until we snapshot the meta pages */
- rc = mdbx_txn_lock(env, false);
- if (unlikely(rc != MDBX_SUCCESS))
- goto bailout;
-
- rc = mdbx_txn_renew0(txn, MDBX_RDONLY);
- if (unlikely(rc != MDBX_SUCCESS)) {
- mdbx_txn_unlock(env);
- goto bailout;
- }
-
- rc = mdbx_write(fd, env->me_map, pgno2bytes(env, NUM_METAS));
- MDBX_meta *const head = mdbx_meta_head(env);
- const uint64_t size =
- mdbx_roundup2(pgno2bytes(env, head->mm_geo.now), env->me_os_psize);
- mdbx_txn_unlock(env);
-
- if (likely(rc == MDBX_SUCCESS))
- rc = mdbx_write(fd, env->me_map + pgno2bytes(env, NUM_METAS),
- pgno2bytes(env, txn->mt_next_pgno - NUM_METAS));
-
- if (likely(rc == MDBX_SUCCESS))
- rc = mdbx_ftruncate(fd, size);
-
-bailout:
- mdbx_txn_abort(txn);
- return rc;
-}
-
-int __cold mdbx_env_copy2fd(MDBX_env *env, mdbx_filehandle_t fd,
- unsigned flags) {
- if (flags & MDBX_CP_COMPACT)
- return mdbx_env_compact(env, fd);
-
- return mdbx_env_copy_asis(env, fd);
-}
-
-int __cold mdbx_env_copy(MDBX_env *env, const char *path, unsigned flags) {
- char *lck_pathname;
- mdbx_filehandle_t newfd = INVALID_HANDLE_VALUE;
-
- if (env->me_flags & MDBX_NOSUBDIR) {
- lck_pathname = (char *)path;
- } else {
- size_t len = strlen(path);
- len += sizeof(MDBX_DATANAME);
- lck_pathname = malloc(len);
- if (!lck_pathname)
- return MDBX_ENOMEM;
- sprintf(lck_pathname, "%s" MDBX_DATANAME, path);
- }
-
- /* The destination path must exist, but the destination file must not.
- * We don't want the OS to cache the writes, since the source data is
- * already in the OS cache. */
- int rc =
- mdbx_openfile(lck_pathname, O_WRONLY | O_CREAT | O_EXCL, 0666, &newfd);
- if (rc == MDBX_SUCCESS) {
- if (env->me_psize >= env->me_os_psize) {
-#ifdef F_NOCACHE /* __APPLE__ */
- (void)fcntl(newfd, F_NOCACHE, 1);
-#elif defined(O_DIRECT) && defined(F_GETFL)
- /* Set O_DIRECT if the file system supports it */
- if ((rc = fcntl(newfd, F_GETFL)) != -1)
- (void)fcntl(newfd, F_SETFL, rc | O_DIRECT);
-#endif
- }
- rc = mdbx_env_copy2fd(env, newfd, flags);
- }
-
- if (!(env->me_flags & MDBX_NOSUBDIR))
- free(lck_pathname);
-
- if (newfd != INVALID_HANDLE_VALUE) {
- int err = mdbx_closefile(newfd);
- if (rc == MDBX_SUCCESS && err != rc)
- rc = err;
- }
-
- return rc;
-}
-
-int __cold mdbx_env_set_flags(MDBX_env *env, unsigned flags, int onoff) {
- if (unlikely(flags & ~CHANGEABLE))
- return MDBX_EINVAL;
-
- int rc = mdbx_txn_lock(env, false);
- if (unlikely(rc))
- return rc;
-
- if (onoff)
- env->me_flags |= flags;
- else
- env->me_flags &= ~flags;
-
- mdbx_txn_unlock(env);
- return MDBX_SUCCESS;
-}
-
-int __cold mdbx_env_get_flags(MDBX_env *env, unsigned *arg) {
- if (unlikely(!env || !arg))
- return MDBX_EINVAL;
-
- *arg = env->me_flags & (CHANGEABLE | CHANGELESS);
- return MDBX_SUCCESS;
-}
-
-int __cold mdbx_env_set_userctx(MDBX_env *env, void *ctx) {
- if (unlikely(!env))
- return MDBX_EINVAL;
- env->me_userctx = ctx;
- return MDBX_SUCCESS;
-}
-
-void *__cold mdbx_env_get_userctx(MDBX_env *env) {
- return env ? env->me_userctx : NULL;
-}
-
-int __cold mdbx_env_set_assert(MDBX_env *env, MDBX_assert_func *func) {
- if (unlikely(!env))
- return MDBX_EINVAL;
-#if MDBX_DEBUG
- env->me_assert_func = func;
- return MDBX_SUCCESS;
-#else
- (void)func;
- return MDBX_ENOSYS;
-#endif
-}
-
-int __cold mdbx_env_get_path(MDBX_env *env, const char **arg) {
- if (unlikely(!env || !arg))
- return MDBX_EINVAL;
-
- *arg = env->me_path;
- return MDBX_SUCCESS;
-}
-
-int __cold mdbx_env_get_fd(MDBX_env *env, mdbx_filehandle_t *arg) {
- if (unlikely(!env || !arg))
- return MDBX_EINVAL;
-
- *arg = env->me_fd;
- return MDBX_SUCCESS;
-}
-
-/* Common code for mdbx_dbi_stat() and mdbx_env_stat().
- * [in] env the environment to operate in.
- * [in] db the MDBX_db record containing the stats to return.
- * [out] arg the address of an MDBX_stat structure to receive the stats.
- * Returns 0, this function always succeeds. */
-static int __cold mdbx_stat0(MDBX_env *env, MDBX_db *db, MDBX_stat *arg) {
- arg->ms_psize = env->me_psize;
- arg->ms_depth = db->md_depth;
- arg->ms_branch_pages = db->md_branch_pages;
- arg->ms_leaf_pages = db->md_leaf_pages;
- arg->ms_overflow_pages = db->md_overflow_pages;
- arg->ms_entries = db->md_entries;
- return MDBX_SUCCESS;
-}
-
-int __cold mdbx_env_stat(MDBX_env *env, MDBX_stat *arg, size_t bytes) {
- MDBX_meta *meta;
-
- if (unlikely(env == NULL || arg == NULL))
- return MDBX_EINVAL;
- if (unlikely(bytes != sizeof(MDBX_stat)))
- return MDBX_EINVAL;
-
- meta = mdbx_meta_head(env);
- return mdbx_stat0(env, &meta->mm_dbs[MAIN_DBI], arg);
-}
-
-int __cold mdbx_env_info(MDBX_env *env, MDBX_envinfo *arg, size_t bytes) {
-
- if (unlikely(env == NULL || arg == NULL))
- return MDBX_EINVAL;
-
- if (bytes != sizeof(MDBX_envinfo))
- return MDBX_EINVAL;
-
- const MDBX_meta *const meta0 = METAPAGE(env, 0);
- const MDBX_meta *const meta1 = METAPAGE(env, 1);
- const MDBX_meta *const meta2 = METAPAGE(env, 2);
- const MDBX_meta *meta;
- do {
- meta = mdbx_meta_head(env);
- arg->mi_recent_txnid = mdbx_meta_txnid_fluid(env, meta);
- arg->mi_meta0_txnid = mdbx_meta_txnid_fluid(env, meta0);
- arg->mi_meta0_sign = meta0->mm_datasync_sign;
- arg->mi_meta1_txnid = mdbx_meta_txnid_fluid(env, meta1);
- arg->mi_meta1_sign = meta1->mm_datasync_sign;
- arg->mi_meta2_txnid = mdbx_meta_txnid_fluid(env, meta2);
- arg->mi_meta2_sign = meta2->mm_datasync_sign;
- arg->mi_last_pgno = meta->mm_geo.next - 1;
- arg->mi_geo.lower = pgno2bytes(env, meta->mm_geo.lower);
- arg->mi_geo.upper = pgno2bytes(env, meta->mm_geo.upper);
- arg->mi_geo.current = pgno2bytes(env, meta->mm_geo.now);
- arg->mi_geo.shrink = pgno2bytes(env, meta->mm_geo.shrink);
- arg->mi_geo.grow = pgno2bytes(env, meta->mm_geo.grow);
- arg->mi_mapsize = env->me_mapsize;
- mdbx_compiler_barrier();
- } while (unlikely(arg->mi_meta0_txnid != mdbx_meta_txnid_fluid(env, meta0) ||
- arg->mi_meta0_sign != meta0->mm_datasync_sign ||
- arg->mi_meta1_txnid != mdbx_meta_txnid_fluid(env, meta1) ||
- arg->mi_meta1_sign != meta1->mm_datasync_sign ||
- arg->mi_meta2_txnid != mdbx_meta_txnid_fluid(env, meta2) ||
- arg->mi_meta2_sign != meta2->mm_datasync_sign ||
- meta != mdbx_meta_head(env) ||
- arg->mi_recent_txnid != mdbx_meta_txnid_fluid(env, meta)));
-
- arg->mi_maxreaders = env->me_maxreaders;
- arg->mi_numreaders = env->me_lck ? env->me_lck->mti_numreaders : INT32_MAX;
- arg->mi_dxb_pagesize = env->me_psize;
- arg->mi_sys_pagesize = env->me_os_psize;
-
- arg->mi_latter_reader_txnid = 0;
- if (env->me_lck) {
- MDBX_reader *r = env->me_lck->mti_readers;
- arg->mi_latter_reader_txnid = arg->mi_recent_txnid;
- for (unsigned i = 0; i < arg->mi_numreaders; ++i) {
- if (r[i].mr_pid) {
- const txnid_t txnid = r[i].mr_txnid;
- if (arg->mi_latter_reader_txnid > txnid)
- arg->mi_latter_reader_txnid = txnid;
- }
- }
- }
-
- return MDBX_SUCCESS;
-}
-
-static MDBX_cmp_func *mdbx_default_keycmp(unsigned flags) {
- return (flags & MDBX_REVERSEKEY) ? mdbx_cmp_memnr : (flags & MDBX_INTEGERKEY)
- ? mdbx_cmp_int_a2
- : mdbx_cmp_memn;
-}
-
-static MDBX_cmp_func *mdbx_default_datacmp(unsigned flags) {
- return !(flags & MDBX_DUPSORT)
- ? 0
- : ((flags & MDBX_INTEGERDUP)
- ? mdbx_cmp_int_ua
- : ((flags & MDBX_REVERSEDUP) ? mdbx_cmp_memnr
- : mdbx_cmp_memn));
-}
-
-static int mdbx_dbi_bind(MDBX_txn *txn, const MDBX_dbi dbi, unsigned user_flags,
- MDBX_cmp_func *keycmp, MDBX_cmp_func *datacmp) {
- /* LY: so, accepting only three cases for the table's flags:
- * 1) user_flags and both comparators are zero
- * = assume that a by-default mode/flags is requested for reading;
- * 2) user_flags exactly the same
- * = assume that the target mode/flags are requested properly;
- * 3) user_flags differs, but table is empty and MDBX_CREATE is provided
- * = assume that a properly create request with custom flags;
- */
- if ((user_flags ^ txn->mt_dbs[dbi].md_flags) & PERSISTENT_FLAGS) {
- /* flags ara differs, check other conditions */
- if (!user_flags && (!keycmp || keycmp == txn->mt_dbxs[dbi].md_cmp) &&
- (!datacmp || datacmp == txn->mt_dbxs[dbi].md_dcmp)) {
- /* no comparators were provided and flags are zero,
- * seems that is case #1 above */
- user_flags = txn->mt_dbs[dbi].md_flags;
- } else if ((user_flags & MDBX_CREATE) && txn->mt_dbs[dbi].md_entries == 0) {
- if (txn->mt_flags & MDBX_TXN_RDONLY)
- return /* FIXME: return extended info */ MDBX_EACCESS;
- /* make sure flags changes get committed */
- txn->mt_dbs[dbi].md_flags = user_flags & PERSISTENT_FLAGS;
- txn->mt_flags |= MDBX_TXN_DIRTY;
- } else {
- return /* FIXME: return extended info */ MDBX_INCOMPATIBLE;
- }
- }
-
- if (!txn->mt_dbxs[dbi].md_cmp || MDBX_DEBUG) {
- if (!keycmp)
- keycmp = mdbx_default_keycmp(user_flags);
- assert(!txn->mt_dbxs[dbi].md_cmp || txn->mt_dbxs[dbi].md_cmp == keycmp);
- txn->mt_dbxs[dbi].md_cmp = keycmp;
- }
-
- if (!txn->mt_dbxs[dbi].md_dcmp || MDBX_DEBUG) {
- if (!datacmp)
- datacmp = mdbx_default_datacmp(user_flags);
- assert(!txn->mt_dbxs[dbi].md_dcmp || txn->mt_dbxs[dbi].md_dcmp == datacmp);
- txn->mt_dbxs[dbi].md_dcmp = datacmp;
- }
-
- return MDBX_SUCCESS;
-}
-
-int mdbx_dbi_open_ex(MDBX_txn *txn, const char *table_name, unsigned user_flags,
- MDBX_dbi *dbi, MDBX_cmp_func *keycmp,
- MDBX_cmp_func *datacmp) {
- if (unlikely(!txn || !dbi || (user_flags & ~VALID_FLAGS) != 0))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED))
- return MDBX_BAD_TXN;
-
- /* main table? */
- if (!table_name) {
- *dbi = MAIN_DBI;
- return mdbx_dbi_bind(txn, MAIN_DBI, user_flags, keycmp, datacmp);
- }
-
- if (txn->mt_dbxs[MAIN_DBI].md_cmp == NULL) {
- txn->mt_dbxs[MAIN_DBI].md_cmp =
- mdbx_default_keycmp(txn->mt_dbs[MAIN_DBI].md_flags);
- txn->mt_dbxs[MAIN_DBI].md_dcmp =
- mdbx_default_datacmp(txn->mt_dbs[MAIN_DBI].md_flags);
- }
-
- /* Is the DB already open? */
- size_t len = strlen(table_name);
- MDBX_dbi scan, slot = txn->mt_numdbs;
- for (scan = txn->mt_numdbs; --scan >= CORE_DBS;) {
- if (!txn->mt_dbxs[scan].md_name.iov_len) {
- /* Remember this free slot */
- slot = scan;
- continue;
- }
- if (len == txn->mt_dbxs[scan].md_name.iov_len &&
- !strncmp(table_name, txn->mt_dbxs[scan].md_name.iov_base, len)) {
- *dbi = scan;
- return mdbx_dbi_bind(txn, scan, user_flags, keycmp, datacmp);
- }
- }
-
- /* Fail, if no free slot and max hit */
- MDBX_env *env = txn->mt_env;
- if (unlikely(slot >= env->me_maxdbs))
- return MDBX_DBS_FULL;
-
- /* Cannot mix named table with some main-table flags */
- if (unlikely(txn->mt_dbs[MAIN_DBI].md_flags &
- (MDBX_DUPSORT | MDBX_INTEGERKEY)))
- return (user_flags & MDBX_CREATE) ? MDBX_INCOMPATIBLE : MDBX_NOTFOUND;
-
- /* Find the DB info */
- int exact = 0;
- MDBX_val key, data;
- key.iov_len = len;
- key.iov_base = (void *)table_name;
- MDBX_cursor mc;
- mdbx_cursor_init(&mc, txn, MAIN_DBI, NULL);
- int rc = mdbx_cursor_set(&mc, &key, &data, MDBX_SET, &exact);
- if (unlikely(rc != MDBX_SUCCESS)) {
- if (rc != MDBX_NOTFOUND || !(user_flags & MDBX_CREATE))
- return rc;
- } else {
- /* make sure this is actually a table */
- MDBX_node *node = NODEPTR(mc.mc_pg[mc.mc_top], mc.mc_ki[mc.mc_top]);
- if (unlikely((node->mn_flags & (F_DUPDATA | F_SUBDATA)) != F_SUBDATA))
- return MDBX_INCOMPATIBLE;
- }
-
- if (rc != MDBX_SUCCESS && unlikely(txn->mt_flags & MDBX_TXN_RDONLY))
- return MDBX_EACCESS;
-
- /* Done here so we cannot fail after creating a new DB */
- char *namedup = mdbx_strdup(table_name);
- if (unlikely(!namedup))
- return MDBX_ENOMEM;
-
- int err = mdbx_fastmutex_acquire(&env->me_dbi_lock);
- if (unlikely(err != MDBX_SUCCESS)) {
- free(namedup);
- return err;
- }
-
- unsigned dbflag = DB_NEW | DB_VALID | DB_USRVALID;
- if (unlikely(rc)) {
- /* MDBX_NOTFOUND and MDBX_CREATE: Create new DB */
- assert(rc == MDBX_NOTFOUND);
- MDBX_db db_dummy;
- memset(&db_dummy, 0, sizeof(db_dummy));
- db_dummy.md_root = P_INVALID;
- db_dummy.md_flags = user_flags & PERSISTENT_FLAGS;
- data.iov_len = sizeof(db_dummy);
- data.iov_base = &db_dummy;
- WITH_CURSOR_TRACKING(
- mc,
- rc = mdbx_cursor_put(&mc, &key, &data, F_SUBDATA | MDBX_NOOVERWRITE));
-
- if (unlikely(rc != MDBX_SUCCESS))
- goto bailout;
-
- dbflag |= DB_DIRTY;
- }
-
- /* Got info, register DBI in this txn */
- txn->mt_dbxs[slot].md_name.iov_base = namedup;
- txn->mt_dbxs[slot].md_name.iov_len = len;
- txn->mt_dbxs[slot].md_cmp = nullptr;
- txn->mt_dbxs[slot].md_dcmp = nullptr;
- txn->mt_dbflags[slot] = (uint8_t)dbflag;
- txn->mt_dbiseqs[slot] = (env->me_dbiseqs[slot] += 1);
-
- txn->mt_dbs[slot] = *(MDBX_db *)data.iov_base;
- rc = mdbx_dbi_bind(txn, slot, user_flags, keycmp, datacmp);
- if (unlikely(rc != MDBX_SUCCESS)) {
- assert((dbflag & DB_DIRTY) == 0);
- /* cleanup slot */
- txn->mt_dbxs[slot].md_name.iov_base = NULL;
- txn->mt_dbxs[slot].md_name.iov_len = 0;
- txn->mt_dbflags[slot] = 0;
- bailout:
- free(namedup);
- } else {
- *dbi = slot;
- if (slot == txn->mt_numdbs)
- txn->mt_numdbs++;
- }
-
- mdbx_ensure(env, mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS);
- return rc;
-}
-
-int mdbx_dbi_open(MDBX_txn *txn, const char *table_name, unsigned table_flags,
- MDBX_dbi *dbi) {
- return mdbx_dbi_open_ex(txn, table_name, table_flags, dbi, nullptr, nullptr);
-}
-
-int __cold mdbx_dbi_stat(MDBX_txn *txn, MDBX_dbi dbi, MDBX_stat *arg,
- size_t bytes) {
- if (unlikely(!arg || !txn))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_VALID)))
- return MDBX_EINVAL;
-
- if (unlikely(bytes != sizeof(MDBX_stat)))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED))
- return MDBX_BAD_TXN;
-
- if (unlikely(txn->mt_dbflags[dbi] & DB_STALE)) {
- MDBX_cursor mc;
- MDBX_xcursor mx;
- /* Stale, must read the DB's root. cursor_init does it for us. */
- mdbx_cursor_init(&mc, txn, dbi, &mx);
- }
- return mdbx_stat0(txn->mt_env, &txn->mt_dbs[dbi], arg);
-}
-
-static int mdbx_dbi_close_locked(MDBX_env *env, MDBX_dbi dbi) {
- if (unlikely(dbi < CORE_DBS || dbi >= env->me_maxdbs))
- return MDBX_EINVAL;
-
- char *ptr = env->me_dbxs[dbi].md_name.iov_base;
- /* If there was no name, this was already closed */
- if (unlikely(!ptr))
- return MDBX_BAD_DBI;
-
- env->me_dbxs[dbi].md_name.iov_base = NULL;
- env->me_dbxs[dbi].md_name.iov_len = 0;
- env->me_dbflags[dbi] = 0;
- env->me_dbiseqs[dbi]++;
- free(ptr);
- return MDBX_SUCCESS;
-}
-
-int mdbx_dbi_close(MDBX_env *env, MDBX_dbi dbi) {
- if (unlikely(dbi < CORE_DBS || dbi >= env->me_maxdbs))
- return MDBX_EINVAL;
-
- int rc = mdbx_fastmutex_acquire(&env->me_dbi_lock);
- if (likely(rc == MDBX_SUCCESS)) {
- rc = mdbx_dbi_close_locked(env, dbi);
- mdbx_ensure(env, mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS);
- }
- return rc;
-}
-
-int mdbx_dbi_flags_ex(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags,
- unsigned *state) {
- if (unlikely(!txn || !flags || !state))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_VALID)))
- return MDBX_EINVAL;
-
- *flags = txn->mt_dbs[dbi].md_flags & PERSISTENT_FLAGS;
- *state = txn->mt_dbflags[dbi] & (DB_NEW | DB_DIRTY | DB_STALE);
-
- return MDBX_SUCCESS;
-}
-
-int mdbx_dbi_flags(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags) {
- unsigned state;
- return mdbx_dbi_flags_ex(txn, dbi, flags, &state);
-}
-
-/* Add all the DB's pages to the free list.
- * [in] mc Cursor on the DB to free.
- * [in] subs non-Zero to check for sub-DBs in this DB.
- * Returns 0 on success, non-zero on failure. */
-static int mdbx_drop0(MDBX_cursor *mc, int subs) {
- int rc;
-
- rc = mdbx_page_search(mc, NULL, MDBX_PS_FIRST);
- if (likely(rc == MDBX_SUCCESS)) {
- MDBX_txn *txn = mc->mc_txn;
- MDBX_node *ni;
- MDBX_cursor mx;
- unsigned i;
-
- /* DUPSORT sub-DBs have no ovpages/DBs. Omit scanning leaves.
- * This also avoids any P_LEAF2 pages, which have no nodes.
- * Also if the DB doesn't have sub-DBs and has no overflow
- * pages, omit scanning leaves. */
- if ((mc->mc_flags & C_SUB) || (!subs && !mc->mc_db->md_overflow_pages))
- mdbx_cursor_pop(mc);
-
- mdbx_cursor_copy(mc, &mx);
- while (mc->mc_snum > 0) {
- MDBX_page *mp = mc->mc_pg[mc->mc_top];
- unsigned n = NUMKEYS(mp);
- if (IS_LEAF(mp)) {
- for (i = 0; i < n; i++) {
- ni = NODEPTR(mp, i);
- if (ni->mn_flags & F_BIGDATA) {
- MDBX_page *omp;
- pgno_t pg;
- memcpy(&pg, NODEDATA(ni), sizeof(pg));
- rc = mdbx_page_get(mc, pg, &omp, NULL);
- if (unlikely(rc))
- goto done;
- mdbx_cassert(mc, IS_OVERFLOW(omp));
- rc =
- mdbx_pnl_append_range(&txn->mt_befree_pages, pg, omp->mp_pages);
- if (unlikely(rc))
- goto done;
- mc->mc_db->md_overflow_pages -= omp->mp_pages;
- if (!mc->mc_db->md_overflow_pages && !subs)
- break;
- } else if (subs && (ni->mn_flags & F_SUBDATA)) {
- mdbx_xcursor_init1(mc, ni);
- rc = mdbx_drop0(&mc->mc_xcursor->mx_cursor, 0);
- if (unlikely(rc))
- goto done;
- }
- }
- if (!subs && !mc->mc_db->md_overflow_pages)
- goto pop;
- } else {
- if (unlikely((rc = mdbx_pnl_need(&txn->mt_befree_pages, n)) != 0))
- goto done;
- for (i = 0; i < n; i++) {
- pgno_t pg;
- ni = NODEPTR(mp, i);
- pg = NODEPGNO(ni);
- /* free it */
- mdbx_pnl_xappend(txn->mt_befree_pages, pg);
- }
- }
- if (!mc->mc_top)
- break;
- mdbx_cassert(mc, i <= UINT16_MAX);
- mc->mc_ki[mc->mc_top] = (indx_t)i;
- rc = mdbx_cursor_sibling(mc, 1);
- if (rc) {
- if (unlikely(rc != MDBX_NOTFOUND))
- goto done;
- /* no more siblings, go back to beginning
- * of previous level. */
- pop:
- mdbx_cursor_pop(mc);
- mc->mc_ki[0] = 0;
- for (i = 1; i < mc->mc_snum; i++) {
- mc->mc_ki[i] = 0;
- mc->mc_pg[i] = mx.mc_pg[i];
- }
- }
- }
- /* free it */
- rc = mdbx_pnl_append(&txn->mt_befree_pages, mc->mc_db->md_root);
- done:
- if (unlikely(rc))
- txn->mt_flags |= MDBX_TXN_ERROR;
- } else if (rc == MDBX_NOTFOUND) {
- rc = MDBX_SUCCESS;
- }
- mc->mc_flags &= ~C_INITIALIZED;
- return rc;
-}
-
-int mdbx_drop(MDBX_txn *txn, MDBX_dbi dbi, int del) {
- if (unlikely(1 < (unsigned)del || !txn))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
- return MDBX_EINVAL;
-
- if (unlikely(TXN_DBI_CHANGED(txn, dbi)))
- return MDBX_BAD_DBI;
-
- if (unlikely(F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY)))
- return MDBX_EACCESS;
-
- MDBX_cursor *mc;
- int rc = mdbx_cursor_open(txn, dbi, &mc);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
-
- MDBX_env *env = txn->mt_env;
- rc = mdbx_fastmutex_acquire(&env->me_dbi_lock);
- if (unlikely(rc != MDBX_SUCCESS)) {
- mdbx_cursor_close(mc);
- return rc;
- }
-
- if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) {
- rc = MDBX_EINVAL;
- goto bailout;
- }
-
- if (unlikely(TXN_DBI_CHANGED(txn, dbi))) {
- rc = MDBX_BAD_DBI;
- goto bailout;
- }
-
- rc = mdbx_drop0(mc, mc->mc_db->md_flags & MDBX_DUPSORT);
- /* Invalidate the dropped DB's cursors */
- for (MDBX_cursor *m2 = txn->mt_cursors[dbi]; m2; m2 = m2->mc_next)
- m2->mc_flags &= ~(C_INITIALIZED | C_EOF);
- if (unlikely(rc))
- goto bailout;
-
- /* Can't delete the main DB */
- if (del && dbi >= CORE_DBS) {
- rc = mdbx_del0(txn, MAIN_DBI, &mc->mc_dbx->md_name, NULL, F_SUBDATA);
- if (likely(!rc)) {
- txn->mt_dbflags[dbi] = DB_STALE;
- mdbx_dbi_close_locked(env, dbi);
- } else {
- txn->mt_flags |= MDBX_TXN_ERROR;
- }
- } else {
- /* reset the DB record, mark it dirty */
- txn->mt_dbflags[dbi] |= DB_DIRTY;
- txn->mt_dbs[dbi].md_depth = 0;
- txn->mt_dbs[dbi].md_branch_pages = 0;
- txn->mt_dbs[dbi].md_leaf_pages = 0;
- txn->mt_dbs[dbi].md_overflow_pages = 0;
- txn->mt_dbs[dbi].md_entries = 0;
- txn->mt_dbs[dbi].md_root = P_INVALID;
- txn->mt_dbs[dbi].md_seq = 0;
-
- txn->mt_flags |= MDBX_TXN_DIRTY;
- }
-
-bailout:
- mdbx_cursor_close(mc);
- mdbx_ensure(env, mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS);
- return rc;
-}
-
-int mdbx_set_compare(MDBX_txn *txn, MDBX_dbi dbi, MDBX_cmp_func *cmp) {
- if (unlikely(!txn))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
- return MDBX_EINVAL;
-
- txn->mt_dbxs[dbi].md_cmp = cmp;
- return MDBX_SUCCESS;
-}
-
-int mdbx_set_dupsort(MDBX_txn *txn, MDBX_dbi dbi, MDBX_cmp_func *cmp) {
- if (unlikely(!txn))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
- return MDBX_EINVAL;
-
- txn->mt_dbxs[dbi].md_dcmp = cmp;
- return MDBX_SUCCESS;
-}
-
-int __cold mdbx_reader_list(MDBX_env *env, MDBX_msg_func *func, void *ctx) {
- char buf[64];
- int rc = 0, first = 1;
-
- if (unlikely(!env || !func))
- return -MDBX_EINVAL;
-
- if (unlikely(env->me_signature != MDBX_ME_SIGNATURE))
- return MDBX_EBADSIGN;
-
- const MDBX_lockinfo *const lck = env->me_lck;
- const unsigned snap_nreaders = lck->mti_numreaders;
- for (unsigned i = 0; i < snap_nreaders; i++) {
- if (lck->mti_readers[i].mr_pid) {
- const txnid_t txnid = lck->mti_readers[i].mr_txnid;
- if (txnid == ~(txnid_t)0)
- snprintf(buf, sizeof(buf), "%10" PRIuPTR " %" PRIxPTR " -\n",
- (uintptr_t)lck->mti_readers[i].mr_pid,
- (uintptr_t)lck->mti_readers[i].mr_tid);
- else
- snprintf(buf, sizeof(buf), "%10" PRIuPTR " %" PRIxPTR " %" PRIaTXN "\n",
- (uintptr_t)lck->mti_readers[i].mr_pid,
- (uintptr_t)lck->mti_readers[i].mr_tid, txnid);
-
- if (first) {
- first = 0;
- rc = func(" pid thread txnid\n", ctx);
- if (rc < 0)
- break;
- }
- rc = func(buf, ctx);
- if (rc < 0)
- break;
- }
- }
- if (first)
- rc = func("(no active readers)\n", ctx);
-
- return rc;
-}
-
-/* Insert pid into list if not already present.
- * return -1 if already present. */
-static int __cold mdbx_pid_insert(mdbx_pid_t *ids, mdbx_pid_t pid) {
- /* binary search of pid in list */
- unsigned base = 0;
- unsigned cursor = 1;
- int val = 0;
- unsigned n = ids[0];
-
- while (n > 0) {
- unsigned pivot = n >> 1;
- cursor = base + pivot + 1;
- val = pid - ids[cursor];
-
- if (val < 0) {
- n = pivot;
- } else if (val > 0) {
- base = cursor;
- n -= pivot + 1;
- } else {
- /* found, so it's a duplicate */
- return -1;
- }
- }
-
- if (val > 0)
- ++cursor;
-
- ids[0]++;
- for (n = ids[0]; n > cursor; n--)
- ids[n] = ids[n - 1];
- ids[n] = pid;
- return 0;
-}
-
-int __cold mdbx_reader_check(MDBX_env *env, int *dead) {
- if (unlikely(!env || env->me_signature != MDBX_ME_SIGNATURE))
- return MDBX_EINVAL;
- if (dead)
- *dead = 0;
- return mdbx_reader_check0(env, false, dead);
-}
-
-/* Return:
- * MDBX_RESULT_TRUE - done and mutex recovered
- * MDBX_SUCCESS - done
- * Otherwise errcode. */
-int __cold mdbx_reader_check0(MDBX_env *env, int rdt_locked, int *dead) {
- assert(rdt_locked >= 0);
-
- if (unlikely(env->me_pid != mdbx_getpid())) {
- env->me_flags |= MDBX_FATAL_ERROR;
- return MDBX_PANIC;
- }
-
- MDBX_lockinfo *const lck = env->me_lck;
- const unsigned snap_nreaders = lck->mti_numreaders;
- mdbx_pid_t *pids = alloca((snap_nreaders + 1) * sizeof(mdbx_pid_t));
- pids[0] = 0;
-
- int rc = MDBX_SUCCESS, count = 0;
- for (unsigned i = 0; i < snap_nreaders; i++) {
- const mdbx_pid_t pid = lck->mti_readers[i].mr_pid;
- if (pid == 0)
- continue /* skip empty */;
- if (pid == env->me_pid)
- continue /* skip self */;
- if (mdbx_pid_insert(pids, pid) != 0)
- continue /* such pid already processed */;
-
- int err = mdbx_rpid_check(env, pid);
- if (err == MDBX_RESULT_TRUE)
- continue /* reader is live */;
-
- if (err != MDBX_SUCCESS) {
- rc = err;
- break /* mdbx_rpid_check() failed */;
- }
-
- /* stale reader found */
- if (!rdt_locked) {
- err = mdbx_rdt_lock(env);
- if (MDBX_IS_ERROR(err)) {
- rc = err;
- break;
- }
-
- rdt_locked = -1;
- if (err == MDBX_RESULT_TRUE) {
- /* mutex recovered, the mdbx_mutex_failed() checked all readers */
- rc = MDBX_RESULT_TRUE;
- break;
- }
-
- /* a other process may have clean and reused slot, recheck */
- if (lck->mti_readers[i].mr_pid != pid)
- continue;
-
- err = mdbx_rpid_check(env, pid);
- if (MDBX_IS_ERROR(err)) {
- rc = err;
- break;
- }
-
- if (err != MDBX_SUCCESS)
- continue /* the race with other process, slot reused */;
- }
-
- /* clean it */
- for (unsigned j = i; j < snap_nreaders; j++) {
- if (lck->mti_readers[j].mr_pid == pid) {
- mdbx_debug("clear stale reader pid %" PRIuPTR " txn %" PRIaTXN "",
- (size_t)pid, lck->mti_readers[j].mr_txnid);
- lck->mti_readers[j].mr_pid = 0;
- lck->mti_readers_refresh_flag = true;
- count++;
- }
- }
- }
-
- if (rdt_locked < 0)
- mdbx_rdt_unlock(env);
-
- if (dead)
- *dead = count;
- return rc;
-}
-
-int __cold mdbx_setup_debug(int flags, MDBX_debug_func *logger) {
- unsigned ret = mdbx_runtime_flags;
- mdbx_runtime_flags = flags;
-
-#ifdef __linux__
- if (flags & MDBX_DBG_DUMP) {
- int core_filter_fd = open("/proc/self/coredump_filter", O_TRUNC | O_RDWR);
- if (core_filter_fd >= 0) {
- char buf[32];
- const unsigned r = pread(core_filter_fd, buf, sizeof(buf), 0);
- if (r > 0 && r < sizeof(buf)) {
- buf[r] = 0;
- unsigned long mask = strtoul(buf, NULL, 16);
- if (mask != ULONG_MAX) {
- mask |= 1 << 3 /* Dump file-backed shared mappings */;
- mask |= 1 << 6 /* Dump shared huge pages */;
- mask |= 1 << 8 /* Dump shared DAX pages */;
- unsigned w = snprintf(buf, sizeof(buf), "0x%lx\n", mask);
- if (w > 0 && w < sizeof(buf)) {
- w = pwrite(core_filter_fd, buf, w, 0);
- (void)w;
- }
- }
- }
- close(core_filter_fd);
- }
- }
-#endif /* __linux__ */
-
- mdbx_debug_logger = logger;
- return ret;
-}
-
-static txnid_t __cold mdbx_oomkick(MDBX_env *env, const txnid_t laggard) {
- mdbx_debug("DB size maxed out");
-
- int retry;
- for (retry = 0; retry < INT_MAX; ++retry) {
- txnid_t oldest = mdbx_reclaiming_detent(env);
- mdbx_assert(env, oldest < env->me_txn0->mt_txnid);
- mdbx_assert(env, oldest >= laggard);
- mdbx_assert(env, oldest >= env->me_oldest[0]);
- if (oldest == laggard)
- return oldest;
-
- if (MDBX_IS_ERROR(mdbx_reader_check0(env, false, NULL)))
- break;
-
- MDBX_reader *const rtbl = env->me_lck->mti_readers;
- MDBX_reader *asleep = nullptr;
- for (int i = env->me_lck->mti_numreaders; --i >= 0;) {
- if (rtbl[i].mr_pid) {
- mdbx_jitter4testing(true);
- const txnid_t snap = rtbl[i].mr_txnid;
- if (oldest > snap && laggard <= /* ignore pending updates */ snap) {
- oldest = snap;
- asleep = &rtbl[i];
- }
- }
- }
-
- if (laggard < oldest || !asleep) {
- if (retry && env->me_oom_func) {
- /* LY: notify end of oom-loop */
- const txnid_t gap = oldest - laggard;
- env->me_oom_func(env, 0, 0, laggard,
- (gap < UINT_MAX) ? (unsigned)gap : UINT_MAX, -retry);
- }
- mdbx_notice("oom-kick: update oldest %" PRIaTXN " -> %" PRIaTXN,
- env->me_oldest[0], oldest);
- mdbx_assert(env, env->me_oldest[0] <= oldest);
- return env->me_oldest[0] = oldest;
- }
-
- mdbx_tid_t tid;
- mdbx_pid_t pid;
- int rc;
-
- if (!env->me_oom_func)
- break;
-
- pid = asleep->mr_pid;
- tid = asleep->mr_tid;
- if (asleep->mr_txnid != laggard || pid <= 0)
- continue;
-
- const txnid_t gap =
- mdbx_meta_txnid_stable(env, mdbx_meta_head(env)) - laggard;
- rc = env->me_oom_func(env, pid, tid, laggard,
- (gap < UINT_MAX) ? (unsigned)gap : UINT_MAX, retry);
- if (rc < 0)
- break;
-
- if (rc) {
- asleep->mr_txnid = ~(txnid_t)0;
- env->me_lck->mti_readers_refresh_flag = true;
- if (rc > 1) {
- asleep->mr_tid = 0;
- asleep->mr_pid = 0;
- mdbx_coherent_barrier();
- }
- }
- }
-
- if (retry && env->me_oom_func) {
- /* LY: notify end of oom-loop */
- env->me_oom_func(env, 0, 0, laggard, 0, -retry);
- }
- return mdbx_find_oldest(env->me_txn);
-}
-
-int __cold mdbx_env_set_syncbytes(MDBX_env *env, size_t bytes) {
- if (unlikely(!env))
- return MDBX_EINVAL;
-
- if (unlikely(env->me_signature != MDBX_ME_SIGNATURE))
- return MDBX_EBADSIGN;
-
- env->me_sync_threshold = bytes;
- return env->me_map ? mdbx_env_sync(env, 0) : MDBX_SUCCESS;
-}
-
-int __cold mdbx_env_set_oomfunc(MDBX_env *env, MDBX_oom_func *oomfunc) {
- if (unlikely(!env))
- return MDBX_EINVAL;
-
- if (unlikely(env->me_signature != MDBX_ME_SIGNATURE))
- return MDBX_EBADSIGN;
-
- env->me_oom_func = oomfunc;
- return MDBX_SUCCESS;
-}
-
-MDBX_oom_func *__cold mdbx_env_get_oomfunc(MDBX_env *env) {
- return likely(env && env->me_signature == MDBX_ME_SIGNATURE)
- ? env->me_oom_func
- : NULL;
-}
-
-#ifdef __SANITIZE_THREAD__
-/* LY: avoid tsan-trap by me_txn, mm_last_pg and mt_next_pgno */
-__attribute__((no_sanitize_thread, noinline))
-#endif
-int mdbx_txn_straggler(MDBX_txn *txn, int *percent)
-{
- if (unlikely(!txn))
- return -MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- MDBX_env *env = txn->mt_env;
- if (unlikely((txn->mt_flags & MDBX_RDONLY) == 0)) {
- if (percent)
- *percent =
- (int)((txn->mt_next_pgno * UINT64_C(100) + txn->mt_end_pgno / 2) /
- txn->mt_end_pgno);
- return -1;
- }
-
- txnid_t recent;
- MDBX_meta *meta;
- do {
- meta = mdbx_meta_head(env);
- recent = mdbx_meta_txnid_fluid(env, meta);
- if (percent) {
- const pgno_t maxpg = meta->mm_geo.now;
- *percent = (int)((meta->mm_geo.next * UINT64_C(100) + maxpg / 2) / maxpg);
- }
- } while (unlikely(recent != mdbx_meta_txnid_fluid(env, meta)));
-
- txnid_t lag = recent - txn->mt_ro_reader->mr_txnid;
- return (lag > INT_MAX) ? INT_MAX : (int)lag;
-}
-
-typedef struct mdbx_walk_ctx {
- MDBX_txn *mw_txn;
- void *mw_user;
- MDBX_pgvisitor_func *mw_visitor;
-} mdbx_walk_ctx_t;
-
-/* Depth-first tree traversal. */
-static int __cold mdbx_env_walk(mdbx_walk_ctx_t *ctx, const char *dbi,
- pgno_t pg, int deep) {
- MDBX_page *mp;
- int rc, i, nkeys;
- size_t header_size, unused_size, payload_size, align_bytes;
- const char *type;
-
- if (pg == P_INVALID)
- return MDBX_SUCCESS; /* empty db */
-
- MDBX_cursor mc;
- memset(&mc, 0, sizeof(mc));
- mc.mc_snum = 1;
- mc.mc_txn = ctx->mw_txn;
-
- rc = mdbx_page_get(&mc, pg, &mp, NULL);
- if (rc)
- return rc;
- if (pg != mp->mp_pgno)
- return MDBX_CORRUPTED;
-
- nkeys = NUMKEYS(mp);
- header_size = IS_LEAF2(mp) ? PAGEHDRSZ : PAGEHDRSZ + mp->mp_lower;
- unused_size = SIZELEFT(mp);
- payload_size = 0;
-
- /* LY: Don't use mask here, e.g bitwise
- * (P_BRANCH|P_LEAF|P_LEAF2|P_META|P_OVERFLOW|P_SUBP).
- * Pages should not me marked dirty/loose or otherwise. */
- switch (mp->mp_flags) {
- case P_BRANCH:
- type = "branch";
- if (nkeys < 1)
- return MDBX_CORRUPTED;
- break;
- case P_LEAF:
- type = "leaf";
- break;
- case P_LEAF | P_SUBP:
- type = "dupsort-subleaf";
- break;
- case P_LEAF | P_LEAF2:
- type = "dupfixed-leaf";
- break;
- case P_LEAF | P_LEAF2 | P_SUBP:
- type = "dupsort-dupfixed-subleaf";
- break;
- case P_META:
- case P_OVERFLOW:
- __fallthrough;
- default:
- return MDBX_CORRUPTED;
- }
-
- for (align_bytes = i = 0; i < nkeys;
- align_bytes += ((payload_size + align_bytes) & 1), i++) {
- MDBX_node *node;
-
- if (IS_LEAF2(mp)) {
- /* LEAF2 pages have no mp_ptrs[] or node headers */
- payload_size += mp->mp_leaf2_ksize;
- continue;
- }
-
- node = NODEPTR(mp, i);
- payload_size += NODESIZE + node->mn_ksize;
-
- if (IS_BRANCH(mp)) {
- rc = mdbx_env_walk(ctx, dbi, NODEPGNO(node), deep);
- if (rc)
- return rc;
- continue;
- }
-
- assert(IS_LEAF(mp));
- if (node->mn_flags & F_BIGDATA) {
- MDBX_page *omp;
- pgno_t *opg;
- size_t over_header, over_payload, over_unused;
-
- payload_size += sizeof(pgno_t);
- opg = NODEDATA(node);
- rc = mdbx_page_get(&mc, *opg, &omp, NULL);
- if (rc)
- return rc;
- if (*opg != omp->mp_pgno)
- return MDBX_CORRUPTED;
- /* LY: Don't use mask here, e.g bitwise
- * (P_BRANCH|P_LEAF|P_LEAF2|P_META|P_OVERFLOW|P_SUBP).
- * Pages should not me marked dirty/loose or otherwise. */
- if (P_OVERFLOW != omp->mp_flags)
- return MDBX_CORRUPTED;
-
- over_header = PAGEHDRSZ;
- over_payload = NODEDSZ(node);
- over_unused = pgno2bytes(ctx->mw_txn->mt_env, omp->mp_pages) -
- over_payload - over_header;
-
- rc = ctx->mw_visitor(*opg, omp->mp_pages, ctx->mw_user, dbi,
- "overflow-data", 1, over_payload, over_header,
- over_unused);
- if (rc)
- return rc;
- continue;
- }
-
- payload_size += NODEDSZ(node);
- if (node->mn_flags & F_SUBDATA) {
- MDBX_db *db = NODEDATA(node);
- char *name = NULL;
-
- if (!(node->mn_flags & F_DUPDATA)) {
- name = NODEKEY(node);
- ptrdiff_t namelen = (char *)db - name;
- name = memcpy(alloca(namelen + 1), name, namelen);
- name[namelen] = 0;
- }
- rc = mdbx_env_walk(ctx, (name && name[0]) ? name : dbi, db->md_root,
- deep + 1);
- if (rc)
- return rc;
- }
- }
-
- return ctx->mw_visitor(mp->mp_pgno, 1, ctx->mw_user, dbi, type, nkeys,
- payload_size, header_size, unused_size + align_bytes);
-}
-
-int __cold mdbx_env_pgwalk(MDBX_txn *txn, MDBX_pgvisitor_func *visitor,
- void *user) {
- if (unlikely(!txn))
- return MDBX_BAD_TXN;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- mdbx_walk_ctx_t ctx;
- ctx.mw_txn = txn;
- ctx.mw_user = user;
- ctx.mw_visitor = visitor;
-
- int rc = visitor(0, NUM_METAS, user, "meta", "meta", NUM_METAS,
- sizeof(MDBX_meta) * NUM_METAS, PAGEHDRSZ * NUM_METAS,
- (txn->mt_env->me_psize - sizeof(MDBX_meta) - PAGEHDRSZ) *
- NUM_METAS);
- if (!rc)
- rc = mdbx_env_walk(&ctx, "free", txn->mt_dbs[FREE_DBI].md_root, 0);
- if (!rc)
- rc = mdbx_env_walk(&ctx, "main", txn->mt_dbs[MAIN_DBI].md_root, 0);
- if (!rc)
- rc = visitor(P_INVALID, 0, user, NULL, NULL, 0, 0, 0, 0);
- return rc;
-}
-
-int mdbx_canary_put(MDBX_txn *txn, const mdbx_canary *canary) {
- if (unlikely(!txn))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED))
- return MDBX_BAD_TXN;
-
- if (unlikely(F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY)))
- return MDBX_EACCESS;
-
- if (likely(canary)) {
- if (txn->mt_canary.x == canary->x && txn->mt_canary.y == canary->y &&
- txn->mt_canary.z == canary->z)
- return MDBX_SUCCESS;
- txn->mt_canary.x = canary->x;
- txn->mt_canary.y = canary->y;
- txn->mt_canary.z = canary->z;
- }
- txn->mt_canary.v = txn->mt_txnid;
-
- if ((txn->mt_flags & MDBX_TXN_DIRTY) == 0) {
- MDBX_env *env = txn->mt_env;
- txn->mt_flags |= MDBX_TXN_DIRTY;
- env->me_sync_pending += env->me_psize;
- }
-
- return MDBX_SUCCESS;
-}
-
-int mdbx_canary_get(MDBX_txn *txn, mdbx_canary *canary) {
- if (unlikely(txn == NULL || canary == NULL))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- *canary = txn->mt_canary;
- return MDBX_SUCCESS;
-}
-
-int mdbx_cursor_on_first(MDBX_cursor *mc) {
- if (unlikely(mc == NULL))
- return MDBX_EINVAL;
-
- if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (!(mc->mc_flags & C_INITIALIZED))
- return MDBX_RESULT_FALSE;
-
- for (unsigned i = 0; i < mc->mc_snum; ++i) {
- if (mc->mc_ki[i])
- return MDBX_RESULT_FALSE;
- }
-
- return MDBX_RESULT_TRUE;
-}
-
-int mdbx_cursor_on_last(MDBX_cursor *mc) {
- if (unlikely(mc == NULL))
- return MDBX_EINVAL;
-
- if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (!(mc->mc_flags & C_INITIALIZED))
- return MDBX_RESULT_FALSE;
-
- for (unsigned i = 0; i < mc->mc_snum; ++i) {
- unsigned nkeys = NUMKEYS(mc->mc_pg[i]);
- if (mc->mc_ki[i] < nkeys - 1)
- return MDBX_RESULT_FALSE;
- }
-
- return MDBX_RESULT_TRUE;
-}
-
-int mdbx_cursor_eof(MDBX_cursor *mc) {
- if (unlikely(mc == NULL))
- return MDBX_EINVAL;
-
- if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if ((mc->mc_flags & C_INITIALIZED) == 0)
- return MDBX_RESULT_TRUE;
-
- if (mc->mc_snum == 0)
- return MDBX_RESULT_TRUE;
-
- if ((mc->mc_flags & C_EOF) &&
- mc->mc_ki[mc->mc_top] >= NUMKEYS(mc->mc_pg[mc->mc_top]))
- return MDBX_RESULT_TRUE;
-
- return MDBX_RESULT_FALSE;
-}
-
-static int mdbx_is_samedata(const MDBX_val *a, const MDBX_val *b) {
- return a->iov_len == b->iov_len &&
- memcmp(a->iov_base, b->iov_base, a->iov_len) == 0;
-}
-
-/* ПозволÑет обновить или удалить ÑущеÑтвующую запиÑÑŒ Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸ÐµÐ¼
- * в old_data предыдущего Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ…. При Ñтом еÑли new_data равен
- * нулю, то выполнÑетÑÑ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ðµ, иначе обновление/вÑтавка.
- *
- * Текущее значение может находитьÑÑ Ð² уже измененной (грÑзной) Ñтранице.
- * Ð’ Ñтом Ñлучае Ñтраница будет перезапиÑана при обновлении, а Ñамо Ñтарое
- * значение утрачено. ПоÑтому иÑходно в old_data должен быть передан
- * дополнительный буфер Ð´Ð»Ñ ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñтарого значениÑ.
- * ЕÑли переданный буфер Ñлишком мал, то Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²ÐµÑ€Ð½ÐµÑ‚ -1, уÑтановив
- * old_data->iov_len в ÑоответÑтвующее значение.
- *
- * Ð”Ð»Ñ Ð½Ðµ-уникальных ключей также возможен второй Ñценарий иÑпользованиÑ,
- * когда поÑредÑтвом old_data из запиÑей Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñ‹Ð¼ ключом длÑ
- * удалениÑ/Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ñ‹Ð±Ð¸Ñ€Ð°ÐµÑ‚ÑÑ ÐºÐ¾Ð½ÐºÑ€ÐµÑ‚Ð½Ð°Ñ. Ð”Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° Ñтого ÑценариÑ
- * во flags Ñледует одновременно указать MDBX_CURRENT и MDBX_NOOVERWRITE.
- * Именно Ñта ÐºÐ¾Ð¼Ð±Ð¸Ð½Ð°Ñ†Ð¸Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð°, так как она лишена ÑмыÑла, и Ñтим позволÑет
- * идентифицировать Ð·Ð°Ð¿Ñ€Ð¾Ñ Ñ‚Ð°ÐºÐ¾Ð³Ð¾ ÑценариÑ.
- *
- * Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ быть замещена ÑоответÑтвующими операциÑми Ñ ÐºÑƒÑ€Ñорами
- * поÑле двух доработок (TODO):
- * - внешнÑÑ Ð°Ð»Ð»Ð¾ÐºÐ°Ñ†Ð¸Ñ ÐºÑƒÑ€Ñоров, в том чиÑле на Ñтеке (без malloc).
- * - Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ ÑтатуÑа Ñтраницы по адреÑу (знать о P_DIRTY).
- */
-int mdbx_replace(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *new_data,
- MDBX_val *old_data, unsigned flags) {
- if (unlikely(!key || !old_data || !txn || old_data == new_data))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- if (unlikely(old_data->iov_base == NULL && old_data->iov_len))
- return MDBX_EINVAL;
-
- if (unlikely(new_data == NULL && !(flags & MDBX_CURRENT)))
- return MDBX_EINVAL;
-
- if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
- return MDBX_EINVAL;
-
- if (unlikely(flags &
- ~(MDBX_NOOVERWRITE | MDBX_NODUPDATA | MDBX_RESERVE |
- MDBX_APPEND | MDBX_APPENDDUP | MDBX_CURRENT)))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED)))
- return (txn->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EACCESS : MDBX_BAD_TXN;
-
- MDBX_cursor mc;
- MDBX_xcursor mx;
- mdbx_cursor_init(&mc, txn, dbi, &mx);
- mc.mc_next = txn->mt_cursors[dbi];
- txn->mt_cursors[dbi] = &mc;
-
- int rc;
- MDBX_val present_key = *key;
- if (F_ISSET(flags, MDBX_CURRENT | MDBX_NOOVERWRITE)) {
- /* в old_data значение Ð´Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° конкретного дубликата */
- if (unlikely(!(txn->mt_dbs[dbi].md_flags & MDBX_DUPSORT))) {
- rc = MDBX_EINVAL;
- goto bailout;
- }
-
- /* убираем лишний бит, он был признаком запрошенного режима */
- flags -= MDBX_NOOVERWRITE;
-
- rc = mdbx_cursor_get(&mc, &present_key, old_data, MDBX_GET_BOTH);
- if (rc != MDBX_SUCCESS)
- goto bailout;
-
- if (new_data) {
- /* обновление конкретного дубликата */
- if (mdbx_is_samedata(old_data, new_data))
- /* еÑли данные Ñовпадают, то ничего делать не надо */
- goto bailout;
- }
- } else {
- /* в old_data буфер Ð´Ð»Ñ ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¿Ñ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰ÐµÐ³Ð¾ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ */
- if (unlikely(new_data && old_data->iov_base == new_data->iov_base))
- return MDBX_EINVAL;
- MDBX_val present_data;
- rc = mdbx_cursor_get(&mc, &present_key, &present_data, MDBX_SET_KEY);
- if (unlikely(rc != MDBX_SUCCESS)) {
- old_data->iov_base = NULL;
- old_data->iov_len = rc;
- if (rc != MDBX_NOTFOUND || (flags & MDBX_CURRENT))
- goto bailout;
- } else if (flags & MDBX_NOOVERWRITE) {
- rc = MDBX_KEYEXIST;
- *old_data = present_data;
- goto bailout;
- } else {
- MDBX_page *page = mc.mc_pg[mc.mc_top];
- if (txn->mt_dbs[dbi].md_flags & MDBX_DUPSORT) {
- if (flags & MDBX_CURRENT) {
- /* Ð´Ð»Ñ Ð½Ðµ-уникальных ключей позволÑем update/delete только еÑли ключ
- * один */
- MDBX_node *leaf = NODEPTR(page, mc.mc_ki[mc.mc_top]);
- if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- mdbx_tassert(txn, XCURSOR_INITED(&mc) &&
- mc.mc_xcursor->mx_db.md_entries > 1);
- if (mc.mc_xcursor->mx_db.md_entries > 1) {
- rc = MDBX_EMULTIVAL;
- goto bailout;
- }
- }
- /* еÑли данные Ñовпадают, то ничего делать не надо */
- if (new_data && mdbx_is_samedata(&present_data, new_data)) {
- *old_data = *new_data;
- goto bailout;
- }
- /* Ð’ оригинальной LMDB фладок MDBX_CURRENT здеÑÑŒ приведет
- * к замене данных без учета MDBX_DUPSORT Ñортировки,
- * но здеÑÑŒ Ñто в любом Ñлучае допуÑтимо, так как мы
- * проверили что Ð´Ð»Ñ ÐºÐ»ÑŽÑ‡Ð° еÑть только одно значение. */
- } else if ((flags & MDBX_NODUPDATA) &&
- mdbx_is_samedata(&present_data, new_data)) {
- /* еÑли данные Ñовпадают и уÑтановлен MDBX_NODUPDATA */
- rc = MDBX_KEYEXIST;
- goto bailout;
- }
- } else {
- /* еÑли данные Ñовпадают, то ничего делать не надо */
- if (new_data && mdbx_is_samedata(&present_data, new_data)) {
- *old_data = *new_data;
- goto bailout;
- }
- flags |= MDBX_CURRENT;
- }
-
- if (page->mp_flags & P_DIRTY) {
- if (unlikely(old_data->iov_len < present_data.iov_len)) {
- old_data->iov_base = NULL;
- old_data->iov_len = present_data.iov_len;
- rc = MDBX_RESULT_TRUE;
- goto bailout;
- }
- memcpy(old_data->iov_base, present_data.iov_base, present_data.iov_len);
- old_data->iov_len = present_data.iov_len;
- } else {
- *old_data = present_data;
- }
- }
- }
-
- if (likely(new_data))
- rc = mdbx_cursor_put(&mc, key, new_data, flags);
- else
- rc = mdbx_cursor_del(&mc, 0);
-
-bailout:
- txn->mt_cursors[dbi] = mc.mc_next;
- return rc;
-}
-
-int mdbx_get_ex(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data,
- size_t *values_count) {
- DKBUF;
- mdbx_debug("===> get db %u key [%s]", dbi, DKEY(key));
-
- if (unlikely(!key || !data || !txn))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED))
- return MDBX_BAD_TXN;
-
- MDBX_cursor mc;
- MDBX_xcursor mx;
- mdbx_cursor_init(&mc, txn, dbi, &mx);
-
- int exact = 0;
- int rc = mdbx_cursor_set(&mc, key, data, MDBX_SET_KEY, &exact);
- if (unlikely(rc != MDBX_SUCCESS)) {
- if (rc == MDBX_NOTFOUND && values_count)
- *values_count = 0;
- return rc;
- }
-
- if (values_count) {
- *values_count = 1;
- if (mc.mc_xcursor != NULL) {
- MDBX_node *leaf = NODEPTR(mc.mc_pg[mc.mc_top], mc.mc_ki[mc.mc_top]);
- if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
- mdbx_tassert(txn, mc.mc_xcursor == &mx &&
- (mx.mx_cursor.mc_flags & C_INITIALIZED));
- *values_count = (sizeof(*values_count) >= sizeof(mx.mx_db.md_entries) ||
- mx.mx_db.md_entries <= SIZE_MAX)
- ? (size_t)mx.mx_db.md_entries
- : SIZE_MAX;
- }
- }
- }
- return MDBX_SUCCESS;
-}
-
-/* Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ñообщает находитÑÑ Ð»Ð¸ указанный Ð°Ð´Ñ€ÐµÑ Ð² "грÑзной" Ñтранице у
- * заданной пишущей транзакции. Ð’ конечном Ñчете Ñто позволÑет избавитьÑÑ Ð¾Ñ‚
- * лишнего ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… из ÐЕ-грÑзных Ñтраниц.
- *
- * "ГрÑзные" Ñтраницы - Ñто те, которые уже были изменены в ходе пишущей
- * транзакции. СоответÑтвенно, какие-либо дальнейшие Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³ÑƒÑ‚ привеÑти
- * к перезапиÑи таких Ñтраниц. ПоÑтому вÑе функции, выполнÑющие изменениÑ, в
- * качеÑтве аргументов ÐЕ должны получать указатели на данные в таких
- * Ñтраницах. Ð’ Ñвою очередь "ÐЕ грÑзные" Ñтраницы перед модификацией будут
- * Ñкопированы.
- *
- * Другими Ñловами, данные из "грÑзных" Ñтраниц должны быть либо Ñкопированы
- * перед передачей в качеÑтве аргументов Ð´Ð»Ñ Ð´Ð°Ð»ÑŒÐ½ÐµÐ¹ÑˆÐ¸Ñ… модификаций, либо
- * отвергнуты на Ñтадии проверки корректноÑти аргументов.
- *
- * Таким образом, Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñет как избавитÑÑ Ð¾Ñ‚ лишнего копированиÑ,
- * так и выполнить более полную проверку аргументов.
- *
- * Ð’ÐЖÐО: Передаваемый указатель должен указывать на начало данных. Только
- * так гарантируетÑÑ Ñ‡Ñ‚Ð¾ актуальный заголовок Ñтраницы будет физичеÑки
- * раÑположен в той-же Ñтранице памÑти, в том чиÑле Ð´Ð»Ñ Ð¼Ð½Ð¾Ð³Ð¾Ñтраничных
- * P_OVERFLOW Ñтраниц Ñ Ð´Ð»Ð¸Ð½Ð½Ñ‹Ð¼Ð¸ данными. */
-int mdbx_is_dirty(const MDBX_txn *txn, const void *ptr) {
- if (unlikely(!txn))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- if (unlikely(txn->mt_flags & MDBX_TXN_RDONLY))
- return MDBX_RESULT_FALSE;
-
- const MDBX_env *env = txn->mt_env;
- const uintptr_t mask = ~(uintptr_t)(env->me_psize - 1);
- const MDBX_page *page = (const MDBX_page *)((uintptr_t)ptr & mask);
-
- /* LY: Тут не вÑÑ‘ хорошо Ñ Ð°Ð±Ñолютной доÑтоверноÑтью результата,
- * так как флажок P_DIRTY в LMDB может означать не ÑовÑем то,
- * что было иÑходно задумано, детали Ñм в логике кода mdbx_page_touch().
- *
- * Более того, в режиме БЕЗ WRITEMAP грÑзные Ñтраницы выделÑÑŽÑ‚ÑÑ Ñ‡ÐµÑ€ÐµÐ·
- * malloc(), Ñ‚.е. находÑÑ‚ÑÑ Ð²Ð½Ðµ mmap-диапазона и тогда чтобы отличить
- * дейÑтвительно грÑзную Ñтраницу от ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ Ð½Ð° данные пользователÑ
- * Ñледует Ñканировать dirtylist, что накладно.
- *
- * Тем не менее, однозначно Ñтраница "не грÑзнаÑ" (не будет перепиÑана
- * во Ð²Ñ€ÐµÐ¼Ñ Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ð¸) еÑли Ð°Ð´Ñ€ÐµÑ Ð½Ð°Ñ…Ð¾Ð´Ð¸Ñ‚ÑÑ Ð²Ð½ÑƒÑ‚Ñ€Ð¸ mmap-диапазона
- * и в заголовке Ñтраницы нет флажка P_DIRTY. */
- if (env->me_map < (uint8_t *)page) {
- const size_t usedbytes = pgno2bytes(env, txn->mt_next_pgno);
- if ((uint8_t *)page < env->me_map + usedbytes) {
- /* Ñтраница внутри диапазона, Ñмотрим на флажки */
- return (page->mp_flags & (P_DIRTY | P_LOOSE | P_KEEP))
- ? MDBX_RESULT_TRUE
- : MDBX_RESULT_FALSE;
- }
- /* ГипотетичеÑки здеÑÑŒ возможна ÑитуациÑ, когда указатель адреÑует что-то
- * в пределах mmap, но за границей раÑпределенных Ñтраниц. Это Ñ‚ÑжелаÑ
- * ошибка, к которой не возможно прийти без каких-то больших нарушений.
- * ПоÑтому не проверÑем Ñтот Ñлучай кроме как assert-ом, на то что
- * Ñтраница вне mmap-диаппазона. */
- mdbx_tassert(txn, (uint8_t *)page >= env->me_map + env->me_mapsize);
- }
-
- /* Страница вне иÑпользуемого mmap-диапазона, Ñ‚.е. либо в функцию был
- * передан некорректный адреÑ, либо Ð°Ð´Ñ€ÐµÑ Ð² теневой Ñтранице, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð±Ñ‹Ð»Ð°
- * выделена поÑредÑтвом malloc().
- *
- * Ð”Ð»Ñ WRITE_MAP режима Ñ‚Ð°ÐºÐ°Ñ Ñтраница однозначно "не грÑзнаÑ",
- * а Ð´Ð»Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ð¾Ð² без WRITE_MAP Ñледует проÑматривать ÑпиÑки dirty
- * и spilled Ñтраниц у каких-либо транзакций (в том чиÑле дочерних).
- *
- * ПоÑтому Ð´Ð»Ñ WRITE_MAP возвращаем false, а Ð´Ð»Ñ Ð¾Ñтальных режимов
- * вÑегда true. Ð¢Ð°ÐºÐ°Ñ Ð»Ð¾Ð³Ð¸ÐºÐ° имеет Ñ€Ñд преимущеÑтв:
- * - не тратим Ð²Ñ€ÐµÐ¼Ñ Ð½Ð° проÑмотр ÑпиÑков;
- * - результат вÑегда безопаÑен (может быть ложно-положительным,
- * но не ложно-отрицательным);
- * - результат не завиÑит от вложенноÑти транзакций и от отноÑительного
- * Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ð½Ð½Ð¾Ð¹ транзакции в Ñтой рекурÑии. */
- return (env->me_flags & MDBX_WRITEMAP) ? MDBX_RESULT_FALSE : MDBX_RESULT_TRUE;
-}
-
-int mdbx_dbi_sequence(MDBX_txn *txn, MDBX_dbi dbi, uint64_t *result,
- uint64_t increment) {
- if (unlikely(!txn))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_EBADSIGN;
-
- if (unlikely(txn->mt_owner != mdbx_thread_self()))
- return MDBX_THREAD_MISMATCH;
-
- if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
- return MDBX_EINVAL;
-
- if (unlikely(TXN_DBI_CHANGED(txn, dbi)))
- return MDBX_BAD_DBI;
-
- MDBX_db *dbs = &txn->mt_dbs[dbi];
- if (likely(result))
- *result = dbs->md_seq;
-
- if (likely(increment > 0)) {
- if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED))
- return MDBX_BAD_TXN;
-
- if (unlikely(F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY)))
- return MDBX_EACCESS;
-
- uint64_t new = dbs->md_seq + increment;
- if (unlikely(new < increment))
- return MDBX_RESULT_TRUE;
-
- assert(new > dbs->md_seq);
- dbs->md_seq = new;
- txn->mt_flags |= MDBX_TXN_DIRTY;
- txn->mt_dbflags[dbi] |= DB_DIRTY;
- }
-
- return MDBX_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------*/
-/* attribute support functions for Nexenta */
-
-static __inline int mdbx_attr_peek(MDBX_val *data, mdbx_attr_t *attrptr) {
- if (unlikely(data->iov_len < sizeof(mdbx_attr_t)))
- return MDBX_INCOMPATIBLE;
-
- if (likely(attrptr != NULL))
- *attrptr = *(mdbx_attr_t *)data->iov_base;
- data->iov_len -= sizeof(mdbx_attr_t);
- data->iov_base =
- likely(data->iov_len > 0) ? ((mdbx_attr_t *)data->iov_base) + 1 : NULL;
-
- return MDBX_SUCCESS;
-}
-
-static __inline int mdbx_attr_poke(MDBX_val *reserved, MDBX_val *data,
- mdbx_attr_t attr, unsigned flags) {
- mdbx_attr_t *space = reserved->iov_base;
- if (flags & MDBX_RESERVE) {
- if (likely(data != NULL)) {
- data->iov_base = data->iov_len ? space + 1 : NULL;
- }
- } else {
- *space = attr;
- if (likely(data != NULL)) {
- memcpy(space + 1, data->iov_base, data->iov_len);
- }
- }
-
- return MDBX_SUCCESS;
-}
-
-int mdbx_cursor_get_attr(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
- mdbx_attr_t *attrptr, MDBX_cursor_op op) {
- int rc = mdbx_cursor_get(mc, key, data, op);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
-
- return mdbx_attr_peek(data, attrptr);
-}
-
-int mdbx_get_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data,
- uint64_t *attrptr) {
- int rc = mdbx_get(txn, dbi, key, data);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
-
- return mdbx_attr_peek(data, attrptr);
-}
-
-int mdbx_put_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data,
- mdbx_attr_t attr, unsigned flags) {
- MDBX_val reserve;
- reserve.iov_base = NULL;
- reserve.iov_len = (data ? data->iov_len : 0) + sizeof(mdbx_attr_t);
-
- int rc = mdbx_put(txn, dbi, key, &reserve, flags | MDBX_RESERVE);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
-
- return mdbx_attr_poke(&reserve, data, attr, flags);
-}
-
-int mdbx_cursor_put_attr(MDBX_cursor *cursor, MDBX_val *key, MDBX_val *data,
- mdbx_attr_t attr, unsigned flags) {
- MDBX_val reserve;
- reserve.iov_base = NULL;
- reserve.iov_len = (data ? data->iov_len : 0) + sizeof(mdbx_attr_t);
-
- int rc = mdbx_cursor_put(cursor, key, &reserve, flags | MDBX_RESERVE);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
-
- return mdbx_attr_poke(&reserve, data, attr, flags);
-}
-
-int mdbx_set_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data,
- mdbx_attr_t attr) {
- if (unlikely(!key || !txn))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
- return MDBX_VERSION_MISMATCH;
-
- if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
- return MDBX_EINVAL;
-
- if (unlikely(txn->mt_flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED)))
- return (txn->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EACCESS : MDBX_BAD_TXN;
-
- MDBX_cursor mc;
- MDBX_xcursor mx;
- MDBX_val old_data;
- mdbx_cursor_init(&mc, txn, dbi, &mx);
- int rc = mdbx_cursor_set(&mc, key, &old_data, MDBX_SET, NULL);
- if (unlikely(rc != MDBX_SUCCESS)) {
- if (rc == MDBX_NOTFOUND && data) {
- mc.mc_next = txn->mt_cursors[dbi];
- txn->mt_cursors[dbi] = &mc;
- rc = mdbx_cursor_put_attr(&mc, key, data, attr, 0);
- txn->mt_cursors[dbi] = mc.mc_next;
- }
- return rc;
- }
-
- mdbx_attr_t old_attr = 0;
- rc = mdbx_attr_peek(&old_data, &old_attr);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
-
- if (old_attr == attr && (!data || (data->iov_len == old_data.iov_len &&
- memcmp(data->iov_base, old_data.iov_base,
- old_data.iov_len) == 0)))
- return MDBX_SUCCESS;
-
- mc.mc_next = txn->mt_cursors[dbi];
- txn->mt_cursors[dbi] = &mc;
- rc = mdbx_cursor_put_attr(&mc, key, data ? data : &old_data, attr,
- MDBX_CURRENT);
- txn->mt_cursors[dbi] = mc.mc_next;
- return rc;
-}
-
-//----------------------------------------------------------------------------
-
-#ifdef __SANITIZE_ADDRESS__
-LIBMDBX_API __attribute__((weak)) const char *__asan_default_options() {
- return "symbolize=1:allow_addr2line=1:"
-#ifdef _DEBUG
- "debug=1:"
-#endif /* _DEBUG */
- "report_globals=1:"
- "replace_str=1:replace_intrin=1:"
- "malloc_context_size=9:"
- "detect_leaks=1:"
- "check_printf=1:"
- "detect_deadlocks=1:"
-#ifndef LTO_ENABLED
- "check_initialization_order=1:"
-#endif
- "detect_stack_use_after_return=1:"
- "intercept_tls_get_addr=1:"
- "decorate_proc_maps=1:"
- "abort_on_error=1";
-}
-#endif /* __SANITIZE_ADDRESS__ */
diff --git a/plugins/Dbx_mdb/src/mdbx/mdbx.h b/plugins/Dbx_mdb/src/mdbx/mdbx.h
deleted file mode 100644
index f7de11c0e4..0000000000
--- a/plugins/Dbx_mdb/src/mdbx/mdbx.h
+++ /dev/null
@@ -1,1825 +0,0 @@
-/* LICENSE AND COPYRUSTING *****************************************************
- *
- * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
- * and other libmdbx authors: please see AUTHORS file.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- *
- * ---
- *
- * This code is derived from "LMDB engine" written by
- * Howard Chu (Symas Corporation), which itself derived from btree.c
- * written by Martin Hedenfalk.
- *
- * ---
- *
- * Portions Copyright 2011-2015 Howard Chu, Symas Corp. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- *
- * ---
- *
- * Portions Copyright (c) 2009, 2010 Martin Hedenfalk <martin@bzero.se>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-
-/* ACKNOWLEDGEMENTS ************************************************************
- *
- * Howard Chu (Symas Corporation) - the author of LMDB,
- * from which originated the MDBX in 2015.
- *
- * Martin Hedenfalk <martin@bzero.se> - the author of `btree.c` code,
- * which was used for begin development of LMDB. */
-
-#pragma once
-#ifndef LIBMDBX_H
-#define LIBMDBX_H
-
-/* IMPENDING CHANGES WARNING ***************************************************
- *
- * Now MDBX is under active development and until November 2017 is expected a
- * big change both of API and database format. Unfortunately those update will
- * lead to loss of compatibility with previous versions.
- *
- * The aim of this revolution in providing a clearer robust API and adding new
- * features, including the database properties. */
-
-/*--------------------------------------------------------------------------*/
-
-#ifdef _MSC_VER
-#pragma warning(push, 1)
-#pragma warning(disable : 4548) /* expression before comma has no effect; \
- expected expression with side - effect */
-#pragma warning(disable : 4530) /* C++ exception handler used, but unwind \
- * semantics are not enabled. Specify /EHsc */
-#pragma warning(disable : 4577) /* 'noexcept' used with no exception handling \
- * mode specified; termination on exception is \
- * not guaranteed. Specify /EHsc */
-#endif /* _MSC_VER (warnings) */
-
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#if defined(_WIN32) || defined(_WIN64)
-
-#include <windows.h>
-#include <winnt.h>
-#ifndef __mode_t_defined
-typedef unsigned short mode_t;
-#endif
-typedef HANDLE mdbx_filehandle_t;
-typedef DWORD mdbx_pid_t;
-typedef DWORD mdbx_tid_t;
-#define MDBX_ENODATA ERROR_HANDLE_EOF
-#define MDBX_EINVAL ERROR_INVALID_PARAMETER
-#define MDBX_EACCESS ERROR_ACCESS_DENIED
-#define MDBX_ENOMEM ERROR_OUTOFMEMORY
-#define MDBX_EROFS ERROR_FILE_READ_ONLY
-#define MDBX_ENOSYS ERROR_NOT_SUPPORTED
-#define MDBX_EIO ERROR_WRITE_FAULT
-#define MDBX_EPERM ERROR_INVALID_FUNCTION
-#define MDBX_EINTR ERROR_CANCELLED
-
-#else
-
-#include <errno.h> /* for error codes */
-#include <pthread.h> /* for pthread_t */
-#include <sys/types.h> /* for pid_t */
-#include <sys/uio.h> /* for truct iovec */
-#define HAVE_STRUCT_IOVEC 1
-typedef int mdbx_filehandle_t;
-typedef pid_t mdbx_pid_t;
-typedef pthread_t mdbx_tid_t;
-#define MDBX_ENODATA ENODATA
-#define MDBX_EINVAL EINVAL
-#define MDBX_EACCESS EACCES
-#define MDBX_ENOMEM ENOMEM
-#define MDBX_EROFS EROFS
-#define MDBX_ENOSYS ENOSYS
-#define MDBX_EIO EIO
-#define MDBX_EPERM EPERM
-#define MDBX_EINTR EINTR
-#endif
-
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
-/*--------------------------------------------------------------------------*/
-
-#ifndef __has_attribute
-#define __has_attribute(x) (0)
-#endif
-
-#ifndef __dll_export
-#if defined(_WIN32) || defined(__CYGWIN__)
-#if defined(__GNUC__) || __has_attribute(dllexport)
-#define __dll_export __attribute__((dllexport))
-#elif defined(_MSC_VER)
-#define __dll_export __declspec(dllexport)
-#else
-#define __dll_export
-#endif
-#elif defined(__GNUC__) || __has_attribute(visibility)
-#define __dll_export __attribute__((visibility("default")))
-#else
-#define __dll_export
-#endif
-#endif /* __dll_export */
-
-#ifndef __dll_import
-#if defined(_WIN32) || defined(__CYGWIN__)
-#if defined(__GNUC__) || __has_attribute(dllimport)
-#define __dll_import __attribute__((dllimport))
-#elif defined(_MSC_VER)
-#define __dll_import __declspec(dllimport)
-#else
-#define __dll_import
-#endif
-#else
-#define __dll_import
-#endif
-#endif /* __dll_import */
-
-/*--------------------------------------------------------------------------*/
-
-#define MDBX_VERSION_MAJOR 0
-#define MDBX_VERSION_MINOR 0
-
-#if defined(LIBMDBX_EXPORTS)
-#define LIBMDBX_API __dll_export
-#elif defined(LIBMDBX_IMPORTS)
-#define LIBMDBX_API __dll_import
-#else
-#define LIBMDBX_API
-#endif /* LIBMDBX_API */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct mdbx_version_info {
- uint8_t major;
- uint8_t minor;
- uint16_t release;
- uint32_t revision;
- struct {
- const char *datetime;
- const char *tree;
- const char *commit;
- const char *describe;
- } git;
-} mdbx_version_info;
-
-typedef struct mdbx_build_info {
- const char *datetime;
- const char *target;
- const char *options;
- const char *compiler;
- const char *flags;
-} mdbx_build_info;
-
-extern LIBMDBX_API const mdbx_version_info mdbx_version;
-extern LIBMDBX_API const mdbx_build_info mdbx_build;
-
-/* The name of the lock file in the DB environment */
-#define MDBX_LOCKNAME "/mdbx.lck"
-/* The name of the data file in the DB environment */
-#define MDBX_DATANAME "/mdbx.dat"
-/* The suffix of the lock file when no subdir is used */
-#define MDBX_LOCK_SUFFIX "-lck"
-
-/* Opaque structure for a database environment.
- *
- * A DB environment supports multiple databases, all residing in the same
- * shared-memory map. */
-typedef struct MDBX_env MDBX_env;
-
-/* Opaque structure for a transaction handle.
- *
- * All database operations require a transaction handle. Transactions may be
- * read-only or read-write. */
-typedef struct MDBX_txn MDBX_txn;
-
-/* A handle for an individual database in the DB environment. */
-typedef uint32_t MDBX_dbi;
-
-/* Opaque structure for navigating through a database */
-typedef struct MDBX_cursor MDBX_cursor;
-
-/* Generic structure used for passing keys and data in and out
- * of the database.
- *
- * Values returned from the database are valid only until a subsequent
- * update operation, or the end of the transaction. Do not modify or
- * free them, they commonly point into the database itself.
- *
- * Key sizes must be between 1 and mdbx_env_get_maxkeysize() inclusive.
- * The same applies to data sizes in databases with the MDBX_DUPSORT flag.
- * Other data items can in theory be from 0 to 0xffffffff bytes long. */
-#ifndef HAVE_STRUCT_IOVEC
-struct iovec {
- void *iov_base;
- size_t iov_len;
-};
-#define HAVE_STRUCT_IOVEC
-#endif /* HAVE_STRUCT_IOVEC */
-
-typedef struct iovec MDBX_val;
-
-/* The maximum size of a data item.
- * MDBX only store a 32 bit value for node sizes. */
-#define MDBX_MAXDATASIZE INT32_MAX
-
-/* A callback function used to compare two keys in a database */
-typedef int(MDBX_cmp_func)(const MDBX_val *a, const MDBX_val *b);
-
-/* Environment Flags */
-/* no environment directory */
-#define MDBX_NOSUBDIR 0x4000u
-/* don't fsync after commit */
-#define MDBX_NOSYNC 0x10000u
-/* read only */
-#define MDBX_RDONLY 0x20000u
-/* don't fsync metapage after commit */
-#define MDBX_NOMETASYNC 0x40000u
-/* use writable mmap */
-#define MDBX_WRITEMAP 0x80000u
-/* use asynchronous msync when MDBX_WRITEMAP is used */
-#define MDBX_MAPASYNC 0x100000u
-/* tie reader locktable slots to MDBX_txn objects instead of to threads */
-#define MDBX_NOTLS 0x200000u
-/* don't do any locking, caller must manage their own locks
- * WARNING: libmdbx don't support this mode. */
-#define MDBX_NOLOCK__UNSUPPORTED 0x400000u
-/* don't do readahead */
-#define MDBX_NORDAHEAD 0x800000u
-/* don't initialize malloc'd memory before writing to datafile */
-#define MDBX_NOMEMINIT 0x1000000u
-/* aim to coalesce FreeDB records */
-#define MDBX_COALESCE 0x2000000u
-/* LIFO policy for reclaiming FreeDB records */
-#define MDBX_LIFORECLAIM 0x4000000u
-/* make a steady-sync only on close and explicit env-sync */
-#define MDBX_UTTERLY_NOSYNC (MDBX_NOSYNC | MDBX_MAPASYNC)
-/* debuging option, fill/perturb released pages */
-#define MDBX_PAGEPERTURB 0x8000000u
-
-/* Database Flags */
-/* use reverse string keys */
-#define MDBX_REVERSEKEY 0x02u
-/* use sorted duplicates */
-#define MDBX_DUPSORT 0x04u
-/* numeric keys in native byte order, either uint32_t or uint64_t.
- * The keys must all be of the same size. */
-#define MDBX_INTEGERKEY 0x08u
-/* with MDBX_DUPSORT, sorted dup items have fixed size */
-#define MDBX_DUPFIXED 0x10u
-/* with MDBX_DUPSORT, dups are MDBX_INTEGERKEY-style integers */
-#define MDBX_INTEGERDUP 0x20u
-/* with MDBX_DUPSORT, use reverse string dups */
-#define MDBX_REVERSEDUP 0x40u
-/* create DB if not already existing */
-#define MDBX_CREATE 0x40000u
-
-/* Write Flags */
-/* For put: Don't write if the key already exists. */
-#define MDBX_NOOVERWRITE 0x10u
-/* Only for MDBX_DUPSORT
- * For put: don't write if the key and data pair already exist.
- * For mdbx_cursor_del: remove all duplicate data items. */
-#define MDBX_NODUPDATA 0x20u
-/* For mdbx_cursor_put: overwrite the current key/data pair
- * MDBX allows this flag for mdbx_put() for explicit overwrite/update without
- * insertion. */
-#define MDBX_CURRENT 0x40u
-/* For put: Just reserve space for data, don't copy it. Return a
- * pointer to the reserved space. */
-#define MDBX_RESERVE 0x10000u
-/* Data is being appended, don't split full pages. */
-#define MDBX_APPEND 0x20000u
-/* Duplicate data is being appended, don't split full pages. */
-#define MDBX_APPENDDUP 0x40000u
-/* Store multiple data items in one call. Only for MDBX_DUPFIXED. */
-#define MDBX_MULTIPLE 0x80000u
-
-/* Transaction Flags */
-/* Do not block when starting a write transaction */
-#define MDBX_TRYTXN 0x10000000u
-
-/* Copy Flags */
-/* Compacting copy: Omit free space from copy, and renumber all
- * pages sequentially. */
-#define MDBX_CP_COMPACT 1u
-
-/* Cursor Get operations.
- *
- * This is the set of all operations for retrieving data
- * using a cursor. */
-typedef enum MDBX_cursor_op {
- MDBX_FIRST, /* Position at first key/data item */
- MDBX_FIRST_DUP, /* MDBX_DUPSORT-only: Position at first data item
- * of current key. */
- MDBX_GET_BOTH, /* MDBX_DUPSORT-only: Position at key/data pair. */
- MDBX_GET_BOTH_RANGE, /* MDBX_DUPSORT-only: position at key, nearest data. */
- MDBX_GET_CURRENT, /* Return key/data at current cursor position */
- MDBX_GET_MULTIPLE, /* MDBX_DUPFIXED-only: Return key and up to a page of
- * duplicate data items from current cursor position.
- * Move cursor to prepare for MDBX_NEXT_MULTIPLE.*/
- MDBX_LAST, /* Position at last key/data item */
- MDBX_LAST_DUP, /* MDBX_DUPSORT-only: Position at last data item
- * of current key. */
- MDBX_NEXT, /* Position at next data item */
- MDBX_NEXT_DUP, /* MDBX_DUPSORT-only: Position at next data item
- * of current key. */
- MDBX_NEXT_MULTIPLE, /* MDBX_DUPFIXED-only: Return key and up to a page of
- * duplicate data items from next cursor position.
- * Move cursor to prepare for MDBX_NEXT_MULTIPLE. */
- MDBX_NEXT_NODUP, /* Position at first data item of next key */
- MDBX_PREV, /* Position at previous data item */
- MDBX_PREV_DUP, /* MDBX_DUPSORT-only: Position at previous data item
- * of current key. */
- MDBX_PREV_NODUP, /* Position at last data item of previous key */
- MDBX_SET, /* Position at specified key */
- MDBX_SET_KEY, /* Position at specified key, return both key and data */
- MDBX_SET_RANGE, /* Position at first key greater than or equal to
- * specified key. */
- MDBX_PREV_MULTIPLE /* MDBX_DUPFIXED-only: Position at previous page and
- * return key and up to a page of duplicate data items. */
-} MDBX_cursor_op;
-
-/* Return Codes
- * BerkeleyDB uses -30800 to -30999, we'll go under them */
-
-/* Successful result */
-#define MDBX_SUCCESS 0
-#define MDBX_RESULT_FALSE MDBX_SUCCESS
-#define MDBX_RESULT_TRUE (-1)
-
-/* key/data pair already exists */
-#define MDBX_KEYEXIST (-30799)
-/* key/data pair not found (EOF) */
-#define MDBX_NOTFOUND (-30798)
-/* Requested page not found - this usually indicates corruption */
-#define MDBX_PAGE_NOTFOUND (-30797)
-/* Located page was wrong type */
-#define MDBX_CORRUPTED (-30796)
-/* Update of meta page failed or environment had fatal error */
-#define MDBX_PANIC (-30795)
-/* DB file version mismatch with libmdbx */
-#define MDBX_VERSION_MISMATCH (-30794)
-/* File is not a valid MDBX file */
-#define MDBX_INVALID (-30793)
-/* Environment mapsize reached */
-#define MDBX_MAP_FULL (-30792)
-/* Environment maxdbs reached */
-#define MDBX_DBS_FULL (-30791)
-/* Environment maxreaders reached */
-#define MDBX_READERS_FULL (-30790)
-/* Txn has too many dirty pages */
-#define MDBX_TXN_FULL (-30788)
-/* Cursor stack too deep - internal error */
-#define MDBX_CURSOR_FULL (-30787)
-/* Page has not enough space - internal error */
-#define MDBX_PAGE_FULL (-30786)
-/* Database contents grew beyond environment mapsize */
-#define MDBX_MAP_RESIZED (-30785)
-/* Operation and DB incompatible, or DB type changed. This can mean:
- * - The operation expects an MDBX_DUPSORT / MDBX_DUPFIXED database.
- * - Opening a named DB when the unnamed DB has MDBX_DUPSORT/MDBX_INTEGERKEY.
- * - Accessing a data record as a database, or vice versa.
- * - The database was dropped and recreated with different flags. */
-#define MDBX_INCOMPATIBLE (-30784)
-/* Invalid reuse of reader locktable slot */
-#define MDBX_BAD_RSLOT (-30783)
-/* Transaction must abort, has a child, or is invalid */
-#define MDBX_BAD_TXN (-30782)
-/* Unsupported size of key/DB name/data, or wrong DUPFIXED size */
-#define MDBX_BAD_VALSIZE (-30781)
-/* The specified DBI was changed unexpectedly */
-#define MDBX_BAD_DBI (-30780)
-/* Unexpected problem - txn should abort */
-#define MDBX_PROBLEM (-30779)
-/* Unexpected problem - txn should abort */
-#define MDBX_BUSY (-30778)
-/* The last defined error code */
-#define MDBX_LAST_ERRCODE MDBX_BUSY
-
-/* The mdbx_put() or mdbx_replace() was called for key,
- that has more that one associated value. */
-#define MDBX_EMULTIVAL (-30421)
-
-/* Bad signature of a runtime object(s), this can mean:
- * - memory corruption or double-free;
- * - ABI version mismatch (rare case); */
-#define MDBX_EBADSIGN (-30420)
-
-/* Database should be recovered, but this could NOT be done automatically
- * right now (e.g. in readonly mode and so forth). */
-#define MDBX_WANNA_RECOVERY (-30419)
-
-/* The given key value is mismatched to the current cursor position,
- * when mdbx_cursor_put() called with MDBX_CURRENT option. */
-#define MDBX_EKEYMISMATCH (-30418)
-
-/* Database is too large for current system,
- * e.g. could NOT be mapped into RAM. */
-#define MDBX_TOO_LARGE (-30417)
-
-/* A thread has attempted to use a not owned object,
- * e.g. a transaction that started by another thread. */
-#define MDBX_THREAD_MISMATCH (-30416)
-
-/* Statistics for a database in the environment */
-typedef struct MDBX_stat {
- uint32_t ms_psize; /* Size of a database page.
- * This is currently the same for all databases. */
- uint32_t ms_depth; /* Depth (height) of the B-tree */
- uint64_t ms_branch_pages; /* Number of internal (non-leaf) pages */
- uint64_t ms_leaf_pages; /* Number of leaf pages */
- uint64_t ms_overflow_pages; /* Number of overflow pages */
- uint64_t ms_entries; /* Number of data items */
-} MDBX_stat;
-
-/* Information about the environment */
-typedef struct MDBX_envinfo {
- struct {
- uint64_t lower; /* lower limit for datafile size */
- uint64_t upper; /* upper limit for datafile size */
- uint64_t current; /* current datafile size */
- uint64_t shrink; /* shrink theshold for datafile */
- uint64_t grow; /* growth step for datafile */
- } mi_geo;
- uint64_t mi_mapsize; /* Size of the data memory map */
- uint64_t mi_last_pgno; /* ID of the last used page */
- uint64_t mi_recent_txnid; /* ID of the last committed transaction */
- uint64_t mi_latter_reader_txnid; /* ID of the last reader transaction */
- uint64_t mi_meta0_txnid, mi_meta0_sign;
- uint64_t mi_meta1_txnid, mi_meta1_sign;
- uint64_t mi_meta2_txnid, mi_meta2_sign;
- uint32_t mi_maxreaders; /* max reader slots in the environment */
- uint32_t mi_numreaders; /* max reader slots used in the environment */
- uint32_t mi_dxb_pagesize; /* database pagesize */
- uint32_t mi_sys_pagesize; /* system pagesize */
-} MDBX_envinfo;
-
-/* Return a string describing a given error code.
- *
- * This function is a superset of the ANSI C X3.159-1989 (ANSI C) strerror(3)
- * function. If the error code is greater than or equal to 0, then the string
- * returned by the system function strerror(3) is returned. If the error code
- * is less than 0, an error string corresponding to the MDBX library error is
- * returned. See errors for a list of MDBX-specific error codes.
- *
- * [in] err The error code
- *
- * Returns "error message" The description of the error */
-LIBMDBX_API const char *mdbx_strerror(int errnum);
-LIBMDBX_API const char *mdbx_strerror_r(int errnum, char *buf, size_t buflen);
-
-/* Create an MDBX environment handle.
- *
- * This function allocates memory for a MDBX_env structure. To release
- * the allocated memory and discard the handle, call mdbx_env_close().
- * Before the handle may be used, it must be opened using mdbx_env_open().
- * Various other options may also need to be set before opening the handle,
- * e.g. mdbx_env_set_mapsize(), mdbx_env_set_maxreaders(),
- * mdbx_env_set_maxdbs(), depending on usage requirements.
- *
- * [out] env The address where the new handle will be stored
- *
- * Returns A non-zero error value on failure and 0 on success. */
-LIBMDBX_API int mdbx_env_create(MDBX_env **penv);
-
-/* Open an environment handle.
- *
- * If this function fails, mdbx_env_close() must be called to discard
- * the MDBX_env handle.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [in] path The directory in which the database files reside.
- * This directory must already exist and be writable.
- * [in] flags Special options for this environment. This parameter
- * must be set to 0 or by bitwise OR'ing together one
- * or more of the values described here.
- *
- * Flags set by mdbx_env_set_flags() are also used:
- * - MDBX_NOSUBDIR
- * By default, MDBX creates its environment in a directory whose
- * pathname is given in path, and creates its data and lock files
- * under that directory. With this option, path is used as-is for
- * the database main data file. The database lock file is the path
- * with "-lock" appended.
- *
- * - MDBX_RDONLY
- * Open the environment in read-only mode. No write operations will
- * be allowed. MDBX will still modify the lock file - except on
- * read-only filesystems, where MDBX does not use locks.
- *
- * - MDBX_WRITEMAP
- * Use a writeable memory map unless MDBX_RDONLY is set. This uses fewer
- * mallocs but loses protection from application bugs like wild pointer
- * writes and other bad updates into the database.
- * This may be slightly faster for DBs that fit entirely in RAM,
- * but is slower for DBs larger than RAM.
- * Incompatible with nested transactions.
- * Do not mix processes with and without MDBX_WRITEMAP on the same
- * environment. This can defeat durability (mdbx_env_sync etc).
- *
- * - MDBX_NOMETASYNC
- * Flush system buffers to disk only once per transaction, omit the
- * metadata flush. Defer that until the system flushes files to disk,
- * or next non-MDBX_RDONLY commit or mdbx_env_sync(). This optimization
- * maintains database integrity, but a system crash may undo the last
- * committed transaction. I.e. it preserves the ACI (atomicity,
- * consistency, isolation) but not D (durability) database property.
- * This flag may be changed at any time using mdbx_env_set_flags().
- *
- * - MDBX_NOSYNC
- * Don't flush system buffers to disk when committing a transaction.
- * This optimization means a system crash can corrupt the database or
- * lose the last transactions if buffers are not yet flushed to disk.
- * The risk is governed by how often the system flushes dirty buffers
- * to disk and how often mdbx_env_sync() is called. However, if the
- * filesystem preserves write order and the MDBX_WRITEMAP and/or
- * MDBX_LIFORECLAIM flags are not used, transactions exhibit ACI
- * (atomicity, consistency, isolation) properties and only lose D
- * (durability). I.e. database integrity is maintained, but a system
- * crash may undo the final transactions.
- *
- * Note that (MDBX_NOSYNC | MDBX_WRITEMAP) leaves the system with no
- * hint for when to write transactions to disk.
- * Therefore the (MDBX_MAPASYNC | MDBX_WRITEMAP) may be preferable.
- * This flag may be changed at any time using mdbx_env_set_flags().
- *
- * - MDBX_UTTERLY_NOSYNC (internally MDBX_NOSYNC | MDBX_MAPASYNC)
- * FIXME: TODO
- *
- * - MDBX_MAPASYNC
- * When using MDBX_WRITEMAP, use asynchronous flushes to disk. As with
- * MDBX_NOSYNC, a system crash can then corrupt the database or lose
- * the last transactions. Calling mdbx_env_sync() ensures on-disk
- * database integrity until next commit. This flag may be changed at
- * any time using mdbx_env_set_flags().
- *
- * - MDBX_NOTLS
- * Don't use Thread-Local Storage. Tie reader locktable slots to
- * MDBX_txn objects instead of to threads. I.e. mdbx_txn_reset() keeps
- * the slot reseved for the MDBX_txn object. A thread may use parallel
- * read-only transactions. A read-only transaction may span threads if
- * the user synchronizes its use. Applications that multiplex many
- * user threads over individual OS threads need this option. Such an
- * application must also serialize the write transactions in an OS
- * thread, since MDBX's write locking is unaware of the user threads.
- *
- * - MDBX_NOLOCK (don't supported by MDBX)
- * Don't do any locking. If concurrent access is anticipated, the
- * caller must manage all concurrency itself. For proper operation
- * the caller must enforce single-writer semantics, and must ensure
- * that no readers are using old transactions while a writer is
- * active. The simplest approach is to use an exclusive lock so that
- * no readers may be active at all when a writer begins.
- *
- * - MDBX_NORDAHEAD
- * Turn off readahead. Most operating systems perform readahead on
- * read requests by default. This option turns it off if the OS
- * supports it. Turning it off may help random read performance
- * when the DB is larger than RAM and system RAM is full.
- *
- * - MDBX_NOMEMINIT
- * Don't initialize malloc'd memory before writing to unused spaces
- * in the data file. By default, memory for pages written to the data
- * file is obtained using malloc. While these pages may be reused in
- * subsequent transactions, freshly malloc'd pages will be initialized
- * to zeroes before use. This avoids persisting leftover data from other
- * code (that used the heap and subsequently freed the memory) into the
- * data file. Note that many other system libraries may allocate and free
- * memory from the heap for arbitrary uses. E.g., stdio may use the heap
- * for file I/O buffers. This initialization step has a modest performance
- * cost so some applications may want to disable it using this flag. This
- * option can be a problem for applications which handle sensitive data
- * like passwords, and it makes memory checkers like Valgrind noisy. This
- * flag is not needed with MDBX_WRITEMAP, which writes directly to the
- * mmap instead of using malloc for pages. The initialization is also
- * skipped if MDBX_RESERVE is used; the caller is expected to overwrite
- * all of the memory that was reserved in that case. This flag may be
- * changed at any time using mdbx_env_set_flags().
- *
- * - MDBX_COALESCE
- * Aim to coalesce records while reclaiming FreeDB. This flag may be
- * changed at any time using mdbx_env_set_flags().
- * FIXME: TODO
- *
- * - MDBX_LIFORECLAIM
- * LIFO policy for reclaiming FreeDB records. This significantly reduce
- * write IPOs in case MDBX_NOSYNC with periodically checkpoints.
- * FIXME: TODO
- *
- * [in] mode The UNIX permissions to set on created files.
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_VERSION_MISMATCH - the version of the MDBX library doesn't match the
- * version that created the database environment.
- * - MDBX_INVALID - the environment file headers are corrupted.
- * - MDBX_ENOENT - the directory specified by the path parameter
- * doesn't exist.
- * - MDBX_EACCES - the user didn't have permission to access
- * the environment files.
- * - MDBX_EAGAIN - the environment was locked by another process. */
-LIBMDBX_API int mdbx_env_open(MDBX_env *env, const char *path, unsigned flags,
- mode_t mode);
-LIBMDBX_API int mdbx_env_open_ex(MDBX_env *env, const char *path,
- unsigned flags, mode_t mode, int *exclusive);
-
-/* Copy an MDBX environment to the specified path, with options.
- *
- * This function may be used to make a backup of an existing environment.
- * No lockfile is created, since it gets recreated at need.
- * NOTE: This call can trigger significant file size growth if run in
- * parallel with write transactions, because it employs a read-only
- * transaction. See long-lived transactions under "Caveats" section.
- *
- * [in] env An environment handle returned by mdbx_env_create(). It must
- * have already been opened successfully.
- * [in] path The directory in which the copy will reside. This directory
- * must already exist and be writable but must otherwise be empty.
- * [in] flags Special options for this operation. This parameter must be set
- * to 0 or by bitwise OR'ing together one or more of the values
- * described here:
- *
- * - MDBX_CP_COMPACT
- * Perform compaction while copying: omit free pages and sequentially
- * renumber all pages in output. This option consumes little bit more
- * CPU for processing, but may running quickly than the default, on
- * account skipping free pages.
- *
- * NOTE: Currently it fails if the environment has suffered a page leak.
- *
- * Returns A non-zero error value on failure and 0 on success. */
-LIBMDBX_API int mdbx_env_copy(MDBX_env *env, const char *path, unsigned flags);
-
-/* Copy an MDBX environment to the specified file descriptor,
- * with options.
- *
- * This function may be used to make a backup of an existing environment.
- * No lockfile is created, since it gets recreated at need. See
- * mdbx_env_copy() for further details.
- *
- * NOTE: This call can trigger significant file size growth if run in
- * parallel with write transactions, because it employs a read-only
- * transaction. See long-lived transactions under "Caveats" section.
- *
- * [in] env An environment handle returned by mdbx_env_create(). It must
- * have already been opened successfully.
- * [in] fd The filedescriptor to write the copy to. It must have already
- * been opened for Write access.
- * [in] flags Special options for this operation. See mdbx_env_copy() for
- * options.
- *
- * Returns A non-zero error value on failure and 0 on success. */
-LIBMDBX_API int mdbx_env_copy2fd(MDBX_env *env, mdbx_filehandle_t fd,
- unsigned flags);
-
-/* Return statistics about the MDBX environment.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [out] stat The address of an MDBX_stat structure where the statistics
- * will be copied */
-LIBMDBX_API int mdbx_env_stat(MDBX_env *env, MDBX_stat *stat, size_t bytes);
-
-/* Return information about the MDBX environment.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [out] stat The address of an MDBX_envinfo structure
- * where the information will be copied */
-LIBMDBX_API int mdbx_env_info(MDBX_env *env, MDBX_envinfo *info, size_t bytes);
-
-/* Flush the data buffers to disk.
- *
- * Data is always written to disk when mdbx_txn_commit() is called,
- * but the operating system may keep it buffered. MDBX always flushes
- * the OS buffers upon commit as well, unless the environment was
- * opened with MDBX_NOSYNC or in part MDBX_NOMETASYNC. This call is
- * not valid if the environment was opened with MDBX_RDONLY.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [in] force If non-zero, force a synchronous flush. Otherwise if the
- * environment has the MDBX_NOSYNC flag set the flushes will be
- * omitted, and with MDBX_MAPASYNC they will be asynchronous.
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EACCES - the environment is read-only.
- * - MDBX_EINVAL - an invalid parameter was specified.
- * - MDBX_EIO - an error occurred during synchronization. */
-LIBMDBX_API int mdbx_env_sync(MDBX_env *env, int force);
-
-/* Close the environment and release the memory map.
- *
- * Only a single thread may call this function. All transactions, databases,
- * and cursors must already be closed before calling this function. Attempts
- * to use any such handles after calling this function will cause a SIGSEGV.
- * The environment handle will be freed and must not be used again after this
- * call.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [in] dont_sync A dont'sync flag, if non-zero the last checkpoint (meta-page
- * update) will be kept "as is" and may be still "weak" in the
- * NOSYNC/MAPASYNC modes. Such "weak" checkpoint will be
- * ignored on opening next time, and transactions since the
- * last non-weak checkpoint (meta-page update) will rolledback
- * for consistency guarantee. */
-LIBMDBX_API void mdbx_env_close(MDBX_env *env);
-
-/* Set environment flags.
- *
- * This may be used to set some flags in addition to those from
- * mdbx_env_open(), or to unset these flags. If several threads
- * change the flags at the same time, the result is undefined.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [in] flags The flags to change, bitwise OR'ed together
- * [in] onoff A non-zero value sets the flags, zero clears them.
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_env_set_flags(MDBX_env *env, unsigned flags, int onoff);
-
-/* Get environment flags.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [out] flags The address of an integer to store the flags
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_env_get_flags(MDBX_env *env, unsigned *flags);
-
-/* Return the path that was used in mdbx_env_open().
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [out] path Address of a string pointer to contain the path.
- * This is the actual string in the environment, not a copy.
- * It should not be altered in any way.
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_env_get_path(MDBX_env *env, const char **path);
-
-/* Return the file descriptor for the given environment.
- *
- * NOTE: All MDBX file descriptors have FD_CLOEXEC and
- * could't be used after exec() and or fork().
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [out] fd Address of a int to contain the descriptor.
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_env_get_fd(MDBX_env *env, mdbx_filehandle_t *fd);
-
-/* Set the size of the memory map to use for this environment.
- *
- * The size should be a multiple of the OS page size. The default is
- * 10485760 bytes. The size of the memory map is also the maximum size
- * of the database. The value should be chosen as large as possible,
- * to accommodate future growth of the database.
- * This function should be called after mdbx_env_create() and before
- * mdbx_env_open(). It may be called at later times if no transactions
- * are active in this process. Note that the library does not check for
- * this condition, the caller must ensure it explicitly.
- *
- * The new size takes effect immediately for the current process but
- * will not be persisted to any others until a write transaction has been
- * committed by the current process. Also, only mapsize increases are
- * persisted into the environment.
- *
- * If the mapsize is increased by another process, and data has grown
- * beyond the range of the current mapsize, mdbx_txn_begin() will
- * return MDBX_MAP_RESIZED. This function may be called with a size
- * of zero to adopt the new size.
- *
- * Any attempt to set a size smaller than the space already consumed by the
- * environment will be silently changed to the current size of the used space.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [in] size The size in bytes
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EINVAL - an invalid parameter was specified,
- * or the environment has an active write transaction. */
-LIBMDBX_API int mdbx_env_set_mapsize(MDBX_env *env, size_t size);
-LIBMDBX_API int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower,
- intptr_t size_now, intptr_t size_upper,
- intptr_t growth_step,
- intptr_t shrink_threshold,
- intptr_t pagesize);
-
-/* Set the maximum number of threads/reader slots for the environment.
- *
- * This defines the number of slots in the lock table that is used to track
- * readers in the the environment. The default is 61.
- * Starting a read-only transaction normally ties a lock table slot to the
- * current thread until the environment closes or the thread exits. If
- * MDBX_NOTLS is in use, mdbx_txn_begin() instead ties the slot to the
- * MDBX_txn object until it or the MDBX_env object is destroyed.
- * This function may only be called after mdbx_env_create() and before
- * mdbx_env_open().
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [in] readers The maximum number of reader lock table slots
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EINVAL - an invalid parameter was specified,
- * or the environment is already open. */
-LIBMDBX_API int mdbx_env_set_maxreaders(MDBX_env *env, unsigned readers);
-
-/* Get the maximum number of threads/reader slots for the environment.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [out] readers Address of an integer to store the number of readers
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_env_get_maxreaders(MDBX_env *env, unsigned *readers);
-
-/* Set the maximum number of named databases for the environment.
- *
- * This function is only needed if multiple databases will be used in the
- * environment. Simpler applications that use the environment as a single
- * unnamed database can ignore this option.
- * This function may only be called after mdbx_env_create() and before
- * mdbx_env_open().
- *
- * Currently a moderate number of slots are cheap but a huge number gets
- * expensive: 7-120 words per transaction, and every mdbx_dbi_open()
- * does a linear search of the opened slots.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [in] dbs The maximum number of databases
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EINVAL - an invalid parameter was specified,
- * or the environment is already open. */
-LIBMDBX_API int mdbx_env_set_maxdbs(MDBX_env *env, MDBX_dbi dbs);
-
-/* Get the maximum size of keys and MDBX_DUPSORT data we can write.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- *
- * Returns The maximum size of a key we can write. */
-LIBMDBX_API int mdbx_env_get_maxkeysize(MDBX_env *env);
-LIBMDBX_API int mdbx_get_maxkeysize(size_t pagesize);
-
-/* Set application information associated with the MDBX_env.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [in] ctx An arbitrary pointer for whatever the application needs.
- *
- * Returns A non-zero error value on failure and 0 on success. */
-LIBMDBX_API int mdbx_env_set_userctx(MDBX_env *env, void *ctx);
-
-/* Get the application information associated with the MDBX_env.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * Returns The pointer set by mdbx_env_set_userctx(). */
-LIBMDBX_API void *mdbx_env_get_userctx(MDBX_env *env);
-
-/* A callback function for most MDBX assert() failures,
- * called before printing the message and aborting.
- *
- * [in] env An environment handle returned by mdbx_env_create().
- * [in] msg The assertion message, not including newline. */
-typedef void MDBX_assert_func(const MDBX_env *env, const char *msg,
- const char *function, unsigned line);
-
-/* Set or reset the assert() callback of the environment.
- *
- * Disabled if libmdbx is buillt with MDBX_DEBUG=0.
- * NOTE: This hack should become obsolete as mdbx's error handling matures.
- *
- * [in] env An environment handle returned by mdbx_env_create().
- * [in] func An MDBX_assert_func function, or 0.
- *
- * Returns A non-zero error value on failure and 0 on success. */
-LIBMDBX_API int mdbx_env_set_assert(MDBX_env *env, MDBX_assert_func *func);
-
-/* Create a transaction for use with the environment.
- *
- * The transaction handle may be discarded using mdbx_txn_abort()
- * or mdbx_txn_commit().
- * NOTE: A transaction and its cursors must only be used by a single
- * thread, and a thread may only have a single transaction at a time.
- * If MDBX_NOTLS is in use, this does not apply to read-only transactions.
- * NOTE: Cursors may not span transactions.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [in] parent If this parameter is non-NULL, the new transaction will be
- * a nested transaction, with the transaction indicated by parent
- * as its parent. Transactions may be nested to any level.
- * A parent transaction and its cursors may not issue any other
- * operations than mdbx_txn_commit and mdbx_txn_abort while it
- * has active child transactions.
- * [in] flags Special options for this transaction. This parameter
- * must be set to 0 or by bitwise OR'ing together one or more
- * of the values described here.
- *
- * - MDBX_RDONLY
- * This transaction will not perform any write operations.
- *
- * - MDBX_TRYTXN
- * Do not block when starting a write transaction
- *
- * [out] txn Address where the new MDBX_txn handle will be stored
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_PANIC - a fatal error occurred earlier and the environment
- * must be shut down.
- * - MDBX_MAP_RESIZED - another process wrote data beyond this MDBX_env's
- * mapsize and this environment's map must be resized
- * as well. See mdbx_env_set_mapsize().
- * - MDBX_READERS_FULL - a read-only transaction was requested and the reader
- * lock table is full. See mdbx_env_set_maxreaders().
- * - MDBX_ENOMEM - out of memory.
- * - MDBX_BUSY - a write transaction is already started. */
-LIBMDBX_API int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
- MDBX_txn **txn);
-
-/* Returns the transaction's MDBX_env
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin() */
-LIBMDBX_API MDBX_env *mdbx_txn_env(MDBX_txn *txn);
-
-/* Return the transaction's ID.
- *
- * This returns the identifier associated with this transaction. For a
- * read-only transaction, this corresponds to the snapshot being read;
- * concurrent readers will frequently have the same transaction ID.
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin()
- *
- * Returns A transaction ID, valid if input is an active transaction. */
-LIBMDBX_API uint64_t mdbx_txn_id(MDBX_txn *txn);
-
-/* Commit all the operations of a transaction into the database.
- *
- * The transaction handle is freed. It and its cursors must not be used
- * again after this call, except with mdbx_cursor_renew().
- *
- * A cursor must be closed explicitly always, before
- * or after its transaction ends. It can be reused with
- * mdbx_cursor_renew() before finally closing it.
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin()
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EINVAL - an invalid parameter was specified.
- * - MDBX_ENOSPC - no more disk space.
- * - MDBX_EIO - a low-level I/O error occurred while writing.
- * - MDBX_ENOMEM - out of memory. */
-LIBMDBX_API int mdbx_txn_commit(MDBX_txn *txn);
-
-/* Abandon all the operations of the transaction instead of saving them.
- *
- * The transaction handle is freed. It and its cursors must not be used
- * again after this call, except with mdbx_cursor_renew().
- *
- * A cursor must be closed explicitly always, before or after its transaction
- * ends. It can be reused with mdbx_cursor_renew() before finally closing it.
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin(). */
-LIBMDBX_API int mdbx_txn_abort(MDBX_txn *txn);
-
-/* Reset a read-only transaction.
- *
- * Abort the transaction like mdbx_txn_abort(), but keep the transaction
- * handle. Therefore mdbx_txn_renew() may reuse the handle. This saves
- * allocation overhead if the process will start a new read-only transaction
- * soon, and also locking overhead if MDBX_NOTLS is in use. The reader table
- * lock is released, but the table slot stays tied to its thread or
- * MDBX_txn. Use mdbx_txn_abort() to discard a reset handle, and to free
- * its lock table slot if MDBX_NOTLS is in use.
- *
- * Cursors opened within the transaction must not be used
- * again after this call, except with mdbx_cursor_renew().
- *
- * Reader locks generally don't interfere with writers, but they keep old
- * versions of database pages allocated. Thus they prevent the old pages
- * from being reused when writers commit new data, and so under heavy load
- * the database size may grow much more rapidly than otherwise.
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin() */
-LIBMDBX_API int mdbx_txn_reset(MDBX_txn *txn);
-
-/* Renew a read-only transaction.
- *
- * This acquires a new reader lock for a transaction handle that had been
- * released by mdbx_txn_reset(). It must be called before a reset transaction
- * may be used again.
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin()
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_PANIC - a fatal error occurred earlier and the environment
- * must be shut down.
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_txn_renew(MDBX_txn *txn);
-
-/* Open a table in the environment.
- *
- * A table handle denotes the name and parameters of a table, independently
- * of whether such a table exists. The table handle may be discarded by
- * calling mdbx_dbi_close(). The old table handle is returned if the table
- * was already open. The handle may only be closed once.
- *
- * The table handle will be private to the current transaction until
- * the transaction is successfully committed. If the transaction is
- * aborted the handle will be closed automatically.
- * After a successful commit the handle will reside in the shared
- * environment, and may be used by other transactions.
- *
- * This function must not be called from multiple concurrent
- * transactions in the same process. A transaction that uses
- * this function must finish (either commit or abort) before
- * any other transaction in the process may use this function.
- *
- * To use named table (with name != NULL), mdbx_env_set_maxdbs()
- * must be called before opening the environment. Table names are
- * keys in the internal unnamed table, and may be read but not written.
- *
- * [in] txn transaction handle returned by mdbx_txn_begin()
- * [in] name The name of the table to open. If only a single
- * table is needed in the environment, this value may be NULL.
- * [in] flags Special options for this table. This parameter must be set
- * to 0 or by bitwise OR'ing together one or more of the values
- * described here:
- * - MDBX_REVERSEKEY
- * Keys are strings to be compared in reverse order, from the end
- * of the strings to the beginning. By default, Keys are treated as
- * strings and compared from beginning to end.
- * - MDBX_DUPSORT
- * Duplicate keys may be used in the table. Or, from another point of
- * view, keys may have multiple data items, stored in sorted order. By
- * default keys must be unique and may have only a single data item.
- * - MDBX_INTEGERKEY
- * Keys are binary integers in native byte order, either uin32_t or
- * uint64_t, and will be sorted as such. The keys must all be of the
- * same size.
- * - MDBX_DUPFIXED
- * This flag may only be used in combination with MDBX_DUPSORT. This
- * option tells the library that the data items for this database are
- * all the same size, which allows further optimizations in storage and
- * retrieval. When all data items are the same size, the MDBX_GET_MULTIPLE,
- * MDBX_NEXT_MULTIPLE and MDBX_PREV_MULTIPLE cursor operations may be used
- * to retrieve multiple items at once.
- * - MDBX_INTEGERDUP
- * This option specifies that duplicate data items are binary integers,
- * similar to MDBX_INTEGERKEY keys.
- * - MDBX_REVERSEDUP
- * This option specifies that duplicate data items should be compared as
- * strings in reverse order (the comparison is performed in the direction
- * from the last byte to the first).
- * - MDBX_CREATE
- * Create the named database if it doesn't exist. This option is not
- * allowed in a read-only transaction or a read-only environment.
- *
- * [out] dbi Address where the new MDBX_dbi handle will be stored
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_NOTFOUND - the specified database doesn't exist in the
- * environment and MDBX_CREATE was not specified.
- * - MDBX_DBS_FULL - too many databases have been opened.
- * See mdbx_env_set_maxdbs(). */
-LIBMDBX_API int mdbx_dbi_open_ex(MDBX_txn *txn, const char *name,
- unsigned flags, MDBX_dbi *dbi,
- MDBX_cmp_func *keycmp, MDBX_cmp_func *datacmp);
-LIBMDBX_API int mdbx_dbi_open(MDBX_txn *txn, const char *name, unsigned flags,
- MDBX_dbi *dbi);
-
-/* Retrieve statistics for a database.
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin()
- * [in] dbi A database handle returned by mdbx_dbi_open()
- * [out] stat The address of an MDBX_stat structure where the statistics
- * will be copied
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_dbi_stat(MDBX_txn *txn, MDBX_dbi dbi, MDBX_stat *stat,
- size_t bytes);
-
-/* Retrieve the DB flags for a database handle.
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin()
- * [in] dbi A database handle returned by mdbx_dbi_open()
- * [out] flags Address where the flags will be returned.
- * [out] state Address where the state will be returned.
- *
- * Returns A non-zero error value on failure and 0 on success. */
-#define MDBX_TBL_DIRTY 0x01 /* DB was written in this txn */
-#define MDBX_TBL_STALE 0x02 /* Named-DB record is older than txnID */
-#define MDBX_TBL_NEW 0x04 /* Named-DB handle opened in this txn */
-LIBMDBX_API int mdbx_dbi_flags_ex(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags,
- unsigned *state);
-LIBMDBX_API int mdbx_dbi_flags(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags);
-
-/* Close a database handle. Normally unnecessary.
- *
- * Use with care:
- * FIXME: This call is not mutex protected. Handles should only be closed by
- * a single thread, and only if no other threads are going to reference
- * the database handle or one of its cursors any further. Do not close
- * a handle if an existing transaction has modified its database.
- * Doing so can cause misbehavior from database corruption to errors
- * like MDBX_BAD_VALSIZE (since the DB name is gone).
- *
- * Closing a database handle is not necessary, but lets mdbx_dbi_open()
- * reuse the handle value. Usually it's better to set a bigger
- * mdbx_env_set_maxdbs(), unless that value would be large.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [in] dbi A database handle returned by mdbx_dbi_open()
- */
-LIBMDBX_API int mdbx_dbi_close(MDBX_env *env, MDBX_dbi dbi);
-
-/* Empty or delete+close a database.
- *
- * See mdbx_dbi_close() for restrictions about closing the DB handle.
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin()
- * [in] dbi A database handle returned by mdbx_dbi_open()
- * [in] del 0 to empty the DB, 1 to delete it from the environment
- * and close the DB handle.
- *
- * Returns A non-zero error value on failure and 0 on success. */
-LIBMDBX_API int mdbx_drop(MDBX_txn *txn, MDBX_dbi dbi, int del);
-
-/* Get items from a database.
- *
- * This function retrieves key/data pairs from the database. The address
- * and length of the data associated with the specified key are returned
- * in the structure to which data refers.
- * If the database supports duplicate keys (MDBX_DUPSORT) then the
- * first data item for the key will be returned. Retrieval of other
- * items requires the use of mdbx_cursor_get().
- *
- * NOTE: The memory pointed to by the returned values is owned by the
- * database. The caller need not dispose of the memory, and may not
- * modify it in any way. For values returned in a read-only transaction
- * any modification attempts will cause a SIGSEGV.
- *
- * NOTE: Values returned from the database are valid only until a
- * subsequent update operation, or the end of the transaction.
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin()
- * [in] dbi A database handle returned by mdbx_dbi_open()
- * [in] key The key to search for in the database
- * [in,out] data The data corresponding to the key
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_NOTFOUND - the key was not in the database.
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_get(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key,
- MDBX_val *data);
-
-/* Store items into a database.
- *
- * This function stores key/data pairs in the database. The default behavior
- * is to enter the new key/data pair, replacing any previously existing key
- * if duplicates are disallowed, or adding a duplicate data item if
- * duplicates are allowed (MDBX_DUPSORT).
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin()
- * [in] dbi A database handle returned by mdbx_dbi_open()
- * [in] key The key to store in the database
- * [in,out] data The data to store
- * [in] flags Special options for this operation. This parameter must be
- * set to 0 or by bitwise OR'ing together one or more of the
- * values described here.
- *
- * - MDBX_NODUPDATA
- * Enter the new key/data pair only if it does not already appear
- * in the database. This flag may only be specified if the database
- * was opened with MDBX_DUPSORT. The function will return MDBX_KEYEXIST
- * if the key/data pair already appears in the database.
- *
- * - MDBX_NOOVERWRITE
- * Enter the new key/data pair only if the key does not already appear
- * in the database. The function will return MDBX_KEYEXIST if the key
- * already appears in the database, even if the database supports
- * duplicates (MDBX_DUPSORT). The data parameter will be set to point
- * to the existing item.
- *
- * - MDBX_CURRENT
- * Update an single existing entry, but not add new ones. The function
- * will return MDBX_NOTFOUND if the given key not exist in the database.
- * Or the MDBX_EMULTIVAL in case duplicates for the given key.
- *
- * - MDBX_RESERVE
- * Reserve space for data of the given size, but don't copy the given
- * data. Instead, return a pointer to the reserved space, which the
- * caller can fill in later - before the next update operation or the
- * transaction ends. This saves an extra memcpy if the data is being
- * generated later. MDBX does nothing else with this memory, the caller
- * is expected to modify all of the space requested. This flag must not
- * be specified if the database was opened with MDBX_DUPSORT.
- *
- * - MDBX_APPEND
- * Append the given key/data pair to the end of the database. This option
- * allows fast bulk loading when keys are already known to be in the
- * correct order. Loading unsorted keys with this flag will cause
- * a MDBX_EKEYMISMATCH error.
- *
- * - MDBX_APPENDDUP
- * As above, but for sorted dup data.
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_KEYEXIST
- * - MDBX_MAP_FULL - the database is full, see mdbx_env_set_mapsize().
- * - MDBX_TXN_FULL - the transaction has too many dirty pages.
- * - MDBX_EACCES - an attempt was made to write in a read-only transaction.
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_put(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key,
- MDBX_val *data, unsigned flags);
-
-/* Delete items from a database.
- *
- * This function removes key/data pairs from the database.
- *
- * The data parameter is NOT ignored regardless the database does
- * support sorted duplicate data items or not. If the data parameter
- * is non-NULL only the matching data item will be deleted.
- *
- * This function will return MDBX_NOTFOUND if the specified key/data
- * pair is not in the database.
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin()
- * [in] dbi A database handle returned by mdbx_dbi_open()
- * [in] key The key to delete from the database
- * [in] data The data to delete
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EACCES - an attempt was made to write in a read-only transaction.
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_del(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key,
- MDBX_val *data);
-
-/* Create a cursor handle.
- *
- * A cursor is associated with a specific transaction and database.
- * A cursor cannot be used when its database handle is closed. Nor
- * when its transaction has ended, except with mdbx_cursor_renew().
- * It can be discarded with mdbx_cursor_close().
- *
- * A cursor must be closed explicitly always, before
- * or after its transaction ends. It can be reused with
- * mdbx_cursor_renew() before finally closing it.
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin()
- * [in] dbi A database handle returned by mdbx_dbi_open()
- * [out] cursor Address where the new MDBX_cursor handle will be stored
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_cursor_open(MDBX_txn *txn, MDBX_dbi dbi,
- MDBX_cursor **cursor);
-
-/* Close a cursor handle.
- *
- * The cursor handle will be freed and must not be used again after this call.
- * Its transaction must still be live if it is a write-transaction.
- *
- * [in] cursor A cursor handle returned by mdbx_cursor_open() */
-LIBMDBX_API void mdbx_cursor_close(MDBX_cursor *cursor);
-
-/* Renew a cursor handle.
- *
- * A cursor is associated with a specific transaction and database.
- * Cursors that are only used in read-only transactions may be re-used,
- * to avoid unnecessary malloc/free overhead. The cursor may be associated
- * with a new read-only transaction, and referencing the same database handle
- * as it was created with.
- *
- * This may be done whether the previous transaction is live or dead.
- * [in] txn A transaction handle returned by mdbx_txn_begin()
- * [in] cursor A cursor handle returned by mdbx_cursor_open()
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_cursor_renew(MDBX_txn *txn, MDBX_cursor *cursor);
-
-/* Return the cursor's transaction handle.
- *
- * [in] cursor A cursor handle returned by mdbx_cursor_open() */
-LIBMDBX_API MDBX_txn *mdbx_cursor_txn(MDBX_cursor *cursor);
-
-/* Return the cursor's database handle.
- *
- * [in] cursor A cursor handle returned by mdbx_cursor_open() */
-LIBMDBX_API MDBX_dbi mdbx_cursor_dbi(MDBX_cursor *cursor);
-
-/* Retrieve by cursor.
- *
- * This function retrieves key/data pairs from the database. The address and
- * length of the key are returned in the object to which key refers (except
- * for the case of the MDBX_SET option, in which the key object is unchanged),
- * and the address and length of the data are returned in the object to which
- * data refers. See mdbx_get() for restrictions on using the output values.
- *
- * [in] cursor A cursor handle returned by mdbx_cursor_open()
- * [in,out] key The key for a retrieved item
- * [in,out] data The data of a retrieved item
- * [in] op A cursor operation MDBX_cursor_op
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_NOTFOUND - no matching key found.
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_cursor_get(MDBX_cursor *cursor, MDBX_val *key,
- MDBX_val *data, MDBX_cursor_op op);
-
-/* Store by cursor.
- *
- * This function stores key/data pairs into the database. The cursor is
- * positioned at the new item, or on failure usually near it.
- *
- * [in] cursor A cursor handle returned by mdbx_cursor_open()
- * [in] key The key operated on.
- * [in] data The data operated on.
- * [in] flags Options for this operation. This parameter
- * must be set to 0 or one of the values described here:
- *
- * - MDBX_CURRENT
- * Replace the item at the current cursor position. The key parameter
- * must still be provided, and must match it, otherwise the function
- * return MDBX_EKEYMISMATCH.
- *
- * NOTE: MDBX unlike LMDB allows you to change the size of the data and
- * automatically handles reordering for sorted duplicates (MDBX_DUPSORT).
- *
- * - MDBX_NODUPDATA
- * Enter the new key/data pair only if it does not already appear in the
- * database. This flag may only be specified if the database was opened
- * with MDBX_DUPSORT. The function will return MDBX_KEYEXIST if the
- * key/data pair already appears in the database.
- *
- * - MDBX_NOOVERWRITE
- * Enter the new key/data pair only if the key does not already appear
- * in the database. The function will return MDBX_KEYEXIST if the key
- * already appears in the database, even if the database supports
- * duplicates (MDBX_DUPSORT).
- *
- * - MDBX_RESERVE
- * Reserve space for data of the given size, but don't copy the given
- * data. Instead, return a pointer to the reserved space, which the
- * caller can fill in later - before the next update operation or the
- * transaction ends. This saves an extra memcpy if the data is being
- * generated later. This flag must not be specified if the database
- * was opened with MDBX_DUPSORT.
- *
- * - MDBX_APPEND
- * Append the given key/data pair to the end of the database. No key
- * comparisons are performed. This option allows fast bulk loading when
- * keys are already known to be in the correct order. Loading unsorted
- * keys with this flag will cause a MDBX_KEYEXIST error.
- *
- * - MDBX_APPENDDUP
- * As above, but for sorted dup data.
- *
- * - MDBX_MULTIPLE
- * Store multiple contiguous data elements in a single request. This flag
- * may only be specified if the database was opened with MDBX_DUPFIXED.
- * The data argument must be an array of two MDBX_vals. The iov_len of the
- * first MDBX_val must be the size of a single data element. The iov_base
- * of the first MDBX_val must point to the beginning of the array of
- * contiguous data elements. The iov_len of the second MDBX_val must be
- * the count of the number of data elements to store. On return this
- * field will be set to the count of the number of elements actually
- * written. The iov_base of the second MDBX_val is unused.
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EKEYMISMATCH
- * - MDBX_MAP_FULL - the database is full, see mdbx_env_set_mapsize().
- * - MDBX_TXN_FULL - the transaction has too many dirty pages.
- * - MDBX_EACCES - an attempt was made to write in a read-only transaction.
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_cursor_put(MDBX_cursor *cursor, MDBX_val *key,
- MDBX_val *data, unsigned flags);
-
-/* Delete current key/data pair
- *
- * This function deletes the key/data pair to which the cursor refers.
- *
- * [in] cursor A cursor handle returned by mdbx_cursor_open()
- * [in] flags Options for this operation. This parameter must be set to 0
- * or one of the values described here.
- *
- * - MDBX_NODUPDATA
- * Delete all of the data items for the current key. This flag may only
- * be specified if the database was opened with MDBX_DUPSORT.
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EACCES - an attempt was made to write in a read-only transaction.
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_cursor_del(MDBX_cursor *cursor, unsigned flags);
-
-/* Return count of duplicates for current key.
- *
- * This call is only valid on databases that support sorted duplicate data
- * items MDBX_DUPSORT.
- *
- * [in] cursor A cursor handle returned by mdbx_cursor_open()
- * [out] countp Address where the count will be stored
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EINVAL - cursor is not initialized, or an invalid parameter
- * was specified. */
-LIBMDBX_API int mdbx_cursor_count(MDBX_cursor *cursor, size_t *countp);
-
-/* Compare two data items according to a particular database.
- *
- * This returns a comparison as if the two data items were keys in the
- * specified database.
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin()
- * [in] dbi A database handle returned by mdbx_dbi_open()
- * [in] a The first item to compare
- * [in] b The second item to compare
- *
- * Returns < 0 if a < b, 0 if a == b, > 0 if a > b */
-LIBMDBX_API int mdbx_cmp(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *a,
- const MDBX_val *b);
-
-/* Compare two data items according to a particular database.
- *
- * This returns a comparison as if the two items were data items of
- * the specified database. The database must have the MDBX_DUPSORT flag.
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin()
- * [in] dbi A database handle returned by mdbx_dbi_open()
- * [in] a The first item to compare
- * [in] b The second item to compare
- *
- * Returns < 0 if a < b, 0 if a == b, > 0 if a > b */
-LIBMDBX_API int mdbx_dcmp(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *a,
- const MDBX_val *b);
-
-/* A callback function used to print a message from the library.
- *
- * [in] msg The string to be printed.
- * [in] ctx An arbitrary context pointer for the callback.
- *
- * Returns < 0 on failure, >= 0 on success. */
-typedef int(MDBX_msg_func)(const char *msg, void *ctx);
-
-/* Dump the entries in the reader lock table.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [in] func A MDBX_msg_func function
- * [in] ctx Anything the message function needs
- *
- * Returns < 0 on failure, >= 0 on success. */
-LIBMDBX_API int mdbx_reader_list(MDBX_env *env, MDBX_msg_func *func, void *ctx);
-
-/* Check for stale entries in the reader lock table.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [out] dead Number of stale slots that were cleared
- *
- * Returns 0 on success, non-zero on failure. */
-LIBMDBX_API int mdbx_reader_check(MDBX_env *env, int *dead);
-
-LIBMDBX_API char *mdbx_dkey(const MDBX_val *key, char *const buf,
- const size_t bufsize);
-
-LIBMDBX_API int mdbx_env_close_ex(MDBX_env *env, int dont_sync);
-
-/* Set threshold to force flush the data buffers to disk,
- * even of MDBX_NOSYNC, MDBX_NOMETASYNC and MDBX_MAPASYNC flags
- * in the environment.
- *
- * Data is always written to disk when mdbx_txn_commit() is called,
- * but the operating system may keep it buffered. MDBX always flushes
- * the OS buffers upon commit as well, unless the environment was
- * opened with MDBX_NOSYNC or in part MDBX_NOMETASYNC.
- *
- * The default is 0, than mean no any threshold checked, and no additional
- * flush will be made.
- *
- * [in] env An environment handle returned by mdbx_env_create()
- * [in] bytes The size in bytes of summary changes when a synchronous
- * flush would be made.
- *
- * Returns A non-zero error value on failure and 0 on success. */
-LIBMDBX_API int mdbx_env_set_syncbytes(MDBX_env *env, size_t bytes);
-
-/* Returns a lag of the reading for the given transaction.
- *
- * Returns an information for estimate how much given read-only
- * transaction is lagging relative the to actual head.
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin()
- * [out] percent Percentage of page allocation in the database.
- *
- * Returns Number of transactions committed after the given was started for
- * read, or -1 on failure. */
-LIBMDBX_API int mdbx_txn_straggler(MDBX_txn *txn, int *percent);
-
-/* A callback function for killing a laggard readers,
- * but also could waiting ones. Called in case of MDBX_MAP_FULL error.
- *
- * [in] env An environment handle returned by mdbx_env_create().
- * [in] pid pid of the reader process.
- * [in] tid thread_id of the reader thread.
- * [in] txn Transaction number on which stalled.
- * [in] gap A lag from the last commited txn.
- * [in] retry A retry number, less that zero for notify end of OOM-loop.
- *
- * Returns -1 on failure (reader is not killed),
- * 0 should wait or retry,
- * 1 drop reader txn-lock (reading-txn was aborted),
- * >1 drop reader registration (reader process was killed). */
-typedef int(MDBX_oom_func)(MDBX_env *env, int pid, mdbx_tid_t tid, uint64_t txn,
- unsigned gap, int retry);
-
-/* Set the OOM callback.
- *
- * Callback will be called only on out-of-pages case for killing
- * a laggard readers to allowing reclaiming of freeDB.
- *
- * [in] env An environment handle returned by mdbx_env_create().
- * [in] oomfunc A MDBX_oom_func function or NULL to disable.
- *
- * Returns A non-zero error value on failure and 0 on success. */
-LIBMDBX_API int mdbx_env_set_oomfunc(MDBX_env *env, MDBX_oom_func *oom_func);
-
-/* Get the current oom_func callback.
- *
- * Callback will be called only on out-of-pages case for killing
- * a laggard readers to allowing reclaiming of freeDB.
- *
- * [in] env An environment handle returned by mdbx_env_create().
- *
- * Returns A MDBX_oom_func function or NULL if disabled. */
-LIBMDBX_API MDBX_oom_func *mdbx_env_get_oomfunc(MDBX_env *env);
-
-#define MDBX_DBG_ASSERT 1
-#define MDBX_DBG_PRINT 2
-#define MDBX_DBG_TRACE 4
-#define MDBX_DBG_EXTRA 8
-#define MDBX_DBG_AUDIT 16
-#define MDBX_DBG_JITTER 32
-#define MDBX_DBG_DUMP 64
-
-typedef void MDBX_debug_func(int type, const char *function, int line,
- const char *msg, va_list args);
-
-LIBMDBX_API int mdbx_setup_debug(int flags, MDBX_debug_func *logger);
-
-typedef int MDBX_pgvisitor_func(uint64_t pgno, unsigned pgnumber, void *ctx,
- const char *dbi, const char *type,
- size_t nentries, size_t payload_bytes,
- size_t header_bytes, size_t unused_bytes);
-LIBMDBX_API int mdbx_env_pgwalk(MDBX_txn *txn, MDBX_pgvisitor_func *visitor,
- void *ctx);
-
-typedef struct mdbx_canary { uint64_t x, y, z, v; } mdbx_canary;
-
-LIBMDBX_API int mdbx_canary_put(MDBX_txn *txn, const mdbx_canary *canary);
-LIBMDBX_API int mdbx_canary_get(MDBX_txn *txn, mdbx_canary *canary);
-
-/* Returns:
- * - MDBX_RESULT_TRUE
- * when no more data available or cursor not positioned;
- * - MDBX_RESULT_FALSE
- * when data available;
- * - Otherwise the error code. */
-LIBMDBX_API int mdbx_cursor_eof(MDBX_cursor *mc);
-
-/* Returns: MDBX_RESULT_TRUE, MDBX_RESULT_FALSE or Error code. */
-LIBMDBX_API int mdbx_cursor_on_first(MDBX_cursor *mc);
-
-/* Returns: MDBX_RESULT_TRUE, MDBX_RESULT_FALSE or Error code. */
-LIBMDBX_API int mdbx_cursor_on_last(MDBX_cursor *mc);
-
-LIBMDBX_API int mdbx_replace(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key,
- MDBX_val *new_data, MDBX_val *old_data,
- unsigned flags);
-/* Same as mdbx_get(), but:
- * 1) if values_count is not NULL, then returns the count
- * of multi-values/duplicates for a given key.
- * 2) updates the key for pointing to the actual key's data inside DB. */
-LIBMDBX_API int mdbx_get_ex(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key,
- MDBX_val *data, size_t *values_count);
-
-LIBMDBX_API int mdbx_is_dirty(const MDBX_txn *txn, const void *ptr);
-
-LIBMDBX_API int mdbx_dbi_sequence(MDBX_txn *txn, MDBX_dbi dbi, uint64_t *result,
- uint64_t increment);
-
-/*----------------------------------------------------------------------------*/
-/* attribute support functions for Nexenta */
-typedef uint_fast64_t mdbx_attr_t;
-
-/* Store by cursor with attribute.
- *
- * This function stores key/data pairs into the database. The cursor is
- * positioned at the new item, or on failure usually near it.
- *
- * NOTE: Internally based on MDBX_RESERVE feature,
- * therefore doesn't support MDBX_DUPSORT.
- *
- * [in] cursor A cursor handle returned by mdbx_cursor_open()
- * [in] key The key operated on.
- * [in] data The data operated on.
- * [in] attr The attribute.
- * [in] flags Options for this operation. This parameter must be set to 0
- * or one of the values described here:
- *
- * - MDBX_CURRENT
- * Replace the item at the current cursor position. The key parameter
- * must still be provided, and must match it, otherwise the function
- * return MDBX_EKEYMISMATCH.
- *
- * - MDBX_APPEND
- * Append the given key/data pair to the end of the database. No key
- * comparisons are performed. This option allows fast bulk loading when
- * keys are already known to be in the correct order. Loading unsorted
- * keys with this flag will cause a MDBX_KEYEXIST error.
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_EKEYMISMATCH
- * - MDBX_MAP_FULL - the database is full, see mdbx_env_set_mapsize().
- * - MDBX_TXN_FULL - the transaction has too many dirty pages.
- * - MDBX_EACCES - an attempt was made to write in a read-only transaction.
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_cursor_put_attr(MDBX_cursor *cursor, MDBX_val *key,
- MDBX_val *data, mdbx_attr_t attr,
- unsigned flags);
-
-/* Store items and attributes into a database.
- *
- * This function stores key/data pairs in the database. The default behavior
- * is to enter the new key/data pair, replacing any previously existing key
- * if duplicates are disallowed.
- *
- * NOTE: Internally based on MDBX_RESERVE feature,
- * therefore doesn't support MDBX_DUPSORT.
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin().
- * [in] dbi A database handle returned by mdbx_dbi_open().
- * [in] key The key to store in the database.
- * [in] attr The attribute to store in the database.
- * [in,out] data The data to store.
- * [in] flags Special options for this operation. This parameter must be
- * set to 0 or by bitwise OR'ing together one or more of the
- * values described here:
- *
- * - MDBX_NOOVERWRITE
- * Enter the new key/data pair only if the key does not already appear
- * in the database. The function will return MDBX_KEYEXIST if the key
- * already appears in the database. The data parameter will be set to
- * point to the existing item.
- *
- * - MDBX_CURRENT
- * Update an single existing entry, but not add new ones. The function
- * will return MDBX_NOTFOUND if the given key not exist in the database.
- * Or the MDBX_EMULTIVAL in case duplicates for the given key.
- *
- * - MDBX_APPEND
- * Append the given key/data pair to the end of the database. This option
- * allows fast bulk loading when keys are already known to be in the
- * correct order. Loading unsorted keys with this flag will cause
- * a MDBX_EKEYMISMATCH error.
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_KEYEXIST
- * - MDBX_MAP_FULL - the database is full, see mdbx_env_set_mapsize().
- * - MDBX_TXN_FULL - the transaction has too many dirty pages.
- * - MDBX_EACCES - an attempt was made to write in a read-only transaction.
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_put_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key,
- MDBX_val *data, mdbx_attr_t attr, unsigned flags);
-
-/* Set items attribute from a database.
- *
- * This function stores key/data pairs attribute to the database.
- *
- * NOTE: Internally based on MDBX_RESERVE feature,
- * therefore doesn't support MDBX_DUPSORT.
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin().
- * [in] dbi A database handle returned by mdbx_dbi_open().
- * [in] key The key to search for in the database.
- * [in] data The data to be stored or NULL to save previous value.
- * [in] attr The attribute to be stored.
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_NOTFOUND - the key-value pair was not in the database.
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_set_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key,
- MDBX_val *data, mdbx_attr_t attr);
-
-/* Get items attribute from a database cursor.
- *
- * This function retrieves key/data pairs from the database. The address and
- * length of the key are returned in the object to which key refers (except
- * for the case of the MDBX_SET option, in which the key object is unchanged),
- * and the address and length of the data are returned in the object to which
- * data refers. See mdbx_get() for restrictions on using the output values.
- *
- * [in] cursor A cursor handle returned by mdbx_cursor_open()
- * [in,out] key The key for a retrieved item
- * [in,out] data The data of a retrieved item
- * [in] op A cursor operation MDBX_cursor_op
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_NOTFOUND - no matching key found.
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_cursor_get_attr(MDBX_cursor *mc, MDBX_val *key,
- MDBX_val *data, mdbx_attr_t *attrptr,
- MDBX_cursor_op op);
-
-/* Get items attribute from a database.
- *
- * This function retrieves key/data pairs from the database. The address
- * and length of the data associated with the specified key are returned
- * in the structure to which data refers.
- * If the database supports duplicate keys (MDBX_DUPSORT) then the
- * first data item for the key will be returned. Retrieval of other
- * items requires the use of mdbx_cursor_get().
- *
- * NOTE: The memory pointed to by the returned values is owned by the
- * database. The caller need not dispose of the memory, and may not
- * modify it in any way. For values returned in a read-only transaction
- * any modification attempts will cause a SIGSEGV.
- *
- * NOTE: Values returned from the database are valid only until a
- * subsequent update operation, or the end of the transaction.
- *
- * [in] txn A transaction handle returned by mdbx_txn_begin()
- * [in] dbi A database handle returned by mdbx_dbi_open()
- * [in] key The key to search for in the database
- * [in,out] data The data corresponding to the key
- *
- * Returns A non-zero error value on failure and 0 on success, some
- * possible errors are:
- * - MDBX_NOTFOUND - the key was not in the database.
- * - MDBX_EINVAL - an invalid parameter was specified. */
-LIBMDBX_API int mdbx_get_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key,
- MDBX_val *data, mdbx_attr_t *attrptr);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* LIBMDBX_H */
diff --git a/plugins/Dbx_mdb/src/mdbx/osal.c b/plugins/Dbx_mdb/src/mdbx/osal.c
deleted file mode 100644
index 5a8ec58002..0000000000
--- a/plugins/Dbx_mdb/src/mdbx/osal.c
+++ /dev/null
@@ -1,1002 +0,0 @@
-/* https://en.wikipedia.org/wiki/Operating_system_abstraction_layer */
-
-/*
- * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
- * and other libmdbx authors: please see AUTHORS file.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "./bits.h"
-
-#if defined(_WIN32) || defined(_WIN64)
-#include <winternl.h>
-
-static int waitstatus2errcode(DWORD result) {
- switch (result) {
- case WAIT_OBJECT_0:
- return MDBX_SUCCESS;
- case WAIT_FAILED:
- return GetLastError();
- case WAIT_ABANDONED:
- return ERROR_ABANDONED_WAIT_0;
- case WAIT_IO_COMPLETION:
- return ERROR_USER_APC;
- case WAIT_TIMEOUT:
- return ERROR_TIMEOUT;
- default:
- return ERROR_UNHANDLED_ERROR;
- }
-}
-
-/* Map a result from an NTAPI call to WIN32 error code. */
-static int ntstatus2errcode(NTSTATUS status) {
- DWORD dummy;
- OVERLAPPED ov;
- memset(&ov, 0, sizeof(ov));
- ov.Internal = status;
- return GetOverlappedResult(NULL, &ov, &dummy, FALSE) ? MDBX_SUCCESS
- : GetLastError();
-}
-
-/* We use native NT APIs to setup the memory map, so that we can
- * let the DB file grow incrementally instead of always preallocating
- * the full size. These APIs are defined in <wdm.h> and <ntifs.h>
- * but those headers are meant for driver-level development and
- * conflict with the regular user-level headers, so we explicitly
- * declare them here. Using these APIs also means we must link to
- * ntdll.dll, which is not linked by default in user code. */
-#pragma comment(lib, "ntdll.lib")
-
-extern NTSTATUS NTAPI NtCreateSection(
- OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess,
- IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes,
- IN OPTIONAL PLARGE_INTEGER MaximumSize, IN ULONG SectionPageProtection,
- IN ULONG AllocationAttributes, IN OPTIONAL HANDLE FileHandle);
-
-extern NTSTATUS NTAPI NtExtendSection(IN HANDLE SectionHandle,
- IN PLARGE_INTEGER NewSectionSize);
-
-typedef enum _SECTION_INHERIT { ViewShare = 1, ViewUnmap = 2 } SECTION_INHERIT;
-
-extern NTSTATUS NTAPI NtMapViewOfSection(
- IN HANDLE SectionHandle, IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress,
- IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize,
- IN OUT OPTIONAL PLARGE_INTEGER SectionOffset, IN OUT PSIZE_T ViewSize,
- IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType,
- IN ULONG Win32Protect);
-
-extern NTSTATUS NTAPI NtUnmapViewOfSection(IN HANDLE ProcessHandle,
- IN OPTIONAL PVOID BaseAddress);
-
-extern NTSTATUS NTAPI NtClose(HANDLE Handle);
-
-extern NTSTATUS NTAPI NtAllocateVirtualMemory(
- IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG ZeroBits,
- IN OUT PULONG RegionSize, IN ULONG AllocationType, IN ULONG Protect);
-
-extern NTSTATUS NTAPI NtFreeVirtualMemory(IN HANDLE ProcessHandle,
- IN PVOID *BaseAddress,
- IN OUT PULONG RegionSize,
- IN ULONG FreeType);
-
-#ifndef FILE_PROVIDER_CURRENT_VERSION
-typedef struct _FILE_PROVIDER_EXTERNAL_INFO_V1 {
- ULONG Version;
- ULONG Algorithm;
- ULONG Flags;
-} FILE_PROVIDER_EXTERNAL_INFO_V1, *PFILE_PROVIDER_EXTERNAL_INFO_V1;
-#endif
-
-#ifndef STATUS_OBJECT_NOT_EXTERNALLY_BACKED
-#define STATUS_OBJECT_NOT_EXTERNALLY_BACKED ((NTSTATUS)0xC000046DL)
-#endif
-#ifndef STATUS_INVALID_DEVICE_REQUEST
-#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS)0xC0000010L)
-#endif
-
-extern NTSTATUS
-NtFsControlFile(IN HANDLE FileHandle, IN OUT HANDLE Event,
- IN OUT PVOID /* PIO_APC_ROUTINE */ ApcRoutine,
- IN OUT PVOID ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock,
- IN ULONG FsControlCode, IN OUT PVOID InputBuffer,
- IN ULONG InputBufferLength, OUT OPTIONAL PVOID OutputBuffer,
- IN ULONG OutputBufferLength);
-
-#endif /* _WIN32 || _WIN64 */
-
-/*----------------------------------------------------------------------------*/
-
-#ifndef _MSC_VER
-/* Prototype should match libc runtime. ISO POSIX (2003) & LSB 3.1 */
-__nothrow __noreturn void __assert_fail(const char *assertion, const char *file,
- unsigned line, const char *function);
-#else
-__extern_C __declspec(dllimport) void __cdecl _assert(char const *message,
- char const *filename,
- unsigned line);
-#endif /* _MSC_VER */
-
-#ifndef mdbx_assert_fail
-void __cold mdbx_assert_fail(const MDBX_env *env, const char *msg,
- const char *func, int line) {
-#if MDBX_DEBUG
- if (env && env->me_assert_func) {
- env->me_assert_func(env, msg, func, line);
- return;
- }
-#else
- (void)env;
-#endif /* MDBX_DEBUG */
-
- if (mdbx_debug_logger)
- mdbx_debug_log(MDBX_DBG_ASSERT, func, line, "assert: %s\n", msg);
-#ifndef _MSC_VER
- __assert_fail(msg, "mdbx", line, func);
-#else
- _assert(msg, func, line);
-#endif /* _MSC_VER */
-}
-#endif /* mdbx_assert_fail */
-
-__cold void mdbx_panic(const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
-#ifdef _MSC_VER
- if (IsDebuggerPresent()) {
- OutputDebugString("\r\n" FIXME "\r\n");
- FatalExit(ERROR_UNHANDLED_ERROR);
- }
-#elif _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L || \
- (__GLIBC_PREREQ(1, 0) && !__GLIBC_PREREQ(2, 10) && defined(_GNU_SOURCE))
- vdprintf(STDERR_FILENO, fmt, ap);
-#else
-#error FIXME
-#endif
- va_end(ap);
- abort();
-}
-
-/*----------------------------------------------------------------------------*/
-
-#ifndef mdbx_asprintf
-int mdbx_asprintf(char **strp, const char *fmt, ...) {
- va_list ap, ones;
-
- va_start(ap, fmt);
- va_copy(ones, ap);
-#ifdef _MSC_VER
- int needed = _vscprintf(fmt, ap);
-#elif defined(vsnprintf) || defined(_BSD_SOURCE) || _XOPEN_SOURCE >= 500 || \
- defined(_ISOC99_SOURCE) || _POSIX_C_SOURCE >= 200112L
- int needed = vsnprintf(nullptr, 0, fmt, ap);
-#else
-#error FIXME
-#endif
- va_end(ap);
-
- if (unlikely(needed < 0 || needed >= INT_MAX)) {
- *strp = nullptr;
- va_end(ones);
- return needed;
- }
-
- *strp = malloc(needed + 1);
- if (unlikely(*strp == nullptr)) {
- va_end(ones);
- SetLastError(MDBX_ENOMEM);
- return -1;
- }
-
-#if defined(vsnprintf) || defined(_BSD_SOURCE) || _XOPEN_SOURCE >= 500 || \
- defined(_ISOC99_SOURCE) || _POSIX_C_SOURCE >= 200112L
- int actual = vsnprintf(*strp, needed + 1, fmt, ones);
-#else
-#error FIXME
-#endif
- va_end(ones);
-
- assert(actual == needed);
- if (unlikely(actual < 0)) {
- free(*strp);
- *strp = nullptr;
- }
- return actual;
-}
-#endif /* mdbx_asprintf */
-
-#ifndef mdbx_memalign_alloc
-int mdbx_memalign_alloc(size_t alignment, size_t bytes, void **result) {
-#if _MSC_VER
- *result = _aligned_malloc(bytes, alignment);
- return *result ? MDBX_SUCCESS : MDBX_ENOMEM /* ERROR_OUTOFMEMORY */;
-#elif __GLIBC_PREREQ(2, 16) || __STDC_VERSION__ >= 201112L
- *result = memalign(alignment, bytes);
- return *result ? MDBX_SUCCESS : errno;
-#elif _POSIX_VERSION >= 200112L
- *result = nullptr;
- return posix_memalign(result, alignment, bytes);
-#else
-#error FIXME
-#endif
-}
-#endif /* mdbx_memalign_alloc */
-
-#ifndef mdbx_memalign_free
-void mdbx_memalign_free(void *ptr) {
-#if _MSC_VER
- _aligned_free(ptr);
-#else
- free(ptr);
-#endif
-}
-#endif /* mdbx_memalign_free */
-
-/*----------------------------------------------------------------------------*/
-
-int mdbx_condmutex_init(mdbx_condmutex_t *condmutex) {
-#if defined(_WIN32) || defined(_WIN64)
- int rc = MDBX_SUCCESS;
- condmutex->event = NULL;
- condmutex->mutex = CreateMutex(NULL, FALSE, NULL);
- if (!condmutex->mutex)
- return GetLastError();
-
- condmutex->event = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (!condmutex->event) {
- rc = GetLastError();
- (void)CloseHandle(condmutex->mutex);
- condmutex->mutex = NULL;
- }
- return rc;
-#else
- memset(condmutex, 0, sizeof(mdbx_condmutex_t));
- int rc = pthread_mutex_init(&condmutex->mutex, NULL);
- if (rc == 0) {
- rc = pthread_cond_init(&condmutex->cond, NULL);
- if (rc != 0)
- (void)pthread_mutex_destroy(&condmutex->mutex);
- }
- return rc;
-#endif
-}
-
-static bool is_allzeros(const void *ptr, size_t bytes) {
- const uint8_t *u8 = ptr;
- for (size_t i = 0; i < bytes; ++i)
- if (u8[i] != 0)
- return false;
- return true;
-}
-
-int mdbx_condmutex_destroy(mdbx_condmutex_t *condmutex) {
- int rc = MDBX_EINVAL;
-#if defined(_WIN32) || defined(_WIN64)
- if (condmutex->event) {
- rc = CloseHandle(condmutex->event) ? MDBX_SUCCESS : GetLastError();
- if (rc == MDBX_SUCCESS)
- condmutex->event = NULL;
- }
- if (condmutex->mutex) {
- rc = CloseHandle(condmutex->mutex) ? MDBX_SUCCESS : GetLastError();
- if (rc == MDBX_SUCCESS)
- condmutex->mutex = NULL;
- }
-#else
- if (!is_allzeros(&condmutex->cond, sizeof(condmutex->cond))) {
- rc = pthread_cond_destroy(&condmutex->cond);
- if (rc == 0)
- memset(&condmutex->cond, 0, sizeof(condmutex->cond));
- }
- if (!is_allzeros(&condmutex->mutex, sizeof(condmutex->mutex))) {
- rc = pthread_mutex_destroy(&condmutex->mutex);
- if (rc == 0)
- memset(&condmutex->mutex, 0, sizeof(condmutex->mutex));
- }
-#endif
- return rc;
-}
-
-int mdbx_condmutex_lock(mdbx_condmutex_t *condmutex) {
-#if defined(_WIN32) || defined(_WIN64)
- DWORD code = WaitForSingleObject(condmutex->mutex, INFINITE);
- return waitstatus2errcode(code);
-#else
- return pthread_mutex_lock(&condmutex->mutex);
-#endif
-}
-
-int mdbx_condmutex_unlock(mdbx_condmutex_t *condmutex) {
-#if defined(_WIN32) || defined(_WIN64)
- return ReleaseMutex(condmutex->mutex) ? MDBX_SUCCESS : GetLastError();
-#else
- return pthread_mutex_unlock(&condmutex->mutex);
-#endif
-}
-
-int mdbx_condmutex_signal(mdbx_condmutex_t *condmutex) {
-#if defined(_WIN32) || defined(_WIN64)
- return SetEvent(condmutex->event) ? MDBX_SUCCESS : GetLastError();
-#else
- return pthread_cond_signal(&condmutex->cond);
-#endif
-}
-
-int mdbx_condmutex_wait(mdbx_condmutex_t *condmutex) {
-#if defined(_WIN32) || defined(_WIN64)
- DWORD code =
- SignalObjectAndWait(condmutex->mutex, condmutex->event, INFINITE, FALSE);
- if (code == WAIT_OBJECT_0)
- code = WaitForSingleObject(condmutex->mutex, INFINITE);
- return waitstatus2errcode(code);
-#else
- return pthread_cond_wait(&condmutex->cond, &condmutex->mutex);
-#endif
-}
-
-/*----------------------------------------------------------------------------*/
-
-int mdbx_fastmutex_init(mdbx_fastmutex_t *fastmutex) {
-#if defined(_WIN32) || defined(_WIN64)
- InitializeCriticalSection(fastmutex);
- return MDBX_SUCCESS;
-#else
- return pthread_mutex_init(fastmutex, NULL);
-#endif
-}
-
-int mdbx_fastmutex_destroy(mdbx_fastmutex_t *fastmutex) {
-#if defined(_WIN32) || defined(_WIN64)
- DeleteCriticalSection(fastmutex);
- return MDBX_SUCCESS;
-#else
- return pthread_mutex_destroy(fastmutex);
-#endif
-}
-
-int mdbx_fastmutex_acquire(mdbx_fastmutex_t *fastmutex) {
-#if defined(_WIN32) || defined(_WIN64)
- EnterCriticalSection(fastmutex);
- return MDBX_SUCCESS;
-#else
- return pthread_mutex_lock(fastmutex);
-#endif
-}
-
-int mdbx_fastmutex_release(mdbx_fastmutex_t *fastmutex) {
-#if defined(_WIN32) || defined(_WIN64)
- LeaveCriticalSection(fastmutex);
- return MDBX_SUCCESS;
-#else
- return pthread_mutex_unlock(fastmutex);
-#endif
-}
-
-/*----------------------------------------------------------------------------*/
-
-int mdbx_openfile(const char *pathname, int flags, mode_t mode,
- mdbx_filehandle_t *fd) {
- *fd = INVALID_HANDLE_VALUE;
-#if defined(_WIN32) || defined(_WIN64)
- (void)mode;
-
- DWORD DesiredAccess;
- DWORD ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
- DWORD FlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
- switch (flags & (O_RDONLY | O_WRONLY | O_RDWR)) {
- default:
- return ERROR_INVALID_PARAMETER;
- case O_RDONLY:
- DesiredAccess = GENERIC_READ;
- break;
- case O_WRONLY: /* assume for MDBX_env_copy() and friends output */
- DesiredAccess = GENERIC_WRITE;
- ShareMode = 0;
- FlagsAndAttributes |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH;
- break;
- case O_RDWR:
- DesiredAccess = GENERIC_READ | GENERIC_WRITE;
- break;
- }
-
- DWORD CreationDisposition;
- switch (flags & (O_EXCL | O_CREAT)) {
- default:
- return ERROR_INVALID_PARAMETER;
- case 0:
- CreationDisposition = OPEN_EXISTING;
- break;
- case O_EXCL | O_CREAT:
- CreationDisposition = CREATE_NEW;
- FlagsAndAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
- break;
- case O_CREAT:
- CreationDisposition = OPEN_ALWAYS;
- FlagsAndAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
- break;
- }
-
- *fd = CreateFileA(pathname, DesiredAccess, ShareMode, NULL,
- CreationDisposition, FlagsAndAttributes, NULL);
-
- if (*fd == INVALID_HANDLE_VALUE)
- return GetLastError();
- if ((flags & O_CREAT) && GetLastError() != ERROR_ALREADY_EXISTS) {
- /* set FILE_ATTRIBUTE_NOT_CONTENT_INDEXED for new file */
- DWORD FileAttributes = GetFileAttributesA(pathname);
- if (FileAttributes == INVALID_FILE_ATTRIBUTES ||
- !SetFileAttributesA(pathname, FileAttributes |
- FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)) {
- int rc = GetLastError();
- CloseHandle(*fd);
- *fd = INVALID_HANDLE_VALUE;
- return rc;
- }
- }
-#else
-
-#ifdef O_CLOEXEC
- flags |= O_CLOEXEC;
-#endif
- *fd = open(pathname, flags, mode);
- if (*fd < 0)
- return errno;
-#if defined(FD_CLOEXEC) && defined(F_GETFD)
- flags = fcntl(*fd, F_GETFD);
- if (flags >= 0)
- (void)fcntl(*fd, F_SETFD, flags | FD_CLOEXEC);
-#endif
-#endif
- return MDBX_SUCCESS;
-}
-
-int mdbx_closefile(mdbx_filehandle_t fd) {
-#if defined(_WIN32) || defined(_WIN64)
- return CloseHandle(fd) ? MDBX_SUCCESS : GetLastError();
-#else
- return (close(fd) == 0) ? MDBX_SUCCESS : errno;
-#endif
-}
-
-int mdbx_pread(mdbx_filehandle_t fd, void *buf, size_t bytes, uint64_t offset) {
- if (bytes > MAX_WRITE)
- return MDBX_EINVAL;
-#if defined(_WIN32) || defined(_WIN64)
-
- OVERLAPPED ov;
- ov.hEvent = 0;
- ov.Offset = (DWORD)offset;
- ov.OffsetHigh = HIGH_DWORD(offset);
-
- DWORD read = 0;
- if (unlikely(!ReadFile(fd, buf, (DWORD)bytes, &read, &ov))) {
- int rc = GetLastError();
- return (rc == MDBX_SUCCESS) ? /* paranoia */ ERROR_READ_FAULT : rc;
- }
-#else
- STATIC_ASSERT_MSG(sizeof(off_t) >= sizeof(size_t),
- "libmdbx requires 64-bit file I/O on 64-bit systems");
- intptr_t read = pread(fd, buf, bytes, offset);
- if (read < 0) {
- int rc = errno;
- return (rc == MDBX_SUCCESS) ? /* paranoia */ MDBX_EIO : rc;
- }
-#endif
- return (bytes == (size_t)read) ? MDBX_SUCCESS : MDBX_ENODATA;
-}
-
-int mdbx_pwrite(mdbx_filehandle_t fd, const void *buf, size_t bytes,
- uint64_t offset) {
-#if defined(_WIN32) || defined(_WIN64)
- if (bytes > MAX_WRITE)
- return ERROR_INVALID_PARAMETER;
-
- OVERLAPPED ov;
- ov.hEvent = 0;
- ov.Offset = (DWORD)offset;
- ov.OffsetHigh = HIGH_DWORD(offset);
-
- DWORD written;
- if (likely(WriteFile(fd, buf, (DWORD)bytes, &written, &ov)))
- return (bytes == written) ? MDBX_SUCCESS : MDBX_EIO /* ERROR_WRITE_FAULT */;
- return GetLastError();
-#else
- int rc;
- intptr_t written;
- do {
- STATIC_ASSERT_MSG(sizeof(off_t) >= sizeof(size_t),
- "libmdbx requires 64-bit file I/O on 64-bit systems");
- written = pwrite(fd, buf, bytes, offset);
- if (likely(bytes == (size_t)written))
- return MDBX_SUCCESS;
- rc = errno;
- } while (rc == EINTR);
- return (written < 0) ? rc : MDBX_EIO /* Use which error code (ENOSPC)? */;
-#endif
-}
-
-int mdbx_pwritev(mdbx_filehandle_t fd, struct iovec *iov, int iovcnt,
- uint64_t offset, size_t expected_written) {
-#if defined(_WIN32) || defined(_WIN64)
- size_t written = 0;
- for (int i = 0; i < iovcnt; ++i) {
- int rc = mdbx_pwrite(fd, iov[i].iov_base, iov[i].iov_len, offset);
- if (unlikely(rc != MDBX_SUCCESS))
- return rc;
- written += iov[i].iov_len;
- offset += iov[i].iov_len;
- }
- return (expected_written == written) ? MDBX_SUCCESS
- : MDBX_EIO /* ERROR_WRITE_FAULT */;
-#else
- int rc;
- intptr_t written;
- do {
- STATIC_ASSERT_MSG(sizeof(off_t) >= sizeof(size_t),
- "libmdbx requires 64-bit file I/O on 64-bit systems");
- written = pwritev(fd, iov, iovcnt, offset);
- if (likely(expected_written == (size_t)written))
- return MDBX_SUCCESS;
- rc = errno;
- } while (rc == EINTR);
- return (written < 0) ? rc : MDBX_EIO /* Use which error code? */;
-#endif
-}
-
-int mdbx_write(mdbx_filehandle_t fd, const void *buf, size_t bytes) {
-#ifdef SIGPIPE
- sigset_t set, old;
- sigemptyset(&set);
- sigaddset(&set, SIGPIPE);
- int rc = pthread_sigmask(SIG_BLOCK, &set, &old);
- if (rc != 0)
- return rc;
-#endif
-
- const char *ptr = buf;
- for (;;) {
- size_t chunk = (MAX_WRITE < bytes) ? MAX_WRITE : bytes;
-#if defined(_WIN32) || defined(_WIN64)
- DWORD written;
- if (unlikely(!WriteFile(fd, ptr, (DWORD)chunk, &written, NULL)))
- return GetLastError();
-#else
- intptr_t written = write(fd, ptr, chunk);
- if (written < 0) {
- int rc = errno;
-#ifdef SIGPIPE
- if (rc == EPIPE) {
- /* Collect the pending SIGPIPE, otherwise at least OS X
- * gives it to the process on thread-exit (ITS#8504). */
- int tmp;
- sigwait(&set, &tmp);
- written = 0;
- continue;
- }
- pthread_sigmask(SIG_SETMASK, &old, NULL);
-#endif
- return rc;
- }
-#endif
- if (likely(bytes == (size_t)written)) {
-#ifdef SIGPIPE
- pthread_sigmask(SIG_SETMASK, &old, NULL);
-#endif
- return MDBX_SUCCESS;
- }
- ptr += written;
- bytes -= written;
- }
-}
-
-int mdbx_filesync(mdbx_filehandle_t fd, bool filesize_changed) {
-#if defined(_WIN32) || defined(_WIN64)
- (void)filesize_changed;
- return FlushFileBuffers(fd) ? MDBX_SUCCESS : GetLastError();
-#elif __GLIBC_PREREQ(2, 16) || _BSD_SOURCE || _XOPEN_SOURCE || \
- (__GLIBC_PREREQ(2, 8) && _POSIX_C_SOURCE >= 200112L)
- for (;;) {
-/* LY: It is no reason to use fdatasync() here, even in case
- * no such bug in a kernel. Because "no-bug" mean that a kernel
- * internally do nearly the same, e.g. fdatasync() == fsync()
- * when no-kernel-bug and file size was changed.
- *
- * So, this code is always safe and without appreciable
- * performance degradation.
- *
- * For more info about of a corresponding fdatasync() bug
- * see http://www.spinics.net/lists/linux-ext4/msg33714.html */
-#if _POSIX_C_SOURCE >= 199309L || _XOPEN_SOURCE >= 500 || \
- defined(_POSIX_SYNCHRONIZED_IO)
- if (!filesize_changed && fdatasync(fd) == 0)
- return MDBX_SUCCESS;
-#else
- (void)filesize_changed;
-#endif
- if (fsync(fd) == 0)
- return MDBX_SUCCESS;
- int rc = errno;
- if (rc != EINTR)
- return rc;
- }
-#else
-#error FIXME
-#endif
-}
-
-int mdbx_filesize_sync(mdbx_filehandle_t fd) {
-#if defined(_WIN32) || defined(_WIN64)
- (void)fd;
- /* Nothing on Windows (i.e. newer 100% steady) */
- return MDBX_SUCCESS;
-#else
- for (;;) {
- if (fsync(fd) == 0)
- return MDBX_SUCCESS;
- int rc = errno;
- if (rc != EINTR)
- return rc;
- }
-#endif
-}
-
-int mdbx_filesize(mdbx_filehandle_t fd, uint64_t *length) {
-#if defined(_WIN32) || defined(_WIN64)
- BY_HANDLE_FILE_INFORMATION info;
- if (!GetFileInformationByHandle(fd, &info))
- return GetLastError();
- *length = info.nFileSizeLow | (uint64_t)info.nFileSizeHigh << 32;
-#else
- struct stat st;
-
- STATIC_ASSERT_MSG(sizeof(off_t) <= sizeof(uint64_t),
- "libmdbx requires 64-bit file I/O on 64-bit systems");
- if (fstat(fd, &st))
- return errno;
-
- *length = st.st_size;
-#endif
- return MDBX_SUCCESS;
-}
-
-int mdbx_ftruncate(mdbx_filehandle_t fd, uint64_t length) {
-#if defined(_WIN32) || defined(_WIN64)
- LARGE_INTEGER li;
- li.QuadPart = length;
- return (SetFilePointerEx(fd, li, NULL, FILE_BEGIN) && SetEndOfFile(fd))
- ? MDBX_SUCCESS
- : GetLastError();
-#else
- STATIC_ASSERT_MSG(sizeof(off_t) >= sizeof(size_t),
- "libmdbx requires 64-bit file I/O on 64-bit systems");
- return ftruncate(fd, length) == 0 ? MDBX_SUCCESS : errno;
-#endif
-}
-
-/*----------------------------------------------------------------------------*/
-
-int mdbx_thread_key_create(mdbx_thread_key_t *key) {
-#if defined(_WIN32) || defined(_WIN64)
- *key = TlsAlloc();
- return (*key != TLS_OUT_OF_INDEXES) ? MDBX_SUCCESS : GetLastError();
-#else
- return pthread_key_create(key, mdbx_rthc_dtor);
-#endif
-}
-
-void mdbx_thread_key_delete(mdbx_thread_key_t key) {
-#if defined(_WIN32) || defined(_WIN64)
- mdbx_ensure(NULL, TlsFree(key));
-#else
- mdbx_ensure(NULL, pthread_key_delete(key) == 0);
-#endif
-}
-
-void *mdbx_thread_rthc_get(mdbx_thread_key_t key) {
-#if defined(_WIN32) || defined(_WIN64)
- return TlsGetValue(key);
-#else
- return pthread_getspecific(key);
-#endif
-}
-
-void mdbx_thread_rthc_set(mdbx_thread_key_t key, const void *value) {
-#if defined(_WIN32) || defined(_WIN64)
- mdbx_ensure(NULL, TlsSetValue(key, (void *)value));
-#else
- mdbx_ensure(NULL, pthread_setspecific(key, value) == 0);
-#endif
-}
-
-int mdbx_thread_create(mdbx_thread_t *thread,
- THREAD_RESULT(THREAD_CALL *start_routine)(void *),
- void *arg) {
-#if defined(_WIN32) || defined(_WIN64)
- *thread = CreateThread(NULL, 0, start_routine, arg, 0, NULL);
- return *thread ? MDBX_SUCCESS : GetLastError();
-#else
- return pthread_create(thread, NULL, start_routine, arg);
-#endif
-}
-
-int mdbx_thread_join(mdbx_thread_t thread) {
-#if defined(_WIN32) || defined(_WIN64)
- DWORD code = WaitForSingleObject(thread, INFINITE);
- return waitstatus2errcode(code);
-#else
- void *unused_retval = &unused_retval;
- return pthread_join(thread, &unused_retval);
-#endif
-}
-
-/*----------------------------------------------------------------------------*/
-
-int mdbx_msync(mdbx_mmap_t *map, size_t offset, size_t length, int async) {
- uint8_t *ptr = (uint8_t *)map->address + offset;
-#if defined(_WIN32) || defined(_WIN64)
- if (FlushViewOfFile(ptr, length) && (async || FlushFileBuffers(map->fd)))
- return MDBX_SUCCESS;
- return GetLastError();
-#else
- const int mode = async ? MS_ASYNC : MS_SYNC;
- return (msync(ptr, length, mode) == 0) ? MDBX_SUCCESS : errno;
-#endif
-}
-
-int mdbx_mmap(int flags, mdbx_mmap_t *map, size_t must, size_t limit) {
- assert(must <= limit);
-#if defined(_WIN32) || defined(_WIN64)
- map->length = 0;
- map->current = 0;
- map->section = NULL;
- map->address = nullptr;
-
- if (GetFileType(map->fd) != FILE_TYPE_DISK)
- return ERROR_FILE_OFFLINE;
-
- FILE_REMOTE_PROTOCOL_INFO RemoteProtocolInfo;
- if (GetFileInformationByHandleEx(map->fd, FileRemoteProtocolInfo,
- &RemoteProtocolInfo,
- sizeof(RemoteProtocolInfo))) {
- if ((RemoteProtocolInfo.Flags & (REMOTE_PROTOCOL_INFO_FLAG_LOOPBACK |
- REMOTE_PROTOCOL_INFO_FLAG_OFFLINE)) !=
- REMOTE_PROTOCOL_INFO_FLAG_LOOPBACK)
- return ERROR_FILE_OFFLINE;
- }
-
- NTSTATUS rc;
-#if defined(_WIN64) && defined(WOF_CURRENT_VERSION)
- struct {
- WOF_EXTERNAL_INFO wof_info;
- union {
- WIM_PROVIDER_EXTERNAL_INFO wim_info;
- FILE_PROVIDER_EXTERNAL_INFO_V1 file_info;
- };
- size_t reserved_for_microsoft_madness[42];
- } GetExternalBacking_OutputBuffer;
- IO_STATUS_BLOCK StatusBlock;
- rc = NtFsControlFile(map->fd, NULL, NULL, NULL, &StatusBlock,
- FSCTL_GET_EXTERNAL_BACKING, NULL, 0,
- &GetExternalBacking_OutputBuffer,
- sizeof(GetExternalBacking_OutputBuffer));
- if (rc != STATUS_OBJECT_NOT_EXTERNALLY_BACKED &&
- rc != STATUS_INVALID_DEVICE_REQUEST)
- return NT_SUCCESS(rc) ? ERROR_FILE_OFFLINE : ntstatus2errcode(rc);
-#endif
-
- WCHAR PathBuffer[INT16_MAX];
- DWORD VolumeSerialNumber, FileSystemFlags;
- if (!GetVolumeInformationByHandleW(map->fd, PathBuffer, INT16_MAX,
- &VolumeSerialNumber, NULL,
- &FileSystemFlags, NULL, 0))
- return GetLastError();
-
- if ((flags & MDBX_RDONLY) == 0) {
- if (FileSystemFlags & (FILE_SEQUENTIAL_WRITE_ONCE | FILE_READ_ONLY_VOLUME |
- FILE_VOLUME_IS_COMPRESSED))
- return ERROR_FILE_OFFLINE;
- }
-
- if (!GetFinalPathNameByHandleW(map->fd, PathBuffer, INT16_MAX,
- FILE_NAME_NORMALIZED | VOLUME_NAME_NT))
- return GetLastError();
-
- if (_wcsnicmp(PathBuffer, L"\\Device\\Mup\\", 12) == 0)
- return ERROR_FILE_OFFLINE;
-
- if (GetFinalPathNameByHandleW(map->fd, PathBuffer, INT16_MAX,
- FILE_NAME_NORMALIZED | VOLUME_NAME_DOS)) {
- UINT DriveType = GetDriveTypeW(PathBuffer);
- if (DriveType == DRIVE_NO_ROOT_DIR &&
- wcsncmp(PathBuffer, L"\\\\?\\", 4) == 0 &&
- wcsncmp(PathBuffer + 5, L":\\", 2) == 0) {
- PathBuffer[7] = 0;
- DriveType = GetDriveTypeW(PathBuffer + 4);
- }
- switch (DriveType) {
- case DRIVE_CDROM:
- if (flags & MDBX_RDONLY)
- break;
- // fall through
- case DRIVE_UNKNOWN:
- case DRIVE_NO_ROOT_DIR:
- case DRIVE_REMOTE:
- default:
- return ERROR_FILE_OFFLINE;
- case DRIVE_REMOVABLE:
- case DRIVE_FIXED:
- case DRIVE_RAMDISK:
- break;
- }
- }
-
- rc = NtCreateSection(
- &map->section,
- /* DesiredAccess */ SECTION_MAP_READ | SECTION_EXTEND_SIZE |
- ((flags & MDBX_WRITEMAP) ? SECTION_MAP_WRITE : 0),
- /* ObjectAttributes */ NULL, /* MaximumSize */ NULL,
- /* SectionPageProtection */ (flags & MDBX_RDONLY) ? PAGE_READONLY
- : PAGE_READWRITE,
- /* AllocationAttributes */ SEC_RESERVE, map->fd);
-
- if (!NT_SUCCESS(rc))
- return ntstatus2errcode(rc);
-
- map->address = nullptr;
- SIZE_T ViewSize = (flags & MDBX_RDONLY) ? must : limit;
- rc = NtMapViewOfSection(
- map->section, GetCurrentProcess(), &map->address,
- /* ZeroBits */ 0,
- /* CommitSize */ must,
- /* SectionOffset */ NULL, &ViewSize,
- /* InheritDisposition */ ViewUnmap,
- /* AllocationType */ (flags & MDBX_RDONLY) ? 0 : MEM_RESERVE,
- /* Win32Protect */ (flags & MDBX_WRITEMAP) ? PAGE_READWRITE
- : PAGE_READONLY);
-
- if (!NT_SUCCESS(rc)) {
- NtClose(map->section);
- map->section = 0;
- map->address = nullptr;
- return ntstatus2errcode(rc);
- }
- assert(map->address != MAP_FAILED);
-
- uint64_t filesize;
- rc = mdbx_filesize(map->fd, &filesize);
- if (rc != MDBX_SUCCESS) {
- NtClose(map->section);
- NtUnmapViewOfSection(GetCurrentProcess(), map->address);
- map->section = 0;
- map->address = nullptr;
- return rc;
- }
-
- map->current = (must < filesize) ? must : (size_t)filesize;
- map->length = ViewSize;
- return MDBX_SUCCESS;
-#else
- (void)must;
- map->address = mmap(
- NULL, limit, (flags & MDBX_WRITEMAP) ? PROT_READ | PROT_WRITE : PROT_READ,
- MAP_SHARED, map->fd, 0);
- if (likely(map->address != MAP_FAILED)) {
- map->length = limit;
- return MDBX_SUCCESS;
- }
- map->length = 0;
- map->address = nullptr;
- return errno;
-#endif
-}
-
-int mdbx_munmap(mdbx_mmap_t *map) {
-#if defined(_WIN32) || defined(_WIN64)
- if (map->section)
- NtClose(map->section);
- NTSTATUS rc = NtUnmapViewOfSection(GetCurrentProcess(), map->address);
- if (!NT_SUCCESS(rc))
- ntstatus2errcode(rc);
- map->length = 0;
- map->current = 0;
- map->address = nullptr;
-#else
- if (unlikely(munmap(map->address, map->length)))
- return errno;
- map->length = 0;
- map->address = nullptr;
-#endif
- return MDBX_SUCCESS;
-}
-
-int mdbx_mresize(int flags, mdbx_mmap_t *map, size_t atleast, size_t limit) {
- assert(atleast <= limit);
-#if defined(_WIN32) || defined(_WIN64)
- if (limit < map->length) {
- /* Windows is unable shrinking a mapped section */
- return ERROR_USER_MAPPED_FILE;
- }
- if (limit > map->length) {
- /* extend */
- LARGE_INTEGER new_size;
- new_size.QuadPart = limit;
- NTSTATUS rc = NtExtendSection(map->section, &new_size);
- if (!NT_SUCCESS(rc))
- return ntstatus2errcode(rc);
- map->length = limit;
- }
- if (atleast < map->current) {
- /* Windows is unable shrinking a mapped file */
- uint8_t *ptr = (uint8_t *)map->address + atleast;
- if (!VirtualFree(ptr, map->current - atleast, MEM_DECOMMIT))
- return MDBX_RESULT_TRUE;
-
- map->current = atleast;
- int rc = mdbx_ftruncate(map->fd, atleast);
- return (rc != MDBX_SUCCESS) ? MDBX_RESULT_TRUE : rc;
- }
- if (atleast > map->current) {
- /* growth */
- uint8_t *ptr = (uint8_t *)map->address + map->current;
- if (ptr !=
- VirtualAlloc(ptr, atleast - map->current, MEM_COMMIT,
- (flags & MDBX_WRITEMAP) ? PAGE_READWRITE : PAGE_READONLY))
- return GetLastError();
- map->current = atleast;
- }
-
- uint64_t filesize;
- int rc = mdbx_filesize(map->fd, &filesize);
- if (rc != MDBX_SUCCESS)
- return rc;
- if (filesize < atleast) {
- rc = mdbx_ftruncate(map->fd, atleast);
- if (rc != MDBX_SUCCESS)
- return rc;
- }
- return MDBX_SUCCESS;
-#else
- (void)flags;
- if (limit != map->length) {
- void *ptr = mremap(map->address, map->length, limit, MREMAP_MAYMOVE);
- if (ptr == MAP_FAILED)
- return errno;
- map->address = ptr;
- map->length = limit;
- }
- return mdbx_ftruncate(map->fd, atleast);
-#endif
-}
-
-/*----------------------------------------------------------------------------*/
-
-__cold void mdbx_osal_jitter(bool tiny) {
- for (;;) {
-#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \
- defined(__x86_64__)
- const unsigned salt = 277u * (unsigned)__rdtsc();
-#else
- const unsigned salt = rand();
-#endif
-
- const unsigned coin = salt % (tiny ? 29u : 43u);
- if (coin < 43 / 3)
- break;
-#if defined(_WIN32) || defined(_WIN64)
- SwitchToThread();
- if (coin > 43 * 2 / 3)
- Sleep(1);
-#else
- sched_yield();
- if (coin > 43 * 2 / 3)
- usleep(coin);
-#endif
- }
-}
diff --git a/plugins/Dbx_mdb/src/mdbx/osal.h b/plugins/Dbx_mdb/src/mdbx/osal.h
deleted file mode 100644
index e3a503ba1a..0000000000
--- a/plugins/Dbx_mdb/src/mdbx/osal.h
+++ /dev/null
@@ -1,645 +0,0 @@
-/* https://en.wikipedia.org/wiki/Operating_system_abstraction_layer */
-
-/*
- * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
- * and other libmdbx authors: please see AUTHORS file.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#pragma once
-
-/*----------------------------------------------------------------------------*/
-/* Microsoft compiler generates a lot of warning for self includes... */
-
-#ifdef _MSC_VER
-#pragma warning(push, 1)
-#pragma warning(disable : 4548) /* expression before comma has no effect; \
- expected expression with side - effect */
-#pragma warning(disable : 4530) /* C++ exception handler used, but unwind \
- * semantics are not enabled. Specify /EHsc */
-#pragma warning(disable : 4577) /* 'noexcept' used with no exception handling \
- * mode specified; termination on exception is \
- * not guaranteed. Specify /EHsc */
-#if !defined(_CRT_SECURE_NO_WARNINGS)
-#define _CRT_SECURE_NO_WARNINGS
-#endif
-#endif /* _MSC_VER (warnings) */
-
-/*----------------------------------------------------------------------------*/
-/* C99 includes */
-
-#include <inttypes.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#include <assert.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-
-#ifndef _POSIX_C_SOURCE
-#ifdef _POSIX_SOURCE
-#define _POSIX_C_SOURCE 1
-#else
-#define _POSIX_C_SOURCE 0
-#endif
-#endif
-
-#ifndef _XOPEN_SOURCE
-#define _XOPEN_SOURCE 0
-#endif
-
-/*----------------------------------------------------------------------------*/
-/* Systems includes */
-
-#if defined(_WIN32) || defined(_WIN64)
-#include <windows.h>
-#include <winnt.h>
-#define HAVE_SYS_STAT_H
-#define HAVE_SYS_TYPES_H
-typedef HANDLE mdbx_thread_t;
-typedef unsigned mdbx_thread_key_t;
-#define MDBX_OSAL_SECTION HANDLE
-#define MAP_FAILED NULL
-#define HIGH_DWORD(v) ((DWORD)((sizeof(v) > 4) ? ((uint64_t)(v) >> 32) : 0))
-#define THREAD_CALL WINAPI
-#define THREAD_RESULT DWORD
-typedef struct {
- HANDLE mutex;
- HANDLE event;
-} mdbx_condmutex_t;
-typedef CRITICAL_SECTION mdbx_fastmutex_t;
-#else
-#include <pthread.h>
-#include <signal.h>
-#include <sys/file.h>
-#include <sys/mman.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/uio.h>
-#include <unistd.h>
-typedef pthread_t mdbx_thread_t;
-typedef pthread_key_t mdbx_thread_key_t;
-#define INVALID_HANDLE_VALUE (-1)
-#define THREAD_CALL
-#define THREAD_RESULT void *
-typedef struct {
- pthread_mutex_t mutex;
- pthread_cond_t cond;
-} mdbx_condmutex_t;
-typedef pthread_mutex_t mdbx_fastmutex_t;
-#endif /* Platform */
-
-#ifndef SSIZE_MAX
-#define SSIZE_MAX INTPTR_MAX
-#endif
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_FILE_H
-#include <sys/file.h>
-#endif
-
-#if !defined(UNALIGNED_OK)
-#if defined(__i386) || defined(__x86_64__) || defined(_M_IX86) || \
- defined(_M_X64) || defined(i386) || defined(_X86_) || defined(__i386__) || \
- defined(_X86_64_)
-#define UNALIGNED_OK 1
-#else
-#define UNALIGNED_OK 0
-#endif
-#endif /* UNALIGNED_OK */
-
-#if (-6 & 5) || CHAR_BIT != 8 || UINT_MAX < 0xffffffff || ULONG_MAX % 0xFFFF
-#error \
- "Sanity checking failed: Two's complement, reasonably sized integer types"
-#endif
-
-/*----------------------------------------------------------------------------*/
-/* Compiler's includes for builtins/intrinsics */
-
-#ifdef _MSC_VER
-
-#if _MSC_FULL_VER < 190024215
-#if _MSC_FULL_VER < 180040629 && defined(_M_IX86)
-#error Please use Visual Studio 2015 (MSC 19.0) or newer for 32-bit target.
-#else
-#pragma message( \
- "It is recommended to use Visual Studio 2015 (MSC 19.0) or newer.")
-#endif
-#endif
-
-#include <intrin.h>
-
-#elif __GNUC_PREREQ(4, 4) || defined(__clang__)
-#if defined(__i386__) || defined(__x86_64__)
-#include <cpuid.h>
-#include <x86intrin.h>
-#endif
-#elif defined(__INTEL_COMPILER)
-#include <intrin.h>
-#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun)
-#include <mbarrier.h>
-#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \
- (defined(HP_IA64) || defined(__ia64))
-#include <machine/sys/inline.h>
-#elif defined(__IBMC__) && defined(__powerpc)
-#include <atomic.h>
-#elif defined(_AIX)
-#include <builtins.h>
-#include <sys/atomic_op.h>
-#elif (defined(__osf__) && defined(__DECC)) || defined(__alpha)
-#include <c_asm.h>
-#include <machine/builtins.h>
-#elif defined(__MWERKS__)
-/* CodeWarrior - troubles ? */
-#pragma gcc_extensions
-#elif defined(__SNC__)
-/* Sony PS3 - troubles ? */
-#else
-#error Unknown C compiler, please use GNU C 5.x or newer
-#endif /* Compiler */
-
-/*----------------------------------------------------------------------------*/
-/* Byteorder */
-
-#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \
- !defined(__ORDER_BIG_ENDIAN__)
-
-#if defined(HAVE_ENDIAN_H)
-#include <endian.h>
-#elif defined(HAVE_SYS_PARAM_H)
-#include <sys/param.h> /* for endianness */
-#elif defined(HAVE_NETINET_IN_H) && defined(HAVE_RESOLV_H)
-#include <netinet/in.h>
-#include <resolv.h> /* defines BYTE_ORDER on HPUX and Solaris */
-#endif
-
-#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN)
-#define __ORDER_LITTLE_ENDIAN__ __LITTLE_ENDIAN
-#define __ORDER_BIG_ENDIAN__ __BIG_ENDIAN
-#define __BYTE_ORDER__ __BYTE_ORDER
-#else
-#define __ORDER_LITTLE_ENDIAN__ 1234
-#define __ORDER_BIG_ENDIAN__ 4321
-#if defined(__LITTLE_ENDIAN__) || defined(_LITTLE_ENDIAN) || \
- defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \
- defined(__MIPSEL__) || defined(_MIPSEL) || defined(__MIPSEL) || \
- defined(__i386) || defined(__x86_64__) || defined(_M_IX86) || \
- defined(_M_X64) || defined(i386) || defined(_X86_) || defined(__i386__) || \
- defined(_X86_64_) || defined(_M_ARM) || defined(_M_ARM64) || \
- defined(__e2k__)
-#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
-#elif defined(__BIG_ENDIAN__) || defined(_BIG_ENDIAN) || defined(__ARMEB__) || \
- defined(__THUMBEB__) || defined(__AARCH64EB__) || defined(__MIPSEB__) || \
- defined(_MIPSEB) || defined(__MIPSEB) || defined(_M_IA64)
-#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
-#else
-#error __BYTE_ORDER__ should be defined.
-#endif
-#endif
-#endif /* __BYTE_ORDER__ || __ORDER_LITTLE_ENDIAN__ || __ORDER_BIG_ENDIAN__ */
-
-#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ && \
- __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__
-#error Unsupported byte order.
-#endif
-
-/*----------------------------------------------------------------------------*/
-/* Memory/Compiler barriers, cache coherence */
-
-static __inline void mdbx_compiler_barrier(void) {
-#if defined(__clang__) || defined(__GNUC__)
- __asm__ __volatile__("" ::: "memory");
-#elif defined(_MSC_VER)
- _ReadWriteBarrier();
-#elif defined(__INTEL_COMPILER) /* LY: Intel Compiler may mimic GCC and MSC */
- __memory_barrier();
- if (type > MDBX_BARRIER_COMPILER)
-#if defined(__ia64__) || defined(__ia64) || defined(_M_IA64)
- __mf();
-#elif defined(__i386__) || defined(__x86_64__)
- _mm_mfence();
-#else
-#error "Unknown target for Intel Compiler, please report to us."
-#endif
-#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun)
- __compiler_barrier();
-#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \
- (defined(HP_IA64) || defined(__ia64))
- _Asm_sched_fence(/* LY: no-arg meaning 'all expect ALU', e.g. 0x3D3D */);
-#elif defined(_AIX) || defined(__ppc__) || defined(__powerpc__) || \
- defined(__ppc64__) || defined(__powerpc64__)
- __fence();
-#else
-#error "Could not guess the kind of compiler, please report to us."
-#endif
-}
-
-static __inline void mdbx_memory_barrier(void) {
-#if __has_extension(c_atomic) || __has_extension(cxx_atomic)
- __c11_atomic_thread_fence(__ATOMIC_SEQ_CST);
-#elif defined(__ATOMIC_SEQ_CST)
- __atomic_thread_fence(__ATOMIC_SEQ_CST);
-#elif defined(__clang__) || defined(__GNUC__)
- __sync_synchronize();
-#elif defined(_MSC_VER)
- MemoryBarrier();
-#elif defined(__INTEL_COMPILER) /* LY: Intel Compiler may mimic GCC and MSC */
-#if defined(__ia64__) || defined(__ia64) || defined(_M_IA64)
- __mf();
-#elif defined(__i386__) || defined(__x86_64__)
- _mm_mfence();
-#else
-#error "Unknown target for Intel Compiler, please report to us."
-#endif
-#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun)
- __machine_rw_barrier();
-#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \
- (defined(HP_IA64) || defined(__ia64))
- _Asm_mf();
-#elif defined(_AIX) || defined(__ppc__) || defined(__powerpc__) || \
- defined(__ppc64__) || defined(__powerpc64__)
- __lwsync();
-#else
-#error "Could not guess the kind of compiler, please report to us."
-#endif
-}
-
-/*----------------------------------------------------------------------------*/
-/* Cache coherence and invalidation */
-
-#if defined(__i386__) || defined(__x86_64__) || defined(_M_AMD64) || \
- defined(_M_IX86) || defined(__i386) || defined(__amd64) || \
- defined(i386) || defined(__x86_64) || defined(_AMD64_) || defined(_M_X64)
-#define MDBX_CACHE_IS_COHERENT 1
-#elif defined(__hppa) || defined(__hppa__)
-#define MDBX_CACHE_IS_COHERENT 1
-#endif
-
-#ifndef MDBX_CACHE_IS_COHERENT
-#define MDBX_CACHE_IS_COHERENT 0
-#endif
-
-#ifndef MDBX_CACHELINE_SIZE
-#if defined(SYSTEM_CACHE_ALIGNMENT_SIZE)
-#define MDBX_CACHELINE_SIZE SYSTEM_CACHE_ALIGNMENT_SIZE
-#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64)
-#define MDBX_CACHELINE_SIZE 128
-#else
-#define MDBX_CACHELINE_SIZE 64
-#endif
-#endif /* MDBX_CACHELINE_SIZE */
-
-#ifndef __cache_aligned
-#define __cache_aligned __aligned(MDBX_CACHELINE_SIZE)
-#endif
-
-#if MDBX_CACHE_IS_COHERENT
-#define mdbx_coherent_barrier() mdbx_compiler_barrier()
-#else
-#define mdbx_coherent_barrier() mdbx_memory_barrier()
-#endif
-
-#if defined(__mips) && defined(__linux)
-/* Only MIPS has explicit cache control */
-#include <asm/cachectl.h>
-#endif
-
-static __inline void mdbx_invalidate_cache(void *addr, size_t nbytes) {
- mdbx_coherent_barrier();
-#if defined(__mips) && defined(__linux)
- /* MIPS has cache coherency issues.
- * Note: for any nbytes >= on-chip cache size, entire is flushed. */
- cacheflush(addr, nbytes, DCACHE);
-#elif defined(_M_MRX000) || defined(_MIPS_)
-#error "Sorry, cacheflush() for MIPS not implemented"
-#else
- /* LY: assume no relevant mmap/dcache issues. */
- (void)addr;
- (void)nbytes;
-#endif
-}
-
-/*----------------------------------------------------------------------------*/
-/* libc compatibility stuff */
-
-#ifndef mdbx_assert_fail
-void mdbx_assert_fail(const MDBX_env *env, const char *msg, const char *func,
- int line);
-#endif /* mdbx_assert_fail */
-
-#if __GLIBC_PREREQ(2, 1)
-#define mdbx_asprintf asprintf
-#else
-int mdbx_asprintf(char **strp, const char *fmt, ...);
-#endif
-
-#ifdef _MSC_VER
-
-#ifndef snprintf
-#define snprintf(buffer, buffer_size, format, ...) \
- _snprintf_s(buffer, buffer_size, _TRUNCATE, format, __VA_ARGS__)
-#endif /* snprintf */
-
-#ifndef vsnprintf
-#define vsnprintf(buffer, buffer_size, format, args) \
- _vsnprintf_s(buffer, buffer_size, _TRUNCATE, format, args)
-#endif /* vsnprintf */
-
-#ifdef _ASSERTE
-#undef assert
-#define assert _ASSERTE
-#endif
-
-#endif /* _MSC_VER */
-
-/*----------------------------------------------------------------------------*/
-/* OS abstraction layer stuff */
-
-/* max bytes to write in one call */
-#define MAX_WRITE UINT32_C(0x3fff0000)
-
-/* Get the size of a memory page for the system.
- * This is the basic size that the platform's memory manager uses, and is
- * fundamental to the use of memory-mapped files. */
-static __inline size_t mdbx_syspagesize(void) {
-#if defined(_WIN32) || defined(_WIN64)
- SYSTEM_INFO si;
- GetSystemInfo(&si);
- return si.dwPageSize;
-#else
- return sysconf(_SC_PAGE_SIZE);
-#endif
-}
-
-static __inline char *mdbx_strdup(const char *str) {
-#ifdef _MSC_VER
- return _strdup(str);
-#else
- return strdup(str);
-#endif
-}
-
-static __inline int mdbx_get_errno(void) {
-#if defined(_WIN32) || defined(_WIN64)
- DWORD rc = GetLastError();
-#else
- int rc = errno;
-#endif
- return rc;
-}
-
-int mdbx_memalign_alloc(size_t alignment, size_t bytes, void **result);
-void mdbx_memalign_free(void *ptr);
-
-int mdbx_condmutex_init(mdbx_condmutex_t *condmutex);
-int mdbx_condmutex_lock(mdbx_condmutex_t *condmutex);
-int mdbx_condmutex_unlock(mdbx_condmutex_t *condmutex);
-int mdbx_condmutex_signal(mdbx_condmutex_t *condmutex);
-int mdbx_condmutex_wait(mdbx_condmutex_t *condmutex);
-int mdbx_condmutex_destroy(mdbx_condmutex_t *condmutex);
-
-int mdbx_fastmutex_init(mdbx_fastmutex_t *fastmutex);
-int mdbx_fastmutex_acquire(mdbx_fastmutex_t *fastmutex);
-int mdbx_fastmutex_release(mdbx_fastmutex_t *fastmutex);
-int mdbx_fastmutex_destroy(mdbx_fastmutex_t *fastmutex);
-
-int mdbx_pwritev(mdbx_filehandle_t fd, struct iovec *iov, int iovcnt,
- uint64_t offset, size_t expected_written);
-int mdbx_pread(mdbx_filehandle_t fd, void *buf, size_t count, uint64_t offset);
-int mdbx_pwrite(mdbx_filehandle_t fd, const void *buf, size_t count,
- uint64_t offset);
-int mdbx_write(mdbx_filehandle_t fd, const void *buf, size_t count);
-
-int mdbx_thread_create(mdbx_thread_t *thread,
- THREAD_RESULT(THREAD_CALL *start_routine)(void *),
- void *arg);
-int mdbx_thread_join(mdbx_thread_t thread);
-int mdbx_thread_key_create(mdbx_thread_key_t *key);
-void mdbx_thread_key_delete(mdbx_thread_key_t key);
-void *mdbx_thread_rthc_get(mdbx_thread_key_t key);
-void mdbx_thread_rthc_set(mdbx_thread_key_t key, const void *value);
-
-int mdbx_filesync(mdbx_filehandle_t fd, bool fullsync);
-int mdbx_filesize_sync(mdbx_filehandle_t fd);
-int mdbx_ftruncate(mdbx_filehandle_t fd, uint64_t length);
-int mdbx_filesize(mdbx_filehandle_t fd, uint64_t *length);
-int mdbx_openfile(const char *pathname, int flags, mode_t mode,
- mdbx_filehandle_t *fd);
-int mdbx_closefile(mdbx_filehandle_t fd);
-
-typedef struct mdbx_mmap_param {
- union {
- void *address;
- uint8_t *dxb;
- struct MDBX_lockinfo *lck;
- };
- mdbx_filehandle_t fd;
- size_t length; /* mapping length, but NOT a size of file or DB */
-#if defined(_WIN32) || defined(_WIN64)
- size_t current; /* mapped region size, e.g. file and DB */
-#endif
-#ifdef MDBX_OSAL_SECTION
- MDBX_OSAL_SECTION section;
-#endif
-} mdbx_mmap_t;
-
-int mdbx_mmap(int flags, mdbx_mmap_t *map, size_t must, size_t limit);
-int mdbx_munmap(mdbx_mmap_t *map);
-int mdbx_mresize(int flags, mdbx_mmap_t *map, size_t current, size_t wanna);
-int mdbx_msync(mdbx_mmap_t *map, size_t offset, size_t length, int async);
-
-static __inline mdbx_pid_t mdbx_getpid(void) {
-#if defined(_WIN32) || defined(_WIN64)
- return GetCurrentProcessId();
-#else
- return getpid();
-#endif
-}
-
-static __inline mdbx_tid_t mdbx_thread_self(void) {
-#if defined(_WIN32) || defined(_WIN64)
- return GetCurrentThreadId();
-#else
- return pthread_self();
-#endif
-}
-
-void mdbx_osal_jitter(bool tiny);
-
-/*----------------------------------------------------------------------------*/
-/* lck stuff */
-
-#if defined(_WIN32) || defined(_WIN64)
-#undef MDBX_OSAL_LOCK
-#define MDBX_OSAL_LOCK_SIGN UINT32_C(0xF10C)
-#else
-#define MDBX_OSAL_LOCK pthread_mutex_t
-#define MDBX_OSAL_LOCK_SIGN UINT32_C(0x8017)
-#endif
-
-int mdbx_lck_init(MDBX_env *env);
-
-int mdbx_lck_seize(MDBX_env *env);
-int mdbx_lck_downgrade(MDBX_env *env, bool complete);
-int mdbx_lck_upgrade(MDBX_env *env);
-void mdbx_lck_destroy(MDBX_env *env);
-
-int mdbx_rdt_lock(MDBX_env *env);
-void mdbx_rdt_unlock(MDBX_env *env);
-
-int mdbx_txn_lock(MDBX_env *env, bool dontwait);
-void mdbx_txn_unlock(MDBX_env *env);
-
-int mdbx_rpid_set(MDBX_env *env);
-int mdbx_rpid_clear(MDBX_env *env);
-
-/* Checks reader by pid.
- *
- * Returns:
- * MDBX_RESULT_TRUE, if pid is live (unable to acquire lock)
- * MDBX_RESULT_FALSE, if pid is dead (lock acquired)
- * or otherwise the errcode. */
-int mdbx_rpid_check(MDBX_env *env, mdbx_pid_t pid);
-
-/*----------------------------------------------------------------------------*/
-/* Atomics */
-
-#if !defined(__cplusplus) && (__STDC_VERSION__ >= 201112L) && \
- !defined(__STDC_NO_ATOMICS__) && \
- (__GNUC_PREREQ(4, 9) || __CLANG_PREREQ(3, 8) || \
- !(defined(__GNUC__) || defined(__clang__)))
-#include <stdatomic.h>
-#elif defined(__GNUC__) || defined(__clang__)
-/* LY: nothing required */
-#elif defined(_MSC_VER)
-#pragma warning(disable : 4163) /* 'xyz': not available as an intrinsic */
-#pragma warning(disable : 4133) /* 'function': incompatible types - from \
- 'size_t' to 'LONGLONG' */
-#pragma warning(disable : 4244) /* 'return': conversion from 'LONGLONG' to \
- 'std::size_t', possible loss of data */
-#pragma warning(disable : 4267) /* 'function': conversion from 'size_t' to \
- 'long', possible loss of data */
-#pragma intrinsic(_InterlockedExchangeAdd, _InterlockedCompareExchange)
-#pragma intrinsic(_InterlockedExchangeAdd64, _InterlockedCompareExchange64)
-#elif defined(__APPLE__)
-#include <libkern/OSAtomic.h>
-#else
-#error FIXME atomic-ops
-#endif
-
-static __inline uint32_t mdbx_atomic_add32(volatile uint32_t *p, uint32_t v) {
-#if !defined(__cplusplus) && defined(ATOMIC_VAR_INIT)
- assert(atomic_is_lock_free(p));
- return atomic_fetch_add((_Atomic uint32_t *)p, v);
-#elif defined(__GNUC__) || defined(__clang__)
- return __sync_fetch_and_add(p, v);
-#else
-#ifdef _MSC_VER
- return _InterlockedExchangeAdd(p, v);
-#endif
-#ifdef __APPLE__
- return OSAtomicAdd32(v, (volatile int32_t *)p);
-#endif
-#endif
-}
-
-static __inline uint64_t mdbx_atomic_add64(volatile uint64_t *p, uint64_t v) {
-#if !defined(__cplusplus) && defined(ATOMIC_VAR_INIT)
- assert(atomic_is_lock_free(p));
- return atomic_fetch_add((_Atomic uint64_t *)p, v);
-#elif defined(__GNUC__) || defined(__clang__)
- return __sync_fetch_and_add(p, v);
-#else
-#ifdef _MSC_VER
- return _InterlockedExchangeAdd64((volatile int64_t *)p, v);
-#endif
-#ifdef __APPLE__
- return OSAtomicAdd64(v, (volatile int64_t *)p);
-#endif
-#endif
-}
-
-#define mdbx_atomic_sub32(p, v) mdbx_atomic_add32(p, 0 - (v))
-#define mdbx_atomic_sub64(p, v) mdbx_atomic_add64(p, 0 - (v))
-
-static __inline bool mdbx_atomic_compare_and_swap32(volatile uint32_t *p,
- uint32_t c, uint32_t v) {
-#if !defined(__cplusplus) && defined(ATOMIC_VAR_INIT)
- assert(atomic_is_lock_free(p));
- return atomic_compare_exchange_strong((_Atomic uint32_t *)p, &c, v);
-#elif defined(__GNUC__) || defined(__clang__)
- return __sync_bool_compare_and_swap(p, c, v);
-#else
-#ifdef _MSC_VER
- return c == _InterlockedCompareExchange(p, v, c);
-#endif
-#ifdef __APPLE__
- return c == OSAtomicCompareAndSwap32Barrier(c, v, (volatile int32_t *)p);
-#endif
-#endif
-}
-
-static __inline bool mdbx_atomic_compare_and_swap64(volatile uint64_t *p,
- uint64_t c, uint64_t v) {
-#if !defined(__cplusplus) && defined(ATOMIC_VAR_INIT)
- assert(atomic_is_lock_free(p));
- return atomic_compare_exchange_strong((_Atomic uint64_t *)p, &c, v);
-#elif defined(__GNUC__) || defined(__clang__)
- return __sync_bool_compare_and_swap(p, c, v);
-#else
-#ifdef _MSC_VER
- return c == _InterlockedCompareExchange64((volatile int64_t *)p, v, c);
-#endif
-#ifdef __APPLE__
- return c == OSAtomicCompareAndSwap64Barrier(c, v, (volatile uint64_t *)p);
-#endif
-#endif
-}
-
-/*----------------------------------------------------------------------------*/
-
-#if defined(_MSC_VER) && _MSC_VER >= 1900 && _MSC_VER < 1920
-/* LY: MSVC 2015/2017 has buggy/inconsistent PRIuPTR/PRIxPTR macros
- * for internal format-args checker. */
-#undef PRIuPTR
-#undef PRIiPTR
-#undef PRIdPTR
-#undef PRIxPTR
-#define PRIuPTR "Iu"
-#define PRIiPTR "Ii"
-#define PRIdPTR "Id"
-#define PRIxPTR "Ix"
-#define PRIuSIZE "zu"
-#define PRIiSIZE "zi"
-#define PRIdSIZE "zd"
-#define PRIxSIZE "zx"
-#endif /* fix PRI*PTR for _MSC_VER */
-
-#ifndef PRIuSIZE
-#define PRIuSIZE PRIuPTR
-#define PRIiSIZE PRIiPTR
-#define PRIdSIZE PRIdPTR
-#define PRIxSIZE PRIxPTR
-#endif /* PRI*SIZE macros for MSVC */
-
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
diff --git a/plugins/Dbx_mdb/src/mdbx/version.c b/plugins/Dbx_mdb/src/mdbx/version.c
deleted file mode 100644
index ef4f99088d..0000000000
--- a/plugins/Dbx_mdb/src/mdbx/version.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
- * and other libmdbx authors: please see AUTHORS file.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "./bits.h"
-
-#if MDBX_VERSION_MAJOR != 0 || MDBX_VERSION_MINOR != 0
-#error "API version mismatch!"
-#endif
-
-#define MDBX_VERSION_RELEASE 0
-#define MDBX_VERSION_REVISION 0
-
-/*LIBMDBX_EXPORTS*/ const mdbx_version_info mdbx_version = {
- MDBX_VERSION_MAJOR,
- MDBX_VERSION_MINOR,
- MDBX_VERSION_RELEASE,
- MDBX_VERSION_REVISION,
- {"@MDBX_GIT_TIMESTAMP@", "@MDBX_GIT_TREE@", "@MDBX_GIT_COMMIT@",
- "@MDBX_GIT_DESCRIBE@"}};
-
-/*LIBMDBX_EXPORTS*/ const mdbx_build_info mdbx_build = {
- "@MDBX_BUILD_TIMESTAMP@", "@MDBX_BUILD_TAGRET@", "@MDBX_BUILD_OPTIONS@",
- "@MDBX_BUILD_COMPILER@", "@MDBX_BUILD_FLAGS@"};
diff --git a/plugins/Dbx_mdb/src/stdafx.h b/plugins/Dbx_mdb/src/stdafx.h
index 93865631ea..ffbcdb8037 100644
--- a/plugins/Dbx_mdb/src/stdafx.h
+++ b/plugins/Dbx_mdb/src/stdafx.h
@@ -44,7 +44,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <m_netlib.h>
#include <m_gui.h>
-#include "mdbx/mdbx.h"
+#include "libmdbx/mdbx.h"
#ifndef thread_local
# define thread_local __declspec(thread)
diff --git a/plugins/Dbx_mdb/src/version.h b/plugins/Dbx_mdb/src/version.h
index 49ab4f5196..503addec53 100644
--- a/plugins/Dbx_mdb/src/version.h
+++ b/plugins/Dbx_mdb/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Dbx_mdb.dll"
#define __DESCRIPTION "Provides Miranda database support: global settings, contacts, history, settings per contact."
#define __AUTHOR "Miranda-NG project"
-#define __AUTHOREMAIL "ghazan@miranda.im"
#define __AUTHORWEB "https://miranda-ng.org/p/Dbx_mdb/"
#define __COPYRIGHT "© 2015-17 Miranda NG project"
diff --git a/plugins/Exchange/src/exchange.cpp b/plugins/Exchange/src/exchange.cpp
index 57ac5f3fe0..0a0ef5f291 100644
--- a/plugins/Exchange/src/exchange.cpp
+++ b/plugins/Exchange/src/exchange.cpp
@@ -34,7 +34,6 @@ PLUGININFOEX pluginInfo = {
__VERSION_DWORD,
__DESC,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Exchange/src/version.h b/plugins/Exchange/src/version.h
index 036b0e6996..f57f11dcec 100644
--- a/plugins/Exchange/src/version.h
+++ b/plugins/Exchange/src/version.h
@@ -30,7 +30,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define __DESC "Notifies you if you have unread email on an exchange server."
#define __AUTHOR "Cristian Libotean, Attila Vajda, MaKaR (NG)"
-#define __AUTHOREMAIL "makar@poczta.of.pl"
#define __COPYRIGHT "© 2006-2013 Cristian Libotean and Attila Vajda"
#define __AUTHORWEB "https://miranda-ng.org/p/Exchange/"
diff --git a/plugins/FTPFileYM/src/ftpfile.cpp b/plugins/FTPFileYM/src/ftpfile.cpp
index bc4d4dc996..0d81de53f0 100644
--- a/plugins/FTPFileYM/src/ftpfile.cpp
+++ b/plugins/FTPFileYM/src/ftpfile.cpp
@@ -43,7 +43,6 @@ static PLUGININFOEX pluginInfoEx =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/FTPFileYM/src/version.h b/plugins/FTPFileYM/src/version.h
index ea36fb539f..c551742f77 100644
--- a/plugins/FTPFileYM/src/version.h
+++ b/plugins/FTPFileYM/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "FTPFile.dll"
#define __DESCRIPTION "FTP a file to a server and send the URL to your friend. Supported automatic zipping before upload and encryption via SFTP and FTPS."
#define __AUTHOR "yaho"
-#define __AUTHOREMAIL "yaho@miranda-easy.net"
#define __AUTHORWEB "https://miranda-ng.org/p/FTPFile/"
#define __COPYRIGHT "© 2007-2010 Jan Holub"
diff --git a/plugins/FavContacts/src/main.cpp b/plugins/FavContacts/src/main.cpp
index 04d429a82b..149a9527ad 100644
--- a/plugins/FavContacts/src/main.cpp
+++ b/plugins/FavContacts/src/main.cpp
@@ -34,7 +34,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/FavContacts/src/version.h b/plugins/FavContacts/src/version.h
index 057d4f6502..56b78919f1 100644
--- a/plugins/FavContacts/src/version.h
+++ b/plugins/FavContacts/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "FavContacts.dll"
#define __DESCRIPTION "Favorite contacts menu."
#define __AUTHOR "Victor Pavlychko"
-#define __AUTHOREMAIL "nullbie@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/FavContacts/"
#define __COPYRIGHT "© 2007-2009 Victor Pavlychko"
diff --git a/protocols/AimOscar/proto_aim/Proto_AIM.vcxproj b/plugins/FileAsMessage/fileecho.vcxproj
index a37a52b7e8..f06261bfeb 100644
--- a/protocols/AimOscar/proto_aim/Proto_AIM.vcxproj
+++ b/plugins/FileAsMessage/fileecho.vcxproj
@@ -1,28 +1,33 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectName>Proto_AIM</ProjectName>
- <ProjectGuid>{975505EA-F0C7-4DAC-A95E-75249615F30C}</ProjectGuid>
- </PropertyGroup>
- <ImportGroup Label="PropertySheets">
- <Import Project="$(ProjectDir)..\..\..\build\vc.common\icons.props" />
- </ImportGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}</ProjectGuid>
+ <ProjectName>FileAsMessage</ProjectName>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(ProjectDir)..\..\build\vc.common\plugin.props" />
+ </ImportGroup>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
</Project> \ No newline at end of file
diff --git a/plugins/FileAsMessage/fileecho.vcxproj.filters b/plugins/FileAsMessage/fileecho.vcxproj.filters
new file mode 100644
index 0000000000..fcae13a9d8
--- /dev/null
+++ b/plugins/FileAsMessage/fileecho.vcxproj.filters
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(ProjectDir)..\..\build\vc.common\common.filters" />
+</Project> \ No newline at end of file
diff --git a/plugins/FileAsMessage/fileecho_15.vcxproj b/plugins/FileAsMessage/fileecho_15.vcxproj
deleted file mode 100644
index ad58b889c1..0000000000
--- a/plugins/FileAsMessage/fileecho_15.vcxproj
+++ /dev/null
@@ -1,213 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectName>FileAsMessage</ProjectName>
- <ProjectGuid>{D7A3B8D0-425A-2286-8E2F-2C0BF1EE5C2E}</ProjectGuid>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v141_xp</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v141_xp</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v141_xp</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v141_xp</PlatformToolset>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup>
- <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
- <IgnoreImportLibrary>true</IgnoreImportLibrary>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <Optimization>Full</Optimization>
- <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
- <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
- <StringPooling>true</StringPooling>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <WarningLevel>Level4</WarningLevel>
- <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
- <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <ExceptionHandling>false</ExceptionHandling>
- <PrecompiledHeader>Use</PrecompiledHeader>
- <PrecompiledHeaderFile>main.h</PrecompiledHeaderFile>
- <AdditionalOptions>/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
- </ClCompile>
- <Link>
- <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- <OptimizeReferences>true</OptimizeReferences>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <SubSystem>Windows</SubSystem>
- <RandomizedBaseAddress>false</RandomizedBaseAddress>
- <AdditionalLibraryDirectories>$(ProfileDir)..\..\libs\win$(PlatformArchitecture)</AdditionalLibraryDirectories>
- </Link>
- <ResourceCompile>
- <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
- </ResourceCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <ClCompile>
- <Optimization>Full</Optimization>
- <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
- <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <StringPooling>true</StringPooling>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <WarningLevel>Level4</WarningLevel>
- <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
- <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <ExceptionHandling>false</ExceptionHandling>
- <PrecompiledHeader>Use</PrecompiledHeader>
- <PrecompiledHeaderFile>main.h</PrecompiledHeaderFile>
- <AdditionalOptions>/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
- </ClCompile>
- <Link>
- <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- <OptimizeReferences>true</OptimizeReferences>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <SubSystem>Windows</SubSystem>
- <RandomizedBaseAddress>false</RandomizedBaseAddress>
- <AdditionalLibraryDirectories>$(ProfileDir)..\..\libs\win$(PlatformArchitecture)</AdditionalLibraryDirectories>
- </Link>
- <ResourceCompile>
- <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
- </ResourceCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
- <WarningLevel>Level4</WarningLevel>
- <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
- <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <ExceptionHandling>false</ExceptionHandling>
- <PrecompiledHeader>Use</PrecompiledHeader>
- <PrecompiledHeaderFile>main.h</PrecompiledHeaderFile>
- <AdditionalOptions>/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
- </ClCompile>
- <Link>
- <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- <SubSystem>Windows</SubSystem>
- <RandomizedBaseAddress>false</RandomizedBaseAddress>
- <AdditionalLibraryDirectories>$(ProfileDir)..\..\libs\win$(PlatformArchitecture)</AdditionalLibraryDirectories>
- <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
- </Link>
- <ResourceCompile>
- <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
- </ResourceCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
- <WarningLevel>Level4</WarningLevel>
- <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <ExceptionHandling>false</ExceptionHandling>
- <PrecompiledHeader>Use</PrecompiledHeader>
- <PrecompiledHeaderFile>main.h</PrecompiledHeaderFile>
- <AdditionalOptions>/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
- </ClCompile>
- <Link>
- <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- <SubSystem>Windows</SubSystem>
- <RandomizedBaseAddress>false</RandomizedBaseAddress>
- <AdditionalLibraryDirectories>$(ProfileDir)..\..\libs\win$(PlatformArchitecture)</AdditionalLibraryDirectories>
- </Link>
- <ResourceCompile>
- <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
- </ResourceCompile>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="src\crc32.cpp" />
- <ClCompile Include="src\dialog.cpp" />
- <ClCompile Include="src\main.cpp" />
- <ClCompile Include="src\optionsdlg.cpp" />
- <ClCompile Include="src\stdafx.cpp">
- <PrecompiledHeader>Create</PrecompiledHeader>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="src\dialog.h" />
- <ClInclude Include="src\main.h" />
- <ClInclude Include="src\resource.h" />
- <ClInclude Include="src\Version.h" />
- </ItemGroup>
- <ItemGroup>
- <ResourceCompile Include="res\resources.rc" />
- <ResourceCompile Include="res\Version.rc" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project> \ No newline at end of file
diff --git a/plugins/FileAsMessage/fileecho_15.vcxproj.filters b/plugins/FileAsMessage/fileecho_15.vcxproj.filters
deleted file mode 100644
index 3a89d474af..0000000000
--- a/plugins/FileAsMessage/fileecho_15.vcxproj.filters
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <Filter Include="Source Files">
- <UniqueIdentifier>{91cea954-c950-4791-8ce9-443edfb3dabe}</UniqueIdentifier>
- <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
- </Filter>
- <Filter Include="Header Files">
- <UniqueIdentifier>{ea4654ae-48b4-4664-bc0e-c880a231e1f9}</UniqueIdentifier>
- <Extensions>h;hpp;hxx;hm;inl</Extensions>
- </Filter>
- <Filter Include="Resource Files">
- <UniqueIdentifier>{03c6b185-748a-4512-8aeb-8f6b2e4b8024}</UniqueIdentifier>
- <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
- </Filter>
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="src\dialog.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\main.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\optionsdlg.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\crc32.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\stdafx.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="src\dialog.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\main.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\resource.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\Version.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- </ItemGroup>
- <ItemGroup>
- <ResourceCompile Include="res\Version.rc">
- <Filter>Resource Files</Filter>
- </ResourceCompile>
- <ResourceCompile Include="res\resources.rc">
- <Filter>Resource Files</Filter>
- </ResourceCompile>
- </ItemGroup>
-</Project> \ No newline at end of file
diff --git a/plugins/FileAsMessage/src/crc32.cpp b/plugins/FileAsMessage/src/crc32.cpp
index dc40c1a6fb..9bf7a63d2d 100644
--- a/plugins/FileAsMessage/src/crc32.cpp
+++ b/plugins/FileAsMessage/src/crc32.cpp
@@ -1,4 +1,4 @@
-#include "main.h"
+#include "stdafx.h"
const ulong CRCPoly = 0xEDB88320;
ulong CRC32Table[256];
diff --git a/plugins/FileAsMessage/src/dialog.cpp b/plugins/FileAsMessage/src/dialog.cpp
index 36fbd38780..e935b2204e 100644
--- a/plugins/FileAsMessage/src/dialog.cpp
+++ b/plugins/FileAsMessage/src/dialog.cpp
@@ -1,4 +1,4 @@
-#include"main.h"
+#include "stdafx.h"
char *szFEMode[] =
{
@@ -9,18 +9,15 @@ char *szFEMode[] =
char* ltoax(char* s, DWORD value)
{
if (value == 0)
- {
*s++ = '0';
- }
+
uchar data;
int indx = 8;
- while (indx && !(data = (uchar)(value >> 28) & 0x0F))
- {
+ while (indx && !(data = (uchar)(value >> 28) & 0x0F)) {
value <<= 4;
indx--;
}
- while (indx)
- {
+ while (indx) {
data = (uchar)(value >> 28) & 0x0F;
if (data > 9) data += 'A' - 10;
else data += '0';
@@ -30,15 +27,14 @@ char* ltoax(char* s, DWORD value)
}
return s;
}
+
uint atolx(char* &value)
{
uint result = 0;
uchar ch;
- while (*value && (ch = *value - '0') >= 0)
- {
- if (ch > 9)
- {
+ while (*value && (ch = *value - '0') >= 0) {
+ if (ch > 9) {
ch -= 'A' - '0';
if (ch > 5) break;
ch += 10;
@@ -69,19 +65,18 @@ static LRESULT CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPA
switch (message) {
case WM_COMMAND:
- {
- PUDeletePopup(hWnd);
- pcli->pfnRemoveEvent(hContact, 0);
-
- if (IsWindow(hDlg))
{
- ShowWindow(hDlg, SW_SHOWNORMAL);
- SetForegroundWindow(hDlg);
- SetFocus(hDlg);
- }
+ PUDeletePopup(hWnd);
+ pcli->pfnRemoveEvent(hContact, 0);
- break;
- }
+ if (IsWindow(hDlg)) {
+ ShowWindow(hDlg, SW_SHOWNORMAL);
+ SetForegroundWindow(hDlg);
+ SetFocus(hDlg);
+ }
+
+ break;
+ }
case WM_CONTEXTMENU:
PUDeletePopup(hWnd);
break;
@@ -92,58 +87,56 @@ static LRESULT CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPA
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
-//
+
+/////////////////////////////////////////////////////////////////////////////////////////
// Just create simple Popup for specified contact
-//
-void MakePopupMsg(HWND hDlg, MCONTACT hContact, char *msg)
+
+void MakePopupMsg(HWND hDlg, MCONTACT hContact, wchar_t *msg)
{
HWND hFocused = GetForegroundWindow();
if (hDlg == hFocused || hDlg == GetParent(hFocused)) return;
- //
- //The text for the second line. You could even make something like: char lpzText[128]; mir_wstrcpy(lpzText, "Hello world!"); It's your choice.
- //
- POPUPDATA ppd = { 0 };
+ POPUPDATAW ppd = { 0 };
ppd.lchContact = hContact;
ppd.lchIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_SMALLICON));
- mir_strcpy(ppd.lpzContactName, _T2A(pcli->pfnGetContactDisplayName(hContact, 0)));
- mir_strcpy(ppd.lpzText, msg);
+ mir_wstrcpy(ppd.lpwzContactName, pcli->pfnGetContactDisplayName(hContact, 0));
+ mir_wstrcpy(ppd.lpwzText, msg);
ppd.colorBack = GetSysColor(COLOR_INFOBK);
ppd.colorText = GetSysColor(COLOR_INFOTEXT);
ppd.PluginWindowProc = PopupDlgProc;
ppd.PluginData = (void*)hDlg;
ppd.iSeconds = -1;
- PUAddPopup(&ppd);
+ PUAddPopupW(&ppd);
}
-//
+
+/////////////////////////////////////////////////////////////////////////////////////////
// Get ID of string message
-//
+
int getMsgId(char *msg)
{
for (int indx = 0; indx < CMD_COUNT; indx++)
- {
- if (*msg == cCmdList[indx]) return indx;
- }
+ if (*msg == cCmdList[indx])
+ return indx;
+
return -1;
};
-int RetrieveFileSize(char *filename)
+int RetrieveFileSize(wchar_t *filename)
{
- int handle = open(filename, O_RDONLY | O_BINARY, 0);
- if (handle != -1)
- {
- int size = filelength(handle);
- close(handle);
+ FILE *hFile = _wfopen(filename, L"rb");
+ if (hFile != NULL) {
+ fseek(hFile, 0, SEEK_END);
+ int size = ftell(hFile);
+ fclose(hFile);
return size;
}
- return handle;
+ return 0;
}
FILEECHO::FILEECHO(MCONTACT Contact)
{
hContact = Contact;
dwSendInterval = db_get_dw(NULL, SERVICE_NAME, "SendDelay", 6000);
- //dwChunkSize = db_get_dw(NULL, SERVICE_NAME, "ChunkSize", 5000);
chunkMaxLen = db_get_dw(NULL, SERVICE_NAME, "ChunkSize", 5000);
chunkCount = 0;
@@ -162,26 +155,10 @@ uint controlEnabled[][2] =
STATE_OPERATE | STATE_PAUSED | STATE_PRERECV | STATE_ACKREQ | STATE_IDLE,
IDC_STOP,
STATE_OPERATE | STATE_PAUSED | STATE_PRERECV | STATE_REQSENT | STATE_ACKREQ,
- // IDC_FILENAME,
- // STATE_IDLE|STATE_PRERECV|STATE_FINISHED|STATE_CANCELLED,
- // IDC_BROWSE,
- // STATE_IDLE|STATE_PRERECV|STATE_FINISHED|STATE_CANCELLED,
-};
-/*
-char *stateMsg[][2] =
-{
-(char*)STATE_IDLE,"Idle",
-(char*)STATE_REQSENT,"ReqSent",
-(char*)STATE_PRERECV,"PreRecv",
-(char*)STATE_OPERATE,"Operate",
-(char*)STATE_ACKREQ,"AckReq",
-(char*)STATE_CANCELLED,"Canceled",
-(char*)STATE_FINISHED,"Finished",
-(char*)STATE_PAUSED,"Paused"
};
-*/
-char *hint_controls[4] = {
+char *hint_controls[4] =
+{
"Perform",
"Pause",
"Revive a transfer",
@@ -191,21 +168,16 @@ char *hint_controls[4] = {
void FILEECHO::setState(DWORD state)
{
iState = state;
- int indx;
- for (indx = 0; indx < _countof(controlEnabled); indx++)
- {
+ for (int indx = 0; indx < _countof(controlEnabled); indx++)
EnableWindow(GetDlgItem(hDlg, controlEnabled[indx][0]), (iState & controlEnabled[indx][1]) != 0);
- }
- if (!inSend) // recv
- {
+ if (!inSend) {
+ // recv
int kind;
SendDlgItemMessage(hDlg, IDC_FILENAME, EM_SETREADONLY, (state != STATE_PRERECV), 0);
EnableWindow(GetDlgItem(hDlg, IDC_BROWSE), (iState & (STATE_PRERECV | STATE_FINISHED)));
- //SendDlgItemMessage(hDlg, IDC_FILENAME, EM_SETREADONLY, (iState & STATE_PRERECV) == 0, 0);
- //EnableWindow(GetDlgItem(hDlg, IDC_FILENAME), (iState == STATE_PRERECV));
- //EnableWindow(GetDlgItem(hDlg, IDC_FILENAME), (iState & STATE_IDLE|STATE_PRERECV|STATE_FINISHED|STATE_CANCELLED) != 0);
+
if (state & (STATE_IDLE | STATE_FINISHED | STATE_CANCELLED | STATE_PRERECV))
kind = ICON_PLAY;
else
@@ -213,13 +185,11 @@ void FILEECHO::setState(DWORD state)
SendDlgItemMessage(hDlg, IDC_PLAY, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcons[kind]);
SendDlgItemMessage(hDlg, IDC_PLAY, BUTTONADDTOOLTIP, (WPARAM)Translate(hint_controls[kind]), 0);
}
- else
- {
+ else {
SendDlgItemMessage(hDlg, IDC_FILENAME, EM_SETREADONLY, (iState & (STATE_IDLE | STATE_FINISHED | STATE_CANCELLED)) == 0, 0);
EnableWindow(GetDlgItem(hDlg, IDC_BROWSE), (iState & (STATE_IDLE | STATE_FINISHED | STATE_CANCELLED)) != 0);
- //EnableWindow(GetDlgItem(hDlg, IDC_FILENAME), (iState & STATE_IDLE|STATE_PRERECV|STATE_FINISHED|STATE_CANCELLED) != 0);
- switch (state)
- {
+
+ switch (state) {
case STATE_FINISHED:
case STATE_CANCELLED:
case STATE_IDLE:
@@ -246,7 +216,7 @@ void FILEECHO::updateTitle()
mir_snprintf(newtitle, "%d%% - %s: %s", chunkSent * 100 / chunkCount, Translate(szFEMode[inSend]), contactName);
else
mir_snprintf(newtitle, "%s: %s", Translate(szFEMode[inSend]), contactName);
- SetWindowText(hDlg, newtitle);
+ SetWindowTextA(hDlg, newtitle);
}
void BuildFreqTable(uchar *data, uint len, uint *freqTable)
@@ -267,58 +237,49 @@ int FILEECHO::createTransfer()
#endif
BYTE bAuto = db_get_b(NULL, "SRFile", "AutoAccept", 0);
- hFile = CreateFile(filename, inSend ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE), inSend ? FILE_SHARE_READ : 0, nullptr, inSend ? OPEN_EXISTING : (bAuto ? CREATE_ALWAYS : CREATE_NEW), FILE_ATTRIBUTE_NORMAL, nullptr);
- if (hFile == INVALID_HANDLE_VALUE && !inSend && GetLastError() == ERROR_FILE_EXISTS)
- {
- if (MessageBox(hDlg, Translate("File already exists. Overwrite?"),
- Translate(SERVICE_TITLE),
+ hFile = CreateFileA(filename, inSend ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE), inSend ? FILE_SHARE_READ : 0, nullptr, inSend ? OPEN_EXISTING : (bAuto ? CREATE_ALWAYS : CREATE_NEW), FILE_ATTRIBUTE_NORMAL, nullptr);
+ if (hFile == INVALID_HANDLE_VALUE && !inSend && GetLastError() == ERROR_FILE_EXISTS) {
+ if (MessageBox(hDlg, TranslateT("File already exists. Overwrite?"),
+ TranslateT(SERVICE_TITLE),
MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) != IDYES) return 0;
- hFile = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 0,
+ hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0,
nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
}
- if (hFile == INVALID_HANDLE_VALUE) goto createTransfer_FAILED;
- if (!inSend)
- {
+ if (hFile == INVALID_HANDLE_VALUE)
+ goto createTransfer_FAILED;
+
+ if (!inSend) {
SetFilePointer(hFile, fileSize, nullptr, FILE_BEGIN);
SetEndOfFile(hFile);
}
- else
- fileSize = GetFileSize(hFile, nullptr);
- hMapping = CreateFileMapping(hFile, nullptr, inSend ? PAGE_READONLY : PAGE_READWRITE,
- 0, fileSize, nullptr);
+ else fileSize = GetFileSize(hFile, nullptr);
+
+ hMapping = CreateFileMapping(hFile, nullptr, inSend ? PAGE_READONLY : PAGE_READWRITE, 0, fileSize, nullptr);
LastError = GetLastError();
- if (hMapping == nullptr) goto createTransfer_FAILED;
+ if (hMapping == nullptr)
+ goto createTransfer_FAILED;
+
lpData = (uchar*)MapViewOfFile(hMapping, inSend ? FILE_MAP_READ : FILE_MAP_WRITE, 0, 0, 0);
LastError = GetLastError();
- if (lpData == nullptr) goto createTransfer_FAILED;
+ if (lpData == nullptr)
+ goto createTransfer_FAILED;
- if (inSend)
- //
- // frequency analysis of source file
- // and building the table of offsets
- //
- {
- if (asBinary)
- {
+ if (inSend) {
+ // frequency analysis of source file and building the table of offsets
+ if (asBinary) {
uint freq_table[256] = { 0 };
codeSymb = 1;
- //
+
// searching for symbol with lowest frequency: "codeSymb"
- //
BuildFreqTable(lpData, fileSize, freq_table);
- for (uint i = codeSymb + 1; i < 256; ++i)
- {
+ for (uint i = codeSymb + 1; i < 256; ++i) {
if (freq_table[codeSymb] > freq_table[i])
codeSymb = i;
}
- //DEBUG
- //codeSymb = ':';
- //
// calculating chunks sizes
// build table of chunks offsets: chunkPos
- //
uint chunk_count_limit = 2 * fileSize / chunkMaxLen + 2;
chunkPos = (uint*)calloc(chunk_count_limit, sizeof(uint));
@@ -328,16 +289,14 @@ int FILEECHO::createTransfer()
uint indx = 0;
uint chunk_offset = 0;
- for (uint len = fileSize; len; --len)
- {
+ for (uint len = fileSize; len; --len) {
if (*data == 0 || *data == codeSymb)
out_size += 2;
else
++out_size;
data++; chunk_size++;
- if (out_size >= chunkMaxLen - 1)
- {
+ if (out_size >= chunkMaxLen - 1) {
chunkPos[indx] = chunk_offset;
chunk_offset += chunk_size;
chunk_size = 0; out_size = 0;
@@ -348,8 +307,7 @@ int FILEECHO::createTransfer()
chunkPos = (uint*)realloc(chunkPos, sizeof(uint)*(chunkCount + 1));
chunkPos[indx] = chunk_offset + chunk_size;
}
- else
- {
+ else {
int EncodedMaxLen = Netlib_GetBase64EncodedBufferSize(Netlib_GetBase64DecodedBufferSize(chunkMaxLen));
int DecodedMaxLen = Netlib_GetBase64DecodedBufferSize(EncodedMaxLen);
@@ -358,21 +316,19 @@ int FILEECHO::createTransfer()
chunkPos = (uint*)calloc(chunkCount + 1, sizeof(uint));
uint i = 0;
- for (uint chunk_offset = 0; i < chunkCount; ++i, chunk_offset += DecodedMaxLen)
- {
+ for (uint chunk_offset = 0; i < chunkCount; ++i, chunk_offset += DecodedMaxLen) {
chunkPos[i] = chunk_offset;
}
chunkPos[i] = chunkPos[i - 1] + (fileSize % DecodedMaxLen);
}
}
- else
- chunkCount = chunkCountx;
+ else chunkCount = chunkCountx;
chunkAck = (uchar*)calloc(chunkCount, sizeof(uchar));
chunkIndx = 0; chunkSent = 0;
-
return 1;
+
createTransfer_FAILED:
if (lpData != nullptr) UnmapViewOfFile(lpData);
if (hMapping != nullptr) CloseHandle(hMapping);
@@ -382,8 +338,7 @@ createTransfer_FAILED:
void FILEECHO::destroyTransfer()
{
- if (chunkCount)
- {
+ if (chunkCount) {
chunkCount = 0;
if (inSend)
free(chunkPos);
@@ -392,19 +347,17 @@ void FILEECHO::destroyTransfer()
if (hMapping != nullptr) CloseHandle(hMapping);
if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
}
- //setState(STATE_IDLE);
- return;
}
void FILEECHO::sendReq()
{
char sendbuf[MAX_PATH];
- if (!createTransfer())
- {
- SetDlgItemText(hDlg, IDC_FILESIZE, Translate("Couldn't open a file"));
+ if (!createTransfer()) {
+ SetDlgItemText(hDlg, IDC_FILESIZE, TranslateT("Couldn't open a file"));
return;
}
+
///!!!!!!!
char *p = filename + mir_strlen(filename);
while (p != filename && *p != '\\')
@@ -413,11 +366,11 @@ void FILEECHO::sendReq()
mir_strcpy(filename, p + 1);
mir_snprintf(sendbuf, Translate("Size: %d bytes"), fileSize);
- SetDlgItemText(hDlg, IDC_FILESIZE, sendbuf);
+ SetDlgItemTextA(hDlg, IDC_FILESIZE, sendbuf);
mir_snprintf(sendbuf, "?%c%c%d:%d \n" NOPLUGIN_MESSAGE, asBinary + '0', codeSymb, chunkCount, fileSize);
sendCmd(0, CMD_REQ, sendbuf, filename);
- SetDlgItemText(hDlg, IDC_STATUS, Translate("Request sent. Awaiting of acceptance.."));
+ SetDlgItemText(hDlg, IDC_STATUS, TranslateT("Request sent. Awaiting of acceptance.."));
setState(STATE_REQSENT);
}
@@ -444,16 +397,15 @@ void FILEECHO::incomeRequest(char *param)
fileSize = atoi(param);
mir_snprintf(buf, Translate("Size: %d bytes"), fileSize);
- SetDlgItemText(hDlg, IDC_FILENAME, filename);
- SetDlgItemText(hDlg, IDC_FILESIZE, buf);
+ SetDlgItemTextA(hDlg, IDC_FILENAME, filename);
+ SetDlgItemTextA(hDlg, IDC_FILESIZE, buf);
setState(STATE_PRERECV);
inSend = FALSE;
Skin_PlaySound("RecvFile");
int AutoMin = db_get_b(NULL, "SRFile", "AutoMin", 0);
- if (db_get_b(NULL, "SRFile", "AutoAccept", 0) && !db_get_b(hContact, "CList", "NotOnList", 0))
- {
+ if (db_get_b(NULL, "SRFile", "AutoAccept", 0) && !db_get_b(hContact, "CList", "NotOnList", 0)) {
PostMessage(hDlg, WM_COMMAND, IDC_PLAY, 0);
if (AutoMin)
ShowWindow(hDlg, SW_SHOWMINIMIZED);
@@ -461,8 +413,7 @@ void FILEECHO::incomeRequest(char *param)
// UpdateWindow(hDlg);
}
// else
- if (!IsWindowVisible(hDlg) && !AutoMin)
- {
+ if (!IsWindowVisible(hDlg) && !AutoMin) {
CLISTEVENT cle = {};
cle.hContact = hContact;
cle.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_SMALLICON));
@@ -471,7 +422,7 @@ void FILEECHO::incomeRequest(char *param)
cle.pszService = SERVICE_NAME "/FERecvFile";
pcli->pfnAddEvent(&cle);
- MakePopupMsg(hDlg, hContact, "Incoming file...");
+ MakePopupMsg(hDlg, hContact, L"Incoming file...");
}
}
@@ -479,10 +430,9 @@ void FILEECHO::cmdACCEPT()
{
if (chunkCount == 0) return;
setState(STATE_OPERATE);
- SetDlgItemText(hDlg, IDC_STATUS, Translate("Sending..."));
+ SetDlgItemText(hDlg, IDC_STATUS, TranslateT("Sending..."));
lastTimestamp = GetTickCount();
- //PostMessage(hDlg, WM_TIMER, 0,0);
- //onSendTimer();
+
SetTimer(hDlg, TIMER_SEND, dwSendInterval, nullptr);
}
@@ -491,10 +441,11 @@ void FILEECHO::updateProgress()
InvalidateRect(GetDlgItem(hDlg, IDC_PROGRESS), nullptr, TRUE);
updateTitle();
}
-//
+
+/////////////////////////////////////////////////////////////////////////////////////////
// called in receive mode
// used to transfer acknowledge
-//
+
void FILEECHO::onRecvTimer()
{
if (chunkCount == 0) return;
@@ -504,19 +455,14 @@ void FILEECHO::onRecvTimer()
uint indx, jndx;
KillTimer(hDlg, TIMER_SEND);
- //
+
// Build response about successfully received chunks
- //
indx = jndx = 0; prev_value = chunkAck[jndx];
- while (jndx < chunkCount)
- {
- if (chunkAck[jndx] != prev_value)
- {
- if (prev_value != CHUNK_ACK)
- {
+ while (jndx < chunkCount) {
+ if (chunkAck[jndx] != prev_value) {
+ if (prev_value != CHUNK_ACK) {
p = ltoax(p, indx);
- if (indx != jndx - 1)
- {
+ if (indx != jndx - 1) {
*p++ = '-';
p = ltoax(p, jndx - 1);
}
@@ -527,24 +473,20 @@ void FILEECHO::onRecvTimer()
}
jndx++;
}
- if (prev_value != CHUNK_ACK)
- {
+ if (prev_value != CHUNK_ACK) {
p = ltoax(p, indx);
- if (indx != jndx - 1)
- {
+ if (indx != jndx - 1) {
*p++ = '-';
p = ltoax(p, jndx - 1);
}
}
*p = 0;
- if (*buffer == 0)
- {
- char *msg = Translate("Received successfully");
+ if (*buffer == 0) {
+ wchar_t *msg = TranslateT("Received successfully");
SetDlgItemText(hDlg, IDC_STATUS, msg);
MakePopupMsg(hDlg, hContact, msg);
setState(STATE_FINISHED);
- if (db_get_b(NULL, "SRFile", "AutoClose", 0))
- {
+ if (db_get_b(NULL, "SRFile", "AutoClose", 0)) {
PostMessage(hDlg, WM_CLOSE, 0, 0);
pcli->pfnRemoveEvent(hContact, 0);
}
@@ -554,27 +496,24 @@ void FILEECHO::onRecvTimer()
}
sendCmd(0, CMD_DACK, buffer);
free(buffer);
- //if(iState != STATE_FINISHED) SetTimer(hDlg, TIMER_SEND, lastDelay*2, 0);
}
-//
+
+/////////////////////////////////////////////////////////////////////////////////////////
// called in sending mode
// used to data transfer and
// sending of scheduled commands
-//
+
void FILEECHO::onSendTimer()
{
if (chunkCount == 0) return;
- //
+
// perform request of acknowledge, if scheduled
- //
KillTimer(hDlg, TIMER_SEND);
- //
+
// Search for next unsent chunk
- //
while (chunkIndx < chunkCount && chunkAck[chunkIndx] != CHUNK_UNSENT) chunkIndx++;
- if (iState == STATE_ACKREQ || chunkIndx == chunkCount)
- {
- SetDlgItemText(hDlg, IDC_STATUS, Translate("Requesting of missing chunks"));
+ if (iState == STATE_ACKREQ || chunkIndx == chunkCount) {
+ SetDlgItemText(hDlg, IDC_STATUS, TranslateT("Requesting of missing chunks"));
setState(STATE_OPERATE);
sendCmd(0, CMD_END, "", nullptr);
chunkIndx = chunkCount + 1;
@@ -588,20 +527,14 @@ void FILEECHO::onSendTimer()
uchar *data_end = lpData + chunkPos[chunkIndx + 1];
ulong chksum = memcrc32(data, data_end - data, INITCRC);
- if (asBinary)
- {
- //
+ if (asBinary) {
// Encoding data to transfer with symb. filtering
- //
- while (data < data_end)
- {
+ while (data < data_end) {
uchar ch = *data++;
- if (ch == 0)
- {
+ if (ch == 0) {
*p++ = codeSymb; *p++ = '0';
}
- else if (ch == codeSymb)
- {
+ else if (ch == codeSymb) {
*p++ = codeSymb; *p++ = '+';
}
else
@@ -609,8 +542,7 @@ void FILEECHO::onSendTimer()
}
*p = 0;
}
- else
- {
+ else {
ptrA enc(mir_base64_encode(data, data_end - data));
mir_strncpy((char*)buffer, enc, chunkMaxLen * 2);
}
@@ -618,7 +550,7 @@ void FILEECHO::onSendTimer()
char prefix[128];
mir_snprintf(prefix, "%X,%X,%X>", chunkIndx + 1, chunkPos[chunkIndx], chksum);
#ifdef DEBUG
- overhead += mir_wstrlen((char*)buffer);
+ overhead += mir_strlen((char*)buffer);
#endif
sendCmd(0, CMD_DATA, (char*)buffer, (char*)prefix);
chunkAck[chunkIndx] = CHUNK_SENT;
@@ -629,13 +561,13 @@ void FILEECHO::onSendTimer()
if (chunkIndx == chunkCount)
setState(STATE_ACKREQ);
- else
- {
- SetDlgItemText(hDlg, IDC_STATUS, Translate("Sending..."));
+ else {
+ SetDlgItemText(hDlg, IDC_STATUS, TranslateT("Sending..."));
updateProgress();
}
SetTimer(hDlg, TIMER_SEND, dwSendInterval, nullptr);
}
+
void FILEECHO::cmdDATA(char *param)
{
if (chunkCount == 0) return;
@@ -649,21 +581,17 @@ void FILEECHO::cmdDATA(char *param)
KillTimer(hDlg, TIMER_SEND);
- //
// Decoding of incoming data
- //
uchar *data = lpData + filepos;
uchar *data_end = lpData + fileSize;
- if (asBinary)
- {
+ if (asBinary) {
uchar ch;
- while (ch = *param++)
- {
- if (ch == codeSymb)
- {
- if ((ch = *param++) == 0) goto cmdDATA_corrupted;
- switch (ch)
- {
+ while (ch = *param++) {
+ if (ch == codeSymb) {
+ if ((ch = *param++) == 0)
+ return;
+
+ switch (ch) {
case '+':
ch = codeSymb;
break;
@@ -671,52 +599,46 @@ void FILEECHO::cmdDATA(char *param)
ch = 0;
break;
default:
- goto cmdDATA_corrupted;
+ return;
}
}
- if (data > data_end) goto cmdDATA_corrupted;
+ if (data > data_end)
+ return;
*data++ = ch;
}
}
- else
- {
- unsigned bufLen;
+ else {
+ size_t bufLen;
mir_ptr<BYTE> buf((BYTE*)mir_base64_decode(param, &bufLen));
memcpy(data, buf, min(bufLen, unsigned(data_end - data)));
data += bufLen;
}
- //
+
// let's check it up
- //
chksum_local = memcrc32(lpData + filepos, data - (lpData + filepos), INITCRC);
- if (chksum_local == chksum_remote)
- {
+ if (chksum_local == chksum_remote) {
if (chunkAck[chunkIndx] != CHUNK_ACK) chunkSent++;
chunkAck[chunkIndx] = CHUNK_ACK;
- //chunkPos[chunkIndx++] = filepos;
}
- SetDlgItemText(hDlg, IDC_STATUS, Translate("Receiving..."));
+ SetDlgItemText(hDlg, IDC_STATUS, TranslateT("Receiving..."));
updateProgress();
-cmdDATA_corrupted:
- //SetTimer(hDlg, TIMER_SEND, lastDelay*2, 0);
- ;
}
+
void FILEECHO::cmdEND()
{
SetTimer(hDlg, TIMER_SEND, dwSendInterval, nullptr);
}
+
void FILEECHO::cmdDACK(char *param)
{
uint indx, jndx;
if (chunkCount == 0) return;
memset(chunkAck, CHUNK_ACK, sizeof(uchar)*chunkCount);
- if (*param == 'x')
- //
- // All chunks has been received successfully
- //
- {
- char *msg = Translate("Sent successfully");
+
+ // All chunks has been received successfully
+ if (*param == 'x') {
+ wchar_t *msg = TranslateT("Sent successfully");
SetDlgItemText(hDlg, IDC_STATUS, msg);
Skin_PlaySound("FileDone");
@@ -726,27 +648,22 @@ void FILEECHO::cmdDACK(char *param)
return;
}
chunkSent = chunkCount;
- //
+
// Mark chunks to re-transfer,
// according received info
//
// format: chunk1, chunk3-chunk10, etc..
- //
- while (*param)
- {
+
+ while (*param) {
indx = atolx(param);
- if (*param == '-')
- {
+ if (*param == '-') {
param++; jndx = atolx(param);
}
- else
- jndx = indx;
- if (*param == 0 || *param == ',')
- {
- for (uint p = indx; p <= jndx; p++)
- {
- if (p < chunkCount)
- {
+ else jndx = indx;
+
+ if (*param == 0 || *param == ',') {
+ for (uint p = indx; p <= jndx; p++) {
+ if (p < chunkCount) {
chunkAck[p] = CHUNK_UNSENT;
chunkSent--;
}
@@ -757,9 +674,7 @@ void FILEECHO::cmdDACK(char *param)
}
updateProgress();
- //
// retransfer some parts
- //
chunkIndx = 0;
SetTimer(hDlg, TIMER_SEND, dwSendInterval, nullptr);
}
@@ -767,19 +682,16 @@ void FILEECHO::cmdDACK(char *param)
void FILEECHO::perform(char *str)
{
int msgId = getMsgId(str);
- if (msgId == -1)
- {
- MakePopupMsg(hDlg, hContact, Translate("Unknown command for \"File As Message\" was received"));
+ if (msgId == -1) {
+ MakePopupMsg(hDlg, hContact, TranslateT("Unknown command for \"File As Message\" was received"));
return;
}
if (inSend)
- switch (msgId)
- {
+ switch (msgId) {
case CMD_REQ:
- if (MessageBox(hDlg, Translate("Incoming file request. Do you want to proceed?"),
- Translate(SERVICE_TITLE), MB_YESNO | MB_ICONWARNING) == IDYES)
- {
- SetDlgItemText(hDlg, IDC_STATUS, "");
+ if (MessageBox(hDlg, TranslateT("Incoming file request. Do you want to proceed?"),
+ TranslateT(SERVICE_TITLE), MB_YESNO | MB_ICONWARNING) == IDYES) {
+ SetDlgItemText(hDlg, IDC_STATUS, L"");
SendMessage(hDlg, WM_COMMAND, IDC_STOP, 0);
incomeRequest(str + 1);
@@ -791,55 +703,54 @@ void FILEECHO::perform(char *str)
cmdACCEPT();
break;
case CMD_CANCEL:
- {
- if (iState & (STATE_PRERECV | STATE_REQSENT | STATE_OPERATE | STATE_ACKREQ | STATE_PAUSED))
{
- char *msg = Translate("Canceled by remote user");
- SetDlgItemText(hDlg, IDC_STATUS, msg);
- MakePopupMsg(hDlg, hContact, msg);
- destroyTransfer();
- setState(STATE_CANCELLED);
+ if (iState & (STATE_PRERECV | STATE_REQSENT | STATE_OPERATE | STATE_ACKREQ | STATE_PAUSED)) {
+ wchar_t *msg = TranslateT("Canceled by remote user");
+ SetDlgItemText(hDlg, IDC_STATUS, msg);
+ MakePopupMsg(hDlg, hContact, msg);
+ destroyTransfer();
+ setState(STATE_CANCELLED);
+ }
+ break;
}
- break;
- }
case CMD_DACK:
cmdDACK(str + 1);
break;
- }
+ }
else
- switch (msgId)
- {
+ switch (msgId) {
case CMD_CANCEL:
- {
- if (iState & (STATE_PRERECV | STATE_REQSENT | STATE_OPERATE | STATE_ACKREQ | STATE_PAUSED))
{
- char *msg = Translate("Canceled by remote user");
- SetDlgItemText(hDlg, IDC_STATUS, msg);
- MakePopupMsg(hDlg, hContact, msg);
- destroyTransfer();
- setState(STATE_CANCELLED);
+ if (iState & (STATE_PRERECV | STATE_REQSENT | STATE_OPERATE | STATE_ACKREQ | STATE_PAUSED)) {
+ wchar_t *msg = TranslateT("Canceled by remote user");
+ SetDlgItemText(hDlg, IDC_STATUS, msg);
+ MakePopupMsg(hDlg, hContact, msg);
+ destroyTransfer();
+ setState(STATE_CANCELLED);
+ }
+ break;
}
- break;
- }
+
case CMD_REQ:
- if (chunkCount)
- {
- if (MessageBox(hDlg, Translate("New incoming file request. Do you want to proceed?"),
- Translate(SERVICE_TITLE), MB_YESNO | MB_ICONWARNING) != IDYES)
+ if (chunkCount) {
+ if (MessageBox(hDlg, TranslateT("New incoming file request. Do you want to proceed?"),
+ TranslateT(SERVICE_TITLE), MB_YESNO | MB_ICONWARNING) != IDYES)
break;
//sendCmd(0, CMD_CANCEL, "", NULL);
destroyTransfer();
}
- SetDlgItemText(hDlg, IDC_STATUS, "");
+ SetDlgItemText(hDlg, IDC_STATUS, L"");
incomeRequest(str + 1);
break;
+
case CMD_DATA:
cmdDATA(str + 1);
break;
+
case CMD_END:
cmdEND();
break;
- };
+ };
};
int FILEECHO::sendCmd(int, int cmd, char *szParam, char *szPrefix)
@@ -861,137 +772,102 @@ int FILEECHO::sendCmd(int, int cmd, char *szParam, char *szPrefix)
}
-void CreateDirectoryTree(char *szDir)
-{
- DWORD dwAttributes;
- char *pszLastBackslash, szTestDir[MAX_PATH];
-
- mir_strncpy(szTestDir, szDir, _countof(szTestDir));
- if ((dwAttributes = GetFileAttributes(szTestDir)) != 0xffffffff && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
- return;
- pszLastBackslash = strrchr(szTestDir, '\\');
- if (pszLastBackslash == nullptr) {
- GetCurrentDirectory(MAX_PATH, szDir);
- return;
- }
- *pszLastBackslash = 0;
- CreateDirectoryTree(szTestDir);
- CreateDirectory(szTestDir, nullptr);
-}
-
LRESULT CALLBACK ProgressWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
- switch (uMsg)
- {
+ switch (uMsg) {
case WM_NCPAINT:
return 0;
+
case WM_PAINT:
- {
- HDC hdc;
- PAINTSTRUCT ps;
- RECT rc;
- HRGN hrgn;
- HBRUSH frameBrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
- struct FILEECHO *dat;
-
- dat = (struct FILEECHO*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA);
- //if(dat == NULL)
- // return CallSubclassed(hwnd, uMsg, wParam, lParam);
- GetClientRect(hwnd, &rc);
- if (dat == nullptr || dat->chunkCount == 0)
{
- COLORREF colour;
- HBRUSH hbr;
-
- if (dat == nullptr || dat->iState != STATE_FINISHED)
- {
- hbr = (HBRUSH)(COLOR_3DFACE + 1);
- }
- else
- {
- colour = dat->rgbRecv;
- hbr = CreateSolidBrush(colour);
+ HDC hdc;
+ PAINTSTRUCT ps;
+ RECT rc;
+ HRGN hrgn;
+ HBRUSH frameBrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ FILEECHO *dat = (FILEECHO*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA);
+
+ GetClientRect(hwnd, &rc);
+ if (dat == nullptr || dat->chunkCount == 0) {
+ COLORREF colour;
+ HBRUSH hbr;
+
+ if (dat == nullptr || dat->iState != STATE_FINISHED) {
+ hbr = (HBRUSH)(COLOR_3DFACE + 1);
+ }
+ else {
+ colour = dat->rgbRecv;
+ hbr = CreateSolidBrush(colour);
+ }
+ hdc = BeginPaint(hwnd, &ps);
+ FillRect(hdc, &rc, hbr);
+ FrameRect(hdc, &rc, frameBrush);
+ if (hbr != (HBRUSH)(COLOR_3DFACE + 1))
+ DeleteObject(hbr);
+ EndPaint(hwnd, &ps);
+ return 0;
}
+
+ hrgn = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
+
hdc = BeginPaint(hwnd, &ps);
- FillRect(hdc, &rc, hbr);
- FrameRect(hdc, &rc, frameBrush);
- if (hbr != (HBRUSH)(COLOR_3DFACE + 1))
+ SelectClipRgn(hdc, hrgn);
+
+ RECT rc2 = rc;
+ float sliceWidth = (float)((float)(rc.right - rc.left) / (float)dat->chunkCount);
+ float dx = (float)rc2.left;
+ for (uint indx = 0; indx < dat->chunkCount; indx++) {
+ HBRUSH hbr;
+ COLORREF colour = 0;
+ if (dat->inSend && indx == dat->chunkIndx)
+ colour = dat->rgbToSend;
+ else
+ switch (dat->chunkAck[indx]) {
+ case CHUNK_UNSENT:
+ colour = dat->rgbUnSent;
+ break;
+ case CHUNK_SENT:
+ colour = dat->rgbSent;
+ break;
+ case CHUNK_ACK:
+ colour = dat->rgbRecv;
+ break;
+ }
+ hbr = CreateSolidBrush(colour);
+ rc2.left = (int)dx;
+ rc2.right = (int)(dx + sliceWidth);
+ FillRect(hdc, &rc2, hbr);
+ FrameRect(hdc, &rc2, frameBrush);
DeleteObject(hbr);
+ dx += sliceWidth - 1;
+ }
+ if (rc2.right < rc.right) {
+ rc2.left = rc2.right;
+ rc2.right = rc.right;
+ FillRect(hdc, &rc2, (HBRUSH)(COLOR_3DFACE + 1));
+ }
EndPaint(hwnd, &ps);
- return 0;
- }
-
- hrgn = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
-
- hdc = BeginPaint(hwnd, &ps);
- SelectClipRgn(hdc, hrgn);
- RECT rc2 = rc;
- //uint sliceWidth = (rc.right - rc.left) / dat->chunkCount;
- float sliceWidth = (float)((float)(rc.right - rc.left) / (float)dat->chunkCount);
- float dx = (float)rc2.left;
- for (uint indx = 0; indx < dat->chunkCount; indx++)
- {
- HBRUSH hbr;
- COLORREF colour = 0;
- if (dat->inSend && indx == dat->chunkIndx)
- colour = dat->rgbToSend;
- else
- switch (dat->chunkAck[indx])
- {
- case CHUNK_UNSENT:
- colour = dat->rgbUnSent;
- break;
- case CHUNK_SENT:
- colour = dat->rgbSent;
- break;
- case CHUNK_ACK:
- colour = dat->rgbRecv;
- break;
- }
- hbr = CreateSolidBrush(colour);
- rc2.left = (int)dx;
- rc2.right = (int)(dx + sliceWidth);
- FillRect(hdc, &rc2, hbr);
- FrameRect(hdc, &rc2, frameBrush);
- DeleteObject(hbr);
- dx += sliceWidth - 1;
- }
- if (rc2.right < rc.right)
- {
- rc2.left = rc2.right;
- rc2.right = rc.right;
- FillRect(hdc, &rc2, (HBRUSH)(COLOR_3DFACE + 1));
+ DeleteObject(hrgn);
+ return 0;
}
- //FrameRect(hdc, &rc, (HBRUSH)(COLOR_3DLIGHT+1));
- //OffsetRect(&rc, 1,1);
- //FrameRect(hdc, &rc, (HBRUSH)(COLOR_BTNTEXT+1));
- //FrameRect(hdc, &rc, (HBRUSH)(COLOR_BTNTEXT+1));
- EndPaint(hwnd, &ps);
-
- DeleteObject(hrgn);
-
- return 0;
- }
}
return mir_callNextSubclass(hwnd, ProgressWndProc, uMsg, wParam, lParam);
}
INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
- struct FILEECHO *dat = (struct FILEECHO*)GetWindowLongPtr(hDlg, GWLP_USERDATA);
+ FILEECHO *dat = (FILEECHO*)GetWindowLongPtr(hDlg, GWLP_USERDATA);
HWND hwndStatus = nullptr;
- switch (uMsg)
- {
+ switch (uMsg) {
case WM_INITDIALOG:
TranslateDialogDefault(hDlg);
- {
+
dat = (FILEECHO*)lParam;
dat->hDlg = hDlg;
-
dat->updateTitle();
- hwndStatus = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hDlg, IDC_STATUS);
+ hwndStatus = CreateStatusWindow(WS_CHILD | WS_VISIBLE, L"", hDlg, IDC_STATUS);
SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)dat);
WindowList_Add(hFileList, hDlg, dat->hContact);
Window_SetIcon_IcoLib(hDlg, iconList[ICON_MAIN].hIcolib);
@@ -1007,56 +883,49 @@ INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
if (dat->inSend)
PostMessage(hDlg, WM_COMMAND, IDC_BROWSE, NULL);
-
return FALSE;
- }
+
case WM_FE_MESSAGE:
- {
dat->perform((char *)lParam);
delete (char *)lParam;
-
return TRUE;
- }
+
case WM_FE_SKINCHANGE:
Window_SetIcon_IcoLib(hDlg, iconList[ICON_MAIN].hIcolib);
dat->setState(dat->iState);
SendDlgItemMessage(hDlg, IDC_STOP, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcons[ICON_STOP]);
break;
+
case WM_FE_STATUSCHANGE:
- {
- char *szProto = GetContactProto(dat->hContact);
- if (szProto)
{
- int dwStatus = db_get_w(dat->hContact, szProto, "Status", ID_STATUS_OFFLINE);
- if (dat->inSend && dwStatus != dat->contactStatus)
- {
- if (dat->contactStatus == ID_STATUS_OFFLINE)
- {
- dat->chunkIndx = dat->chunkCount;
- }
- else
- if (dwStatus == ID_STATUS_OFFLINE)
- {
- if (dat->iState & (STATE_OPERATE | STATE_ACKREQ))
- {
- char *msg = Translate("File transfer is paused because of dropped connection");
- SetDlgItemText(hDlg, IDC_STATUS, msg);
- MakePopupMsg(dat->hDlg, dat->hContact, msg);
- dat->setState(STATE_PAUSED);
- KillTimer(hDlg, TIMER_SEND);
- }
+ char *szProto = GetContactProto(dat->hContact);
+ if (szProto) {
+ int dwStatus = db_get_w(dat->hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ if (dat->inSend && dwStatus != dat->contactStatus) {
+ if (dat->contactStatus == ID_STATUS_OFFLINE) {
+ dat->chunkIndx = dat->chunkCount;
}
+ else
+ if (dwStatus == ID_STATUS_OFFLINE) {
+ if (dat->iState & (STATE_OPERATE | STATE_ACKREQ)) {
+ wchar_t *msg = TranslateT("File transfer is paused because of dropped connection");
+ SetDlgItemText(hDlg, IDC_STATUS, msg);
+ MakePopupMsg(dat->hDlg, dat->hContact, msg);
+ dat->setState(STATE_PAUSED);
+ KillTimer(hDlg, TIMER_SEND);
+ }
+ }
+ }
+ dat->contactStatus = dwStatus;
}
- dat->contactStatus = dwStatus;
}
return TRUE;
- }
+
case WM_DESTROY:
WindowList_Remove(hFileList, hDlg);
DestroyWindow(hwndStatus);
delete dat;
-
return TRUE;
case WM_TIMER:
@@ -1065,121 +934,106 @@ INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
else
dat->onRecvTimer();
break;
+
case WM_COMMAND:
- switch (wParam)
- {
+ switch (wParam) {
case IDC_PLAY:
- {
- if (dat->iState & (STATE_IDLE | STATE_FINISHED | STATE_CANCELLED | STATE_PRERECV))
- {
- int len = GetWindowTextLength(GetDlgItem(hDlg, IDC_FILENAME)) + 1;
- free(dat->filename);
- dat->filename = (char*)malloc(len);
- GetDlgItemText(hDlg, IDC_FILENAME, dat->filename, len);
- if (dat->inSend)
- // Send offer to remote side
- {
- dat->sendReq();
- }
- else
- // Send the accept and starting to receive
- {
- char buff[MAX_PATH];
- char *bufname;
-
- GetFullPathName(dat->filename, sizeof(buff), buff, &bufname);
- *bufname = 0;
- CreateDirectoryTree(buff);
- if (!dat->createTransfer())
- {
- SetDlgItemText(hDlg, IDC_STATUS, Translate("Failed on file initialization"));
- break;
- }
- dat->sendCmd(0, CMD_ACCEPT, "");
- dat->lastTimestamp = GetTickCount();
- SetDlgItemText(hDlg, IDC_STATUS, Translate("Receiving..."));
- dat->setState(STATE_OPERATE);
- }
- }
- else
{
- if (dat->inSend)
- {
- if (dat->iState == STATE_OPERATE)
+ if (dat->iState & (STATE_IDLE | STATE_FINISHED | STATE_CANCELLED | STATE_PRERECV)) {
+ int len = GetWindowTextLength(GetDlgItem(hDlg, IDC_FILENAME)) + 1;
+ free(dat->filename);
+ dat->filename = (char*)malloc(len);
+ GetDlgItemTextA(hDlg, IDC_FILENAME, dat->filename, len);
+ if (dat->inSend)
+ // Send offer to remote side
{
- SetDlgItemText(hDlg, IDC_STATUS, Translate("Paused..."));
- dat->setState(STATE_PAUSED);
- KillTimer(hDlg, TIMER_SEND);
+ dat->sendReq();
}
else
+ // Send the accept and starting to receive
{
- SetDlgItemText(hDlg, IDC_STATUS, Translate("Sending..."));
- if (dat->chunkIndx < dat->chunkCount)
- dat->setState(STATE_OPERATE);
- else
- dat->setState(STATE_ACKREQ);
- PostMessage(hDlg, WM_TIMER, 0, 0);
- //dat->onRecvTimer();
- //SetTimer(hDlg, TIMER_SEND, dwSendInterval, NULL);
+ char buff[MAX_PATH];
+ char *bufname;
+
+ GetFullPathNameA(dat->filename, sizeof(buff), buff, &bufname);
+ *bufname = 0;
+ CreateDirectoryTree(buff);
+ if (!dat->createTransfer()) {
+ SetDlgItemText(hDlg, IDC_STATUS, TranslateT("Failed on file initialization"));
+ break;
+ }
+ dat->sendCmd(0, CMD_ACCEPT, "");
+ dat->lastTimestamp = GetTickCount();
+ SetDlgItemText(hDlg, IDC_STATUS, TranslateT("Receiving..."));
+ dat->setState(STATE_OPERATE);
}
}
- else
- {
- SetDlgItemText(hDlg, IDC_STATUS, Translate("Synchronizing..."));
- dat->setState(STATE_ACKREQ);
- PostMessage(hDlg, WM_TIMER, 0, 0);
- //dat->onRecvTimer();
- //SetTimer(hDlg, TIMER_SEND, dwSendInterval, 0);
+ else {
+ if (dat->inSend) {
+ if (dat->iState == STATE_OPERATE) {
+ SetDlgItemText(hDlg, IDC_STATUS, TranslateT("Paused..."));
+ dat->setState(STATE_PAUSED);
+ KillTimer(hDlg, TIMER_SEND);
+ }
+ else {
+ SetDlgItemText(hDlg, IDC_STATUS, TranslateT("Sending..."));
+ if (dat->chunkIndx < dat->chunkCount)
+ dat->setState(STATE_OPERATE);
+ else
+ dat->setState(STATE_ACKREQ);
+ PostMessage(hDlg, WM_TIMER, 0, 0);
+ }
+ }
+ else {
+ SetDlgItemText(hDlg, IDC_STATUS, TranslateT("Synchronizing..."));
+ dat->setState(STATE_ACKREQ);
+ PostMessage(hDlg, WM_TIMER, 0, 0);
+ }
+ break;
}
- break;
}
break;
- }
+
case IDC_BROWSE:
- {
- char str[MAX_PATH];
- OPENFILENAME ofn;
-
- memset(&ofn, 0, sizeof(ofn));
- *str = 0;
- GetDlgItemText(hDlg, IDC_FILENAME, str, _countof(str));
- //ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
- ofn.lStructSize = sizeof(ofn);
- ofn.hwndOwner = hDlg;
- //ofn.lpstrFilter = "*.*";
- ofn.lpstrFile = str;
- ofn.Flags = dat->inSend ? OFN_FILEMUSTEXIST : 0;
- ofn.lpstrTitle = dat->inSend ? Translate("Select a file") : Translate("Save as");
- ofn.nMaxFile = _countof(str);
- ofn.nMaxFileTitle = MAX_PATH;
- if (!GetOpenFileName(&ofn)) break;
- if (!dat->inSend && dat->iState == STATE_FINISHED) break;
- SetDlgItemText(hDlg, IDC_FILENAME, str);
-
- int size = RetrieveFileSize(str);
- if (size != -1)
- mir_snprintf(str, Translate("Size: %d bytes"), size);
- else
- mir_strncpy(str, Translate("Can't get a file size"), _countof(str));
- SetDlgItemText(hDlg, IDC_FILESIZE, str);
+ {
+ wchar_t str[MAX_PATH]; *str = 0;
+ GetDlgItemText(hDlg, IDC_FILENAME, str, _countof(str));
+
+ OPENFILENAME ofn = {};
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = hDlg;
+ ofn.lpstrFile = str;
+ ofn.Flags = dat->inSend ? OFN_FILEMUSTEXIST : 0;
+ ofn.lpstrTitle = dat->inSend ? TranslateT("Select a file") : TranslateT("Save as");
+ ofn.nMaxFile = _countof(str);
+ ofn.nMaxFileTitle = MAX_PATH;
+ if (!GetOpenFileName(&ofn))
+ break;
+ if (!dat->inSend && dat->iState == STATE_FINISHED)
+ break;
+
+ SetDlgItemText(hDlg, IDC_FILENAME, str);
+ int size = RetrieveFileSize(str);
+ if (size != -1)
+ mir_snwprintf(str, TranslateT("Size: %d bytes"), size);
+ else
+ mir_wstrncpy(str, TranslateT("Can't get a file size"), _countof(str));
+ SetDlgItemText(hDlg, IDC_FILESIZE, str);
+ }
break;
- }
case IDC_STOP:
case IDCANCEL:
- if (dat->iState == STATE_PRERECV)
- {
- SetDlgItemText(hDlg, IDC_STATUS, Translate("Canceled by user"));
+ if (dat->iState == STATE_PRERECV) {
+ SetDlgItemText(hDlg, IDC_STATUS, TranslateT("Canceled by user"));
dat->sendCmd(0, CMD_CANCEL, "", nullptr);
dat->setState(STATE_CANCELLED);
}
- if (dat->chunkCount)
- {
- if (MessageBox(hDlg, Translate("Transfer is in progress. Do you really want to close?"),
- Translate(SERVICE_TITLE), MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2) == IDYES)
- {
- SetDlgItemText(hDlg, IDC_STATUS, Translate("Canceled by user"));
+ if (dat->chunkCount) {
+ if (MessageBox(hDlg, TranslateT("Transfer is in progress. Do you really want to close?"),
+ TranslateT(SERVICE_TITLE), MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2) == IDYES) {
+ SetDlgItemText(hDlg, IDC_STATUS, TranslateT("Canceled by user"));
dat->setState(STATE_CANCELLED);
dat->sendCmd(0, CMD_CANCEL, "", nullptr);
dat->destroyTransfer();
@@ -1187,10 +1041,9 @@ INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
DestroyWindow(hDlg);
}
}
- else
- if (wParam == IDCANCEL)
- DestroyWindow(hDlg);
- break;//return TRUE;
+ else if (wParam == IDCANCEL)
+ DestroyWindow(hDlg);
+ break;
}
break;
}
diff --git a/plugins/FileAsMessage/src/main.cpp b/plugins/FileAsMessage/src/main.cpp
index 594e95e395..092e6cc6f0 100644
--- a/plugins/FileAsMessage/src/main.cpp
+++ b/plugins/FileAsMessage/src/main.cpp
@@ -1,4 +1,4 @@
-#include "main.h"
+#include "stdafx.h"
PLUGININFOEX pluginInfo =
{
@@ -7,7 +7,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/FileAsMessage/src/optionsdlg.cpp b/plugins/FileAsMessage/src/optionsdlg.cpp
index 519e5287ee..c889e3cf95 100644
--- a/plugins/FileAsMessage/src/optionsdlg.cpp
+++ b/plugins/FileAsMessage/src/optionsdlg.cpp
@@ -1,4 +1,4 @@
-#include "main.h"
+#include "stdafx.h"
DWORD settingDefault[] =
{
diff --git a/plugins/FileAsMessage/src/stdafx.cpp b/plugins/FileAsMessage/src/stdafx.cpp
deleted file mode 100644
index 5cc77ed966..0000000000
--- a/plugins/FileAsMessage/src/stdafx.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
-Copyright (C) 2012-17 Miranda NG project (https://miranda-ng.org)
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation version 2
-of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "main.h" \ No newline at end of file
diff --git a/plugins/FileAsMessage/src/stdafx.cxx b/plugins/FileAsMessage/src/stdafx.cxx
new file mode 100644
index 0000000000..fd4f341c7b
--- /dev/null
+++ b/plugins/FileAsMessage/src/stdafx.cxx
@@ -0,0 +1 @@
+#include "stdafx.h"
diff --git a/plugins/FileAsMessage/src/main.h b/plugins/FileAsMessage/src/stdafx.h
index a2130ee940..af2ed0eda7 100644
--- a/plugins/FileAsMessage/src/main.h
+++ b/plugins/FileAsMessage/src/stdafx.h
@@ -1,51 +1,50 @@
-#define _CRT_SECURE_NO_WARNINGS
-#define _CRT_NONSTDC_NO_DEPRECATE
-
-#include <windows.h>
-#include <io.h>
-#include <fcntl.h>
-#include <commctrl.h>
-
-#include <newpluginapi.h>
-#include <m_database.h>
-#include <m_protosvc.h>
-#include <m_langpack.h>
-#include <m_clist.h>
-#include <m_options.h>
-#include <m_skin.h>
-#include <m_popup.h>
-#include <m_icolib.h>
-#include <m_button.h>
-#include <m_netlib.h>
-#include <m_file.h>
-#include <win2k.h>
-
-#include "dialog.h"
-#include "resource.h"
-#include "version.h"
-
-#define MAXBUFSIZE 4096
-#define SERVICE_TITLE LPGEN("File As Message")
-#define SERVICE_NAME "FileAsMessage"
-
-#define SERVICE_PREFIX "<%fAM-0023%>"
-
-#define NOPLUGIN_MESSAGE "If you see this \"garbage\", probably you have no \"fileAsMessage\" plugin installed, see https://miranda-ng.org/p/FileAsMessage/ for more information and download."
-
-extern char *szServiceTitle;
-extern char *szServicePrefix;
-extern const ulong INITCRC;
-
-#define WM_FE_MESSAGE WM_USER+100
-#define WM_FE_STATUSCHANGE WM_USER+101
-#define WM_FE_SKINCHANGE WM_USER+102
-
-extern HINSTANCE hInst;
-extern MWindowList hFileList;
-extern HANDLE hEventNewFile;
-
-extern HICON hIcons[5];
-extern IconItem iconList[];
-
-ulong memcrc32(uchar *ptr, int size, ulong crc);
-INT_PTR CALLBACK OptionsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+#define _CRT_NONSTDC_NO_DEPRECATE
+
+#include <windows.h>
+#include <io.h>
+#include <fcntl.h>
+#include <commctrl.h>
+
+#include <newpluginapi.h>
+#include <m_database.h>
+#include <m_protosvc.h>
+#include <m_langpack.h>
+#include <m_clist.h>
+#include <m_options.h>
+#include <m_skin.h>
+#include <m_popup.h>
+#include <m_icolib.h>
+#include <m_button.h>
+#include <m_netlib.h>
+#include <m_file.h>
+#include <win2k.h>
+
+#include "dialog.h"
+#include "resource.h"
+#include "version.h"
+
+#define MAXBUFSIZE 4096
+#define SERVICE_TITLE LPGEN("File As Message")
+#define SERVICE_NAME "FileAsMessage"
+
+#define SERVICE_PREFIX "<%fAM-0023%>"
+
+#define NOPLUGIN_MESSAGE "If you see this \"garbage\", probably you have no \"fileAsMessage\" plugin installed, see https://miranda-ng.org/p/FileAsMessage/ for more information and download."
+
+extern char *szServiceTitle;
+extern char *szServicePrefix;
+extern const ulong INITCRC;
+
+#define WM_FE_MESSAGE WM_USER+100
+#define WM_FE_STATUSCHANGE WM_USER+101
+#define WM_FE_SKINCHANGE WM_USER+102
+
+extern HINSTANCE hInst;
+extern MWindowList hFileList;
+extern HANDLE hEventNewFile;
+
+extern HICON hIcons[5];
+extern IconItem iconList[];
+
+ulong memcrc32(uchar *ptr, int size, ulong crc);
+INT_PTR CALLBACK OptionsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
diff --git a/plugins/FileAsMessage/src/version.h b/plugins/FileAsMessage/src/version.h
index ddb306b2f3..9f7a5f8488 100644
--- a/plugins/FileAsMessage/src/version.h
+++ b/plugins/FileAsMessage/src/version.h
@@ -1,14 +1,13 @@
-#define __MAJOR_VERSION 0
-#define __MINOR_VERSION 0
-#define __RELEASE_NUM 2
-#define __BUILD_NUM 4
+#define __MAJOR_VERSION 0
+#define __MINOR_VERSION 1
+#define __RELEASE_NUM 0
+#define __BUILD_NUM 1
#include <stdver.h>
#define __PLUGIN_NAME "File as message"
#define __FILENAME "FileAsMessage.dll"
-#define __DESCRIPTION "File transfer by using the messaging services - as plain text."
-#define __AUTHOR "Denis Stanishevskiy"
-#define __AUTHOREMAIL "stdenformiranda@fromru.com"
-#define __AUTHORWEB "https://miranda-ng.org/p/FileAsMessage/"
-#define __COPYRIGHT "© 2004 Denis Stanishevskiy"
+#define __DESCRIPTION "File transfer by using the messaging services - as plain text."
+#define __AUTHOR "Denis Stanishevskiy"
+#define __AUTHORWEB "https://miranda-ng.org/p/FileAsMessage/"
+#define __COPYRIGHT "© 2004 Denis Stanishevskiy"
diff --git a/plugins/FingerprintNG/iconpacks/res/AIM/AIM_6.x.ico b/plugins/FingerprintNG/iconpacks/res/AIM/AIM_6.x.ico
deleted file mode 100644
index 7676f25d65..0000000000
--- a/plugins/FingerprintNG/iconpacks/res/AIM/AIM_6.x.ico
+++ /dev/null
Binary files differ
diff --git a/plugins/FingerprintNG/iconpacks/res/AIM/AIM_7.x.ico b/plugins/FingerprintNG/iconpacks/res/AIM/AIM_7.x.ico
deleted file mode 100644
index 4e8ccf5377..0000000000
--- a/plugins/FingerprintNG/iconpacks/res/AIM/AIM_7.x.ico
+++ /dev/null
Binary files differ
diff --git a/plugins/FingerprintNG/iconpacks/res/AIM/AIM_Mac.ico b/plugins/FingerprintNG/iconpacks/res/AIM/AIM_Mac.ico
deleted file mode 100644
index 7f69db2598..0000000000
--- a/plugins/FingerprintNG/iconpacks/res/AIM/AIM_Mac.ico
+++ /dev/null
Binary files differ
diff --git a/plugins/FingerprintNG/iconpacks/res/AIM/AIM_Mobile.ico b/plugins/FingerprintNG/iconpacks/res/AIM/AIM_Mobile.ico
deleted file mode 100644
index 00bd08b486..0000000000
--- a/plugins/FingerprintNG/iconpacks/res/AIM/AIM_Mobile.ico
+++ /dev/null
Binary files differ
diff --git a/plugins/FingerprintNG/iconpacks/res/AIM/AIM_Triton.ico b/plugins/FingerprintNG/iconpacks/res/AIM/AIM_Triton.ico
deleted file mode 100644
index a211a49df0..0000000000
--- a/plugins/FingerprintNG/iconpacks/res/AIM/AIM_Triton.ico
+++ /dev/null
Binary files differ
diff --git a/plugins/FingerprintNG/iconpacks/res/AIM/TerraIM.ico b/plugins/FingerprintNG/iconpacks/res/AIM/TerraIM.ico
deleted file mode 100644
index ce9b610cc7..0000000000
--- a/plugins/FingerprintNG/iconpacks/res/AIM/TerraIM.ico
+++ /dev/null
Binary files differ
diff --git a/plugins/FingerprintNG/iconpacks/res/AIM/miniaim.ico b/plugins/FingerprintNG/iconpacks/res/AIM/miniaim.ico
deleted file mode 100644
index 8268b726ff..0000000000
--- a/plugins/FingerprintNG/iconpacks/res/AIM/miniaim.ico
+++ /dev/null
Binary files differ
diff --git a/plugins/FingerprintNG/iconpacks/res/AIM/naim.ico b/plugins/FingerprintNG/iconpacks/res/AIM/naim.ico
deleted file mode 100644
index 0a8d916cfe..0000000000
--- a/plugins/FingerprintNG/iconpacks/res/AIM/naim.ico
+++ /dev/null
Binary files differ
diff --git a/plugins/FingerprintNG/iconpacks/res/Jabber/PyAIMt.ico b/plugins/FingerprintNG/iconpacks/res/Jabber/PyAIMt.ico
deleted file mode 100644
index e5e4db6c9a..0000000000
--- a/plugins/FingerprintNG/iconpacks/res/Jabber/PyAIMt.ico
+++ /dev/null
Binary files differ
diff --git a/plugins/FingerprintNG/iconpacks/res/Overlays/overlay_proto_AIM.ico b/plugins/FingerprintNG/iconpacks/res/Overlays/overlay_proto_AIM.ico
deleted file mode 100644
index e1b38aab85..0000000000
--- a/plugins/FingerprintNG/iconpacks/res/Overlays/overlay_proto_AIM.ico
+++ /dev/null
Binary files differ
diff --git a/plugins/FingerprintNG/iconpacks/res/fp_icons.rc b/plugins/FingerprintNG/iconpacks/res/fp_icons.rc
index 498d408065..0ce62fdc09 100644
--- a/plugins/FingerprintNG/iconpacks/res/fp_icons.rc
+++ b/plugins/FingerprintNG/iconpacks/res/fp_icons.rc
@@ -395,14 +395,6 @@ IDI_ICQ5_OVERLAY ICON "ICQ\\overlay_ICQ_v5.ico"
IDI_ICQ6_OVERLAY ICON "ICQ\\overlay_ICQ_v6.ico"
IDI_ICQ7_OVERLAY ICON "ICQ\\overlay_ICQ_v7.ico"
IDI_ICQ8_OVERLAY ICON "ICQ\\overlay_ICQ_v8.ico"
-IDI_AIM_6 ICON "AIM\\AIM_6.x.ico"
-IDI_AIM_7 ICON "AIM\\AIM_7.x.ico"
-IDI_AIM_MAC ICON "AIM\\AIM_Mac.ico"
-IDI_AIM_MOBILE ICON "AIM\\AIM_Mobile.ico"
-IDI_AIM_TRITON ICON "AIM\\AIM_Triton.ico"
-IDI_MINIAIM ICON "AIM\\miniaim.ico"
-IDI_NAIM ICON "AIM\\naim.ico"
-IDI_TERRAIM ICON "AIM\\TerraIM.ico"
IDI_AMIRC ICON "IRC\\AmIRC.ico"
IDI_AMULE ICON "IRC\\aMule.ico"
IDI_BABBEL ICON "IRC\\Babbel.ico"
@@ -543,7 +535,6 @@ IDI_TWITTER ICON "others\\Twitter.ico"
IDI_HANGOUTS ICON "others\\Google+ Hangouts.ico"
IDI_WHATSAPP ICON "others\\WhatsApp.ico"
IDI_STEAM ICON "others\\Steam.ico"
-IDI_AIM_OVERLAY ICON "overlays\\overlay_proto_AIM.ico"
IDI_GMAIL_OVERLAY ICON "overlays\\overlay_proto_Gmail.ico"
IDI_ICQJ_OVERLAY ICON "overlays\\overlay_proto_ICQJ.ico"
IDI_ICQJ_PLUS_OVERLAY ICON "overlays\\overlay_proto_ICQJ_Plus.ico"
diff --git a/plugins/FingerprintNG/res/resource.rc b/plugins/FingerprintNG/res/resource.rc
index 0187107716..59ab77eed4 100644
--- a/plugins/FingerprintNG/res/resource.rc
+++ b/plugins/FingerprintNG/res/resource.rc
@@ -78,7 +78,6 @@ BEGIN
CONTROL "Unicode overlay",IDC_GROUP_OVERLAYS_UNICODE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,60,120,10
CONTROL "Secure overlays",IDC_GROUP_OVERLAYS_SECURITY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,50,140,10
GROUPBOX "Select protocols",IDC_STATIC,15,75,290,140
- CONTROL "AIM clients",IDC_GROUP_AIM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,90,120,10
CONTROL "Gadu-Gadu clients",IDC_GROUP_GG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,100,120,10
CONTROL "ICQ clients",IDC_GROUP_ICQ,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,110,120,10
CONTROL "IRC clients",IDC_GROUP_IRC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,120,120,10
diff --git a/plugins/FingerprintNG/src/finger_groups.h b/plugins/FingerprintNG/src/finger_groups.h
index d0ac9b3b30..10e6bff723 100644
--- a/plugins/FingerprintNG/src/finger_groups.h
+++ b/plugins/FingerprintNG/src/finger_groups.h
@@ -18,11 +18,6 @@ case MULTI_CASE:
return LPGENW("Client icons") L"/" LPGENW("Multi-proto clients");
break;
-case AIM_CASE:
- if (db_get_b(NULL, MODULENAME, "GroupAIM", 1))
- return LPGENW("Client icons") L"/" LPGENW("AIM clients");
- break;
-
case GG_CASE:
if (db_get_b(NULL, MODULENAME, "GroupGG", 1))
return LPGENW("Client icons") L"/" LPGENW("Gadu-Gadu clients");
diff --git a/plugins/FingerprintNG/src/main.cpp b/plugins/FingerprintNG/src/main.cpp
index f8af6c8a48..27c7d41e6f 100644
--- a/plugins/FingerprintNG/src/main.cpp
+++ b/plugins/FingerprintNG/src/main.cpp
@@ -37,7 +37,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/FingerprintNG/src/masks.cpp b/plugins/FingerprintNG/src/masks.cpp
index 52cc5cb5ae..d2a49fca73 100644
--- a/plugins/FingerprintNG/src/masks.cpp
+++ b/plugins/FingerprintNG/src/masks.cpp
@@ -487,20 +487,6 @@ KN_FP_MASK def_kn_fp_mask[] =
{ "client_IRCUnknown", L"*IRC*", L"Unknown IRC client", IDI_IRC, IRC_CASE, TRUE },
//#########################################################################################################################################################################
- //################################# AIM ###############################################################################################################################
- //#########################################################################################################################################################################
- { "client_Aim7", L"AIM*7.*", L"AIM v7.x", IDI_AIM_7, AIM_CASE, TRUE },
- { "client_Aim6", L"AIM*6.*", L"AIM v6.x", IDI_AIM_6, AIM_CASE, TRUE },
-
- { "client_AIM_Triton", L"*AIM*Triton*", L"AIM Triton", IDI_AIM_TRITON, AIM_CASE, TRUE },
- { "client_AimMac", L"AIM*Mac*", L"AIM for MacOS", IDI_AIM_MAC, AIM_CASE, TRUE },
- { "client_AimMobile", L"|AIM*Mobile*|AIM*gprs*|Aim*sms*", L"AIM Mobile", IDI_AIM_MOBILE, AIM_CASE, TRUE },
- { "client_Naim", L"*naim*", L"Naim", IDI_NAIM, AIM_CASE, TRUE },
- { "client_miniaim", L"*miniaim*", L"miniaim", IDI_MINIAIM, AIM_CASE, TRUE },
- { "client_TerraIM", L"*Terra*", L"TerraIM", IDI_TERRAIM, AIM_CASE, TRUE },
- { "client_AIM", L"AIM*", L"AIM", IDI_AIM_7, AIM_CASE, TRUE },
-
- //#########################################################################################################################################################################
//################################# MSN ###############################################################################################################################
//#########################################################################################################################################################################
{ "client_WLM11", L"WLM*2011*", L"Windows Live 11", IDI_WLM_10, MSN_CASE, TRUE },
@@ -679,7 +665,6 @@ KN_FP_MASK def_kn_fp_overlays_mask[] =
//#########################################################################################################################################################################
//################################# PROTO OVERLAYS ####################################################################################################################
//#########################################################################################################################################################################
- { "client_AIM_overlay", L"|^AIM*|*AIM*", LPGENW("AIM overlay"), IDI_AIM_OVERLAY, OVERLAYS_PROTO_CASE },
{ "client_ICQJ_Plus_over", L"*ICQ*Plus*", LPGENW("ICQJ Plus Mod overlay"), IDI_ICQJ_PLUS_OVERLAY, OVERLAYS_PROTO_CASE },
{ "client_ICQJ_overlay", L"|^ICQ|^ICQ*|*ICQ*|MRA client", LPGENW("ICQJ overlay"), IDI_ICQJ_OVERLAY, OVERLAYS_PROTO_CASE },
{ "client_IRC_overlay", L"|^IRC*|Miranda*IRC*", LPGENW("IRC overlay"), IDI_IRC_OVERLAY, OVERLAYS_PROTO_CASE },
diff --git a/plugins/FingerprintNG/src/options.cpp b/plugins/FingerprintNG/src/options.cpp
index 5ec7b7a793..e6f262d8f2 100644
--- a/plugins/FingerprintNG/src/options.cpp
+++ b/plugins/FingerprintNG/src/options.cpp
@@ -33,7 +33,6 @@ static settings[] =
{ IDC_GROUP_MIRANDA_PACKS, TRUE, "GroupMirandaPacks" },
{ IDC_GROUP_MULTI, TRUE, "GroupMulti" },
- { IDC_GROUP_AIM, TRUE, "GroupAIM" },
{ IDC_GROUP_GG, TRUE, "GroupGG" },
{ IDC_GROUP_ICQ, TRUE, "GroupICQ" },
{ IDC_GROUP_IRC, TRUE, "GroupIRC" },
diff --git a/plugins/FingerprintNG/src/resource.h b/plugins/FingerprintNG/src/resource.h
index 8420af7194..df9580af53 100644
--- a/plugins/FingerprintNG/src/resource.h
+++ b/plugins/FingerprintNG/src/resource.h
@@ -54,7 +54,6 @@
#define IDI_UNICODE_CLIENT 75
#define IDI_PLATFORM_X32 76
#define IDI_PLATFORM_X64 77
-#define IDI_AIM_OVERLAY 78
#define IDI_GMAIL_OVERLAY 79
#define IDI_ICQJ_OVERLAY 80
#define IDI_ICQJ_PLUS_OVERLAY 81
@@ -399,14 +398,6 @@
#define IDI_MAIL_RU_OFFICIAL 702
#define IDI_MAIL_RU_UNKNOWN 703
#define IDI_MAIL_RU_WEBAGENT 704
-#define IDI_AIM_6 714
-#define IDI_AIM_7 715
-#define IDI_AIM_MAC 716
-#define IDI_AIM_MOBILE 717
-#define IDI_AIM_TRITON 718
-#define IDI_MINIAIM 719
-#define IDI_NAIM 720
-#define IDI_TERRAIM 721
#define IDI_GG 724
#define IDI_GG8_OVERLAY 725
#define IDI_GG9_OVERLAY 726
@@ -585,7 +576,6 @@
#define IDC_GROUP_MIRANDA_VERSION 10026
#define IDC_GROUP_MIRANDA_PACKS 10027
#define IDC_GROUP_MULTI 10028
-#define IDC_GROUP_AIM 10029
#define IDC_GROUP_GG 10030
#define IDC_GROUP_ICQ 10032
#define IDC_GROUP_IRC 10033
diff --git a/plugins/FingerprintNG/src/stdafx.h b/plugins/FingerprintNG/src/stdafx.h
index a44ede6da4..08f0b72fa7 100644
--- a/plugins/FingerprintNG/src/stdafx.h
+++ b/plugins/FingerprintNG/src/stdafx.h
@@ -74,7 +74,6 @@ typedef struct _foundInfo
#define MIRANDA_PACKS_CASE 3003 // Miranda packs overlays
#define MULTI_CASE 3004 // multi-protocol clients
-#define AIM_CASE 3005 // AIM clients
#define GG_CASE 3006 // Gadu-Gadu clients
#define ICQ_CASE 3008 // ICQ clients
#define IRC_CASE 3009 // IRC clients
diff --git a/plugins/FingerprintNG/src/version.h b/plugins/FingerprintNG/src/version.h
index 4ee2eaffab..90d47300b8 100644
--- a/plugins/FingerprintNG/src/version.h
+++ b/plugins/FingerprintNG/src/version.h
@@ -28,6 +28,5 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define __FILENAME "Fingerprint.dll"
#define __DESCRIPTION "Fingerprint NG (client version) icons module for Miranda NG."
#define __AUTHOR "faith_healer, ghazan, Mataes"
-#define __AUTHOREMAIL "faith_healer@miranda.im"
#define __AUTHORWEB "https://miranda-ng.org/p/Fingerprint/"
#define __COPYRIGHT "© 2006-17 ghazan, Mataes, HierOS, FYR, Bio, nullbie, faith_healer and all respective contributors."
diff --git a/plugins/FloatingContacts/src/main.cpp b/plugins/FloatingContacts/src/main.cpp
index d840c61e62..fb098b2752 100644
--- a/plugins/FloatingContacts/src/main.cpp
+++ b/plugins/FloatingContacts/src/main.cpp
@@ -96,7 +96,6 @@ PLUGININFOEX pluginInfoEx =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/FloatingContacts/src/version.h b/plugins/FloatingContacts/src/version.h
index 5af00f2c44..fa0d9ca2d2 100644
--- a/plugins/FloatingContacts/src/version.h
+++ b/plugins/FloatingContacts/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "FltContacts.dll"
#define __DESCRIPTION "Floating Contacts plugin for Miranda."
#define __AUTHOR "Iavor Vajarov, Kosh&chka, Victor Pavlychko"
-#define __AUTHOREMAIL "ell-6@ya.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/FloatingContacts/"
#define __COPYRIGHT "© 2002-2004 I. Vajarov (ivajarov@code.bg), 2008 Kosh&chka, V. Pavlychko"
diff --git a/plugins/Folders/src/folders.cpp b/plugins/Folders/src/folders.cpp
index b6d8ded550..512d619ece 100644
--- a/plugins/Folders/src/folders.cpp
+++ b/plugins/Folders/src/folders.cpp
@@ -32,7 +32,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Folders/src/version.h b/plugins/Folders/src/version.h
index 886868da09..bd045b1ebd 100644
--- a/plugins/Folders/src/version.h
+++ b/plugins/Folders/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Folders.dll"
#define __DESCRIPTION "Allows plugins to save their data to user selected folders; supports variables."
#define __AUTHOR "Cristian Libotean, Miranda NG Team"
-#define __AUTHOREMAIL "eblis102@yahoo.com"
#define __AUTHORWEB "https://miranda-ng.org/p/Folders/"
#define __COPYRIGHT "© 2005-2012 Cristian Libotean, 2012-17 Miranda NG Team"
diff --git a/plugins/GmailNotifier/src/check.cpp b/plugins/GmailNotifier/src/check.cpp
index 6bf60cd2c7..0d642a8a42 100644
--- a/plugins/GmailNotifier/src/check.cpp
+++ b/plugins/GmailNotifier/src/check.cpp
@@ -98,7 +98,7 @@ void CheckMailInbox(Account *curAcc)
// go!
CMStringA loginPass(FORMAT, "%s:%s", curAcc->name, curAcc->pass);
- ptrA loginPassEncoded(mir_base64_encode((BYTE*)loginPass.c_str(), loginPass.GetLength()));
+ ptrA loginPassEncoded(mir_base64_encode(loginPass.c_str(), loginPass.GetLength()));
CMStringA szUrl("https://mail.google.com"), szAuth(FORMAT, "Basic %s", loginPassEncoded.get());
if (curAcc->hosted[0])
diff --git a/plugins/GmailNotifier/src/main.cpp b/plugins/GmailNotifier/src/main.cpp
index ff6946fadc..3fc69d130d 100644
--- a/plugins/GmailNotifier/src/main.cpp
+++ b/plugins/GmailNotifier/src/main.cpp
@@ -30,7 +30,6 @@ static PLUGININFOEX pluginInfoEx =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/GmailNotifier/src/version.h b/plugins/GmailNotifier/src/version.h
index 7834d0d829..e75e38a1e6 100644
--- a/plugins/GmailNotifier/src/version.h
+++ b/plugins/GmailNotifier/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "GmailNotifier.dll"
#define __DESCRIPTION "Check your Gmail inboxes locally."
#define __AUTHOR "Mixwind"
-#define __AUTHOREMAIL "mixwind@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/GmailNotifier/"
#define __COPYRIGHT "© 2005 Sun Zhuo"
diff --git a/plugins/HTTPServer/src/main.cpp b/plugins/HTTPServer/src/main.cpp
index 82aca337b6..859806d57e 100644
--- a/plugins/HTTPServer/src/main.cpp
+++ b/plugins/HTTPServer/src/main.cpp
@@ -93,7 +93,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/HTTPServer/src/version.h b/plugins/HTTPServer/src/version.h
index c58cfb21e1..6c93022e1c 100644
--- a/plugins/HTTPServer/src/version.h
+++ b/plugins/HTTPServer/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "HTTPServer.dll"
#define __DESCRIPTION "HTTP Web Server plugin for Miranda."
#define __AUTHOR "Kennet Nielsen, modified by Vampik, Houdini"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/HTTPServer/"
#define __COPYRIGHT "© 2003-2009 Kennet Nielsen, Vampik, Houdini"
diff --git a/plugins/HistoryLinkListPlus/src/linklist.cpp b/plugins/HistoryLinkListPlus/src/linklist.cpp
index 3c8a94d11a..9799c022fa 100644
--- a/plugins/HistoryLinkListPlus/src/linklist.cpp
+++ b/plugins/HistoryLinkListPlus/src/linklist.cpp
@@ -31,7 +31,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/HistoryLinkListPlus/src/version.h b/plugins/HistoryLinkListPlus/src/version.h
index c8ab34ae17..9d5b8e8e95 100644
--- a/plugins/HistoryLinkListPlus/src/version.h
+++ b/plugins/HistoryLinkListPlus/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "LinkList.dll"
#define __DESCRIPTION "Generates a list of extracted URIs from the history."
#define __AUTHOR "Thomas Wendel, gureedo"
-#define __AUTHOREMAIL "gureedo@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/LinkList/"
#define __COPYRIGHT "© 2010-2011 gureedo"
diff --git a/plugins/HistoryPlusPlus/historypp.dpr b/plugins/HistoryPlusPlus/historypp.dpr
index 7a5a4dbd09..746459a1a6 100644
--- a/plugins/HistoryPlusPlus/historypp.dpr
+++ b/plugins/HistoryPlusPlus/historypp.dpr
@@ -136,7 +136,6 @@ begin
PluginInfo.version:= hppVersion;
PluginInfo.description:= hppDescription;
PluginInfo.author:= hppAuthor;
- PluginInfo.authorEmail:= hppAuthorEmail;
PluginInfo.copyright:= hppCopyright;
PluginInfo.homepage:= hppHomePageURL;
PluginInfo.flags:= UNICODE_AWARE;
diff --git a/plugins/HistoryPlusPlus/hpp_global.pas b/plugins/HistoryPlusPlus/hpp_global.pas
index dba7710003..f9f198da2a 100644
--- a/plugins/HistoryPlusPlus/hpp_global.pas
+++ b/plugins/HistoryPlusPlus/hpp_global.pas
@@ -168,7 +168,6 @@ const
hppDescription = 'Easy, fast and feature complete history viewer.';
hppAuthor = 'theMIROn, Art Fedorov';
- hppAuthorEmail = 'themiron@mail.ru, artemf@mail.ru';
hppCopyright = '© 2006-2009 theMIROn, 2003-2006 Art Fedorov. History+ parts © 2001 Christian Kastner';
hppHomePageURL = 'https://miranda-ng.org/p/HistoryPP/';
diff --git a/plugins/HistoryStats/src/main.cpp b/plugins/HistoryStats/src/main.cpp
index 202a6fcea0..7f64ab6243 100644
--- a/plugins/HistoryStats/src/main.cpp
+++ b/plugins/HistoryStats/src/main.cpp
@@ -23,7 +23,6 @@ PLUGININFOEX g_pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/HistoryStats/src/stdafx.h b/plugins/HistoryStats/src/stdafx.h
index d0b4aee7ce..06800ecb98 100644
--- a/plugins/HistoryStats/src/stdafx.h
+++ b/plugins/HistoryStats/src/stdafx.h
@@ -64,7 +64,6 @@
#include <m_imgsrvc.h>
#include <m_timezones.h>
-#include <m_addcontact.h> // not used, depends on m_protosvc.h
#include <m_icq.h> // depends on m_protosvc.h
#include <m_metacontacts.h>
diff --git a/plugins/HistoryStats/src/version.h b/plugins/HistoryStats/src/version.h
index 0255da74da..a4cbbb7f7b 100644
--- a/plugins/HistoryStats/src/version.h
+++ b/plugins/HistoryStats/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "HistoryStats.dll"
#define __DESCRIPTION "Creates detailed, colorful and highly customizable statistics using your message history."
#define __AUTHOR "Martin Afanasjew"
-#define __AUTHOREMAIL "miranda@dark-passage.de"
#define __AUTHORWEB "https://miranda-ng.org/p/HistoryStats/"
#define __COPYRIGHT "© 2005-2007 Martin Afanasjew (see README for further credits)"
diff --git a/plugins/HistorySweeperLight/src/main.cpp b/plugins/HistorySweeperLight/src/main.cpp
index ade9f3e678..0c1fdc4aac 100644
--- a/plugins/HistorySweeperLight/src/main.cpp
+++ b/plugins/HistorySweeperLight/src/main.cpp
@@ -34,7 +34,6 @@ static PLUGININFOEX pluginInfoEx =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/HistorySweeperLight/src/version.h b/plugins/HistorySweeperLight/src/version.h
index dfbb36af6d..a9f0e3fdf1 100644
--- a/plugins/HistorySweeperLight/src/version.h
+++ b/plugins/HistorySweeperLight/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "HistorySweeperLight.dll"
#define __DESCRIPTION "This plugin can sweep system history, history from all contacts or only from chosen; also it may sweep history older than certain time; and may do it at Miranda NG startup/shutdown."
#define __AUTHOR "Sergey V. Gershovich a.k.a. Jazzy$, Boris Krasnovskiy, tico-tico"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/HistorySweeperLight/"
#define __COPYRIGHT "© 2002-2003 Sergey V. Gershovich a.k.a. Jazzy$, 2006-2009 Boris Krasnovskiy, 2010-2011 tico-tico"
diff --git a/plugins/HwHotKeys/src/HwHotKeys_DllMain.cpp b/plugins/HwHotKeys/src/HwHotKeys_DllMain.cpp
index 22814e4c9d..dce4f52a75 100644
--- a/plugins/HwHotKeys/src/HwHotKeys_DllMain.cpp
+++ b/plugins/HwHotKeys/src/HwHotKeys_DllMain.cpp
@@ -81,7 +81,6 @@ PLUGININFOEX PluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION_MIR,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/HwHotKeys/src/version.h b/plugins/HwHotKeys/src/version.h
index 344f756348..bb13d2f797 100644
--- a/plugins/HwHotKeys/src/version.h
+++ b/plugins/HwHotKeys/src/version.h
@@ -33,7 +33,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 - 1307, USA.
#define __DESCRIPTION_MIR "Allows you to assign expanded multimedia keys (only for PS/2 keyboards)." // опиÑание плагина в миранде (локализуемое)
#define __DESCRIPTION_DLL "Hardware HotKeys plugin for Miranda NG." // опиÑание плагина в dll-fileinfo "FileDescription" (там многоÑтрочные Ñтроки - не работают). Ðелокализуемое!
#define __AUTHOR "Eugene f2065" // опиÑание плагина в миранде
-#define __AUTHOREMAIL "f2065@mail.ru" // опиÑание плагина в миранде
#define __AUTHORWEB "http://f2065.narod.ru/" // опиÑание плагина в dll-fileinfo "CompanyName", опиÑание плагина в миранде
#define __COPYRIGHT "© 2010-2017 Eugene f2065" // опиÑание плагина в dll-fileinfo "LegalCopyright", опиÑание плагина в миранде
diff --git a/plugins/IEHistory/src/IEHistory.cpp b/plugins/IEHistory/src/IEHistory.cpp
index 6f8151f72d..06fabc6490 100644
--- a/plugins/IEHistory/src/IEHistory.cpp
+++ b/plugins/IEHistory/src/IEHistory.cpp
@@ -35,7 +35,7 @@ PLUGININFOEX pluginInfo = {
__PLUGIN_DISPLAY_NAME,
__VERSION_DWORD,
__DESC,
- __AUTHOR, __AUTHOREMAIL,
+ __AUTHOR,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/IEHistory/src/version.h b/plugins/IEHistory/src/version.h
index 34d50e6bcf..92cb7eff94 100644
--- a/plugins/IEHistory/src/version.h
+++ b/plugins/IEHistory/src/version.h
@@ -30,7 +30,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define __DESC "Shows the history for a given contact using IEView."
#define __AUTHOR "Cristian Libotean, Miranda NG team"
-#define __AUTHOREMAIL "eblis102@yahoo.com"
#define __COPYRIGHT "© 2006 Cristian Libotean, 2014-17 Miranda NG team"
#define __AUTHORWEB "https://miranda-ng.org/p/IEHistory"
#define __PLUGIN_DISPLAY_NAME "IEView history viewer"
diff --git a/plugins/IEView/src/ieview_main.cpp b/plugins/IEView/src/ieview_main.cpp
index 4b86be1748..64710f6511 100644
--- a/plugins/IEView/src/ieview_main.cpp
+++ b/plugins/IEView/src/ieview_main.cpp
@@ -32,7 +32,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/IEView/src/version.h b/plugins/IEView/src/version.h
index ebd233c51c..e617e9f5a1 100644
--- a/plugins/IEView/src/version.h
+++ b/plugins/IEView/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "IEView.dll"
#define __DESCRIPTION "IE Based Chat Log."
#define __AUTHOR "Piotr Piastucki, Francois Mean"
-#define __AUTHOREMAIL "the_leech@users.berlios.de"
#define __AUTHORWEB "https://miranda-ng.org/p/IEView/"
#define __COPYRIGHT "© 2005-2011 Piotr Piastucki, Francois Mean"
diff --git a/plugins/IgnoreState/src/main.cpp b/plugins/IgnoreState/src/main.cpp
index df6aa14bbd..b99fcd0317 100644
--- a/plugins/IgnoreState/src/main.cpp
+++ b/plugins/IgnoreState/src/main.cpp
@@ -53,7 +53,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/IgnoreState/src/version.h b/plugins/IgnoreState/src/version.h
index 71b8f06747..2bbea78b59 100644
--- a/plugins/IgnoreState/src/version.h
+++ b/plugins/IgnoreState/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "IgnoreState.dll"
#define __DESCRIPTION "Shows ignore state of contact in contact list."
#define __AUTHOR "Kildor"
-#define __AUTHOREMAIL "kostia@ngs.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/IgnoreState/"
#define __COPYRIGHT "© 2009-2010 Kostia Romanov"
diff --git a/plugins/Import/src/main.cpp b/plugins/Import/src/main.cpp
index 6657111100..847049919b 100644
--- a/plugins/Import/src/main.cpp
+++ b/plugins/Import/src/main.cpp
@@ -38,7 +38,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Import/src/version.h b/plugins/Import/src/version.h
index 3408e433eb..4bd8769287 100644
--- a/plugins/Import/src/version.h
+++ b/plugins/Import/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Import.dll"
#define __DESCRIPTION "Imports contacts and messages from another Miranda profile or from an external program."
#define __AUTHOR "Miranda team"
-#define __AUTHOREMAIL "info@miranda-im.org"
#define __AUTHORWEB "https://miranda-ng.org/p/Import/"
#define __COPYRIGHT "© 2012-2017 George Hazan"
diff --git a/plugins/ImportTXT/importtxt.dpr b/plugins/ImportTXT/importtxt.dpr
index 5c5d635e0b..8a7959a197 100644
--- a/plugins/ImportTXT/importtxt.dpr
+++ b/plugins/ImportTXT/importtxt.dpr
@@ -56,7 +56,6 @@ begin
PluginInfo.version :=$0000010A;
PluginInfo.description:='Imports history saved in TXT files from other clients.';
PluginInfo.author :='Abyss';
- PluginInfo.authorEmail:='abyss.andrey@gmail.com';
PluginInfo.copyright :='© 2008 Abyss';
PluginInfo.homepage :='https://miranda-ng.org/p/ImportTXT/';
PluginInfo.flags :=UNICODE_AWARE;
diff --git a/plugins/KeyboardNotify/src/main.cpp b/plugins/KeyboardNotify/src/main.cpp
index 5b675e4421..71575ed798 100644
--- a/plugins/KeyboardNotify/src/main.cpp
+++ b/plugins/KeyboardNotify/src/main.cpp
@@ -93,7 +93,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/KeyboardNotify/src/version.h b/plugins/KeyboardNotify/src/version.h
index 201bf2d1be..b71d9703b6 100644
--- a/plugins/KeyboardNotify/src/version.h
+++ b/plugins/KeyboardNotify/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "KeyboardNotify.dll"
#define __DESCRIPTION "Flashes your keyboard LEDs when a message has arrived."
#define __AUTHOR "TioDuke"
-#define __AUTHOREMAIL "tioduke@yahoo.ca"
#define __AUTHORWEB "https://miranda-ng.org/p/KeyboardNotify/"
#define __COPYRIGHT "© 2002-2003 Martin Öberg, 2004 Std, 2005-2008 TioDuke"
diff --git a/plugins/ListeningTo/src/main.cpp b/plugins/ListeningTo/src/main.cpp
index d3eb164123..d3ca7b9aa0 100644
--- a/plugins/ListeningTo/src/main.cpp
+++ b/plugins/ListeningTo/src/main.cpp
@@ -29,7 +29,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/ListeningTo/src/version.h b/plugins/ListeningTo/src/version.h
index 95b6a13741..d65fb44463 100644
--- a/plugins/ListeningTo/src/version.h
+++ b/plugins/ListeningTo/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "ListeningTo.dll"
#define __DESCRIPTION "Handles listening information to/for contacts."
#define __AUTHOR "Ricardo Pescuma Domenecci"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/ListeningTo/"
#define __COPYRIGHT "© 2006-2009 Ricardo Pescuma Domenecci"
diff --git a/plugins/LotusNotify/src/LotusNotify.cpp b/plugins/LotusNotify/src/LotusNotify.cpp
index e76912891c..362811eed2 100644
--- a/plugins/LotusNotify/src/LotusNotify.cpp
+++ b/plugins/LotusNotify/src/LotusNotify.cpp
@@ -72,7 +72,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/LotusNotify/src/version.h b/plugins/LotusNotify/src/version.h
index fc759fffe4..e350839f09 100644
--- a/plugins/LotusNotify/src/version.h
+++ b/plugins/LotusNotify/src/version.h
@@ -10,7 +10,6 @@
#define __DESCRIPTION "Notify about new mail in Lotus Database"
#define __FILECOMMENTS "Miranda NG Plugin - Notify about new mail in Lotus Database"
#define __AUTHOR "MaKaRSoFT - http://maciej.wycik.pl/miranda"
-#define __AUTHOREMAIL "makar@poczta.of.pl"
#define __AUTHORWEB "https://miranda-ng.org/p/LotusNotify/"
#define __COPYRIGHT "© 2006 MaKaRSoFT, 2013 wsx22, 2015 pepinlebref"
#define __LEGALTRADEMARKS "Freeware"
diff --git a/plugins/MenuItemEx/src/main.cpp b/plugins/MenuItemEx/src/main.cpp
index 4a2ba849e7..e77177358f 100644
--- a/plugins/MenuItemEx/src/main.cpp
+++ b/plugins/MenuItemEx/src/main.cpp
@@ -82,7 +82,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/MenuItemEx/src/version.h b/plugins/MenuItemEx/src/version.h
index b413e2676b..4989795f8c 100644
--- a/plugins/MenuItemEx/src/version.h
+++ b/plugins/MenuItemEx/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "MenuEx.dll"
#define __DESCRIPTION "Adds some useful options to a contacts menu."
#define __AUTHOR "Heiko Schillinger, Baloo, Billy_Bons, Robert Pösel"
-#define __AUTHOREMAIL "micron@nexgo.de; baloo@bk.ru; tatarinov.sergey@gmail.com; robyer@seznam.cz"
#define __AUTHORWEB "https://miranda-ng.org/p/MenuEx/"
#define __COPYRIGHT "© 2001-03 Heiko Schillinger, © 2006-08 Baloo, © 2009-10 Billy_Bons, © 2011-13 Robert Pösel"
diff --git a/plugins/MessageState/src/main.cpp b/plugins/MessageState/src/main.cpp
index 38b83bf5ec..519522b54d 100644
--- a/plugins/MessageState/src/main.cpp
+++ b/plugins/MessageState/src/main.cpp
@@ -10,7 +10,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/MessageState/src/version.h b/plugins/MessageState/src/version.h
index fea0d8d59f..a3ea4a01db 100644
--- a/plugins/MessageState/src/version.h
+++ b/plugins/MessageState/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "MessageState.dll"
#define __DESCRIPTION "Displays icons in message window showing whether your last outgoing message was read / is still unread."
#define __AUTHOR "MikalaiR"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/MessageState/"
#define __COPYRIGHT "© 2015-17 Miranda NG Team"
diff --git a/plugins/MimCmd/src/version.h b/plugins/MimCmd/src/version.h
index 319023d290..c9625d9e64 100644
--- a/plugins/MimCmd/src/version.h
+++ b/plugins/MimCmd/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "MimCmd.exe"
#define __DESCRIPTION "This will tell Miranda to run the specified command."
#define __AUTHOR "Cristian Libotean"
-#define __AUTHOREMAIL "eblis102@yahoo.com"
#define __AUTHORWEB "https://miranda-ng.org/p/CmdLine/"
#define __COPYRIGHT "© 2007-2011 Cristian Libotean"
diff --git a/plugins/MirFox/src/MirandaInterface.cpp b/plugins/MirFox/src/MirandaInterface.cpp
index 439b859643..95d9d0feb5 100644
--- a/plugins/MirFox/src/MirandaInterface.cpp
+++ b/plugins/MirFox/src/MirandaInterface.cpp
@@ -26,7 +26,6 @@ PLUGININFOEX pluginInfo={
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/MirFox/src/version.h b/plugins/MirFox/src/version.h
index 7f9f2df000..b7873ba2e7 100644
--- a/plugins/MirFox/src/version.h
+++ b/plugins/MirFox/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "MirFox.dll"
#define __DESCRIPTION "MirFox (Miranda NG) - part of Miranda-Firefox integration - http://wsx22.3.xpdev-hosted.com"
#define __AUTHOR "Szymon Tokarz"
-#define __AUTHOREMAIL "wsx22@o2.pl"
#define __AUTHORWEB "https://miranda-ng.org/p/MirFox/"
#define __COPYRIGHT "© 2013 - 2017 Szymon Tokarz"
diff --git a/plugins/MirLua/src/main.cpp b/plugins/MirLua/src/main.cpp
index 1795c56878..22fabbbdef 100644
--- a/plugins/MirLua/src/main.cpp
+++ b/plugins/MirLua/src/main.cpp
@@ -18,7 +18,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/MirLua/src/version.h b/plugins/MirLua/src/version.h
index 1525666f2a..b43e6301d0 100644
--- a/plugins/MirLua/src/version.h
+++ b/plugins/MirLua/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "MirLua.dll"
#define __DESCRIPTION "Extends Miranda NG functionality with Lua scripts."
#define __AUTHOR "Miranda NG team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/MirLua/"
#define __COPYRIGHT "© 2015-17 Miranda NG project"
diff --git a/plugins/MirOTR/src/dllmain.cpp b/plugins/MirOTR/src/dllmain.cpp
index 9e499f897a..bb72c7746b 100644
--- a/plugins/MirOTR/src/dllmain.cpp
+++ b/plugins/MirOTR/src/dllmain.cpp
@@ -13,7 +13,6 @@ PLUGININFOEX pluginInfo={
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/MirOTR/src/version.h b/plugins/MirOTR/src/version.h
index 275fa1166b..bfe6b1cf86 100644
--- a/plugins/MirOTR/src/version.h
+++ b/plugins/MirOTR/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "MirOTR.dll"
#define __DESCRIPTION "OTR (Off-the-Record) plugin for Miranda NG (using some code and ideas from SecureIM, Pidgin-OTR and old Miranda OTR (by SJE))."
#define __AUTHOR "ProgAndy & CHEF-KOCH"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/MirOTR/"
#define __COPYRIGHT "© ProgAndy & CHEF-KOCH"
diff --git a/plugins/MirandaG15/src/Miranda.cpp b/plugins/MirandaG15/src/Miranda.cpp
index 7da57367f3..10a1ec6919 100644
--- a/plugins/MirandaG15/src/Miranda.cpp
+++ b/plugins/MirandaG15/src/Miranda.cpp
@@ -73,7 +73,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/MirandaG15/src/version.h b/plugins/MirandaG15/src/version.h
index 3095c901db..fb41a9e806 100644
--- a/plugins/MirandaG15/src/version.h
+++ b/plugins/MirandaG15/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "MirandaG15.dll"
#define __DESCRIPTION "Provides an interface to use Miranda from the LCD of various Logitech devices."
#define __AUTHOR "Martin Kleinhans"
-#define __AUTHOREMAIL "mail@mkleinhans.de"
#define __AUTHORWEB "https://miranda-ng.org/p/MirandaG15/"
#define __COPYRIGHT "© 2009 Martin Kleinhans"
diff --git a/plugins/MobileState/src/main.cpp b/plugins/MobileState/src/main.cpp
index 63db7151bb..d5eb32f7c2 100644
--- a/plugins/MobileState/src/main.cpp
+++ b/plugins/MobileState/src/main.cpp
@@ -29,7 +29,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/MobileState/src/version.h b/plugins/MobileState/src/version.h
index bfd59aee34..b077e9a106 100644
--- a/plugins/MobileState/src/version.h
+++ b/plugins/MobileState/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "MobileState.dll"
#define __DESCRIPTION "Plugin shows mobile icon in contact list next to contacts which are using mobile client."
#define __AUTHOR "Robert Pösel"
-#define __AUTHOREMAIL "robyer@seznam.cz"
#define __AUTHORWEB "https://miranda-ng.org/p/MobileState/"
#define __COPYRIGHT "© 2012-17 Robert Pösel"
diff --git a/plugins/MsgPopup/src/main.cpp b/plugins/MsgPopup/src/main.cpp
index f9bc4d51f1..cc39c0653e 100644
--- a/plugins/MsgPopup/src/main.cpp
+++ b/plugins/MsgPopup/src/main.cpp
@@ -40,7 +40,6 @@ PLUGININFOEX pluginInfo={
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/MsgPopup/src/version.h b/plugins/MsgPopup/src/version.h
index 54379e6606..ecbccc9161 100644
--- a/plugins/MsgPopup/src/version.h
+++ b/plugins/MsgPopup/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "MsgPopup.dll"
#define __DESCRIPTION "Plugin replaces message boxes (those having only OK button) with popups."
#define __AUTHOR "StDenis"
-#define __AUTHOREMAIL "stdenformiranda@fromru.com"
#define __AUTHORWEB "https://miranda-ng.org/p/MsgPopup/"
#define __COPYRIGHT "© 2004 Denis Stanishevskiy"
diff --git a/plugins/Msg_Export/src/main.cpp b/plugins/Msg_Export/src/main.cpp
index 686294963b..2afea9225a 100755
--- a/plugins/Msg_Export/src/main.cpp
+++ b/plugins/Msg_Export/src/main.cpp
@@ -34,7 +34,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Msg_Export/src/version.h b/plugins/Msg_Export/src/version.h
index cb04f386aa..4ffd396e6a 100644
--- a/plugins/Msg_Export/src/version.h
+++ b/plugins/Msg_Export/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Msg_Export.dll"
#define __DESCRIPTION "Exports every message, URL or file you receive to a text file."
#define __AUTHOR "Kennet Nielsen, mod by ring0"
-#define __AUTHOREMAIL "Kennet_N@ofir.dk"
#define __AUTHORWEB "https://miranda-ng.org/p/Msg_Export/"
#define __COPYRIGHT "© 2002 Kennet Nielsen, 2012-17 Miranda NG Team"
diff --git a/plugins/MyDetails/src/mydetails.cpp b/plugins/MyDetails/src/mydetails.cpp
index 459ee0572d..5f00d1a8dd 100644
--- a/plugins/MyDetails/src/mydetails.cpp
+++ b/plugins/MyDetails/src/mydetails.cpp
@@ -33,7 +33,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/MyDetails/src/version.h b/plugins/MyDetails/src/version.h
index c621144e1a..263549e2b1 100644
--- a/plugins/MyDetails/src/version.h
+++ b/plugins/MyDetails/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "MyDetails.dll"
#define __DESCRIPTION "Shows and allows you to edit your details for all accounts."
#define __AUTHOR "Ricardo Pescuma Domenecci, Drugwash"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/MyDetails/"
#define __COPYRIGHT "© 2005-2008 Ricardo Pescuma Domenecci, Drugwash"
diff --git a/plugins/NewAwaySysMod/src/AwaySys.cpp b/plugins/NewAwaySysMod/src/AwaySys.cpp
index 4ab5f98280..eef50f0655 100644
--- a/plugins/NewAwaySysMod/src/AwaySys.cpp
+++ b/plugins/NewAwaySysMod/src/AwaySys.cpp
@@ -82,7 +82,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/NewAwaySysMod/src/version.h b/plugins/NewAwaySysMod/src/version.h
index 0058c6b912..2fc57d631e 100644
--- a/plugins/NewAwaySysMod/src/version.h
+++ b/plugins/NewAwaySysMod/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "NewAwaySys.dll"
#define __DESCRIPTION "Allows you to handle your status messages in a convenient way."
#define __AUTHOR "NightFox, Deathdemon, XF007, Goblineye Entertainment"
-#define __AUTHOREMAIL "NightFox@myied.org"
#define __AUTHORWEB "https://miranda-ng.org/p/NewAwaySys/"
#define __COPYRIGHT "© 2010 NightFox; © 2005-2007 Chervov Dmitry; © 2004-2005 Iksaif; © 2002-2003 Goblineye Entertainment"
diff --git a/plugins/NewEventNotify/src/main.cpp b/plugins/NewEventNotify/src/main.cpp
index bb33f4a236..571abdd1be 100644
--- a/plugins/NewEventNotify/src/main.cpp
+++ b/plugins/NewEventNotify/src/main.cpp
@@ -39,7 +39,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/NewEventNotify/src/version.h b/plugins/NewEventNotify/src/version.h
index 98c2ebd589..908b73fc10 100644
--- a/plugins/NewEventNotify/src/version.h
+++ b/plugins/NewEventNotify/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "NewEventNotify.dll"
#define __DESCRIPTION "Notifies you when you receive a message, URL, file or any other event by displaying a popup."
#define __AUTHOR "icebreaker, Prezes, vj, vlko, Joe @ Whale"
-#define __AUTHOREMAIL "jokusoftware@miranda-im.org"
#define __AUTHORWEB "https://miranda-ng.org/p/NewEventNotify/"
#define __COPYRIGHT ""
diff --git a/plugins/NewXstatusNotify/src/main.cpp b/plugins/NewXstatusNotify/src/main.cpp
index eea1cf800f..70a7303963 100644
--- a/plugins/NewXstatusNotify/src/main.cpp
+++ b/plugins/NewXstatusNotify/src/main.cpp
@@ -45,7 +45,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/NewXstatusNotify/src/version.h b/plugins/NewXstatusNotify/src/version.h
index afc55f67f3..76e9ddac61 100644
--- a/plugins/NewXstatusNotify/src/version.h
+++ b/plugins/NewXstatusNotify/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "NewXstatusNotify.dll"
#define __DESCRIPTION "Notifies you when a contact changes his/her (X)status or status message."
#define __AUTHOR "Luca Santarelli, Vasilich, yaho"
-#define __AUTHOREMAIL "yaho@miranda-easy.net"
#define __AUTHORWEB "https://miranda-ng.org/p/NewXstatusNotify/"
#define __COPYRIGHT "© 2001-2004 Luca Santarelli, 2005-2007 Vasilich, 2007-2011 yaho"
diff --git a/plugins/New_GPG/src/init.cpp b/plugins/New_GPG/src/init.cpp
index 1736462b5e..11239e5610 100755
--- a/plugins/New_GPG/src/init.cpp
+++ b/plugins/New_GPG/src/init.cpp
@@ -27,7 +27,6 @@ PLUGININFOEX pluginInfo={
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/New_GPG/src/version.h b/plugins/New_GPG/src/version.h
index 8c156b9a16..d0d01312aa 100755
--- a/plugins/New_GPG/src/version.h
+++ b/plugins/New_GPG/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "New_GPG.dll"
#define __DESCRIPTION "New GPG encryption support plugin, based on code from old GPG plugin and SecureIM."
#define __AUTHOR "sss"
-#define __AUTHOREMAIL "sss123next@list.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/New_GPG/"
#define __COPYRIGHT "© 2010-17 sss"
diff --git a/plugins/NewsAggregator/Src/Authentication.cpp b/plugins/NewsAggregator/Src/Authentication.cpp
index 4d01851929..e53c4791a0 100644
--- a/plugins/NewsAggregator/Src/Authentication.cpp
+++ b/plugins/NewsAggregator/Src/Authentication.cpp
@@ -42,7 +42,7 @@ void CreateAuthString(char *auth, MCONTACT hContact, HWND hwndDlg)
mir_free(tlogin);
mir_free(tpass);
- mir_snprintf(auth, 250, "Basic %s", ptrA(mir_base64_encode((PBYTE)str, len)));
+ mir_snprintf(auth, 250, "Basic %s", ptrA(mir_base64_encode(str, len)));
}
INT_PTR CALLBACK AuthenticationProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
diff --git a/plugins/NewsAggregator/Src/NewsAggregator.cpp b/plugins/NewsAggregator/Src/NewsAggregator.cpp
index 01a57f1ac1..bc9d91ac3a 100644
--- a/plugins/NewsAggregator/Src/NewsAggregator.cpp
+++ b/plugins/NewsAggregator/Src/NewsAggregator.cpp
@@ -34,7 +34,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/NewsAggregator/Src/version.h b/plugins/NewsAggregator/Src/version.h
index b9197c3d5d..d47f44e9c8 100644
--- a/plugins/NewsAggregator/Src/version.h
+++ b/plugins/NewsAggregator/Src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "NewsAggregator.dll"
#define __DESCRIPTION "RSS/Atom news aggregator."
#define __AUTHOR "Mataes, FREAK_THEMIGHTY"
-#define __AUTHOREMAIL "mataes2007@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/NewsAggregator/"
#define __COPYRIGHT "© 2012-17 Mataes, FREAK_THEMIGHTY"
diff --git a/plugins/NoHistory/src/dllmain.cpp b/plugins/NoHistory/src/dllmain.cpp
index f20a68161b..cbd5db623c 100644
--- a/plugins/NoHistory/src/dllmain.cpp
+++ b/plugins/NoHistory/src/dllmain.cpp
@@ -34,7 +34,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/NoHistory/src/version.h b/plugins/NoHistory/src/version.h
index 31b68721b2..1519b6c710 100644
--- a/plugins/NoHistory/src/version.h
+++ b/plugins/NoHistory/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "NoHistory.dll"
#define __DESCRIPTION "Prevent Miranda from storing any history."
#define __AUTHOR "Scott Ellis, NightFox"
-#define __AUTHOREMAIL "mail@scottellis.com.au; nightfox@myied.org"
#define __AUTHORWEB "https://miranda-ng.org/p/NoHistory/"
#define __COPYRIGHT "© 2005 Scott Ellis, 2010-17 NightFox"
diff --git a/plugins/Non-IM Contact/src/main.cpp b/plugins/Non-IM Contact/src/main.cpp
index 5f7f769469..209967923b 100644
--- a/plugins/Non-IM Contact/src/main.cpp
+++ b/plugins/Non-IM Contact/src/main.cpp
@@ -16,7 +16,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Non-IM Contact/src/version.h b/plugins/Non-IM Contact/src/version.h
index a2e19e413a..d8bf664b36 100644
--- a/plugins/Non-IM Contact/src/version.h
+++ b/plugins/Non-IM Contact/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "NimContact.dll"
#define __DESCRIPTION "Non-IM Contact allows you to add 'contacts' that can act as shortcuts to other programs, or links to web pages.\r\nThe contacts name can be read from a text file (includes any ASCII file).\r\nThis plugin is a combination of Favorites and Text Reader plugins both made by me)"
#define __AUTHOR "Jonathan Gordon"
-#define __AUTHOREMAIL "ICQ 98791178, MSN jonnog@hotmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/NimContact/"
#define __COPYRIGHT "© 2003-2004 Jonathan Gordon, jdgordy@gmail.com"
diff --git a/plugins/NotesAndReminders/src/main.cpp b/plugins/NotesAndReminders/src/main.cpp
index 0ea7fd65e3..f3d2c3af51 100644
--- a/plugins/NotesAndReminders/src/main.cpp
+++ b/plugins/NotesAndReminders/src/main.cpp
@@ -22,7 +22,6 @@ static PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/NotesAndReminders/src/version.h b/plugins/NotesAndReminders/src/version.h
index 295d18edec..8ab090eb82 100644
--- a/plugins/NotesAndReminders/src/version.h
+++ b/plugins/NotesAndReminders/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "NotesReminders.dll"
#define __DESCRIPTION "Sticky Notes & Reminders Implementation for Miranda NG."
#define __AUTHOR "Joe Kucera, Lubomir Kolev Ivanov, Georg Fischer"
-#define __AUTHOREMAIL "jokusoftware@users.sourceforge.net; d00mEr@dir.bg"
#define __AUTHORWEB "https://miranda-ng.org/p/NotesAndReminders/"
#define __COPYRIGHT "© 2003-2005 Joe Kucera, Lubomir Ivanov"
diff --git a/plugins/NotifyAnything/src/main.cpp b/plugins/NotifyAnything/src/main.cpp
index 5367ea5fa4..6069a5962e 100644
--- a/plugins/NotifyAnything/src/main.cpp
+++ b/plugins/NotifyAnything/src/main.cpp
@@ -33,7 +33,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/NotifyAnything/src/version.h b/plugins/NotifyAnything/src/version.h
index 5e87c48eef..c102285c27 100644
--- a/plugins/NotifyAnything/src/version.h
+++ b/plugins/NotifyAnything/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "NotifyAnything.dll"
#define __DESCRIPTION "Displays popups for custom events, triggered by UDP packages."
#define __AUTHOR "Daniel Wesslen, Korney San"
-#define __AUTHOREMAIL "wesslen@users.sourceforge.net, kora@users.sourceforge.net"
#define __AUTHORWEB "https://miranda-ng.org/p/NotifyAnything/"
#define __COPYRIGHT "© 2003 Daniel Wesslen"
diff --git a/plugins/Nudge/src/main.cpp b/plugins/Nudge/src/main.cpp
index 990546769b..0524554f05 100644
--- a/plugins/Nudge/src/main.cpp
+++ b/plugins/Nudge/src/main.cpp
@@ -22,7 +22,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Nudge/src/version.h b/plugins/Nudge/src/version.h
index 553c4efea7..7516394138 100644
--- a/plugins/Nudge/src/version.h
+++ b/plugins/Nudge/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Nudge.dll"
#define __DESCRIPTION "Plugin to shake the contact list and chat window."
#define __AUTHOR "Tweety/GouZ, FREAK_THEMIGHTY"
-#define __AUTHOREMAIL "francois.mean@skynet.be, Sylvain.gougouzian@gmail.com, wishmaster51@googlemail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/Nudge/"
#define __COPYRIGHT "© the miranda community"
diff --git a/plugins/OpenFolder/src/openFolder.cpp b/plugins/OpenFolder/src/openFolder.cpp
index 97509a117b..695aa6ac73 100644
--- a/plugins/OpenFolder/src/openFolder.cpp
+++ b/plugins/OpenFolder/src/openFolder.cpp
@@ -11,7 +11,6 @@ PLUGININFOEX pluginInfoEx =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/OpenFolder/src/version.h b/plugins/OpenFolder/src/version.h
index 05f208d2df..588839c6fe 100644
--- a/plugins/OpenFolder/src/version.h
+++ b/plugins/OpenFolder/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "OpenFolder.dll"
#define __DESCRIPTION "Adds a menu/toolbar item which opens the main Miranda NG folder."
#define __AUTHOR "jarvis, Kreisquadratur"
-#define __AUTHOREMAIL "jarvis@jabber.cz, djui@kreisquadratur.de"
#define __AUTHORWEB "https://miranda-ng.org/p/OpenFolder/"
#define __COPYRIGHT "© 2008 jarvis, © 2004 Kreisquadratur"
diff --git a/plugins/OpenSSL/src/main.cpp b/plugins/OpenSSL/src/main.cpp
index e523acc96d..0cb0c0f95a 100644
--- a/plugins/OpenSSL/src/main.cpp
+++ b/plugins/OpenSSL/src/main.cpp
@@ -32,7 +32,6 @@ PLUGININFOEX pluginInfo = {
__VERSION_DWORD,
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE | STATIC_PLUGIN,
diff --git a/plugins/OpenSSL/src/version.h b/plugins/OpenSSL/src/version.h
index 6dff056a72..b3a5cab126 100644
--- a/plugins/OpenSSL/src/version.h
+++ b/plugins/OpenSSL/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "OpenSSL.dll"
#define __DESCRIPTION "Core driver to provide OpenSSL-based SSL services."
#define __AUTHOR "Miranda NG Team"
-#define __AUTHOREMAIL ""
-#define __AUTHORWEB ""
+#define __AUTHORWEB "https://miranda-ng.org/p/OpenSSL/"
#define __COPYRIGHT "© 2014-17 Miranda NG Team"
diff --git a/plugins/PackUpdater/Src/PackUpdater.cpp b/plugins/PackUpdater/Src/PackUpdater.cpp
index 2d889f6911..cd6165785f 100644
--- a/plugins/PackUpdater/Src/PackUpdater.cpp
+++ b/plugins/PackUpdater/Src/PackUpdater.cpp
@@ -31,7 +31,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/PackUpdater/Src/version.h b/plugins/PackUpdater/Src/version.h
index 2823d340ee..1c086069fd 100644
--- a/plugins/PackUpdater/Src/version.h
+++ b/plugins/PackUpdater/Src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "PackUpdater.dll"
#define __DESCRIPTION "Simple updater for Miranda NG premodified packs."
#define __AUTHOR "Mataes, ZERO_BiT"
-#define __AUTHOREMAIL "mataes2007@gmail.com, zero-bit@mail.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/PackUpdater/"
#define __COPYRIGHT "© 2011-2017 Mataes, 2007 ZERO_BiT"
diff --git a/plugins/PasteIt/src/PasteIt.cpp b/plugins/PasteIt/src/PasteIt.cpp
index 96de6b8a51..6839195d4b 100644
--- a/plugins/PasteIt/src/PasteIt.cpp
+++ b/plugins/PasteIt/src/PasteIt.cpp
@@ -42,7 +42,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/PasteIt/src/version.h b/plugins/PasteIt/src/version.h
index 68de25f823..bea6149880 100644
--- a/plugins/PasteIt/src/version.h
+++ b/plugins/PasteIt/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "PasteIt.dll"
#define __DESCRIPTION "Uploads the text to web page and sends the URL to your friends."
#define __AUTHOR "Krzysztof Kral"
-#define __AUTHOREMAIL "programista@poczta.of.pl"
#define __AUTHORWEB "https://miranda-ng.org/p/PasteIt/"
#define __COPYRIGHT "© 2011 Krzysztof Kral"
diff --git a/plugins/Ping/src/ping.cpp b/plugins/Ping/src/ping.cpp
index c703feba7a..42112e98bc 100644
--- a/plugins/Ping/src/ping.cpp
+++ b/plugins/Ping/src/ping.cpp
@@ -16,7 +16,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Ping/src/version.h b/plugins/Ping/src/version.h
index 16ad496842..6a5b2f22e9 100644
--- a/plugins/Ping/src/version.h
+++ b/plugins/Ping/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Ping.dll"
#define __DESCRIPTION "Ping labelled IP addresses or domain names."
#define __AUTHOR "Scott Ellis"
-#define __AUTHOREMAIL "mail@scottellis.com.au"
#define __AUTHORWEB "https://miranda-ng.org/p/Ping/"
#define __COPYRIGHT "© 2005 Scott Ellis"
diff --git a/plugins/PluginUpdater/src/DlgUpdate.cpp b/plugins/PluginUpdater/src/DlgUpdate.cpp
index 8e3ef7228a..abf740038b 100644
--- a/plugins/PluginUpdater/src/DlgUpdate.cpp
+++ b/plugins/PluginUpdater/src/DlgUpdate.cpp
@@ -591,6 +591,7 @@ static renameTable[] =
{ L"gender.dll", nullptr },
{ L"gtalkext.dll", nullptr },
{ L"langman.dll", nullptr },
+ { L"libtox.dll", nullptr },
{ L"metacontacts.dll", nullptr },
{ L"modernopt.dll", nullptr },
{ L"msvcp100.dll", nullptr },
diff --git a/plugins/PluginUpdater/src/PluginUpdater.cpp b/plugins/PluginUpdater/src/PluginUpdater.cpp
index 863a93ac7b..629ff6961c 100644
--- a/plugins/PluginUpdater/src/PluginUpdater.cpp
+++ b/plugins/PluginUpdater/src/PluginUpdater.cpp
@@ -30,7 +30,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/PluginUpdater/src/version.h b/plugins/PluginUpdater/src/version.h
index d3477ff6fd..101680e3a2 100644
--- a/plugins/PluginUpdater/src/version.h
+++ b/plugins/PluginUpdater/src/version.h
@@ -7,8 +7,7 @@
#define __PLUGIN_NAME "Plugin updater"
#define __FILENAME "PluginUpdater.dll"
-#define __DESCRIPTION "Install and update plugins and other Miranda NG components."
+#define __DESCRIPTION "Installs and updates plugins and other Miranda NG components."
#define __AUTHOR "Mataes, George Hazan"
-#define __AUTHOREMAIL "mataes2007@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/PluginUpdater/"
#define __COPYRIGHT "© 2012-17 Mataes, George Hazan"
diff --git a/plugins/Popup/src/config.cpp b/plugins/Popup/src/config.cpp
index c6ae1a1ffc..fc276a1b63 100644
--- a/plugins/Popup/src/config.cpp
+++ b/plugins/Popup/src/config.cpp
@@ -54,7 +54,6 @@ PLUGININFOEX pluginInfoEx =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Popup/src/popup_wnd2.cpp b/plugins/Popup/src/popup_wnd2.cpp
index a3d5c3c425..fada19920f 100644
--- a/plugins/Popup/src/popup_wnd2.cpp
+++ b/plugins/Popup/src/popup_wnd2.cpp
@@ -545,9 +545,9 @@ int PopupWnd2::fixActions(POPUPACTION *theActions, int count)
{
bool isIm = (m_hContact && (CallProtoService(GetContactProto(m_hContact), PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IM)) ? true : false;
- bool enableDefaultGen = (m_hContact || !(PopupOptions.actions&ACT_DEF_NOGLOBAL)) ? true : false;
- bool enableDefaultUsr = (isIm || m_hContact && !(PopupOptions.actions&ACT_DEF_IMONLY)) ? true : false;
- bool iconSize = PopupOptions.actions&ACT_LARGE ? TRUE : FALSE;
+ bool enableDefaultGen = (m_hContact || !(PopupOptions.actions & ACT_DEF_NOGLOBAL)) ? true : false;
+ bool enableDefaultUsr = (isIm || m_hContact && !(PopupOptions.actions & ACT_DEF_IMONLY)) ? true : false;
+ bool iconSize = PopupOptions.actions & ACT_LARGE ? TRUE : FALSE;
if (PopupOptions.actions & ACT_ENABLE) {
if (enableDefaultUsr && isIm && IsActionEnabled("General/Quick reply")) ++m_actionCount;
@@ -857,7 +857,7 @@ LRESULT CALLBACK ReplyEditWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM
case WM_DESTROY:
PopupThreadUnlock();
- if (!(PopupOptions.actions&ACT_DEF_KEEPWND))
+ if (!(PopupOptions.actions & ACT_DEF_KEEPWND))
PUDeletePopup(dat->hwndPopup);
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)dat->oldWndProc);
SetWindowLongPtr(hwnd, GWLP_USERDATA, 0);
@@ -908,7 +908,7 @@ LRESULT CALLBACK PopupWnd2::WindowProc(UINT message, WPARAM wParam, LPARAM lPara
switch (lParam) {
case ACT_DEF_MESSAGE:
CallServiceSync(MS_MSG_SENDMESSAGE, (WPARAM)m_hContact, 0);
- if (!(PopupOptions.actions&ACT_DEF_KEEPWND))
+ if (!(PopupOptions.actions & ACT_DEF_KEEPWND))
PUDeletePopup(m_hwnd);
break;
@@ -936,7 +936,7 @@ LRESULT CALLBACK PopupWnd2::WindowProc(UINT message, WPARAM wParam, LPARAM lPara
case ACT_DEF_DETAILS:
CallServiceSync(MS_USERINFO_SHOWDIALOG, (WPARAM)m_hContact, 0);
- if (!(PopupOptions.actions&ACT_DEF_KEEPWND))
+ if (!(PopupOptions.actions & ACT_DEF_KEEPWND))
PUDeletePopup(m_hwnd);
break;
@@ -946,15 +946,9 @@ LRESULT CALLBACK PopupWnd2::WindowProc(UINT message, WPARAM wParam, LPARAM lPara
break;
case ACT_DEF_ADD:
- {
- ADDCONTACTSTRUCT acs = { 0 };
- acs.hContact = m_hContact;
- acs.handleType = HANDLE_CONTACT;
- acs.szProto = nullptr;
- CallServiceSync(MS_ADDCONTACT_SHOW, NULL, (LPARAM)&acs);
- if (!(PopupOptions.actions&ACT_DEF_KEEPWND))
- PUDeletePopup(m_hwnd);
- }
+ Contact_Add(m_hContact);
+ if (!(PopupOptions.actions & ACT_DEF_KEEPWND))
+ PUDeletePopup(m_hwnd);
break;
case ACT_DEF_PIN:
@@ -965,7 +959,7 @@ LRESULT CALLBACK PopupWnd2::WindowProc(UINT message, WPARAM wParam, LPARAM lPara
m_bIsPinned = !m_bIsPinned;
{
- bool iconSize = PopupOptions.actions&ACT_LARGE ? TRUE : FALSE;
+ bool iconSize = PopupOptions.actions & ACT_LARGE ? TRUE : FALSE;
PUModifyActionIcon(m_hwnd, wParam, lParam, m_bIsPinned ? LoadIconEx(IDI_ACT_PINNED, iconSize) : LoadIconEx(IDI_ACT_PIN, iconSize));
}
break;
@@ -1011,7 +1005,7 @@ LRESULT CALLBACK PopupWnd2::WindowProc(UINT message, WPARAM wParam, LPARAM lPara
case UM_MENUDONE:
{
unlock();
- if (!(PopupOptions.actions&ACT_DEF_KEEPWND))
+ if (!(PopupOptions.actions & ACT_DEF_KEEPWND))
PUDeletePopup(m_hwnd);
break;
}
diff --git a/plugins/Popup/src/skin.cpp b/plugins/Popup/src/skin.cpp
index 157c9aa981..bd912cf115 100644
--- a/plugins/Popup/src/skin.cpp
+++ b/plugins/Popup/src/skin.cpp
@@ -128,8 +128,8 @@ void PopupSkin::drawAction(MyBitmap *bmp, POPUPACTION *act, int x, int y, bool h
wchar_t *str = TranslateW(wname);
GetTextExtentPoint32(bmp->getDC(), str, (int)mir_wstrlen(str), &szText);
bmp->Draw_Text(str,
- (PopupOptions.actions&ACT_LARGE) ? (x + szSpace.cx + 32) : (x + szSpace.cx + 16),
- max(y + 2, y + 2 + (((PopupOptions.actions&ACT_LARGE) ? 32 : 16) - szText.cy) / 2));
+ (PopupOptions.actions & ACT_LARGE) ? (x + szSpace.cx + 32) : (x + szSpace.cx + 16),
+ max(y + 2, y + 2 + (((PopupOptions.actions & ACT_LARGE) ? 32 : 16) - szText.cy) / 2));
mir_free(wname);
SelectObject(bmp->getDC(), hFntSave);
@@ -139,8 +139,8 @@ void PopupSkin::drawAction(MyBitmap *bmp, POPUPACTION *act, int x, int y, bool h
RECT rc;
rc.left = x;
rc.top = y;
- rc.right = x + ((PopupOptions.actions&ACT_LARGE) ? 32 : 16) + 4;
- rc.bottom = y + ((PopupOptions.actions&ACT_LARGE) ? 32 : 16) + 4;
+ rc.right = x + ((PopupOptions.actions & ACT_LARGE) ? 32 : 16) + 4;
+ rc.bottom = y + ((PopupOptions.actions & ACT_LARGE) ? 32 : 16) + 4;
bmp->saveAlpha(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
HBRUSH hbr = CreateSolidBrush(fonts.clActionHover);
FrameRect(bmp->getDC(), &rc, hbr);
@@ -520,7 +520,7 @@ void PopupSkin::display(MyBitmap *bmp, PopupWnd2 *wnd, POPUPOPTIONS *options, DW
drawActionBar(bmp, wnd,
db_get_b(NULL, MODULNAME, "CenterActions", 0) ?
(pt.x + (textAreaWidth - wnd->getRenderInfo()->actw) / 2) :
- (PopupOptions.actions&ACT_RIGHTICONS) ?
+ (PopupOptions.actions & ACT_RIGHTICONS) ?
(pt.x + textAreaWidth - wnd->getRenderInfo()->actw) :
// else
pt.x,
diff --git a/plugins/Popup/src/stdafx.h b/plugins/Popup/src/stdafx.h
index e892d518f6..75e7733f12 100644
--- a/plugins/Popup/src/stdafx.h
+++ b/plugins/Popup/src/stdafx.h
@@ -72,7 +72,7 @@ https://miranda-ng.org/distr/
#include <m_button.h>
#include <m_message.h>
#include <m_userinfo.h>
-#include <m_addcontact.h>
+#include <m_contacts.h>
#include <m_clc.h>
#include <m_icolib.h>
#include <m_genmenu.h>
diff --git a/plugins/Popup/src/version.h b/plugins/Popup/src/version.h
index 45bbca6f8c..cbbaf99aa8 100644
--- a/plugins/Popup/src/version.h
+++ b/plugins/Popup/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Popup.dll"
#define __DESCRIPTION "Provides popup notification services for different plugins."
#define __AUTHOR "MPK, Merlin_de (Luca Santarelli, Victor Pavlychko)"
-#define __AUTHOREMAIL "mp-king@web.de"
#define __AUTHORWEB "https://miranda-ng.org/p/Popup/"
#define __COPYRIGHT "© 2002 Luca Santarelli, 2004-2007 Victor Pavlychko, 2010 MPK, Merlin_de"
diff --git a/plugins/ProfileManager/src/pmanagerEx.cpp b/plugins/ProfileManager/src/pmanagerEx.cpp
index 4b221431e1..860414c0d5 100644
--- a/plugins/ProfileManager/src/pmanagerEx.cpp
+++ b/plugins/ProfileManager/src/pmanagerEx.cpp
@@ -23,7 +23,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/ProfileManager/src/version.h b/plugins/ProfileManager/src/version.h
index dbcb79f127..6fe96108dc 100644
--- a/plugins/ProfileManager/src/version.h
+++ b/plugins/ProfileManager/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "PManagerEx.dll"
#define __DESCRIPTION "Adds a menu item to change or load a different profile of Miranda NG, restart or run DbChecker."
#define __AUTHOR "Roman Gemini"
-#define __AUTHOREMAIL "woobind@ukr.net"
#define __AUTHORWEB "https://miranda-ng.org/p/PManagerEx/"
#define __COPYRIGHT "© 2008-10 Roman Gemini"
diff --git a/plugins/QuickContacts/src/quickcontacts.cpp b/plugins/QuickContacts/src/quickcontacts.cpp
index 75034af9ca..7407230a1f 100644
--- a/plugins/QuickContacts/src/quickcontacts.cpp
+++ b/plugins/QuickContacts/src/quickcontacts.cpp
@@ -28,7 +28,6 @@ PLUGININFOEX pluginInfo={
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/QuickContacts/src/version.h b/plugins/QuickContacts/src/version.h
index eee85d9015..9f499e0d6f 100644
--- a/plugins/QuickContacts/src/version.h
+++ b/plugins/QuickContacts/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "QuickContacts.dll"
#define __DESCRIPTION "Open contact-specific windows by hotkey."
#define __AUTHOR "Ricardo Pescuma Domenecci, Heiko Schillinger"
-#define __AUTHOREMAIL "pescuma@miranda-im.org"
#define __AUTHORWEB "https://miranda-ng.org/p/QuickContacts/"
#define __COPYRIGHT "© 2007-2009 Ricardo Pescuma Domenecci"
diff --git a/plugins/QuickMessages/src/main.cpp b/plugins/QuickMessages/src/main.cpp
index f16c798875..5502ea2d14 100644
--- a/plugins/QuickMessages/src/main.cpp
+++ b/plugins/QuickMessages/src/main.cpp
@@ -38,7 +38,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/QuickMessages/src/version.h b/plugins/QuickMessages/src/version.h
index b3ead27ca7..460fe7d3a2 100644
--- a/plugins/QuickMessages/src/version.h
+++ b/plugins/QuickMessages/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "QuickMessages.dll"
#define __DESCRIPTION "Plugin for quick insert pre-defined messages in message input area."
#define __AUTHOR "MaD_CLuSTeR"
-#define __AUTHOREMAIL "daniok@yandex.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/QuickMessages/"
#define __COPYRIGHT "© 2008 Danil Mozhar"
diff --git a/plugins/QuickReplies/src/quickreplies.cpp b/plugins/QuickReplies/src/quickreplies.cpp
index cf424fa336..428b0ec6b2 100644
--- a/plugins/QuickReplies/src/quickreplies.cpp
+++ b/plugins/QuickReplies/src/quickreplies.cpp
@@ -28,7 +28,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/QuickReplies/src/version.h b/plugins/QuickReplies/src/version.h
index 9d1580a360..d98e4c1821 100644
--- a/plugins/QuickReplies/src/version.h
+++ b/plugins/QuickReplies/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "QuickReplies.dll"
#define __DESCRIPTION "Plugin for quick insert (or sending) pre-defined messages in message input area."
#define __AUTHOR "Unsane"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/QuickReplies/"
#define __COPYRIGHT "© 2010 Unsane"
diff --git a/plugins/QuickSearch/quicksearch.dpr b/plugins/QuickSearch/quicksearch.dpr
index c9f90d01fb..5dede8135b 100644
--- a/plugins/QuickSearch/quicksearch.dpr
+++ b/plugins/QuickSearch/quicksearch.dpr
@@ -32,7 +32,6 @@ begin
'And now you may add any setting to display - for example '+
'user''s version of Miranda, group or city.';
PluginInfo.author :='Awkward, based on Bethoven sources';
- PluginInfo.authorEmail:='panda75@bk.ru; awk1975@ya.ru';
PluginInfo.copyright :='(c) 2004,2005 Bethoven; 2006-2013 Awkward';
PluginInfo.homepage :='http://code.google.com/p/delphi-miranda-plugins/';
PluginInfo.flags :=UNICODE_AWARE;
diff --git a/plugins/Quotes/docs/Utility/google.xml b/plugins/Quotes/docs/Utility/google.xml
index 7b22acd3ac..c6304da1a6 100644
--- a/plugins/Quotes/docs/Utility/google.xml
+++ b/plugins/Quotes/docs/Utility/google.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Provider>
<name>Google</name>
@@ -8,26 +8,57 @@
<section>
<name>Currencies</name>
<quote>
- <id>AED</id>
- <symbol>AED</symbol>
- <description>United Arab Emirates Dirham (AED)</description>
+ <id>AED</id><symbol>AED</symbol><description>United Arab Emirates Dirham (AED)</description>
+ </quote>
+ <quote>
+ <id>AFN</id><symbol>AFN</symbol><description>Afghan Afghani (AFN)</description>
+ </quote>
+ <quote>
+ <id>ALL</id><symbol>ALL</symbol><description>Albanian Lek (ALL)</description>
+ </quote>
+ <quote>
+ <id>AMD</id><symbol>AMD</symbol><description>Armenian Dram (AMD)</description>
</quote>
<quote>
<id>ANG</id><symbol>ANG</symbol><description>Netherlands Antillean Gulden (ANG)</description>
</quote>
<quote>
+ <id>AOA</id><symbol>AOA</symbol><description>Angolan Kwanza (AOA)</description>
+ </quote>
+ <quote>
<id>ARS</id><symbol>ARS</symbol><description>Argentine Peso (ARS)</description>
</quote>
<quote>
<id>AUD</id><symbol>AUD</symbol><description>Australian Dollar (AUD)</description>
</quote>
<quote>
+ <id>AWG</id><symbol>AWG</symbol><description>Aruban Florin (AWG)</description>
+ </quote>
+ <quote>
+ <id>AZN</id><symbol>AZN</symbol><description>Azerbaijani Manat (AZN)</description>
+ </quote>
+ <quote>
+ <id>BAM</id><symbol>BAM</symbol><description>Bosnia-Herzegovina Convertible Mark (BAM)</description>
+ </quote>
+ <quote>
+ <id>BBD</id><symbol>BBD</symbol><description>Barbadian Dollar (BBD)</description>
+ </quote>
+ <quote>
+ <id>BDT</id><symbol>BDT</symbol><description>Bangladeshi Taka (BDT)</description>
+ </quote>
+ <quote>
<id>BGN</id><symbol>BGN</symbol><description>Bulgarian Lev (BGN)</description>
</quote>
<quote>
<id>BHD</id><symbol>BHD</symbol><description>Bahraini Dinar (BHD)</description>
</quote>
<quote>
+ <id>BIF</id><symbol>BIF</symbol><description>Burundian Franc (BIF)</description>
+ </quote>
+ <quote>
+ <id>BMD</id><symbol>BMD</symbol><description>Bermudan Dollar (BMD)</description>
+ </quote>
+ <quote>
<id>BND</id><symbol>BND</symbol><description>Brunei Dollar (BND)</description>
</quote>
<quote>
@@ -37,58 +68,451 @@
<id>BRL</id><symbol>BRL</symbol><description>Brazilian Real (BRL)</description>
</quote>
<quote>
+ <id>BSD</id><symbol>BSD</symbol><description>Bahamian Dollar (BSD)</description>
+ </quote>
+ <quote>
+ <id>BTC</id><symbol>BTC</symbol><description>Bitcoin (BTC)</description>
+ </quote>
+ <quote>
+ <id>BTN</id><symbol>BTN</symbol><description>Bhutanese Ngultrum (BTN)</description>
+ </quote>
+ <quote>
<id>BWP</id><symbol>BWP</symbol><description>Botswana Pula (BWP)</description>
</quote>
<quote>
- <id>BYR</id><symbol>BYR</symbol><description>Belarusian Ruble (BYR)</description>
+ <id>BYN</id><symbol>BYN</symbol><description>Belarusian Ruble (BYN)</description>
+ </quote>
+ <quote>
+ <id>BYR</id><symbol>BYR</symbol><description>Belarusian Ruble (2000–2016) (BYR)</description>
+ </quote>
+ <quote>
+ <id>BZD</id><symbol>BZD</symbol><description>Belize Dollar (BZD)</description>
</quote>
<quote>
<id>CAD</id><symbol>CAD</symbol><description>Canadian Dollar (CAD)</description>
</quote>
<quote>
+ <id>CDF</id><symbol>CDF</symbol><description>Congolese Franc (CDF)</description>
+ </quote>
+ <quote>
<id>CHF</id><symbol>CHF</symbol><description>Swiss Franc (CHF)</description>
</quote>
<quote>
+ <id>CLF</id><symbol>CLF</symbol><description>Chilean Unit of Account (UF) (CLF)</description>
+ </quote>
+ <quote>
<id>CLP</id><symbol>CLP</symbol><description>Chilean Peso (CLP)</description>
</quote>
<quote>
- <id>CNY</id><symbol>CNY</symbol><description>Chinese Yuan (renminbi) (CNY)</description>
+ <id>CNH</id><symbol>CNH</symbol><description>CNH (CNH)</description>
+ </quote>
+ <quote>
+ <id>CNY</id><symbol>CNY</symbol><description>Chinese Yuan (CNY)</description>
</quote>
<quote>
<id>COP</id><symbol>COP</symbol><description>Colombian Peso (COP)</description>
</quote>
<quote>
- <id>CSD</id><symbol>CSD</symbol><description>Serbian Dinar (CSD)</description>
+ <id>CRC</id><symbol>CRC</symbol><description>Costa Rican Colón (CRC)</description>
+ </quote>
+ <quote>
+ <id>CUP</id><symbol>CUP</symbol><description>Cuban Peso (CUP)</description>
+ </quote>
+ <quote>
+ <id>CVE</id><symbol>CVE</symbol><description>Cape Verdean Escudo (CVE)</description>
</quote>
<quote>
<id>CZK</id><symbol>CZK</symbol><description>Czech Koruna (CZK)</description>
</quote>
<quote>
+ <id>DEM</id><symbol>DEM</symbol><description>German Mark (DEM)</description>
+ </quote>
+ <quote>
+ <id>DJF</id><symbol>DJF</symbol><description>Djiboutian Franc (DJF)</description>
+ </quote>
+ <quote>
<id>DKK</id><symbol>DKK</symbol><description>Danish Krone (DKK)</description>
</quote>
<quote>
- <id>EEK</id><symbol>EEK</symbol><description>Estonian Kroon (EEK)</description>
- </quote>
+ <id>DOP</id><symbol>DOP</symbol><description>Dominican Peso (DOP)</description>
+ </quote>
+ <quote>
+ <id>DZD</id><symbol>DZD</symbol><description>Algerian Dinar (DZD)</description>
+ </quote>
<quote>
<id>EGP</id><symbol>EGP</symbol><description>Egyptian Pound (EGP)</description>
</quote>
<quote>
+ <id>ERN</id><symbol>ERN</symbol><description>Eritrean Nakfa (ERN)</description>
+ </quote>
+ <quote>
+ <id>ETB</id><symbol>ETB</symbol><description>Ethiopian Birr (ETB)</description>
+ </quote>
+ <quote>
<id>EUR</id><symbol>EUR</symbol><description>Euro (EUR)</description>
</quote>
<quote>
+ <id>FIM</id><symbol>FIM</symbol><description>Finnish Markka (FIM)</description>
+ </quote>
+ <quote>
<id>FJD</id><symbol>FJD</symbol><description>Fijian Dollar (FJD)</description>
</quote>
- <quote><id>GBP</id><symbol>GBP</symbol><description>British Pound (GBP)</description></quote><quote><id>HKD</id><symbol>HKD</symbol><description>Hong Kong Dollar (HKD)</description></quote><quote><id>HNL</id><symbol>HNL</symbol><description>Honduran Lempira (HNL)</description></quote><quote><id>HRK</id><symbol>HRK</symbol><description>Croatian Kuna (HRK)</description></quote><quote><id>HUF</id><symbol>HUF</symbol><description>Hungarian Forint (HUF)</description></quote><quote><id>IDR</id><symbol>IDR</symbol><description>Indonesian Rupiah (IDR)</description></quote><quote><id>ILS</id><symbol>ILS</symbol><description>New Israeli Sheqel (ILS)</description></quote><quote><id>INR</id><symbol>INR</symbol><description>Indian Rupee (INR)</description></quote><quote><id>ISK</id><symbol>ISK</symbol><description>Icelandic Króna (ISK)</description></quote><quote><id>JPY</id><symbol>JPY</symbol><description>Japanese Yen (JPY)</description></quote><quote><id>KRW</id><symbol>KRW</symbol><description>South Korean Won (KRW)</description></quote><quote><id>KWD</id><symbol>KWD</symbol><description>Kuwaiti Dinar (KWD)</description></quote><quote><id>KZT</id><symbol>KZT</symbol><description>Kazakhstani Tenge (KZT)</description></quote><quote><id>LKR</id><symbol>LKR</symbol><description>Sri Lankan Rupee (LKR)</description></quote><quote><id>LTL</id><symbol>LTL</symbol><description>Lithuanian Litas (LTL)</description></quote><quote><id>MAD</id><symbol>MAD</symbol><description>Moroccan Dirham (MAD)</description></quote><quote><id>MUR</id><symbol>MUR</symbol><description>Mauritian Rupee (MUR)</description></quote><quote><id>MXN</id><symbol>MXN</symbol><description>Mexican Peso (MXN)</description></quote><quote><id>MYR</id><symbol>MYR</symbol><description>Malaysian Ringgit (MYR)</description></quote><quote><id>NOK</id><symbol>NOK</symbol><description>Norwegian Krone (NOK)</description></quote><quote><id>NPR</id><symbol>NPR</symbol><description>Nepalese Rupee (NPR)</description></quote><quote><id>NZD</id><symbol>NZD</symbol><description>New Zealand Dollar (NZD)</description></quote><quote><id>OMR</id><symbol>OMR</symbol><description>Omani Rial (OMR)</description></quote><quote><id>PEN</id><symbol>PEN</symbol><description>Peruvian Nuevo Sol (PEN)</description></quote><quote><id>PHP</id><symbol>PHP</symbol><description>Philippine Peso (PHP)</description></quote><quote><id>PKR</id><symbol>PKR</symbol><description>Pakistani Rupee (PKR)</description></quote><quote><id>PLN</id><symbol>PLN</symbol><description>Polish Złoty (PLN)</description></quote><quote><id>QAR</id><symbol>QAR</symbol><description>Qatari Riyal (QAR)</description></quote><quote><id>RON</id><symbol>RON</symbol><description>New Romanian Leu (RON)</description></quote>
-
+ <quote>
+ <id>FKP</id><symbol>FKP</symbol><description>Falkland Islands Pound (FKP)</description>
+ </quote>
+ <quote>
+ <id>FRF</id><symbol>FRF</symbol><description>French Franc (FRF)</description>
+ </quote>
+ <quote>
+ <id>GBP</id><symbol>GBP</symbol><description>British Pound (GBP)</description>
+ </quote>
+ <quote>
+ <id>GEL</id><symbol>GEL</symbol><description>Georgian Lari (GEL)</description>
+ </quote>
+ <quote>
+ <id>GHS</id><symbol>GHS</symbol><description>Ghanaian Cedi (GHS)</description>
+ </quote>
+ <quote>
+ <id>GIP</id><symbol>GIP</symbol><description>Gibraltar Pound (GIP)</description>
+ </quote>
+ <quote>
+ <id>GMD</id><symbol>GMD</symbol><description>Gambian Dalasi (GMD)</description>
+ </quote>
+ <quote>
+ <id>GNF</id><symbol>GNF</symbol><description>Guinean Franc (GNF)</description>
+ </quote>
+ <quote>
+ <id>GTQ</id><symbol>GTQ</symbol><description>Guatemalan Quetzal (GTQ)</description>
+ </quote>
+ <quote>
+ <id>GYD</id><symbol>GYD</symbol><description>Guyanaese Dollar (GYD)</description>
+ </quote>
+ <quote>
+ <id>HKD</id><symbol>HKD</symbol><description>Hong Kong Dollar (HKD)</description>
+ </quote>
+ <quote>
+ <id>HNL</id><symbol>HNL</symbol><description>Honduran Lempira (HNL)</description>
+ </quote>
+ <quote>
+ <id>HRK</id><symbol>HRK</symbol><description>Croatian Kuna (HRK)</description>
+ </quote>
+ <quote>
+ <id>HTG</id><symbol>HTG</symbol><description>Haitian Gourde (HTG)</description>
+ </quote>
+ <quote>
+ <id>HUF</id><symbol>HUF</symbol><description>Hungarian Forint (HUF)</description>
+ </quote>
+ <quote>
+ <id>IDR</id><symbol>IDR</symbol><description>Indonesian Rupiah (IDR)</description>
+ </quote>
+ <quote>
+ <id>IEP</id><symbol>IEP</symbol><description>Irish Pound (IEP)</description>
+ </quote>
+ <quote>
+ <id>ILS</id><symbol>ILS</symbol><description>Israeli New Shekel (ILS)</description>
+ </quote>
+ <quote>
+ <id>INR</id><symbol>INR</symbol><description>Indian Rupee (INR)</description>
+ </quote>
+ <quote>
+ <id>IQD</id><symbol>IQD</symbol><description>Iraqi Dinar (IQD)</description>
+ </quote>
+ <quote>
+ <id>IRR</id><symbol>IRR</symbol><description>Iranian Rial (IRR)</description>
+ </quote>
+ <quote>
+ <id>ISK</id><symbol>ISK</symbol><description>Icelandic Króna (ISK)</description>
+ </quote>
+ <quote>
+ <id>ITL</id><symbol>ITL</symbol><description>Italian Lira (ITL)</description>
+ </quote>
+ <quote>
+ <id>JMD</id><symbol>JMD</symbol><description>Jamaican Dollar (JMD)</description>
+ </quote>
+ <quote>
+ <id>JOD</id><symbol>JOD</symbol><description>Jordanian Dinar (JOD)</description>
+ </quote>
+ <quote>
+ <id>JPY</id><symbol>JPY</symbol><description>Japanese Yen (JPY)</description>
+ </quote>
+ <quote>
+ <id>KES</id><symbol>KES</symbol><description>Kenyan Shilling (KES)</description>
+ </quote>
+ <quote>
+ <id>KGS</id><symbol>KGS</symbol><description>Kyrgystani Som (KGS)</description>
+ </quote>
+ <quote>
+ <id>KHR</id><symbol>KHR</symbol><description>Cambodian Riel (KHR)</description>
+ </quote>
+ <quote>
+ <id>KMF</id><symbol>KMF</symbol><description>Comorian Franc (KMF)</description>
+ </quote>
+ <quote>
+ <id>KPW</id><symbol>KPW</symbol><description>North Korean Won (KPW)</description>
+ </quote>
+ <quote>
+ <id>KRW</id><symbol>KRW</symbol><description>South Korean Won (KRW)</description>
+ </quote>
+ <quote>
+ <id>KWD</id><symbol>KWD</symbol><description>Kuwaiti Dinar (KWD)</description>
+ </quote>
+ <quote>
+ <id>KYD</id><symbol>KYD</symbol><description>Cayman Islands Dollar (KYD)</description>
+ </quote>
+ <quote>
+ <id>KZT</id><symbol>KZT</symbol><description>Kazakhstani Tenge (KZT)</description>
+ </quote>
+ <quote>
+ <id>LAK</id><symbol>LAK</symbol><description>Laotian Kip (LAK)</description>
+ </quote>
+ <quote>
+ <id>LBP</id><symbol>LBP</symbol><description>Lebanese Pound (LBP)</description>
+ </quote>
+ <quote>
+ <id>LKR</id><symbol>LKR</symbol><description>Sri Lankan Rupee (LKR)</description>
+ </quote>
+ <quote>
+ <id>LRD</id><symbol>LRD</symbol><description>Liberian Dollar (LRD)</description>
+ </quote>
+ <quote>
+ <id>LSL</id><symbol>LSL</symbol><description>Lesotho Loti (LSL)</description>
+ </quote>
+ <quote>
+ <id>LTL</id><symbol>LTL</symbol><description>Lithuanian Litas (LTL)</description>
+ </quote>
+ <quote>
+ <id>LVL</id><symbol>LVL</symbol><description>Latvian Lats (LVL)</description>
+ </quote>
+ <quote>
+ <id>LYD</id><symbol>LYD</symbol><description>Libyan Dinar (LYD)</description>
+ </quote>
+ <quote>
+ <id>MAD</id><symbol>MAD</symbol><description>Moroccan Dirham (MAD)</description>
+ </quote>
+ <quote>
+ <id>MDL</id><symbol>MDL</symbol><description>Moldovan Leu (MDL)</description>
+ </quote>
+ <quote>
+ <id>MGA</id><symbol>MGA</symbol><description>Malagasy Ariary (MGA)</description>
+ </quote>
+ <quote>
+ <id>MKD</id><symbol>MKD</symbol><description>Macedonian Denar (MKD)</description>
+ </quote>
+ <quote>
+ <id>MNT</id><symbol>MNT</symbol><description>Mongolian Tugrik (MNT)</description>
+ </quote>
+ <quote>
+ <id>MOP</id><symbol>MOP</symbol><description>Macanese Pataca (MOP)</description>
+ </quote>
+ <quote>
+ <id>MRO</id><symbol>MRO</symbol><description>Mauritanian Ouguiya (MRO)</description>
+ </quote>
+ <quote>
+ <id>MUR</id><symbol>MUR</symbol><description>Mauritian Rupee (MUR)</description>
+ </quote>
+ <quote>
+ <id>MVR</id><symbol>MVR</symbol><description>Maldivian Rufiyaa (MVR)</description>
+ </quote>
+ <quote>
+ <id>MWK</id><symbol>MWK</symbol><description>Malawian Kwacha (MWK)</description>
+ </quote>
+ <quote>
+ <id>MXN</id><symbol>MXN</symbol><description>Mexican Peso (MXN)</description>
+ </quote>
+ <quote>
+ <id>MYR</id><symbol>MYR</symbol><description>Malaysian Ringgit (MYR)</description>
+ </quote>
+ <quote>
+ <id>MZN</id><symbol>MZN</symbol><description>Mozambican Metical (MZN)</description>
+ </quote>
+ <quote>
+ <id>NAD</id><symbol>NAD</symbol><description>Namibian Dollar (NAD)</description>
+ </quote>
+ <quote>
+ <id>NGN</id><symbol>NGN</symbol><description>Nigerian Naira (NGN)</description>
+ </quote>
+ <quote>
+ <id>NIO</id><symbol>NIO</symbol><description>Nicaraguan Córdoba (NIO)</description>
+ </quote>
+ <quote>
+ <id>NOK</id><symbol>NOK</symbol><description>Norwegian Krone (NOK)</description>
+ </quote>
+ <quote>
+ <id>NPR</id><symbol>NPR</symbol><description>Nepalese Rupee (NPR)</description>
+ </quote>
+ <quote>
+ <id>NZD</id><symbol>NZD</symbol><description>New Zealand Dollar (NZD)</description>
+ </quote>
+ <quote>
+ <id>OMR</id><symbol>OMR</symbol><description>Omani Rial (OMR)</description>
+ </quote>
+ <quote>
+ <id>PAB</id><symbol>PAB</symbol><description>Panamanian Balboa (PAB)</description>
+ </quote>
+ <quote>
+ <id>PEN</id><symbol>PEN</symbol><description>Peruvian Nuevo Sol (PEN)</description>
+ </quote>
+ <quote>
+ <id>PGK</id><symbol>PGK</symbol><description>Papua New Guinean Kina (PGK)</description>
+ </quote>
+ <quote>
+ <id>PHP</id><symbol>PHP</symbol><description>Philippine Peso (PHP)</description>
+ </quote>
+ <quote>
+ <id>PKG</id><symbol>PKG</symbol><description>PKG (PKG)</description>
+ </quote>
+ <quote>
+ <id>PKR</id><symbol>PKR</symbol><description>Pakistani Rupee (PKR)</description>
+ </quote>
+ <quote>
+ <id>PLN</id><symbol>PLN</symbol><description>Polish Zloty (PLN)</description>
+ </quote>
+ <quote>
+ <id>PYG</id><symbol>PYG</symbol><description>Paraguayan Guarani (PYG)</description>
+ </quote>
+ <quote>
+ <id>QAR</id><symbol>QAR</symbol><description>Qatari Riyal (QAR)</description>
+ </quote>
+ <quote>
+ <id>RON</id><symbol>RON</symbol><description>New Romanian Leu (RON)</description>
+ </quote>
+ <quote>
+ <id>RSD</id><symbol>RSD</symbol><description>Serbian Dinar (RSD)</description>
+ </quote>
<quote>
<id>RUB</id><symbol>RUB</symbol><description>Russian Ruble (RUB)</description>
</quote>
<quote>
+ <id>RWF</id><symbol>RWF</symbol><description>Rwandan Franc (RWF)</description>
+ </quote>
+ <quote>
<id>SAR</id><symbol>SAR</symbol><description>Saudi Riyal (SAR)</description>
</quote>
- <quote><id>SEK</id><symbol>SEK</symbol><description>Swedish Krona (SEK)</description></quote><quote><id>SGD</id><symbol>SGD</symbol><description>Singapore Dollar (SGD)</description></quote><quote><id>SIT</id><symbol>SIT</symbol><description>Slovenian Tolar (SIT)</description></quote><quote><id>SKK</id><symbol>SKK</symbol><description>Slovak Koruna (SKK)</description></quote><quote><id>THB</id><symbol>THB</symbol><description>Thai Baht (THB)</description></quote><quote><id>TRY</id><symbol>TRY</symbol><description>New Turkish Lira (TRY)</description></quote><quote><id>TTD</id><symbol>TTD</symbol><description>Trinidad and Tobago Dollar (TTD)</description></quote><quote><id>TWD</id><symbol>TWD</symbol><description>New Taiwan Dollar (TWD)</description></quote><quote><id>UAH</id><symbol>UAH</symbol><description>Ukrainian Hryvnia (UAH)</description></quote><quote><id>USD</id><symbol>USD</symbol><description>United States Dollar (USD)</description></quote><quote><id>VEB</id><symbol>VEB</symbol><description>Venezuelan Bolívar (VEB)</description></quote><quote><id>ZAR</id><symbol>ZAR</symbol><description>South African Rand (ZAR)</description></quote>
+ <quote>
+ <id>SBD</id><symbol>SBD</symbol><description>Solomon Islands Dollar (SBD)</description>
+ </quote>
+ <quote>
+ <id>SCR</id><symbol>SCR</symbol><description>Seychellois Rupee (SCR)</description>
+ </quote>
+ <quote>
+ <id>SDG</id><symbol>SDG</symbol><description>Sudanese Pound (SDG)</description>
+ </quote>
+ <quote>
+ <id>SEK</id><symbol>SEK</symbol><description>Swedish Krona (SEK)</description>
+ </quote>
+ <quote>
+ <id>SGD</id><symbol>SGD</symbol><description>Singapore Dollar (SGD)</description>
+ </quote>
+ <quote>
+ <id>SHP</id><symbol>SHP</symbol><description>St. Helena Pound (SHP)</description>
+ </quote>
+ <quote>
+ <id>SKK</id><symbol>SKK</symbol><description>Slovak Koruna (SKK)</description>
+ </quote>
+ <quote>
+ <id>SLL</id><symbol>SLL</symbol><description>Sierra Leonean Leone (SLL)</description>
+ </quote>
+ <quote>
+ <id>SOS</id><symbol>SOS</symbol><description>Somali Shilling (SOS)</description>
+ </quote>
+ <quote>
+ <id>SRD</id><symbol>SRD</symbol><description>Surinamese Dollar (SRD)</description>
+ </quote>
+ <quote>
+ <id>STD</id><symbol>STD</symbol><description>São Tomé & Príncipe Dobra (STD)</description>
+ </quote>
+ <quote>
+ <id>SVC</id><symbol>SVC</symbol><description>Salvadoran Colón (SVC)</description>
+ </quote>
+ <quote>
+ <id>SYP</id><symbol>SYP</symbol><description>Syrian Pound (SYP)</description>
+ </quote>
+ <quote>
+ <id>SZL</id><symbol>SZL</symbol><description>Swazi Lilangeni (SZL)</description>
+ </quote>
+ <quote>
+ <id>THB</id><symbol>THB</symbol><description>Thai Baht (THB)</description>
+ </quote>
+ <quote>
+ <id>TJS</id><symbol>TJS</symbol><description>Tajikistani Somoni (TJS)</description>
+ </quote>
+ <quote>
+ <id>TMT</id><symbol>TMT</symbol><description>Turkmenistani Manat (TMT)</description>
+ </quote>
+ <quote>
+ <id>TND</id><symbol>TND</symbol><description>Tunisian Dinar (TND)</description>
+ </quote>
+ <quote>
+ <id>TOP</id><symbol>TOP</symbol><description>Tongan Paʻanga (TOP)</description>
+ </quote>
+ <quote>
+ <id>TRY</id><symbol>TRY</symbol><description>Turkish Lira (TRY)</description>
+ </quote>
+ <quote>
+ <id>TTD</id><symbol>TTD</symbol><description>Trinidad & Tobago Dollar (TTD)</description>
+ </quote>
+ <quote>
+ <id>TWD</id><symbol>TWD</symbol><description>New Taiwan Dollar (TWD)</description>
+ </quote>
+ <quote>
+ <id>TZS</id><symbol>TZS</symbol><description>Tanzanian Shilling (TZS)</description>
+ </quote>
+ <quote>
+ <id>UAH</id><symbol>UAH</symbol><description>Ukrainian Hryvnia (UAH)</description>
+ </quote>
+ <quote>
+ <id>UGX</id><symbol>UGX</symbol><description>Ugandan Shilling (UGX)</description>
+ </quote>
+ <quote>
+ <id>USD</id><symbol>USD</symbol><description>United States Dollar (USD)</description>
+ </quote>
+ <quote>
+ <id>UYU</id><symbol>UYU</symbol><description>Uruguayan Peso (UYU)</description>
+ </quote>
+ <quote>
+ <id>UZS</id><symbol>UZS</symbol><description>Uzbekistani Som (UZS)</description>
+ </quote>
+ <quote>
+ <id>VEF</id><symbol>VEF</symbol><description>Venezuelan Bolívar (VEF)</description>
+ </quote>
<quote>
<id>VND</id><symbol>VND</symbol><description>Vietnamese Dong (VND)</description>
</quote>
+ <quote>
+ <id>VUV</id><symbol>VUV</symbol><description>Vanuatu Vatu (VUV)</description>
+ </quote>
+ <quote>
+ <id>WST</id><symbol>WST</symbol><description>Samoan Tala (WST)</description>
+ </quote>
+ <quote>
+ <id>XAF</id><symbol>XAF</symbol><description>Central African CFA Franc (FCFA)</description>
+ </quote>
+ <quote>
+ <id>XCD</id><symbol>XCD</symbol><description>East Caribbean Dollar (XCD)</description>
+ </quote>
+ <quote>
+ <id>XDR</id><symbol>XDR</symbol><description>Special Drawing Rights (XDR)</description>
+ </quote>
+ <quote>
+ <id>XOF</id><symbol>XOF</symbol><description>West African CFA Franc (CFA)</description>
+ </quote>
+ <quote>
+ <id>XPF</id><symbol>XPF</symbol><description>CFP Franc (CFPF)</description>
+ </quote>
+ <quote>
+ <id>YER</id><symbol>YER</symbol><description>Yemeni Rial (YER)</description>
+ </quote>
+ <quote>
+ <id>ZAR</id><symbol>ZAR</symbol><description>South African Rand (ZAR)</description>
+ </quote>
+ <quote>
+ <id>ZMK</id><symbol>ZMK</symbol><description>Zambian Kwacha (1968–2012) (ZMK)</description>
+ </quote>
+ <quote>
+ <id>ZMW</id><symbol>ZMW</symbol><description>Zambian Kwacha (ZMW)</description>
+ </quote>
+ <quote>
+ <id>ZWL</id><symbol>ZWL</symbol><description>Zimbabwean Dollar (2009) (ZWL)</description>
+ </quote>
</section>
</Provider> \ No newline at end of file
diff --git a/plugins/Quotes/src/Forex.cpp b/plugins/Quotes/src/Forex.cpp
index 0a56404ca4..c8eb6d0a04 100644
--- a/plugins/Quotes/src/Forex.cpp
+++ b/plugins/Quotes/src/Forex.cpp
@@ -32,7 +32,6 @@ PLUGININFOEX Global_pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Quotes/src/ImportExport.cpp b/plugins/Quotes/src/ImportExport.cpp
index b2c15faa0d..6836c11520 100644
--- a/plugins/Quotes/src/ImportExport.cpp
+++ b/plugins/Quotes/src/ImportExport.cpp
@@ -331,7 +331,7 @@ bool handle_module(MCONTACT hContact, const IXMLNode::TXMLNodePtr& pXmlModule)
mir_free(dbs.value.pwszVal);
}
else if (0 == mir_wstrcmpi(g_pszXmlTypeBlob, sType.c_str())) {
- unsigned bufLen;
+ size_t bufLen;
mir_ptr<BYTE> buf((PBYTE)mir_base64_decode(_T2A(sValue.c_str()), &bufLen));
if (buf) {
dbs.value.pbVal = buf;
diff --git a/plugins/Quotes/src/QuotesProviderGoogle.cpp b/plugins/Quotes/src/QuotesProviderGoogle.cpp
index d63ac57a46..f52be5a6c0 100644
--- a/plugins/Quotes/src/QuotesProviderGoogle.cpp
+++ b/plugins/Quotes/src/QuotesProviderGoogle.cpp
@@ -398,7 +398,7 @@ double CQuotesProviderGoogle::Convert(double dAmount, const CQuote& from, const
if ((true == parse_responce(sHTML, dResult)))
return dResult;
- throw std::runtime_error(Translate("Error occurred during html parsing."));
+ throw std::runtime_error(Translate("Error occurred during HTML parsing."));
}
else throw std::runtime_error(Translate("Error occurred during site access."));
}
diff --git a/plugins/Quotes/src/version.h b/plugins/Quotes/src/version.h
index 07e7119cf4..b153c00a64 100644
--- a/plugins/Quotes/src/version.h
+++ b/plugins/Quotes/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Quotes.dll"
#define __DESCRIPTION "Shows currency rates and economic quotes."
#define __AUTHOR "Dioksin"
-#define __AUTHOREMAIL "dioksin@ua.fm"
#define __AUTHORWEB "https://miranda-ng.org/p/Quotes/"
#define __COPYRIGHT ""
diff --git a/plugins/Rate/src/main.cpp b/plugins/Rate/src/main.cpp
index aa15bbe0d4..1f411a7bde 100644
--- a/plugins/Rate/src/main.cpp
+++ b/plugins/Rate/src/main.cpp
@@ -47,7 +47,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Rate/src/version.h b/plugins/Rate/src/version.h
index ccfe060611..adf40d6fa9 100644
--- a/plugins/Rate/src/version.h
+++ b/plugins/Rate/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Rate.dll"
#define __DESCRIPTION "Shows rating of contact in contact list (if present)."
#define __AUTHOR "Kildor, Thief"
-#define __AUTHOREMAIL "kostia@ngs.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/Rate/"
#define __COPYRIGHT "© 2006-2009 Kostia Romanov, based on AuthState by Alexander Turyak"
diff --git a/plugins/RecentContacts/src/RecentContacts.cpp b/plugins/RecentContacts/src/RecentContacts.cpp
index 0ed7142472..599a166dd8 100644
--- a/plugins/RecentContacts/src/RecentContacts.cpp
+++ b/plugins/RecentContacts/src/RecentContacts.cpp
@@ -37,7 +37,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/RecentContacts/src/version.h b/plugins/RecentContacts/src/version.h
index 5f5c0b84fc..4036d2ec22 100644
--- a/plugins/RecentContacts/src/version.h
+++ b/plugins/RecentContacts/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "RecentContacts.dll"
#define __DESCRIPTION "Adds a menu item in main menu, which open the window with list of last used contacts names, sorted in order from most recent to least."
#define __AUTHOR "ValeraVi, Kildor"
-#define __AUTHOREMAIL "kostia@ngs.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/RecentContacts/"
#define __COPYRIGHT "© 2005 ValeraVi, 2009 Kildor"
diff --git a/plugins/RemovePersonalSettings/src/rps.cpp b/plugins/RemovePersonalSettings/src/rps.cpp
index ea49a01dab..d355fcf927 100644
--- a/plugins/RemovePersonalSettings/src/rps.cpp
+++ b/plugins/RemovePersonalSettings/src/rps.cpp
@@ -41,7 +41,6 @@ PLUGININFOEX pluginInfo={
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/RemovePersonalSettings/src/version.h b/plugins/RemovePersonalSettings/src/version.h
index 57e04b8703..6c2088274f 100644
--- a/plugins/RemovePersonalSettings/src/version.h
+++ b/plugins/RemovePersonalSettings/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "RemovePersonalSettings.dll"
#define __DESCRIPTION "Remove personal settings to allow you to send a profile to other user(s) without sending personal data."
#define __AUTHOR "Ricardo Pescuma Domenecci"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/RemovePersonalSettings/"
#define __COPYRIGHT "© 2007-2009 Ricardo Pescuma Domenecci"
diff --git a/plugins/Restart/src/restart.cpp b/plugins/Restart/src/restart.cpp
index 7f2ad366ac..08cb470b64 100644
--- a/plugins/Restart/src/restart.cpp
+++ b/plugins/Restart/src/restart.cpp
@@ -10,7 +10,6 @@ PLUGININFOEX pluginInfo={
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Restart/src/version.h b/plugins/Restart/src/version.h
index bd550e6dc5..7439329690 100644
--- a/plugins/Restart/src/version.h
+++ b/plugins/Restart/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Restart.dll"
#define __DESCRIPTION "Adds Restart menu item."
#define __AUTHOR "eugene.nv"
-#define __AUTHOREMAIL "ep@eugn.me"
#define __AUTHORWEB "https://miranda-ng.org/p/Restart/"
#define __COPYRIGHT "© 2008-13 eugene.nv"
diff --git a/plugins/SMS/src/main.cpp b/plugins/SMS/src/main.cpp
index c62edf3376..b8962e9fb6 100644
--- a/plugins/SMS/src/main.cpp
+++ b/plugins/SMS/src/main.cpp
@@ -39,7 +39,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/SMS/src/version.h b/plugins/SMS/src/version.h
index b923ad70ca..e7bb0efc2c 100644
--- a/plugins/SMS/src/version.h
+++ b/plugins/SMS/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "SMS.dll"
#define __DESCRIPTION "Send SMS text messages to mobile phones through the IM networks."
#define __AUTHOR "Richard Hughes, Improved by Ariel Shulman, rewritten by Rozhuk Ivan"
-#define __AUTHOREMAIL "Rozhuk_I@mail.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/SMS/"
#define __COPYRIGHT "© 2001-02 Richard Hughes, 2003 Ariel Shulman, 2007-09 Rozhuk Ivan (Rozhuk_I@mail.ru)"
diff --git a/plugins/Scriver/src/cmdlist.h b/plugins/Scriver/src/cmdlist.h
index 9f2b89bb91..5495f5f103 100644
--- a/plugins/Scriver/src/cmdlist.h
+++ b/plugins/Scriver/src/cmdlist.h
@@ -1,6 +1,4 @@
/*
-AOL Instant Messenger Plugin for Miranda IM
-
Copyright (c) 2003 Robert Rainwater
This program is free software; you can redistribute it and/or
diff --git a/plugins/Scriver/src/msgdialog.cpp b/plugins/Scriver/src/msgdialog.cpp
index 162b22b7de..b85b0f413e 100644
--- a/plugins/Scriver/src/msgdialog.cpp
+++ b/plugins/Scriver/src/msgdialog.cpp
@@ -540,10 +540,7 @@ void CSrmmWindow::onClick_Quote(CCtrlButton*)
void CSrmmWindow::onClick_Add(CCtrlButton*)
{
- ADDCONTACTSTRUCT acs = {};
- acs.hContact = m_hContact;
- acs.handleType = HANDLE_CONTACT;
- CallService(MS_ADDCONTACT_SHOW, (WPARAM)m_hwnd, (LPARAM)&acs);
+ Contact_Add(m_hContact, m_hwnd);
if (!db_get_b(m_hContact, "CList", "NotOnList", 0))
ShowWindow(GetDlgItem(m_hwnd, IDC_ADD), SW_HIDE);
diff --git a/plugins/Scriver/src/srmm.cpp b/plugins/Scriver/src/srmm.cpp
index d3fdd9ed67..6b47a73fa7 100644
--- a/plugins/Scriver/src/srmm.cpp
+++ b/plugins/Scriver/src/srmm.cpp
@@ -38,7 +38,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Scriver/src/stdafx.h b/plugins/Scriver/src/stdafx.h
index 422d4fb8ae..2076df25a0 100644
--- a/plugins/Scriver/src/stdafx.h
+++ b/plugins/Scriver/src/stdafx.h
@@ -50,7 +50,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <m_contacts.h>
#include <m_userinfo.h>
#include <m_history.h>
-#include <m_addcontact.h>
#include <m_message.h>
#include <m_file.h>
#include <m_fontservice.h>
diff --git a/plugins/Scriver/src/version.h b/plugins/Scriver/src/version.h
index 7cd1c93cd9..0215a882eb 100644
--- a/plugins/Scriver/src/version.h
+++ b/plugins/Scriver/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Scriver.dll"
#define __DESCRIPTION "Scriver - send and receive instant messages."
#define __AUTHOR "Miranda NG Development Team"
-#define __AUTHOREMAIL "the_leech@users.berlios.de"
#define __AUTHORWEB "https://miranda-ng.org/p/Scriver/"
#define __COPYRIGHT "© 2000-2012 Miranda IM Project, 2012-17 Miranda NG project"
diff --git a/plugins/SecureIM/src/main.cpp b/plugins/SecureIM/src/main.cpp
index a56200fff4..d062711c6f 100644
--- a/plugins/SecureIM/src/main.cpp
+++ b/plugins/SecureIM/src/main.cpp
@@ -9,7 +9,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/SecureIM/src/version.h b/plugins/SecureIM/src/version.h
index f23117aab2..5911977447 100644
--- a/plugins/SecureIM/src/version.h
+++ b/plugins/SecureIM/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "SecureIM.dll"
#define __DESCRIPTION "SecureIM plugin for Miranda NG."
#define __AUTHOR "Johell, Ghost, Nightwish, __alex, Baloo"
-#define __AUTHOREMAIL "Johell@ifrance.com, baloo@bk.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/SecureIM/"
#define __COPYRIGHT "© 2003 Johell, 2005-09 Baloo"
diff --git a/plugins/SeenPlugin/src/main.cpp b/plugins/SeenPlugin/src/main.cpp
index 172897d4ef..b52d98e957 100644
--- a/plugins/SeenPlugin/src/main.cpp
+++ b/plugins/SeenPlugin/src/main.cpp
@@ -34,7 +34,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/SeenPlugin/src/version.h b/plugins/SeenPlugin/src/version.h
index a71af62bab..2658d14b39 100644
--- a/plugins/SeenPlugin/src/version.h
+++ b/plugins/SeenPlugin/src/version.h
@@ -30,6 +30,5 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define __FILENAME "SeenPlugin.dll"
#define __DESCRIPTION "Logs when a user was last seen online and which users were online while you were away."
#define __AUTHOR "Heiko Schillinger, YB"
-#define __AUTHOREMAIL "y_b@saaplugin.no-ip.info"
#define __AUTHORWEB "https://miranda-ng.org/p/SeenPlugin/"
#define __COPYRIGHT "© 2001-2002 Heiko Schillinger, 2003 modified by Bruno Rino, 2005-07 modified by YB"
diff --git a/plugins/SendScreenshotPlus/src/Main.cpp b/plugins/SendScreenshotPlus/src/Main.cpp
index 309dbbc5b5..6ad6c12c97 100644
--- a/plugins/SendScreenshotPlus/src/Main.cpp
+++ b/plugins/SendScreenshotPlus/src/Main.cpp
@@ -220,7 +220,7 @@ static const PLUGININFOEX pluginInfo = {
__PLUGIN_NAME,
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
- __AUTHOR, __AUTHOREMAIL,
+ __AUTHOR,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/SendScreenshotPlus/src/version.h b/plugins/SendScreenshotPlus/src/version.h
index 10f0ebe1be..85869bc7e5 100644
--- a/plugins/SendScreenshotPlus/src/version.h
+++ b/plugins/SendScreenshotPlus/src/version.h
@@ -9,7 +9,6 @@
#define __FILENAME "SendSS.dll"
#define __DESCRIPTION "Take a screenshot and send it to a contact."
#define __AUTHOR "Merlin"
-#define __AUTHOREMAIL "ing.u.horn@googlemail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/SendSS/"
#define __COPYRIGHT "© 2010 Merlin, 2004-2006 Sergio Vieira Rolanski"
#define __USER_AGENT_STRING "SendSS/" __VERSION_STRING_DOTS
diff --git a/plugins/Sessions/Src/Main.cpp b/plugins/Sessions/Src/Main.cpp
index 6a365b73dc..303fcf3fd5 100644
--- a/plugins/Sessions/Src/Main.cpp
+++ b/plugins/Sessions/Src/Main.cpp
@@ -57,7 +57,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Sessions/Src/version.h b/plugins/Sessions/Src/version.h
index 580a5abde1..6900e6a108 100644
--- a/plugins/Sessions/Src/version.h
+++ b/plugins/Sessions/Src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Sessions.dll"
#define __DESCRIPTION "Sessions Manager for Miranda NG."
#define __AUTHOR "MaD_CLuSTeR"
-#define __AUTHOREMAIL "daniok@yandex.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/Sessions/"
#define __COPYRIGHT "© 2007-2008 Danil Mozhar"
diff --git a/plugins/ShellExt/src/main.cpp b/plugins/ShellExt/src/main.cpp
index c356ef7b94..266c80287e 100644
--- a/plugins/ShellExt/src/main.cpp
+++ b/plugins/ShellExt/src/main.cpp
@@ -14,7 +14,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/ShellExt/src/version.h b/plugins/ShellExt/src/version.h
index 35500637c1..6856245420 100644
--- a/plugins/ShellExt/src/version.h
+++ b/plugins/ShellExt/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "ShlExt.dll"
#define __DESCRIPTION "Windows Explorer extension for Miranda NG."
#define __AUTHOR "Sam Kothari, Miranda NG Team"
-#define __AUTHOREMAIL "egodust@users.sourceforge.net"
#define __AUTHORWEB "https://miranda-ng.org/p/ShellExt/"
#define __COPYRIGHT "© 2009 Sam Kothari (egoDust)"
diff --git a/plugins/SimpleAR/src/Main.cpp b/plugins/SimpleAR/src/Main.cpp
index 8feceb95bf..0ffc1ffefc 100644
--- a/plugins/SimpleAR/src/Main.cpp
+++ b/plugins/SimpleAR/src/Main.cpp
@@ -39,7 +39,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/SimpleAR/src/version.h b/plugins/SimpleAR/src/version.h
index ca9699cb5b..64af845a5f 100644
--- a/plugins/SimpleAR/src/version.h
+++ b/plugins/SimpleAR/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "SimpleAR.dll"
#define __DESCRIPTION "Simple Auto Replier."
#define __AUTHOR "Stark Wong, Mataes, Mikel-Ard-Ri"
-#define __AUTHOREMAIL "mikelardri@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/SimpleAR/"
#define __COPYRIGHT "© 2012"
diff --git a/plugins/SimpleStatusMsg/src/main.cpp b/plugins/SimpleStatusMsg/src/main.cpp
index fae0b03fcd..dafe0449b2 100644
--- a/plugins/SimpleStatusMsg/src/main.cpp
+++ b/plugins/SimpleStatusMsg/src/main.cpp
@@ -39,7 +39,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
@@ -204,9 +203,8 @@ wchar_t* InsertBuiltinVarsIntoMsg(wchar_t *in, const char *szProto, int)
}
else if (!wcsnicmp(msg + i, L"%time%", 6))
{
- MIRANDA_IDLE_INFO mii = {0};
- mii.cbSize = sizeof(mii);
- CallService(MS_IDLE_GETIDLEINFO, 0, (LPARAM)&mii);
+ MIRANDA_IDLE_INFO mii;
+ Idle_GetInfo(mii);
if (mii.idleType)
{
@@ -1268,9 +1266,8 @@ VOID CALLBACK SetStartupStatusProc(HWND hwnd, UINT, UINT_PTR idEvent, DWORD)
VOID CALLBACK UpdateMsgTimerProc(HWND, UINT, UINT_PTR, DWORD)
{
- MIRANDA_IDLE_INFO mii = {0};
- mii.cbSize = sizeof(mii);
- CallService(MS_IDLE_GETIDLEINFO, 0, (LPARAM)&mii);
+ MIRANDA_IDLE_INFO mii;
+ Idle_GetInfo(mii);
if (db_get_b(NULL, "SimpleStatusMsg", "NoUpdateOnIdle", 1) && mii.idleType)
return;
@@ -1436,9 +1433,9 @@ static int OnIdleChanged(WPARAM, LPARAM lParam)
if (!(lParam & IDF_ISIDLE))
g_iIdleTime = -1;
- MIRANDA_IDLE_INFO mii = {0};
- mii.cbSize = sizeof(mii);
- CallService(MS_IDLE_GETIDLEINFO, 0, (LPARAM)&mii);
+ MIRANDA_IDLE_INFO mii;
+ Idle_GetInfo(mii);
+
if (mii.aaStatus == 0)
{
#ifdef _DEBUG
diff --git a/plugins/SimpleStatusMsg/src/version.h b/plugins/SimpleStatusMsg/src/version.h
index 153618cc56..2b0c1c8398 100644
--- a/plugins/SimpleStatusMsg/src/version.h
+++ b/plugins/SimpleStatusMsg/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "SimpleStatusMsg.dll"
#define __DESCRIPTION "Provides a simple way to set status and away messages."
#define __AUTHOR "Bartosz 'Dezeath' Białek, Harven"
-#define __AUTHOREMAIL "dezred@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/SimpleStatusMsg/"
#define __COPYRIGHT "© 2006-2011 Bartosz Białek, 2005 Harven"
diff --git a/plugins/SkypeStatusChange/src/main.cpp b/plugins/SkypeStatusChange/src/main.cpp
index c6a233ed39..a5c6fe37e1 100644
--- a/plugins/SkypeStatusChange/src/main.cpp
+++ b/plugins/SkypeStatusChange/src/main.cpp
@@ -15,7 +15,6 @@ PLUGININFOEX g_pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE, //not transient
diff --git a/plugins/SkypeStatusChange/src/version.h b/plugins/SkypeStatusChange/src/version.h
index d0873aacd9..bae6b5221a 100644
--- a/plugins/SkypeStatusChange/src/version.h
+++ b/plugins/SkypeStatusChange/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "SkypeStatusChange.dll"
#define __DESCRIPTION "Skype status change according to Miranda status."
#define __AUTHOR "Dioksin"
-#define __AUTHOREMAIL "dioksin@ua.fm"
#define __AUTHORWEB "https://miranda-ng.org/p/SkypeStatusChange/"
#define __COPYRIGHT "© 2009-2010 Dioksin"
diff --git a/plugins/SmileyAdd/smileys/nova/AIM.msl b/plugins/SmileyAdd/smileys/nova/AIM.msl
deleted file mode 100644
index f19834ee24..0000000000
--- a/plugins/SmileyAdd/smileys/nova/AIM.msl
+++ /dev/null
Binary files differ
diff --git a/plugins/SmileyAdd/src/customsmiley.cpp b/plugins/SmileyAdd/src/customsmiley.cpp
index aa631e3b2e..72690198d3 100644
--- a/plugins/SmileyAdd/src/customsmiley.cpp
+++ b/plugins/SmileyAdd/src/customsmiley.cpp
@@ -72,7 +72,7 @@ bool SmileyCType::CreateTriggerText(char *text)
int len = (int)mir_strlen(text);
if (len == 0) return false;
- unsigned reslen;
+ size_t reslen;
ptrA res((char*)mir_base64_decode(text, &reslen));
if (res == NULL)
return false;
diff --git a/plugins/SmileyAdd/src/main.cpp b/plugins/SmileyAdd/src/main.cpp
index 81c3c9bb19..3a6cfee311 100644
--- a/plugins/SmileyAdd/src/main.cpp
+++ b/plugins/SmileyAdd/src/main.cpp
@@ -35,7 +35,6 @@ static const PLUGININFOEX pluginInfoEx =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/SmileyAdd/src/version.h b/plugins/SmileyAdd/src/version.h
index 8d5a256e61..f820339434 100644
--- a/plugins/SmileyAdd/src/version.h
+++ b/plugins/SmileyAdd/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "SmileyAdd.dll"
#define __DESCRIPTION "Smiley support for Miranda NG."
#define __AUTHOR "Peacow, nightwish, bid, borkra"
-#define __AUTHOREMAIL "borkra@miranda-im.org"
#define __AUTHORWEB "https://miranda-ng.org/p/SmileyAdd/"
#define __COPYRIGHT "© 2012-17 Miranda NG Team, 2004-12 Boris Krasnovskiy, portions by Rein-Peter de Boer"
diff --git a/plugins/Spamotron/src/spamotron.cpp b/plugins/Spamotron/src/spamotron.cpp
index f9462b77e6..9464ca0a32 100644
--- a/plugins/Spamotron/src/spamotron.cpp
+++ b/plugins/Spamotron/src/spamotron.cpp
@@ -12,7 +12,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Spamotron/src/version.h b/plugins/Spamotron/src/version.h
index 55823a9f3b..2b68799605 100644
--- a/plugins/Spamotron/src/version.h
+++ b/plugins/Spamotron/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Spamotron.dll"
#define __DESCRIPTION "Anti-spam plugin with captcha and Bayes filtering."
#define __AUTHOR "vu1tur"
-#define __AUTHOREMAIL "to@vu1tur.eu.org"
#define __AUTHORWEB "https://miranda-ng.org/p/Spamotron/"
#define __COPYRIGHT "© 2010 vu1tur"
diff --git a/plugins/SpellChecker/src/spellchecker.cpp b/plugins/SpellChecker/src/spellchecker.cpp
index 935749e4ac..0640f6f10b 100644
--- a/plugins/SpellChecker/src/spellchecker.cpp
+++ b/plugins/SpellChecker/src/spellchecker.cpp
@@ -27,7 +27,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/SpellChecker/src/version.h b/plugins/SpellChecker/src/version.h
index 3562484366..3aa2f41b06 100644
--- a/plugins/SpellChecker/src/version.h
+++ b/plugins/SpellChecker/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "SpellChecker.dll"
#define __DESCRIPTION "Spell checker for the message windows. Uses Hunspell to do the checking."
#define __AUTHOR "Ricardo Pescuma Domenecci, Wishmaster"
-#define __AUTHOREMAIL "pescuma@miranda-im.org"
#define __AUTHORWEB "https://miranda-ng.org/p/SpellChecker/"
#define __COPYRIGHT "© 2006-2010 Ricardo Pescuma Domenecci"
diff --git a/plugins/SplashScreen/src/main.cpp b/plugins/SplashScreen/src/main.cpp
index 3b453000be..0c8b476dc5 100644
--- a/plugins/SplashScreen/src/main.cpp
+++ b/plugins/SplashScreen/src/main.cpp
@@ -46,7 +46,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/SplashScreen/src/version.h b/plugins/SplashScreen/src/version.h
index 91b22115a2..300f9a086d 100644
--- a/plugins/SplashScreen/src/version.h
+++ b/plugins/SplashScreen/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "SplashScreen.dll"
#define __DESCRIPTION "Shows a splash at Miranda startup."
#define __AUTHOR "nullbie, Thief"
-#define __AUTHOREMAIL "thief@miranda.im"
#define __AUTHORWEB "https://miranda-ng.org/p/SplashScreen/"
#define __COPYRIGHT "© 2004-2007 Victor Pavlychko, 2005-2011 Alexander Turyak"
diff --git a/plugins/StartPosition/src/main.cpp b/plugins/StartPosition/src/main.cpp
index 1302faac10..14bf4b1941 100644
--- a/plugins/StartPosition/src/main.cpp
+++ b/plugins/StartPosition/src/main.cpp
@@ -34,7 +34,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/StartPosition/src/version.h b/plugins/StartPosition/src/version.h
index 807d53434f..8847da8096 100644
--- a/plugins/StartPosition/src/version.h
+++ b/plugins/StartPosition/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "StartPosition.dll"
#define __DESCRIPTION "Plugin supports starting position of Contact List relative to the taskbar and screen side."
#define __AUTHOR "Felipe Brahm - souFrag"
-#define __AUTHOREMAIL "felipebrahm@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/StartPosition/"
#define __COPYRIGHT "© 2005-2008 Felipe Brahm - souFrag, © 2012-17 Miranda NG project"
diff --git a/plugins/StartupSilence/src/main.cpp b/plugins/StartupSilence/src/main.cpp
index 11f0153843..74d3f383c9 100644
--- a/plugins/StartupSilence/src/main.cpp
+++ b/plugins/StartupSilence/src/main.cpp
@@ -68,7 +68,6 @@ PLUGININFOEX pluginInfo={
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESC,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/StartupSilence/src/version.h b/plugins/StartupSilence/src/version.h
index 88c7193a98..05ef107b88 100644
--- a/plugins/StartupSilence/src/version.h
+++ b/plugins/StartupSilence/src/version.h
@@ -15,7 +15,6 @@
#define __FILENAME "StartupSilence.dll"
#define __DESC "Suppresses popups and mutes sounds for 10-300 sec at Miranda NG startup, then sets them back to predefined state (Automatically per computer settings)."
#define __AUTHOR "Vladimir Lyubimov"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/"
#define __COPYRIGHT "© 2012-17 Vladimir Lyubimov"
diff --git a/plugins/StatusChange/src/main.cpp b/plugins/StatusChange/src/main.cpp
index fc34c136b3..75f30ff4b5 100644
--- a/plugins/StatusChange/src/main.cpp
+++ b/plugins/StatusChange/src/main.cpp
@@ -13,7 +13,6 @@ PLUGININFOEX pluginInfo={
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/StatusChange/src/version.h b/plugins/StatusChange/src/version.h
index f03a2bf1e5..510cb9b538 100644
--- a/plugins/StatusChange/src/version.h
+++ b/plugins/StatusChange/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "StatusChange.dll"
#define __DESCRIPTION "Change status when you send/receive an event."
#define __AUTHOR "Angelo Luiz Tartari"
-#define __AUTHOREMAIL "corsario-br@users.sourceforge.net"
#define __AUTHORWEB "https://miranda-ng.org/p/StatusChange/"
#define __COPYRIGHT "© 2002 Angelo Luiz Tartari"
diff --git a/plugins/StatusManager/src/StartupStatus/ss_options.cpp b/plugins/StatusManager/src/StartupStatus/ss_options.cpp
index 1fdf8141bd..90bdc218aa 100644
--- a/plugins/StatusManager/src/StartupStatus/ss_options.cpp
+++ b/plugins/StatusManager/src/StartupStatus/ss_options.cpp
@@ -507,24 +507,6 @@ static int DeleteSetting(const char *szSetting, void *lParam)
return 0;
}
-static int ClearDatabase(char* filter)
-{
- LIST<char> arSettings(10);
- db_enum_settings(0, DeleteSetting, SSMODULENAME, &arSettings);
-
- for (int i = 0; i < arSettings.getCount(); i++) {
- if ((filter == nullptr) || (!strncmp(filter, arSettings[i], mir_strlen(filter))))
- db_unset(0, SSMODULENAME, arSettings[i]);
- mir_free(arSettings[i]);
- }
-
- if (filter == nullptr)
- db_unset(0, "AutoAway", "Confirm");
-
- return 0;
-}
-
-
INT_PTR CALLBACK addProfileDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HWND hwndParent;
@@ -748,12 +730,20 @@ public:
virtual void OnApply() override
{
- char setting[128];
int oldCount = db_get_w(0, SSMODULENAME, SETTING_PROFILECOUNT, 0);
for (int i = 0; i < oldCount; i++) {
- mir_snprintf(setting, "%d_", i);
- ClearDatabase(setting);
+ LIST<char> arSettings(10);
+ db_enum_settings(0, DeleteSetting, SSMODULENAME, &arSettings);
+
+ char setting[128];
+ int len = mir_snprintf(setting, "%d_", i);
+ for (int k = 0; k < arSettings.getCount(); k++) {
+ if (!strncmp(setting, arSettings[k], len))
+ db_unset(0, SSMODULENAME, arSettings[k]);
+ mir_free(arSettings[k]);
+ }
}
+
for (int i = 0; i < arProfiles.getCount(); i++) {
PROFILEOPTIONS& po = arProfiles[i];
db_set_b(0, SSMODULENAME, OptName(i, SETTING_SHOWCONFIRMDIALOG), po.showDialog);
@@ -767,6 +757,7 @@ public:
TSettingsList& ar = *po.ps;
for (int j = 0; j < ar.getCount(); j++) {
if (ar[j].m_szMsg != nullptr) {
+ char setting[128];
mir_snprintf(setting, "%s_%s", ar[j].m_szName, SETTING_PROFILE_STSMSG);
db_set_ws(0, SSMODULENAME, OptName(i, setting), ar[j].m_szMsg);
}
@@ -820,6 +811,7 @@ public:
if (idx != -1) {
TSSSetting* ps = (TSSSetting*)lstAccount.GetItemData(idx);
ps->m_status = lstStatus.GetItemData(lstStatus.GetCurSel());
+ NotifyChange();
}
SetStatusMsg();
}
diff --git a/plugins/StatusManager/src/main.cpp b/plugins/StatusManager/src/main.cpp
index 7e5b41fd5d..599e3d54ae 100644
--- a/plugins/StatusManager/src/main.cpp
+++ b/plugins/StatusManager/src/main.cpp
@@ -43,7 +43,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESC,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/StatusManager/src/version.h b/plugins/StatusManager/src/version.h
index 0f0117171f..5cac1e4939 100644
--- a/plugins/StatusManager/src/version.h
+++ b/plugins/StatusManager/src/version.h
@@ -12,6 +12,5 @@
#define __FILENAME "StatusManager.dll"
#define __DESC "A connection checker and auto away module. Also allows you to define the status Miranda should set on startup, configurable per protocol."
#define __AUTHOR "P Boon"
-#define __AUTHOREMAIL "unregistered@users.sourceforge.net"
#define __AUTHORWEB "https://miranda-ng.org/p/StatusManager/"
#define __COPYRIGHT "© 2003-08 P. Boon, 2008-17 George Hazan"
diff --git a/plugins/StopSpamMod/src/init.cpp b/plugins/StopSpamMod/src/init.cpp
index 62e09e121f..4d18f3b559 100755
--- a/plugins/StopSpamMod/src/init.cpp
+++ b/plugins/StopSpamMod/src/init.cpp
@@ -64,7 +64,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
@@ -118,9 +117,8 @@ static int OnSystemModulesLoaded(WPARAM, LPARAM)
if (ServiceExists(MS_VARS_FORMATSTRING))
gbVarsServiceExist = TRUE;
InitVars();
- void CleanThread();
if(gbDelAllTempory || gbDelExcluded)
- new boost::thread(&CleanThread);
+ mir_forkthread(&CleanThread);
// Folders plugin support
hStopSpamLogDirH = FoldersRegisterCustomPathT(LPGEN("StopSpam"), LPGEN("StopSpam Logs"), FOLDER_LOGS);
diff --git a/plugins/StopSpamMod/src/stdafx.h b/plugins/StopSpamMod/src/stdafx.h
index c8479ab49b..d5551e8d10 100755
--- a/plugins/StopSpamMod/src/stdafx.h
+++ b/plugins/StopSpamMod/src/stdafx.h
@@ -19,7 +19,9 @@ using namespace std;
#include <m_variables.h>
#include <m_folders.h>
-#include <boost\thread.hpp>
+#include <string>
+#include <sstream>
+
#include <boost\regex.hpp>
#include <boost\algorithm\string.hpp>
#include <boost\nondet_random.hpp>
@@ -38,4 +40,6 @@ extern HANDLE hStopSpamLogDirH;
int OnDbContactSettingChanged(WPARAM w, LPARAM l);
int OnDbEventFilterAdd(WPARAM w, LPARAM l);
int OnDbEventAdded(WPARAM hContact, LPARAM hDbEvent);
-int OnOptInit(WPARAM w, LPARAM l); \ No newline at end of file
+int OnOptInit(WPARAM w, LPARAM l);
+
+void __cdecl CleanThread(void*); \ No newline at end of file
diff --git a/plugins/StopSpamMod/src/utilities.cpp b/plugins/StopSpamMod/src/utilities.cpp
index 7943dada3f..f6f586a5eb 100755
--- a/plugins/StopSpamMod/src/utilities.cpp
+++ b/plugins/StopSpamMod/src/utilities.cpp
@@ -81,8 +81,7 @@ void DeleteCListGroupsByName(wchar_t* szGroupName)
int RemoveTmp(WPARAM, LPARAM)
{
- void CleanThread();
- CleanThread();
+ CleanThread(0);
return 0;
}
@@ -239,59 +238,68 @@ void LogSpamToFile(MCONTACT hContact, wstring message)
file.close();
}
-boost::mutex clean_mutex;
+mir_cs clean_mutex;
-void CleanProtocolTmpThread(std::string proto)
+void __cdecl CleanProtocolTmpThread(void *param)
{
+ const char *szProto = (const char*)param;
+
while (true) {
- UINT status = CallProtoService(proto.c_str(), PS_GETSTATUS, 0, 0);
+ UINT status = CallProtoService(szProto, PS_GETSTATUS, 0, 0);
if (status > ID_STATUS_OFFLINE)
break;
- boost::this_thread::sleep(boost::posix_time::seconds(2));
+ Sleep(2000);
}
std::list<MCONTACT> contacts;
- for (MCONTACT hContact = db_find_first(proto.c_str()); hContact; hContact = db_find_next(hContact, proto.c_str()))
+ for (MCONTACT hContact = db_find_first(szProto); hContact; hContact = db_find_next(hContact, szProto))
if (db_get_b(hContact, "CList", "NotOnList", 0) || (L"Not In List" == DBGetContactSettingStringPAN(hContact, "CList", "Group", L"")))
contacts.push_back(hContact);
- boost::this_thread::sleep(boost::posix_time::seconds(5));
- clean_mutex.lock();
- std::list<MCONTACT>::iterator end = contacts.end();
- for (std::list<MCONTACT>::iterator i = contacts.begin(); i != end; ++i) {
- LogSpamToFile(*i, L"Deleted");
- HistoryLogFunc(*i, "Deleted");
- db_delete_contact(*i);
+ Sleep(5000);
+ {
+ mir_cslock lck(clean_mutex);
+
+ std::list<MCONTACT>::iterator end = contacts.end();
+ for (std::list<MCONTACT>::iterator i = contacts.begin(); i != end; ++i) {
+ LogSpamToFile(*i, L"Deleted");
+ HistoryLogFunc(*i, "Deleted");
+ db_delete_contact(*i);
+ }
}
- clean_mutex.unlock();
+ mir_free(param);
}
-void CleanProtocolExclThread(std::string proto)
+void __cdecl CleanProtocolExclThread(void *param)
{
+ const char *szProto = (const char*)param;
+
while (true) {
- UINT status = CallProtoService(proto.c_str(), PS_GETSTATUS, 0, 0);
+ UINT status = CallProtoService(szProto, PS_GETSTATUS, 0, 0);
if (status > ID_STATUS_OFFLINE)
break;
- boost::this_thread::sleep(boost::posix_time::seconds(2));
+ Sleep(2000);
}
std::list<MCONTACT> contacts;
- for (MCONTACT hContact = db_find_first(proto.c_str()); hContact; hContact = db_find_next(hContact, proto.c_str()))
+ for (MCONTACT hContact = db_find_first(szProto); hContact; hContact = db_find_next(hContact, szProto))
if (db_get_b(hContact, "CList", "NotOnList", 0) && db_get_b(hContact, pluginName, "Excluded", 0))
contacts.push_back(hContact);
- boost::this_thread::sleep(boost::posix_time::seconds(5));
- clean_mutex.lock();
- std::list<MCONTACT>::iterator end = contacts.end();
- for (std::list<MCONTACT>::iterator i = contacts.begin(); i != end; ++i) {
- LogSpamToFile(*i, L"Deleted");
- HistoryLogFunc(*i, "Deleted");
- db_delete_contact(*i);
+ Sleep(5000);
+ {
+ mir_cslock lck(clean_mutex);
+ std::list<MCONTACT>::iterator end = contacts.end();
+ for (std::list<MCONTACT>::iterator i = contacts.begin(); i != end; ++i) {
+ LogSpamToFile(*i, L"Deleted");
+ HistoryLogFunc(*i, "Deleted");
+ db_delete_contact(*i);
+ }
}
- clean_mutex.unlock();
+ mir_free(param);
}
-void CleanThread()
+void __cdecl CleanThread(void*)
{
std::list<std::string> protocols;
int count = 0;
@@ -304,9 +312,9 @@ void CleanThread()
std::list<std::string>::iterator end = protocols.end();
for (std::list<std::string>::iterator i = protocols.begin(); i != end; ++i) {
if (gbDelAllTempory)
- new boost::thread(boost::bind(&CleanProtocolTmpThread, *i));
+ mir_forkthread(CleanProtocolTmpThread, mir_strdup((*i).c_str()));
if (gbDelExcluded)
- new boost::thread(boost::bind(&CleanProtocolExclThread, *i));
+ mir_forkthread(CleanProtocolExclThread, mir_strdup((*i).c_str()));
}
}
diff --git a/plugins/StopSpamMod/src/version.h b/plugins/StopSpamMod/src/version.h
index bce1b7655e..384b6d8607 100755
--- a/plugins/StopSpamMod/src/version.h
+++ b/plugins/StopSpamMod/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "StopSpamMod.dll"
#define __DESCRIPTION "Anti-spam plugin for Miranda NG."
#define __AUTHOR "Roman Miklashevsky, sss, Elzor"
-#define __AUTHOREMAIL "sss123next@list.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/StopSpamMod/"
#define __COPYRIGHT "© 2004-2017 Roman Miklashevsky, A. Petkevich, Kosh&chka, sss, Elzor"
diff --git a/plugins/StopSpamPlus/src/options.cpp b/plugins/StopSpamPlus/src/options.cpp
index 342f446cbb..da64a57d50 100644
--- a/plugins/StopSpamPlus/src/options.cpp
+++ b/plugins/StopSpamPlus/src/options.cpp
@@ -4,13 +4,14 @@ const wchar_t pluginDescription[] = LPGENW("No more spam! Robots can't go! Only
class COptMainDlg : public CPluginDlgBase
{
- CCtrlEdit edtCount;
+ CCtrlEdit edtCount, edtDescr;
CCtrlCheck chk1, chk2, chk3, chk4, chk5, chk6;
public:
COptMainDlg() :
CPluginDlgBase(hInst, IDD_MAIN, pluginName),
edtCount(this, ID_MAXQUESTCOUNT),
+ edtDescr(this, ID_DESCRIPTION),
chk1(this, ID_INFTALKPROT),
chk2(this, ID_ADDPERMANENT),
chk3(this, ID_HANDLEAUTHREQ),
@@ -27,6 +28,11 @@ public:
CreateLink(chk5, g_sets.RemTmpAll);
CreateLink(chk6, g_sets.HistLog);
}
+
+ virtual void OnInitDialog() override
+ {
+ edtDescr.SetText(pluginDescription);
+ }
};
/////////////////////////////////////////////////////////////////////////////////////////
@@ -121,7 +127,7 @@ public:
item.lParam = (LPARAM)p->szModuleName;
item.pszText = p->tszAccountName;
int idx = m_accounts.InsertItem(&item);
- m_accounts.SetCheckState(idx, !g_sets.ProtoDisabled(p->szModuleName));
+ m_accounts.SetCheckState(idx, g_sets.ProtoDisabled(p->szModuleName));
}
}
diff --git a/plugins/StopSpamPlus/src/stopspam.cpp b/plugins/StopSpamPlus/src/stopspam.cpp
index ed9ba96a64..7352177744 100644
--- a/plugins/StopSpamPlus/src/stopspam.cpp
+++ b/plugins/StopSpamPlus/src/stopspam.cpp
@@ -11,7 +11,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/StopSpamPlus/src/version.h b/plugins/StopSpamPlus/src/version.h
index 369ce2f5d8..3349b2f3d2 100644
--- a/plugins/StopSpamPlus/src/version.h
+++ b/plugins/StopSpamPlus/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "StopSpam.dll"
#define __DESCRIPTION "Anti-spam plugin for Miranda NG."
#define __AUTHOR "Roman Miklashevsky, A. Petkevich, Kosh&chka, persei"
-#define __AUTHOREMAIL "koshechka@miranda.im"
#define __AUTHORWEB "https://miranda-ng.org/p/StopSpam/"
#define __COPYRIGHT "© 2004-2010 Roman Miklashevsky, A. Petkevich, Kosh&chka, persei"
diff --git a/plugins/TabSRMM/res/chat.rc b/plugins/TabSRMM/res/chat.rc
index 98daf77d20..35c5f8db20 100644
--- a/plugins/TabSRMM/res/chat.rc
+++ b/plugins/TabSRMM/res/chat.rc
@@ -32,8 +32,8 @@ FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
CONTROL "",IDC_SPLITTERX,"Static",SS_ENHMETAFILE,172,23,10,73
CONTROL "",IDC_SPLITTERY,"Static",SS_ENHMETAFILE,0,132,251,6
- CONTROL "",IDC_SRMM_MESSAGE,"RichEdit50W",WS_VSCROLL | WS_TABSTOP | 0x1144,0,128,127,12,WS_EX_STATICEDGE
- CONTROL "",IDC_SRMM_LOG,"RichEdit50W",WS_VSCROLL | 0x844,8,23,164,72,WS_EX_STATICEDGE
+ CONTROL "",IDC_SRMM_MESSAGE,"RichEdit50W",WS_VSCROLL | WS_TABSTOP | ES_MULTILINE | ES_AUTOVSCROLL | ES_NOHIDESEL | ES_WANTRETURN,0,128,127,12,WS_EX_STATICEDGE
+ CONTROL "",IDC_SRMM_LOG,"RichEdit50W",WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_NOHIDESEL | ES_READONLY,8,23,164,72,WS_EX_STATICEDGE
LISTBOX IDC_SRMM_NICKLIST,182,23,69,73,LBS_MULTIPLESEL | LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | LBS_NODATA | NOT WS_BORDER | WS_VSCROLL | WS_TABSTOP,WS_EX_STATICEDGE
CONTROL "",IDC_PANELSPLITTER,"Static",SS_ENHMETAFILE,0,32,252,1,WS_EX_TRANSPARENT
END
diff --git a/plugins/TabSRMM/res/msgwindow.rc b/plugins/TabSRMM/res/msgwindow.rc
index f934f22b30..6b76b6f1d3 100644
--- a/plugins/TabSRMM/res/msgwindow.rc
+++ b/plugins/TabSRMM/res/msgwindow.rc
@@ -36,10 +36,7 @@ STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPCHILDREN
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
CONTROL "",IDC_SPLITTERY,"Static",SS_ENHMETAFILE,0,46,187,1
- CONTROL "",IDC_SRMM_MESSAGE,"RichEdit50W",ES_MULTILINE |
- ES_AUTOVSCROLL | ES_NOHIDESEL | ES_WANTRETURN |
- WS_VSCROLL | WS_TABSTOP,0,48,144,31,WS_EX_ACCEPTFILES |
- WS_EX_STATICEDGE
+ CONTROL "",IDC_SRMM_MESSAGE,"RichEdit50W",ES_MULTILINE | ES_AUTOVSCROLL | ES_NOHIDESEL | ES_WANTRETURN | WS_VSCROLL | WS_TABSTOP,0,48,144,31,WS_EX_ACCEPTFILES | WS_EX_STATICEDGE
CONTROL "",IDC_CONTACTPIC,"Button",BS_OWNERDRAW,155,48,34,31
CONTROL "",IDC_MULTISPLITTER,"Static",SS_ENHMETAFILE,186,0,2,30
CONTROL "&Retry",IDC_RETRY,"MButtonClass",WS_TABSTOP,26,10,55,12,0x18000000L
diff --git a/plugins/TabSRMM/res/resource.rc b/plugins/TabSRMM/res/resource.rc
index 7a0c7c38f0..3a3fe612e8 100644
--- a/plugins/TabSRMM/res/resource.rc
+++ b/plugins/TabSRMM/res/resource.rc
@@ -742,39 +742,11 @@ BEGIN
MENUITEM "Don't play sounds", ID_TRAYCONTEXT_DON40223
MENUITEM "Be ""super quiet""", ID_TRAYCONTEXT_BE
END
- POPUP "Font"
- BEGIN
- MENUITEM "Default color", ID_FONT_DEFAULTCOLOR
- MENUITEM "Red", ID_FONT_RED
- MENUITEM "Green", ID_FONT_GREEN
- MENUITEM "Blue", ID_FONT_BLUE
- MENUITEM "Magenta", ID_FONT_MAGENTA
- MENUITEM "Yellow", ID_FONT_YELLOW
- MENUITEM "Cyan", ID_FONT_CYAN
- MENUITEM "Black", ID_FONT_BLACK
- MENUITEM "White", ID_FONT_WHITE
- MENUITEM SEPARATOR
- MENUITEM "Clear all formatting", ID_FONT_CLEARALLFORMATTING
- END
- POPUP "Dummy", INACTIVE
- BEGIN
- MENUITEM "No message sessions opened", ID_DUMMY_NOMESSAGESESSIONSOPENED
- END
POPUP "Favorites"
BEGIN
MENUITEM "Add contact to favorites", ID_FAVORITES_ADDCONTACTTOFAVORITES
MENUITEM "Remove contact from favorites", ID_FAVORITES_REMOVECONTACTFROMFAVORITES
END
- POPUP "Apparentmenu"
- BEGIN
- MENUITEM "dummy", 65535
- END
- POPUP "Panelpicmenu"
- BEGIN
- MENUITEM SEPARATOR
- MENUITEM "Contact picture settings...", ID_PICMENU_SETTINGS
- MENUITEM "Save this picture as...", ID_PANELPICMENU_SAVETHISPICTUREAS
- END
POPUP "Splitter context"
BEGIN
MENUITEM "Set position for this session", ID_SPLITTERCONTEXT_SETPOSITIONFORTHISSESSION
diff --git a/plugins/TabSRMM/src/generic_msghandlers.cpp b/plugins/TabSRMM/src/generic_msghandlers.cpp
index 49ca11556a..d603663344 100644
--- a/plugins/TabSRMM/src/generic_msghandlers.cpp
+++ b/plugins/TabSRMM/src/generic_msghandlers.cpp
@@ -335,7 +335,7 @@ LRESULT CTabBaseDlg::DM_MsgWindowCmdHandler(UINT cmd, WPARAM wParam, LPARAM lPar
break;
case IDC_INFOPANELMENU:
- submenu = GetSubMenu(PluginConfig.g_hMenuContext, 9);
+ submenu = GetSubMenu(PluginConfig.g_hMenuContext, 7);
GetWindowRect(GetDlgItem(m_hwnd, IDC_NAME), &rc);
EnableMenuItem(submenu, ID_FAVORITES_ADDCONTACTTOFAVORITES, !m_cache->isFavorite() ? MF_ENABLED : MF_GRAYED);
diff --git a/plugins/TabSRMM/src/globals.cpp b/plugins/TabSRMM/src/globals.cpp
index 89b5fc0194..fcbfb1d36a 100644
--- a/plugins/TabSRMM/src/globals.cpp
+++ b/plugins/TabSRMM/src/globals.cpp
@@ -281,14 +281,6 @@ int CGlobals::ModulesLoaded(WPARAM, LPARAM)
::CreateImageList(TRUE);
::CB_InitCustomButtons();
- MENUITEMINFOA mii = { 0 };
- mii.cbSize = sizeof(mii);
- mii.fMask = MIIM_BITMAP;
- mii.hbmpItem = HBMMENU_CALLBACK;
- HMENU submenu = GetSubMenu(PluginConfig.g_hMenuContext, 7);
- for (int k = 0; k <= 8; k++)
- SetMenuItemInfoA(submenu, (UINT_PTR)k, TRUE, &mii);
-
PluginConfig.reloadSystemModulesChanged();
::Chat_ModulesLoaded();
diff --git a/plugins/TabSRMM/src/hotkeyhandler.cpp b/plugins/TabSRMM/src/hotkeyhandler.cpp
index 75bb584b7d..94b6ccdc9d 100644
--- a/plugins/TabSRMM/src/hotkeyhandler.cpp
+++ b/plugins/TabSRMM/src/hotkeyhandler.cpp
@@ -218,7 +218,7 @@ LONG_PTR CALLBACK HotkeyHandlerDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LP
BOOL iSelection = TrackPopupMenu(PluginConfig.g_hMenuTrayUnread, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, nullptr);
HandleMenuEntryFromhContact((MCONTACT)iSelection);
}
- else TrackPopupMenu(GetSubMenu(PluginConfig.g_hMenuContext, 8), TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, nullptr);
+ else TrackPopupMenu(GetSubMenu(PluginConfig.g_hMenuContext, 6), TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, nullptr);
if (wParam == 100)
PostMessage(hwndDlg, WM_NULL, 0, 0);
diff --git a/plugins/TabSRMM/src/infopanel.cpp b/plugins/TabSRMM/src/infopanel.cpp
index 05fa5f9e8d..1c2f0b106f 100644
--- a/plugins/TabSRMM/src/infopanel.cpp
+++ b/plugins/TabSRMM/src/infopanel.cpp
@@ -329,7 +329,7 @@ void CInfoPanel::renderContent(const HDC hdc)
dis.rcItem = m_dat->m_rcPic;
dis.hDC = hdc;
dis.hwndItem = m_dat->GetHwnd();
- if (m_dat->MsgWindowDrawHandler(0, (LPARAM)&dis) == 0) {
+ if (m_dat->MsgWindowDrawHandler(&dis) == 0) {
::PostMessage(m_dat->GetHwnd(), WM_SIZE, 0, 1);
::PostMessage(m_dat->GetHwnd(), DM_FORCEREDRAW, 0, 0);
}
diff --git a/plugins/TabSRMM/src/msgdialog.cpp b/plugins/TabSRMM/src/msgdialog.cpp
index 82c75e8783..e8a653bbbe 100644
--- a/plugins/TabSRMM/src/msgdialog.cpp
+++ b/plugins/TabSRMM/src/msgdialog.cpp
@@ -358,7 +358,7 @@ void CSrmmWindow::MsgWindowUpdateState(UINT msg)
m_pWnd->Invalidate();
}
-void TSAPI ShowMultipleControls(HWND hwndDlg, const UINT *controls, int cControls, int state)
+static void ShowMultipleControls(HWND hwndDlg, const UINT *controls, int cControls, int state)
{
for (int i = 0; i < cControls; i++)
Utils::showDlgControl(hwndDlg, controls[i], state);
@@ -513,7 +513,7 @@ LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
if (dat->m_bIsAutosizingInput)
selection = ID_SPLITTERCONTEXT_SETPOSITIONFORTHISSESSION;
else
- selection = TrackPopupMenu(GetSubMenu(PluginConfig.g_hMenuContext, 12), TPM_RETURNCMD, pt.x, pt.y, 0, hwndParent, nullptr);
+ selection = TrackPopupMenu(GetSubMenu(PluginConfig.g_hMenuContext, 8), TPM_RETURNCMD, pt.x, pt.y, 0, hwndParent, nullptr);
switch (selection) {
case ID_SPLITTERCONTEXT_SAVEFORTHISCONTACTONLY:
@@ -579,7 +579,6 @@ CSrmmWindow::CSrmmWindow()
m_btnOk.OnClick = Callback(this, &CSrmmWindow::onClick_Ok);
m_btnAdd.OnClick = Callback(this, &CSrmmWindow::onClick_Add);
m_btnQuote.OnClick = Callback(this, &CSrmmWindow::onClick_Quote);
- m_btnColor.OnClick = Callback(this, &CSrmmWindow::onClick_Color);
m_btnCancelAdd.OnClick = Callback(this, &CSrmmWindow::onClick_CancelAdd);
m_message.OnChange = Callback(this, &CSrmmWindow::onChange_Message);
@@ -1169,11 +1168,8 @@ void CSrmmWindow::onClick_Ok(CCtrlButton*)
void CSrmmWindow::onClick_Add(CCtrlButton*)
{
- ADDCONTACTSTRUCT acs = {};
- acs.hContact = m_hContact;
- acs.handleType = HANDLE_CONTACT;
- acs.szProto = nullptr;
- CallService(MS_ADDCONTACT_SHOW, (WPARAM)m_hwnd, (LPARAM)&acs);
+ Contact_Add(m_hContact, m_hwnd);
+
if (!db_get_b(m_hContact, "CList", "NotOnList", 0)) {
m_bNotOnList = FALSE;
ShowMultipleControls(m_hwnd, addControls, _countof(addControls), SW_HIDE);
@@ -1183,42 +1179,6 @@ void CSrmmWindow::onClick_Add(CCtrlButton*)
}
}
-void CSrmmWindow::onClick_Color(CCtrlButton *pButton)
-{
- CHARFORMAT2 cf;
- ZeroMemory(&cf, sizeof(CHARFORMAT2));
- cf.cbSize = sizeof(CHARFORMAT2);
- cf.dwMask = CFM_COLOR;
- cf.dwEffects = 0;
-
- RECT rc;
- GetWindowRect(pButton->GetHwnd(), &rc);
- int iSelection = TrackPopupMenu(GetSubMenu(PluginConfig.g_hMenuContext, 7), TPM_RETURNCMD, rc.left, rc.bottom, 0, m_hwnd, nullptr);
- if (iSelection == ID_FONT_CLEARALLFORMATTING) {
- cf.dwMask = CFM_BOLD | CFM_COLOR | CFM_ITALIC | CFM_UNDERLINE | CFM_STRIKEOUT;
- cf.crTextColor = M.GetDword(FONTMODULE, "Font16Col", 0);
- m_message.SendMsg(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
- return;
- }
-
- if (iSelection == ID_FONT_DEFAULTCOLOR) {
- cf.crTextColor = M.GetDword(FONTMODULE, "Font16Col", 0);
- for (int i = 0; i < Utils::rtf_clrs.getCount(); i++)
- if (Utils::rtf_clrs[i].clr == cf.crTextColor)
- cf.crTextColor = RGB(GetRValue(cf.crTextColor), GetGValue(cf.crTextColor), GetBValue(cf.crTextColor) == 0 ? GetBValue(cf.crTextColor) + 1 : GetBValue(cf.crTextColor) - 1);
-
- m_message.SendMsg(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
- return;
- }
-
- for (int i = 0; i < RTF_CTABLE_DEFSIZE; i++) {
- if (Utils::rtf_clrs[i].menuid == iSelection) {
- cf.crTextColor = Utils::rtf_clrs[i].clr;
- m_message.SendMsg(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
- }
- }
-}
-
void CSrmmWindow::onClick_Quote(CCtrlButton*)
{
CHARRANGE sel;
@@ -2835,7 +2795,7 @@ INT_PTR CSrmmWindow::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
break;
case WM_DRAWITEM:
- return MsgWindowDrawHandler(wParam, lParam);
+ return MsgWindowDrawHandler((DRAWITEMSTRUCT*)lParam);
case WM_APPCOMMAND:
{
diff --git a/plugins/TabSRMM/src/msgdlgutils.cpp b/plugins/TabSRMM/src/msgdlgutils.cpp
index 920bf14be9..85fffcb7c7 100644
--- a/plugins/TabSRMM/src/msgdlgutils.cpp
+++ b/plugins/TabSRMM/src/msgdlgutils.cpp
@@ -887,8 +887,10 @@ BOOL CTabBaseDlg::DoRtfToTags(CMStringW &pszText) const
if (iCol > 0) {
if (isChat()) {
if (mi && mi->bColor) {
- if (iInd >= 0)
- res.AppendFormat(L"%%c%u", iInd);
+ if (iInd >= 0) {
+ if (!(res.IsEmpty() && m_pContainer->theme.fontColors[MSGFONTID_MESSAGEAREA] == pColors[iInd]))
+ res.AppendFormat(L"%%c%u", iInd);
+ }
else if (!res.IsEmpty())
res.Append(L"%%C");
}
@@ -1376,57 +1378,8 @@ void CTabBaseDlg::HandlePasteAndSend()
// draw various elements of the message window, like avatar(s), info panel fields
// and the color formatting menu
-int CTabBaseDlg::MsgWindowDrawHandler(WPARAM, LPARAM lParam)
+int CTabBaseDlg::MsgWindowDrawHandler(DRAWITEMSTRUCT *dis)
{
- LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
- if (dis->CtlType == ODT_MENU && dis->hwndItem == (HWND)GetSubMenu(PluginConfig.g_hMenuContext, 7)) {
- RECT rc = { 0 };
- HBRUSH old, col;
- COLORREF clr;
- switch (dis->itemID) {
- case ID_FONT_RED:
- clr = RGB(255, 0, 0);
- break;
- case ID_FONT_BLUE:
- clr = RGB(0, 0, 255);
- break;
- case ID_FONT_GREEN:
- clr = RGB(0, 255, 0);
- break;
- case ID_FONT_MAGENTA:
- clr = RGB(255, 0, 255);
- break;
- case ID_FONT_YELLOW:
- clr = RGB(255, 255, 0);
- break;
- case ID_FONT_WHITE:
- clr = RGB(255, 255, 255);
- break;
- case ID_FONT_DEFAULTCOLOR:
- clr = GetSysColor(COLOR_MENU);
- break;
- case ID_FONT_CYAN:
- clr = RGB(0, 255, 255);
- break;
- case ID_FONT_BLACK:
- clr = RGB(0, 0, 0);
- break;
- default:
- clr = 0;
- }
- col = (HBRUSH)CreateSolidBrush(clr);
- old = (HBRUSH)SelectObject(dis->hDC, col);
- rc.left = 2;
- rc.top = dis->rcItem.top - 5;
- rc.right = 15;
- rc.bottom = dis->rcItem.bottom + 4;
- Rectangle(dis->hDC, rc.left - 1, rc.top - 1, rc.right + 1, rc.bottom + 1);
- FillRect(dis->hDC, &rc, col);
- SelectObject(dis->hDC, old);
- DeleteObject(col);
- return TRUE;
- }
-
HBITMAP hbmAvatar = m_ace ? m_ace->hbmPic : PluginConfig.g_hbmUnknown;
if ((dis->hwndItem == GetDlgItem(m_hwnd, IDC_CONTACTPIC) && m_bShowAvatar) || (dis->hwndItem == m_hwnd && m_pPanel.isActive())) {
if (hbmAvatar == nullptr)
@@ -1568,7 +1521,7 @@ int CTabBaseDlg::MsgWindowDrawHandler(WPARAM, LPARAM lParam)
return TRUE;
}
- return Menu_DrawItem(lParam);
+ return Menu_DrawItem((LPARAM)dis);
}
void TSAPI LoadThemeDefaults(TContainerData *pContainer)
diff --git a/plugins/TabSRMM/src/msgs.h b/plugins/TabSRMM/src/msgs.h
index f3664676a3..10b69baf5e 100644
--- a/plugins/TabSRMM/src/msgs.h
+++ b/plugins/TabSRMM/src/msgs.h
@@ -445,9 +445,9 @@ public:
void UpdateReadChars() const;
void UpdateSaveAndSendButton();
- int MsgWindowDrawHandler(WPARAM wParam, LPARAM lParam);
- int MsgWindowUpdateMenu(HMENU submenu, int menuID);
+ int MsgWindowDrawHandler(DRAWITEMSTRUCT *dis);
int MsgWindowMenuHandler(int selection, int menuId);
+ int MsgWindowUpdateMenu(HMENU submenu, int menuID);
void RenderToolbarBG(HDC hdc, const RECT &rcWindow) const;
void UpdateToolbarBG();
@@ -490,7 +490,6 @@ public:
void onClick_Ok(CCtrlButton*);
void onClick_Add(CCtrlButton*);
- void onClick_Color(CCtrlButton*);
void onClick_Quote(CCtrlButton*);
void onClick_CancelAdd(CCtrlButton*);
diff --git a/plugins/TabSRMM/src/resource.h b/plugins/TabSRMM/src/resource.h
index ae0ed1e315..c4472425c5 100644
--- a/plugins/TabSRMM/src/resource.h
+++ b/plugins/TabSRMM/src/resource.h
@@ -684,16 +684,6 @@
#define ID_SIZE_NORMAL 40189
#define ID_SIZE_SMALLER 40190
#define ID_SIZE_TINY 40191
-#define ID_FONT_RED 40192
-#define ID_FONT_GREEN 40193
-#define ID_FONT_BLUE 40194
-#define ID_FONT_MAGENTA 40195
-#define ID_FONT_YELLOW 40196
-#define ID_FONT_BLACK 40197
-#define ID_FONT_WHITE 40198
-#define ID_FONT_CLEARALLFORMATTING 40199
-#define ID_FONT_DEFAULTCOLOR 40200
-#define ID_FONT_CYAN 40201
#define ID_DUMMY_NOMESSAGESESSIONSOPENED 40202
#define ID_SENDMENU_SENDWITHOUTTIMEOUTS 40203
#define ID_TRAYCONTEXT_SHOWTHETRAYICON 40204
@@ -734,14 +724,3 @@
#define ID_QUEUEMANAGER_RESUMESELECTED 40259
#define ID_QUEUEMANAGER_CANCELALLMULTISENDJOBS 40260
#define ID_QUEUEMANAGER_COPYMESSAGETOCLIPBOARD 40261
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 18
-#define _APS_NEXT_COMMAND_VALUE 40263
-#define _APS_NEXT_CONTROL_VALUE 1453
-#define _APS_NEXT_SYMED_VALUE 40283
-#endif
-#endif
diff --git a/plugins/TabSRMM/src/sendlater.cpp b/plugins/TabSRMM/src/sendlater.cpp
index 1a294368a9..7377e6f992 100644
--- a/plugins/TabSRMM/src/sendlater.cpp
+++ b/plugins/TabSRMM/src/sendlater.cpp
@@ -700,7 +700,7 @@ INT_PTR CALLBACK CSendLater::DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
switch (((LPNMHDR)lParam)->code) {
case NM_RCLICK:
HMENU hMenu = ::LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_TABCONTEXT));
- HMENU hSubMenu = ::GetSubMenu(hMenu, 13);
+ HMENU hSubMenu = ::GetSubMenu(hMenu, 9);
::TranslateMenu(hSubMenu);
POINT pt;
diff --git a/plugins/TabSRMM/src/sendqueue.h b/plugins/TabSRMM/src/sendqueue.h
index 5f1d8315f7..9929843238 100644
--- a/plugins/TabSRMM/src/sendqueue.h
+++ b/plugins/TabSRMM/src/sendqueue.h
@@ -108,7 +108,6 @@ private:
extern SendQueue *sendQueue;
int TSAPI ActivateExistingTab(TContainerData *pContainer, HWND hwndChild);
-void TSAPI ShowMultipleControls(const HWND hwndDlg, const UINT * controls, int cControls, int state);
void TSAPI HandleIconFeedback(CTabBaseDlg *dat, HICON iIcon);
#endif /* __SENDQUEUE_H */
diff --git a/plugins/TabSRMM/src/srmm.cpp b/plugins/TabSRMM/src/srmm.cpp
index 6ed8559fd7..ec95bf5ce7 100644
--- a/plugins/TabSRMM/src/srmm.cpp
+++ b/plugins/TabSRMM/src/srmm.cpp
@@ -44,7 +44,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/TabSRMM/src/stdafx.h b/plugins/TabSRMM/src/stdafx.h
index 452fb3151a..0f20db7320 100644
--- a/plugins/TabSRMM/src/stdafx.h
+++ b/plugins/TabSRMM/src/stdafx.h
@@ -65,7 +65,6 @@
#include <m_clist.h>
#include <m_userinfo.h>
#include <m_history.h>
-#include <m_addcontact.h>
#include <m_file.h>
#include <m_fontservice.h>
#include <m_acc.h>
diff --git a/plugins/TabSRMM/src/utils.cpp b/plugins/TabSRMM/src/utils.cpp
index 3608625705..df7dae8015 100644
--- a/plugins/TabSRMM/src/utils.cpp
+++ b/plugins/TabSRMM/src/utils.cpp
@@ -112,7 +112,7 @@ search_again:
c_closing = colorname.GetLength();
const wchar_t *wszColname = colorname.c_str();
if (endmark != -1 && c_closing > 2 && c_closing <= 6 && iswalnum(colorname[0]) && iswalnum(colorname[c_closing - 1])) {
- Utils::RTF_ColorAdd(wszColname, c_closing);
+ Utils::RTF_ColorAdd(wszColname);
if (!was_added) {
clr_was_added = was_added = true;
goto search_again;
@@ -414,49 +414,22 @@ int CTabBaseDlg::FindRTLLocale()
/////////////////////////////////////////////////////////////////////////////////////////
// init default color table. the table may grow when using custom colors via bbcodes
-static TRTFColorTable _rtf_ctable[] =
-{
- { L"black", 0, ID_FONT_BLACK },
- { L"", RGB(0,0,128), -1 },
- { L"", RGB(0,128,128), -1 },
- { L"", RGB(128,0,128), -1 },
- { L"", RGB(0,128,0), -1 },
- { L"", RGB(128,128,0), -1 },
- { L"", RGB(128,0,0), -1 },
- { L"", RGB(128,128,128), -1 },
-
- { L"", RGB(192,192,192), -1 },
- { L"blue", RGB(0, 0, 255), ID_FONT_BLUE },
- { L"cyan", RGB(0, 255, 255), ID_FONT_CYAN },
- { L"magenta", RGB(255, 0, 255), ID_FONT_MAGENTA },
- { L"green", RGB(0, 255, 0), ID_FONT_GREEN },
- { L"yellow", RGB(255, 255, 0), ID_FONT_YELLOW },
- { L"red", RGB(255, 0, 0), ID_FONT_RED },
- { L"white", RGB(255, 255, 255), ID_FONT_WHITE }
-};
-
void Utils::RTF_CTableInit()
{
- for (int i = 0; i < _countof(_rtf_ctable); i++)
- rtf_clrs.insert(new TRTFColorTable(_rtf_ctable[i]));
+ int iTableSize;
+ COLORREF *pTable = Srmm_GetColorTable(&iTableSize);
+ for (int i = 0; i < iTableSize; i++)
+ rtf_clrs.insert(new TRTFColorTable(L"", pTable[i]));
}
/////////////////////////////////////////////////////////////////////////////////////////
// add a color to the global rtf color table
-void Utils::RTF_ColorAdd(const wchar_t *tszColname, size_t length)
+void Utils::RTF_ColorAdd(const wchar_t *tszColname)
{
- TRTFColorTable *p = new TRTFColorTable;
-
wchar_t *stopped;
COLORREF clr = wcstol(tszColname, &stopped, 16);
- mir_snwprintf(p->szName, length + 1, L"%06x", clr);
- p->menuid = 0;
-
- clr = wcstol(tszColname, &stopped, 16);
- p->clr = (RGB(GetBValue(clr), GetGValue(clr), GetRValue(clr)));
-
- rtf_clrs.insert(p);
+ rtf_clrs.insert(new TRTFColorTable(tszColname, RGB(GetBValue(clr), GetGValue(clr), GetRValue(clr))));
}
/////////////////////////////////////////////////////////////////////////////////////////
diff --git a/plugins/TabSRMM/src/utils.h b/plugins/TabSRMM/src/utils.h
index 9461b3acde..eac7e070e5 100644
--- a/plugins/TabSRMM/src/utils.h
+++ b/plugins/TabSRMM/src/utils.h
@@ -38,9 +38,14 @@
struct TRTFColorTable
{
- wchar_t szName[10];
+ __forceinline TRTFColorTable(const wchar_t *wszName, COLORREF _clr) :
+ clr(_clr)
+ {
+ mir_wstrncpy(szName, wszName, _countof(szName));
+ }
+
+ wchar_t szName[10];
COLORREF clr;
- int menuid;
};
class Utils {
@@ -51,7 +56,7 @@ public:
static char* FilterEventMarkers(char *szText);
static void DoubleAmpersands(wchar_t *pszText, size_t len);
static void RTF_CTableInit();
- static void RTF_ColorAdd(const wchar_t *tszColname, size_t length);
+ static void RTF_ColorAdd(const wchar_t *tszColname);
static int ReadContainerSettingsFromDB(const MCONTACT hContact, TContainerSettings *cs, const char *szKey = 0);
static int WriteContainerSettingsToDB(const MCONTACT hContact, TContainerSettings *cs, const char *szKey = 0);
static void SettingsToContainer(TContainerData *pContainer);
diff --git a/plugins/TabSRMM/src/version.h b/plugins/TabSRMM/src/version.h
index d591342b56..b4e4e3dc6c 100644
--- a/plugins/TabSRMM/src/version.h
+++ b/plugins/TabSRMM/src/version.h
@@ -1,7 +1,7 @@
#define __MAJOR_VERSION 3
#define __MINOR_VERSION 5
#define __RELEASE_NUM 0
-#define __BUILD_NUM 7
+#define __BUILD_NUM 8
#include <stdver.h>
@@ -9,6 +9,5 @@
#define __FILENAME "TabSRMM.dll"
#define __DESCRIPTION "IM and group chat module for Miranda NG."
#define __AUTHOR "The Miranda developers team and contributors"
-#define __AUTHOREMAIL "silvercircle@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/TabSRMM/"
#define __COPYRIGHT "© 2012-17 Miranda NG team, 2000-2010 Miranda Project and contributors."
diff --git a/plugins/TipperYM/src/tipper.cpp b/plugins/TipperYM/src/tipper.cpp
index a1e9c2a56d..f8616460de 100644
--- a/plugins/TipperYM/src/tipper.cpp
+++ b/plugins/TipperYM/src/tipper.cpp
@@ -45,7 +45,6 @@ PLUGININFOEX pluginInfoEx =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/TipperYM/src/version.h b/plugins/TipperYM/src/version.h
index e8428aee33..7508fe7faf 100644
--- a/plugins/TipperYM/src/version.h
+++ b/plugins/TipperYM/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Tipper.dll"
#define __DESCRIPTION "Tooltip notification windows."
#define __AUTHOR "Scott Ellis, yaho"
-#define __AUTHOREMAIL "yaho@miranda-easy.net"
#define __AUTHORWEB "https://miranda-ng.org/p/Tipper/"
#define __COPYRIGHT "© 2005-2007 Scott Ellis, 2007-2011 Jan Holub"
diff --git a/plugins/Toaster/src/main.cpp b/plugins/Toaster/src/main.cpp
index fe4d45943e..f48c47ea20 100644
--- a/plugins/Toaster/src/main.cpp
+++ b/plugins/Toaster/src/main.cpp
@@ -11,7 +11,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Toaster/src/version.h b/plugins/Toaster/src/version.h
index ecd1e63774..e6fa41db58 100644
--- a/plugins/Toaster/src/version.h
+++ b/plugins/Toaster/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Toaster.dll"
#define __DESCRIPTION "Provides popup services based on Windows toast notification for different plugins."
#define __AUTHOR "Miranda NG team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/Toaster/"
#define __COPYRIGHT "© 2015-17 Miranda NG project"
diff --git a/plugins/TooltipNotify/src/main.cpp b/plugins/TooltipNotify/src/main.cpp
index 7151d44a06..9b84a68cb5 100644
--- a/plugins/TooltipNotify/src/main.cpp
+++ b/plugins/TooltipNotify/src/main.cpp
@@ -40,7 +40,6 @@ static PLUGININFOEX sPluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/TooltipNotify/src/version.h b/plugins/TooltipNotify/src/version.h
index 57407ab729..46c7a062df 100644
--- a/plugins/TooltipNotify/src/version.h
+++ b/plugins/TooltipNotify/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "TooltipNotify.dll"
#define __DESCRIPTION "Shows a small tooltip above system tray area when a contact status is changed."
#define __AUTHOR "perf"
-#define __AUTHOREMAIL "perf@mail333.com"
#define __AUTHORWEB "https://miranda-ng.org/p/TooltipNotify/"
#define __COPYRIGHT "© 2004-2008 Gneedah software"
diff --git a/plugins/TopToolBar/src/main.cpp b/plugins/TopToolBar/src/main.cpp
index 17c3ad9b97..4d39833380 100644
--- a/plugins/TopToolBar/src/main.cpp
+++ b/plugins/TopToolBar/src/main.cpp
@@ -12,7 +12,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/TopToolBar/src/version.h b/plugins/TopToolBar/src/version.h
index 37294d4c91..bf9fee7f1e 100644
--- a/plugins/TopToolBar/src/version.h
+++ b/plugins/TopToolBar/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "TopToolBar.dll"
#define __DESCRIPTION "ToptoolBar adds buttons in top frame for fast access."
#define __AUTHOR "Bethoven"
-#define __AUTHOREMAIL "bethoven@mailgate.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/TopToolBar/"
#define __COPYRIGHT "© 2003-2008 Bethoven"
diff --git a/plugins/TrafficCounter/src/TrafficCounter.cpp b/plugins/TrafficCounter/src/TrafficCounter.cpp
index 3c2c81fa82..f164c09816 100644
--- a/plugins/TrafficCounter/src/TrafficCounter.cpp
+++ b/plugins/TrafficCounter/src/TrafficCounter.cpp
@@ -106,7 +106,6 @@ PLUGININFOEX pluginInfoEx =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/TrafficCounter/src/resource.h b/plugins/TrafficCounter/src/resource.h
index 1618f40849..578cfbb0bc 100644
--- a/plugins/TrafficCounter/src/resource.h
+++ b/plugins/TrafficCounter/src/resource.h
@@ -389,7 +389,6 @@
#define IDC_PLUGINCPYR 1681
#define IDC_PLUGINURL 1682
#define IDC_PLUGINPID 1683
-#define IDC_PLUGINEMAIL 1684
#define IDC_IDLESPIN 1687
#define IDC_NODBDRIVERS 1690
#define IDC_IDLESTATUSLOCK 1691
diff --git a/plugins/TrafficCounter/src/version.h b/plugins/TrafficCounter/src/version.h
index 46154c826f..6acb2ae8ac 100644
--- a/plugins/TrafficCounter/src/version.h
+++ b/plugins/TrafficCounter/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "TrafficCounter.dll"
#define __DESCRIPTION "Adding traffic and time counters."
#define __AUTHOR "Ghost, Mironych"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/TrafficCounter/"
#define __COPYRIGHT "© 2002-2006 Ghost, 2007-2012 Mironych"
diff --git a/plugins/TranslitSwitcher/src/TranslitSwitcher.cpp b/plugins/TranslitSwitcher/src/TranslitSwitcher.cpp
index d61b374d12..7cba65cf85 100644
--- a/plugins/TranslitSwitcher/src/TranslitSwitcher.cpp
+++ b/plugins/TranslitSwitcher/src/TranslitSwitcher.cpp
@@ -29,7 +29,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/TranslitSwitcher/src/version.h b/plugins/TranslitSwitcher/src/version.h
index d308e511c1..7edff2681d 100644
--- a/plugins/TranslitSwitcher/src/version.h
+++ b/plugins/TranslitSwitcher/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "TranslitSwitcher.dll"
#define __DESCRIPTION "Allows you to switch a layout or transliterate or invert case of the entered text in the message window with SmileyAdd support."
#define __AUTHOR "Mataes, tico-tico, Tim"
-#define __AUTHOREMAIL "mataes2007@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/TranslitSwitcher/"
#define __COPYRIGHT "© 2011-17 Mataes, tico-tico, 2007 Dmitry Titkov"
diff --git a/plugins/UserGuide/src/main.cpp b/plugins/UserGuide/src/main.cpp
index de77c75a9d..593d79a022 100644
--- a/plugins/UserGuide/src/main.cpp
+++ b/plugins/UserGuide/src/main.cpp
@@ -10,7 +10,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/UserGuide/src/version.h b/plugins/UserGuide/src/version.h
index ab676d20ec..a725a81115 100644
--- a/plugins/UserGuide/src/version.h
+++ b/plugins/UserGuide/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "UserGuide.dll"
#define __DESCRIPTION "This plugin adds the main menu item used to view Miranda NG pack user guide."
#define __AUTHOR "Yasnovidyashii"
-#define __AUTHOREMAIL "yasnovidyashii@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/UserGuide/"
#define __COPYRIGHT "© 2009 Mikhail Yuriev"
diff --git a/plugins/UserInfoEx/src/ex_import/classExImContactXML.cpp b/plugins/UserInfoEx/src/ex_import/classExImContactXML.cpp
index 1eb4404029..1dec35ecbf 100644
--- a/plugins/UserInfoEx/src/ex_import/classExImContactXML.cpp
+++ b/plugins/UserInfoEx/src/ex_import/classExImContactXML.cpp
@@ -355,7 +355,7 @@ int CExImContactXML::ExportSetting(TiXmlElement *xmlModule, LPCSTR pszModule, LP
str = (LPSTR)mir_alloc(baselen + 6);
assert(str != nullptr);
// encode data
- if ( mir_base64_encodebuf(dbv.pbVal, dbv.cpbVal, str+1, baselen)) {
+ if (mir_base64_encodebuf(dbv.pbVal, dbv.cpbVal, str+1, baselen)) {
str[baselen+1] = 0;
str[0] = 'n';
xmlValue = new TiXmlText(str);
@@ -537,7 +537,7 @@ int CExImContactXML::LoadXmlElemnt(TiXmlElement *xContact)
LPCSTR pUID = xContact->Attribute("uidv");
if (pUID != nullptr) {
- unsigned valLen;
+ size_t valLen;
PBYTE pbVal = nullptr;
switch (*(pUID++)) {
@@ -866,7 +866,7 @@ int CExImContactXML::ImportSetting(LPCSTR pszModule, TiXmlElement *xmlEntry)
DBVARIANT dbv = { 0 };
// convert data
- unsigned baselen;
+ size_t baselen;
switch (value[0]) {
case 'b': //'b' bVal and cVal are valid
@@ -952,7 +952,7 @@ int CExImContactXML::ImportEvent(LPCSTR pszModule, TiXmlElement *xmlEvent)
if (!tmp || tmp[0] == 0)
return ERROR_INVALID_VALUE;
- unsigned baselen;
+ size_t baselen;
mir_ptr<BYTE> tmpVal((PBYTE)mir_base64_decode(tmp, &baselen));
if (tmpVal != NULL) {
// event owning module
diff --git a/plugins/UserInfoEx/src/init.cpp b/plugins/UserInfoEx/src/init.cpp
index b44a98ca60..72e20d8806 100644
--- a/plugins/UserInfoEx/src/init.cpp
+++ b/plugins/UserInfoEx/src/init.cpp
@@ -27,7 +27,6 @@ static PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/UserInfoEx/src/version.h b/plugins/UserInfoEx/src/version.h
index 557c55d5e4..df1cc5a311 100644
--- a/plugins/UserInfoEx/src/version.h
+++ b/plugins/UserInfoEx/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "UInfoEx.dll"
#define __DESCRIPTION "Extended UserInfo module for Miranda NG. Provides interface to edit all contact information."
#define __AUTHOR "DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol"
-#define __AUTHOREMAIL "deathaxe@web.de"
#define __AUTHORWEB "https://miranda-ng.org/p/UInfoEx/"
#define __COPYRIGHT "© 2006-2009 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol"
diff --git a/plugins/Variables/src/main.cpp b/plugins/Variables/src/main.cpp
index 059f49116f..3ddf6b707c 100644
--- a/plugins/Variables/src/main.cpp
+++ b/plugins/Variables/src/main.cpp
@@ -38,7 +38,6 @@ PLUGININFOEX pluginInfoEx =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Variables/src/version.h b/plugins/Variables/src/version.h
index 010c047d72..e93bd0c549 100644
--- a/plugins/Variables/src/version.h
+++ b/plugins/Variables/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Variables.dll"
#define __DESCRIPTION "Adds support for dynamic variables in strings for plugins."
#define __AUTHOR "P Boon"
-#define __AUTHOREMAIL "unregistered@users.sourceforge.net"
#define __AUTHORWEB "https://miranda-ng.org/p/Variables/"
#define __COPYRIGHT "© 2003-2008 P. Boon, Ricardo Pescuma, George Hazan"
diff --git a/plugins/Watrack/docs/sampledll.dpr b/plugins/Watrack/docs/sampledll.dpr
index d9c6839060..5a6c3b0c80 100644
--- a/plugins/Watrack/docs/sampledll.dpr
+++ b/plugins/Watrack/docs/sampledll.dpr
@@ -12,7 +12,6 @@ const
version :$00000001;
description:'The long description of your plugin, to go in the plugin options dialog';
author :'J. Random Hacker';
- authorEmail:'noreply@sourceforge.net';
copyright :'(c) 2003 J. Random Hacker';
homepage :'http://miranda-icq.sourceforge.net/';
flags :UNICODE_AWARE;
diff --git a/plugins/Watrack/player.ini b/plugins/Watrack/player.ini
index 79676eb034..cc356a1707 100644
--- a/plugins/Watrack/player.ini
+++ b/plugins/Watrack/player.ini
@@ -39,7 +39,7 @@ url='http://audioplayer.sourceforge.net/'
[Billy]
class='TAppBilly'
-url='http://sheepfriends.com/?page=billy'
+url='https://www.sheepfriends.com/index-page=billy.html'
[BizzOn]
class='BizzOn v2.x'
@@ -68,6 +68,7 @@ url='http://www.cyberlink.com/'
[Daum PotPlayer]
class='PotPlayer'
class1='PotPlayer64'
+url='http://potplayer.daum.net/'
notes='"Daum PotPlayer" text for stopped player?'
[dBpowerAMP]
@@ -106,7 +107,7 @@ url='http://www.freeboxjukebox.com/'
[J.River Media Center]
class='MJFrame'
class1='J. River Display Window'
-url='http://www.jrmediacenter.com/'
+url='https://jriver.com/'
[HKDC]
text='HKDC_HangWnd'
@@ -125,7 +126,7 @@ class='TApplication'
file='KMPLAYER.EXE'
flags=8
url='http://www.kmplayer.com'
-Notes='Winamp API used to get more info'
+notes='Winamp API used to get more info'
[MPlayer]
class='MPlayer - The Movie Player'
diff --git a/plugins/Watrack/watrack.dpr b/plugins/Watrack/watrack.dpr
index 478ced86a1..8fa8d684c3 100644
--- a/plugins/Watrack/watrack.dpr
+++ b/plugins/Watrack/watrack.dpr
@@ -46,7 +46,6 @@ begin
PluginInfo.version :=$0000060C;
PluginInfo.description:='Paste played music info into message window or status text';
PluginInfo.author :='Awkward';
- PluginInfo.authorEmail:='panda75@bk.ru; awk1975@ya.ru';
PluginInfo.copyright :='(c) 2005-2012 Awkward';
PluginInfo.homepage :='http://code.google.com/p/delphi-miranda-plugins/';
PluginInfo.flags :=UNICODE_AWARE;
diff --git a/plugins/Watrack_MPD/src/init.cpp b/plugins/Watrack_MPD/src/init.cpp
index 41d24efd60..9d28c299ff 100755
--- a/plugins/Watrack_MPD/src/init.cpp
+++ b/plugins/Watrack_MPD/src/init.cpp
@@ -29,7 +29,6 @@ PLUGININFOEX pluginInfo={
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/Watrack_MPD/src/version.h b/plugins/Watrack_MPD/src/version.h
index a973d9afdd..e07d6950e5 100644
--- a/plugins/Watrack_MPD/src/version.h
+++ b/plugins/Watrack_MPD/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Watrack_MPD.dll"
#define __DESCRIPTION "Music Player Daemon support for Watrack."
#define __AUTHOR "sss"
-#define __AUTHOREMAIL "sss123next@list.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/Watrack_MPD/"
#define __COPYRIGHT "© 2009 sss"
diff --git a/plugins/Weather/src/version.h b/plugins/Weather/src/version.h
index 7562216179..ed24bd5ae8 100644
--- a/plugins/Weather/src/version.h
+++ b/plugins/Weather/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Weather.dll"
#define __DESCRIPTION "Retrieves weather information and displays it in your contact list."
#define __AUTHOR "Miranda NG Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/Weather/"
#define __COPYRIGHT "© 2002-2005 NoName, 2005-2010 Boris Krasnovskiy, 2012-17 Miranda NG Team"
diff --git a/plugins/Weather/src/weather.cpp b/plugins/Weather/src/weather.cpp
index 6739dcf5da..3b89d9a4c1 100644
--- a/plugins/Weather/src/weather.cpp
+++ b/plugins/Weather/src/weather.cpp
@@ -66,7 +66,6 @@ static const PLUGININFOEX pluginInfoEx =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/WebView/src/main.cpp b/plugins/WebView/src/main.cpp
index 421e92fdd2..3ba57dd526 100644
--- a/plugins/WebView/src/main.cpp
+++ b/plugins/WebView/src/main.cpp
@@ -37,7 +37,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/WebView/src/version.h b/plugins/WebView/src/version.h
index 42f5d505c1..bd26cbb97e 100644
--- a/plugins/WebView/src/version.h
+++ b/plugins/WebView/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Webview.dll"
#define __DESCRIPTION "Adds web pages as contacts to your contact list and can display text and/or issue change alerts from those pages in a window."
#define __AUTHOR "Vincent Joyce"
-#define __AUTHOREMAIL "ungoliante666@hotmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/WebView/"
#define __COPYRIGHT "© 2011 Vincent Joyce"
diff --git a/plugins/WhenWasIt/src/WhenWasIt.cpp b/plugins/WhenWasIt/src/WhenWasIt.cpp
index b2d18a66ef..a9664c377b 100644
--- a/plugins/WhenWasIt/src/WhenWasIt.cpp
+++ b/plugins/WhenWasIt/src/WhenWasIt.cpp
@@ -37,7 +37,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/WhenWasIt/src/version.h b/plugins/WhenWasIt/src/version.h
index 08db3ede63..6cc416903c 100644
--- a/plugins/WhenWasIt/src/version.h
+++ b/plugins/WhenWasIt/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "WhenWasIt.dll"
#define __DESCRIPTION "Notifies you of upcoming birthdays."
#define __AUTHOR "Cristian Libotean"
-#define __AUTHOREMAIL "eblis102@yahoo.com"
#define __AUTHORWEB "https://miranda-ng.org/p/WhenWasIt/"
#define __COPYRIGHT "© 2006-2011 Cristian Libotean"
diff --git a/plugins/WhoUsesMyFiles/src/version.h b/plugins/WhoUsesMyFiles/src/version.h
index 9fc7bab382..f5696f4df3 100644
--- a/plugins/WhoUsesMyFiles/src/version.h
+++ b/plugins/WhoUsesMyFiles/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "WhoUsesMyFiles.dll"
#define __DESCRIPTION "Scans for network users of your shared files and notify you with popups."
#define __AUTHOR "Nikolay Redko"
-#define __AUTHOREMAIL "nike000@users.sf.net"
#define __AUTHORWEB "https://miranda-ng.org/p/WhoUsesMyFiles/"
#define __COPYRIGHT "© 2003 Nike"
diff --git a/plugins/WhoUsesMyFiles/src/wumfplug.cpp b/plugins/WhoUsesMyFiles/src/wumfplug.cpp
index 1a6ae70dad..f915b42d00 100644
--- a/plugins/WhoUsesMyFiles/src/wumfplug.cpp
+++ b/plugins/WhoUsesMyFiles/src/wumfplug.cpp
@@ -13,7 +13,6 @@ static PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/WinterSpeak/src/main.cpp b/plugins/WinterSpeak/src/main.cpp
index daffa20758..293a296ec5 100644
--- a/plugins/WinterSpeak/src/main.cpp
+++ b/plugins/WinterSpeak/src/main.cpp
@@ -18,7 +18,6 @@ PLUGININFOEX pluginInfo={
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/WinterSpeak/src/version.h b/plugins/WinterSpeak/src/version.h
index d0043659db..96e467db58 100644
--- a/plugins/WinterSpeak/src/version.h
+++ b/plugins/WinterSpeak/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "WinterSpeak.dll"
#define __DESCRIPTION "Miranda interface to the Microsoft Speech API."
#define __AUTHOR "Ryan Winter, BlubbFish"
-#define __AUTHOREMAIL "miranda@blubbfish.net"
#define __AUTHORWEB "https://miranda-ng.org/p/WinterSpeak/"
#define __COPYRIGHT "© 2002 Ryan Winter, 2013 BlubbFish"
diff --git a/plugins/XSoundNotify/src/version.h b/plugins/XSoundNotify/src/version.h
index 420ab55dcc..5a56cf5757 100644
--- a/plugins/XSoundNotify/src/version.h
+++ b/plugins/XSoundNotify/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "XSoundNotify.dll"
#define __DESCRIPTION "Provides extended options for sound notifications."
#define __AUTHOR "Roman Torsten"
-#define __AUTHOREMAIL "rs_torsten-public@yahoo.com"
#define __AUTHORWEB "https://miranda-ng.org/p/XSoundNotify/"
#define __COPYRIGHT "© 2011 Roman Torsten"
diff --git a/plugins/XSoundNotify/src/xsn_main.cpp b/plugins/XSoundNotify/src/xsn_main.cpp
index dc2feaa354..f5b87586cd 100644
--- a/plugins/XSoundNotify/src/xsn_main.cpp
+++ b/plugins/XSoundNotify/src/xsn_main.cpp
@@ -25,7 +25,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/YAMN/res/YAMN.rc b/plugins/YAMN/res/YAMN.rc
index 68436a49ae..c7bf41f838 100644
--- a/plugins/YAMN/res/YAMN.rc
+++ b/plugins/YAMN/res/YAMN.rc
@@ -163,8 +163,6 @@ BEGIN
EDITTEXT IDC_STDESC,85,41,215,23,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | WS_GROUP
LTEXT "Copyright:",IDC_STATIC,13,64,72,10
EDITTEXT IDC_STCOPY,85,63,215,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | WS_GROUP
- LTEXT "E-mail:",IDC_STATIC,13,77,72,11
- EDITTEXT IDC_STMAIL,85,76,214,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | WS_GROUP
LTEXT "Homepage:",IDC_STATIC,13,101,72,11
CONTROL "",IDC_STWWW,"Hyperlink",WS_TABSTOP,85,101,215,11
END
diff --git a/plugins/YAMN/src/main.cpp b/plugins/YAMN/src/main.cpp
index 0a83969f8e..ef98f4f27e 100644
--- a/plugins/YAMN/src/main.cpp
+++ b/plugins/YAMN/src/main.cpp
@@ -38,7 +38,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/YAMN/src/proto/pop3/pop3comm.cpp b/plugins/YAMN/src/proto/pop3/pop3comm.cpp
index edd7598c26..71b34d6a27 100644
--- a/plugins/YAMN/src/proto/pop3/pop3comm.cpp
+++ b/plugins/YAMN/src/proto/pop3/pop3comm.cpp
@@ -126,7 +126,6 @@ YAMN_PROTOREGISTRATION POP3ProtocolRegistration =
__VERSION_STRING_DOTS,
__COPYRIGHT,
__DESCRIPTION,
- __AUTHOREMAIL,
__AUTHORWEB,
};
diff --git a/plugins/YAMN/src/proto/pop3/pop3opt.cpp b/plugins/YAMN/src/proto/pop3/pop3opt.cpp
index 5d239f3e1e..33a679651a 100644
--- a/plugins/YAMN/src/proto/pop3/pop3opt.cpp
+++ b/plugins/YAMN/src/proto/pop3/pop3opt.cpp
@@ -97,7 +97,6 @@ INT_PTR CALLBACK DlgProcPluginOpt(HWND hDlg, UINT msg, WPARAM wParam, LPARAM)
SetDlgItemTextA(hDlg, IDC_STVER, PParser->Plugin->PluginInfo->Ver);
SetDlgItemTextA(hDlg, IDC_STDESC, PParser->Plugin->PluginInfo->Description == nullptr ? "" : PParser->Plugin->PluginInfo->Description);
SetDlgItemTextA(hDlg, IDC_STCOPY, PParser->Plugin->PluginInfo->Copyright == nullptr ? "" : PParser->Plugin->PluginInfo->Copyright);
- SetDlgItemTextA(hDlg, IDC_STMAIL, PParser->Plugin->PluginInfo->Email == nullptr ? "" : PParser->Plugin->PluginInfo->Email);
SetDlgItemTextA(hDlg, IDC_STWWW, PParser->Plugin->PluginInfo->WWW == nullptr ? "" : PParser->Plugin->PluginInfo->WWW);
break;
}
@@ -106,7 +105,6 @@ INT_PTR CALLBACK DlgProcPluginOpt(HWND hDlg, UINT msg, WPARAM wParam, LPARAM)
SetDlgItemTextA(hDlg, IDC_STVER, FParser->Plugin->PluginInfo->Ver);
SetDlgItemTextA(hDlg, IDC_STDESC, FParser->Plugin->PluginInfo->Description == nullptr ? "" : FParser->Plugin->PluginInfo->Description);
SetDlgItemTextA(hDlg, IDC_STCOPY, FParser->Plugin->PluginInfo->Copyright == nullptr ? "" : FParser->Plugin->PluginInfo->Copyright);
- SetDlgItemTextA(hDlg, IDC_STMAIL, FParser->Plugin->PluginInfo->Email == nullptr ? "" : FParser->Plugin->PluginInfo->Email);
SetDlgItemTextA(hDlg, IDC_STWWW, FParser->Plugin->PluginInfo->WWW == nullptr ? "" : FParser->Plugin->PluginInfo->WWW);
break;
}
diff --git a/plugins/YAMN/src/resource.h b/plugins/YAMN/src/resource.h
index 79965d6ae6..32b65d2c91 100644
--- a/plugins/YAMN/src/resource.h
+++ b/plugins/YAMN/src/resource.h
@@ -90,7 +90,6 @@
#define IDC_STSTATUS 1102
#define IDC_COMBOPLUGINS 1104
#define IDC_STWWW 1111
-#define IDC_STMAIL 1113
#define IDC_STCOPY 1114
#define IDC_STDESC 1115
#define IDC_STVER 1116
diff --git a/plugins/YAMN/src/version.h b/plugins/YAMN/src/version.h
index d9e8ed5c85..8efb4975b9 100644
--- a/plugins/YAMN/src/version.h
+++ b/plugins/YAMN/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "YAMN.dll"
#define __DESCRIPTION "Mail notifier and browser for Miranda NG. Included POP3 protocol."
#define __AUTHOR "y_b, tweety, majvan"
-#define __AUTHOREMAIL "francois.mean@skynet.be"
#define __AUTHORWEB "https://miranda-ng.org/p/YAMN/"
#define __COPYRIGHT "© 2002-2004 majvan, 2005-2007 tweety, y_b, Miranda community"
diff --git a/plugins/YAPP/src/version.h b/plugins/YAPP/src/version.h
index 168719a1ab..e0e0797238 100644
--- a/plugins/YAPP/src/version.h
+++ b/plugins/YAPP/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "YAPP.dll"
#define __DESCRIPTION "Yet Another Popup Plugin - Provides popup notification window services to other plugins."
#define __AUTHOR "Scott Ellis"
-#define __AUTHOREMAIL "mail@scottellis.com.au"
#define __AUTHORWEB "https://miranda-ng.org/p/YAPP/"
#define __COPYRIGHT "© 2005-2006 Scott Ellis"
diff --git a/plugins/YAPP/src/yapp.cpp b/plugins/YAPP/src/yapp.cpp
index 482f774ec6..abf01aeb67 100644
--- a/plugins/YAPP/src/yapp.cpp
+++ b/plugins/YAPP/src/yapp.cpp
@@ -34,7 +34,6 @@ PLUGININFOEX pluginInfo={
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/YARelay/src/main.cpp b/plugins/YARelay/src/main.cpp
index d33937b679..4bea49cf35 100644
--- a/plugins/YARelay/src/main.cpp
+++ b/plugins/YARelay/src/main.cpp
@@ -37,7 +37,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/YARelay/src/version.h b/plugins/YARelay/src/version.h
index d565b2ec64..90c48a27de 100644
--- a/plugins/YARelay/src/version.h
+++ b/plugins/YARelay/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "YARelay.dll"
#define __DESCRIPTION "Forwards messages to some contact when you are not available."
#define __AUTHOR "Anar Ibragimoff"
-#define __AUTHOREMAIL "ai91@mail.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/YARelay/"
#define __COPYRIGHT "© 2005 Anar Ibragimoff"
diff --git a/plugins/ZeroNotification/src/main.cpp b/plugins/ZeroNotification/src/main.cpp
index 11983be572..172b961d8e 100644
--- a/plugins/ZeroNotification/src/main.cpp
+++ b/plugins/ZeroNotification/src/main.cpp
@@ -36,7 +36,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/ZeroNotification/src/version.h b/plugins/ZeroNotification/src/version.h
index a69a5c5435..21438a72eb 100644
--- a/plugins/ZeroNotification/src/version.h
+++ b/plugins/ZeroNotification/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "ZeroNotify.dll"
#define __DESCRIPTION "Adds options to automatically disable notifications when a protocol is in a certain status."
#define __AUTHOR "bidyut, Maat"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/ZeroNotify/"
#define __COPYRIGHT "© 2005 bidyut, 2009 Maat"
diff --git a/plugins/ZeroSwitch/src/ZeroSwitch.cpp b/plugins/ZeroSwitch/src/ZeroSwitch.cpp
index e38dc64403..1230b92a2e 100644
--- a/plugins/ZeroSwitch/src/ZeroSwitch.cpp
+++ b/plugins/ZeroSwitch/src/ZeroSwitch.cpp
@@ -15,7 +15,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/ZeroSwitch/src/version.h b/plugins/ZeroSwitch/src/version.h
index 0f3801c22a..bf44a22bc4 100644
--- a/plugins/ZeroSwitch/src/version.h
+++ b/plugins/ZeroSwitch/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "ZeroSwitch.dll"
#define __DESCRIPTION "Adds Miranda NG icon into Alt-Tab switch dialog even if Miranda's main window has style other Title bar."
#define __AUTHOR "ZERO_BiT"
-#define __AUTHOREMAIL "zero-bit@mail.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/ZeroSwitch/"
#define __COPYRIGHT "© 2007 ZERO_BiT"
diff --git a/plugins/helpers/commonheaders.h b/plugins/helpers/commonheaders.h
index f85a681b1e..77ff813360 100644
--- a/plugins/helpers/commonheaders.h
+++ b/plugins/helpers/commonheaders.h
@@ -52,7 +52,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <m_message.h>
#include <m_userinfo.h>
#include <m_history.h>
-#include <m_addcontact.h>
#include <m_findadd.h>
#include <m_file.h>
#include <m_email.h>
diff --git a/plugins/mRadio/mradio.dpr b/plugins/mRadio/mradio.dpr
index 28ee6d3e9c..7133e70002 100644
--- a/plugins/mRadio/mradio.dpr
+++ b/plugins/mRadio/mradio.dpr
@@ -36,7 +36,6 @@ begin
PluginInfo.description:='This plugin plays and records Internet radio streams.'+
' Also local media files can be played.';
PluginInfo.author :='Awkward';
- PluginInfo.authorEmail:='panda75@bk.ru; awk1975@ya.ru';
PluginInfo.copyright :='(c) 2007-2014 Awkward';
PluginInfo.homepage :='http://code.google.com/p/delphi-miranda-plugins/';
PluginInfo.flags :=UNICODE_AWARE;
diff --git a/plugins/mRadio/rbass.pas b/plugins/mRadio/rbass.pas
index 509d4e9057..2ef45bb08f 100644
--- a/plugins/mRadio/rbass.pas
+++ b/plugins/mRadio/rbass.pas
@@ -304,7 +304,7 @@ begin
mGetMem(basspath,1024);
- // trying to load Bass.dll from custom
+ // trying to load bass.dll from custom
custom:=DBReadUnicode(0,PluginName,optBASSPath,nil);
if custom<>nil then
begin
@@ -339,7 +339,7 @@ begin
result:=Load_BASSDLL(basspath);
if not result then
begin
- pc:=StrCopyW(StrCopyEW(pc,'bass\'),BASSName); // %miranda_path%\plugins\bass\
+ pc:=StrCopyW(StrCopyEW(pc,'BASS\'),BASSName); // %miranda_path%\plugins\BASS\
result:=Load_BASSDLL(basspath);
end;
end;
@@ -348,11 +348,11 @@ begin
// not found but custom path is empty
if (not result) and (custom=nil) then
begin
- if MessageboxW(0,TranslateW('BASS.DLL not found! Choose BASS.dll path manually'),
+ if MessageboxW(0,TranslateW('bass.dll not found! Choose bass.dll path manually'),
cPluginName,MB_YESNO)=IDYES then
begin
pc:=nil;
- if SelectDirectory(TranslateW('Choose BASS.dll path'),pc,0) then
+ if SelectDirectory(TranslateW('Choose bass.dll path'),pc,0) then
begin
//!! if options page opened, need to change edit field
@@ -372,18 +372,18 @@ begin
end;
end;
- // check Bass.dll version
+ // check bass.dll version
if result then
begin
if (BASS_GetVersion shr 16)<BASSVERSION then
begin
Unload_BASSDLL;
result:=false;
- BassError('Wrong version of BASS.DLL');
+ BassError('Wrong version of bass.dll');
end
else
begin
- // load Bass plugins
+ // load BASS plugins
pc:=StrCopyW(pc,'bass*.dll');
fh:=FindFirstFileW(basspath,fd);
if fh<>THANDLE(INVALID_HANDLE_VALUE) then
@@ -391,7 +391,7 @@ begin
repeat
StrCopyW(pc,fd.cFileName);
if BASS_PluginLoad(pAnsiChar(basspath),BASS_UNICODE)=0 then
-;// break; // ignore if unsuccefull plugin load
+;// break; // ignore if unsuccessful plugin load
until not FindNextFileW(fh,fd);
FindClose(fh);
end;
@@ -402,7 +402,7 @@ begin
end
else
begin
- BassError('BASS.DLL not found!');
+ BassError('bass.dll not found!');
end;
mFreeMem(custom);
diff --git a/plugins/mTextControl/src/main.cpp b/plugins/mTextControl/src/main.cpp
index afc87735db..6c0a5d60a2 100644
--- a/plugins/mTextControl/src/main.cpp
+++ b/plugins/mTextControl/src/main.cpp
@@ -36,7 +36,6 @@ PLUGININFOEX pluginInfoEx =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/mTextControl/src/version.h b/plugins/mTextControl/src/version.h
index 480791cbd2..45e9e1bf0f 100644
--- a/plugins/mTextControl/src/version.h
+++ b/plugins/mTextControl/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "mTextControl.dll"
#define __DESCRIPTION "Provides text render API for different plugins."
#define __AUTHOR "Merlin_de, Victor Pavlychko"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/mTextControl/"
#define __COPYRIGHT "© 2005-2006 Victor Pavlychko, 2010 Merlin_de"
diff --git a/plugins/wbOSD/src/main.cpp b/plugins/wbOSD/src/main.cpp
index def91cae53..a898fcd591 100644
--- a/plugins/wbOSD/src/main.cpp
+++ b/plugins/wbOSD/src/main.cpp
@@ -27,7 +27,6 @@ static PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/plugins/wbOSD/src/version.h b/plugins/wbOSD/src/version.h
index 8f40116d9f..56b84e750c 100644
--- a/plugins/wbOSD/src/version.h
+++ b/plugins/wbOSD/src/version.h
@@ -30,6 +30,5 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define __FILENAME "wbOSD.dll"
#define __DESCRIPTION "Shows new message/status change info using on-screen display."
#define __AUTHOR "Andrej Krutak"
-#define __AUTHOREMAIL "andree182@gmail.com"
#define __AUTHORWEB "https://miranda-ng.org/p/wbOSD/"
#define __COPYRIGHT "© 2005 Andrej Krutak"
diff --git a/protocols/AimOscar/CMakeLists.txt b/protocols/AimOscar/CMakeLists.txt
deleted file mode 100644
index adb9dbb828..0000000000
--- a/protocols/AimOscar/CMakeLists.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-file(GLOB SOURCES "src/*.h" "src/*.cpp" "res/*.rc")
-set(TARGET AIM)
-include(${CMAKE_SOURCE_DIR}/cmake/plugin.cmake)
-add_subdirectory(proto_aim) \ No newline at end of file
diff --git a/protocols/AimOscar/docs/changelog.txt b/protocols/AimOscar/docs/changelog.txt
deleted file mode 100644
index ff2bf63416..0000000000
--- a/protocols/AimOscar/docs/changelog.txt
+++ /dev/null
@@ -1,455 +0,0 @@
-AimOSCAR Release 6
-
- *fixed contact list snac parsing error.
- *changed sleep limit on contact adding.
- *Aim links support option now stays unticked.
- *fixed first run dialog tabbing fix.
- *fixed the firstrun dialog to show up at the right time(i.e. before miranda loads).
- *fixed a deferencing of a null pointer that caused a crash during the initiation of file transfers.
- *increased size of the profile dialog.
- *added notification of buddy list modifications.
- *bbcode url additions.
- *modification to non-bbcode converted links.
- *away message removed on status change always.
- *now respects the profile path.
- *group and buddy ids do not delete when a buddy goes offline now(caused addition and deletion failures).
- *context menu item to add buddies that aren't on your list(Yes, it knows whose been naughty and who hasn't been at all)
- *Instant Idler Dialog was added to the main menu. *Instant idle options are mostly found there.
- *Added instant idle on login option.
- *Added icons for html away message, profile, instant idle, and adding buddies
- *Addition/Deletion error code string modifications.
- *Error code 0x02 added to deletion error codes.
- *added popups to replace messageboxes.
- *additional parameters for a bunch of functions - so we can connect to multiple servers.
- *email server connection & check.
- *connection does not attempt to sleep for 5 seconds on all family 4 commands anymore.
- *a bit of cleanup.
- *Modifications to the mail checking.
- *An additional option to set mail checking on login.
- *Main menu item to check mail.
- *Main menu item to manage account- includes changing password.
- *Changed the instant idle icon to one in the round icons (colored) 1.0 by maldi.
- *Added an icon for mail taken from the Yahoo plugin(by Faithhealer I believe) & I changed it's contrast a bit.
- *Modified the aesthetics of the first run dialog.
- *fixes for instant idling- so now regular idling is ignored if instant idling is set.
- *a few migration from toc2 to aimoscar additions.
- *Fixed extra clist icons.
- *Extended status icons now delete on log off instead of the "DisableESIcons" key :-D.
- *Moved ES icons to ADV3 column.
- *fixed timer check at start.
- *lots of html & bbcode conversion fixes.
- *fixes for additions and deletions(when someone has multiple copies of the same buddy on the list).
- *More fixing for extra clist icons.
- *Auto-idle now sets AIM's status to Away if 'Do not reply to requests for this message' is ticked in Options>Status>Status Messages.
- *snac length was incorrect by 6 bytes resulting in login error detection problems.
- *stopped increasing sequence number on packet sending failure- so next packet won't get you kicked.
- *fixed a packet length bug in contact list packet.
- *Stopped removing the MirVer Key on log off.
- *stopped removing extra clist icons on logoff.
- *fixed a bug that caused module deletion to not work and potential addition/deletion bugs.
- *tons of cleanup.
- *compiles with mingwstudio now.
- *no more extra winsock dependencies- created my own htons() and htonl() functions :-).
- *fixed a packet sending race condition resulting in possible kicking.(found by ripoff).
- *replace str functions with lstr functions.
- *fix by borkra for failure to close connection handles on abrupt disconnection..
- *fix for tlv crash(thanks borkra).
- *fixed status fallback issues for offline to any status besides online, away, invis, and offline.
- *aimoscar identifies unknown client's as "?" now.
- *close file transfer socket on failure.
- *cleaned up disconnection code a bit.
- *now if you manually check your mail- you'll get a popup even if you don't have mail.
- *Fixed a bug that caused the unknown user string to overwrite the SMS string.
- *fixed a bug that causes a crash on an buddy addition failure.
- *fixed an accidental usage of utf for non-utf miranda.
- *fixed some group addition bugs.
- *fixed a bug causing unknown to be written over known clients on status change.
- *Offline all contacts on miranda startup(Oops :-D).
- *Changed how aimoscar writes the MirVer string to the db- so that client change notifications don't happen twice.
- *set a timeout for peer connection attempts so that it doesn't attempt for 45* seconds.
- *Fixed a bunch of buffer overruns involving DBVARIANTS.
- *Changed the login order to force aol to send us a list on login.
- *Changed group handling to not move manually added users to their actual group.
- *Changed group handling to not lowercase all server-side group names.
- *Added meebo client detection.
- *Added adium client detection(beta adium only).
- *Modified the gaim/adium detection to show as only gaim detection.
- *Removal of some useless strlcpy() somewhere, and #define all client names.
- *Fixed a potential bug in keepalive sending.
- *lowest keepalive value is now 15 seconds
- *fixed login problems from previous login order change.
- *fixed utf8 sending for aim clients.
-
-------------------------
-
-AimOSCAR Beta 5
-
- * fixed sending the autoaway msg- so it shouldn't result in crashes and crap.
- * Idle and automessage tlv's are now considered to be different things.
- * Instant idle- idles you if you change the setting from off to on now(instead of just when you change the time amount).
- * Options dialog changes.
- * Removed pointless structs in code.
- * Removed some functions that were not used.
- * Replaced malloc() with c++ style memory allocation.
- * Replaced free() with c++ style memory deletion.
- * now use delete[] correctly.
- * addition of a tlv class to make code more maintainable and easier to deal with.
- * major code clean up.
- * removed extra generic services not used- here and there.
- * dynamic memory allocation for all strip and conversion functions.
- * Fixed memleaks here and there.
- * Removal of most static memory buffers- they were approximately 8KB allocation for each.
- * Addition of dynamic memory buffers and small memory buffers.
- * attempted to fix buddy addition.
- * Addition of a snac and flap class.
- * gaim clients now detected as gaim/adium clients.
- * fix options dialog to show up when dialog options are not checked.
- * a buffer overrun no longer occurs if there is no profile.
- * a buffer overrun no longer occurs when viewing things with %n in them.
- * some more reorganization.
-
-------------------------
-
-AimOSCAR Beta 4
-
- * Fixed overlapping text in the options window.
- * Shows the aimoscar icon in the firstrun window now.
- * naim, gaim, aim 5.x, aim 4.x, aim triton, aim express, and aim toc detection.
- * Hiptop users now detected as GPRS clients.
- * Mobile users are now detected as SMS clients.
- * message length limit- so messages don't timeout.
- * error snac now works correctly.
- * error handling for all snac families.
- * %n now changed to a name in auto-away messages.
- * goim links(taken from AimTOC2).
- * modifications to html link handling(No longer strips the title).
- * fixed idling(forgot to flip bytes from host to network byte order).
- * Instant idling option.
- * No longer attempts to grab the away message for people who are offline.
- * Changed the confirmed, unconfirmed, aol, and bot icons.
-
-------------------------
-
-AimOSCAR Beta 3
-
- * modifications for visual studio 2005.
- * added strlcpy and wcslcpy for buffer overrun protection.
- * Modifications to handle aim links.
- * Temporary users now appear online.
- * Contacts are now added correctly when the buddy list is recieved.
- * html to bbcode conversion when a contact messages you for both wide char and ascii messages.
- * bbcode to html conversion when you message a contact for both wide char and ascii messages.
- * bold, italic, underline, and text color natively supported too and from contacts.
- * modified the strip_html functions to remove a possible buffer overrun.
- * fixed the strip_html(wide char) function.
- * if recieve flap type 4 after connection- aimoscar now offlines you and your buddies.
- * fixed a memory leak in find_contact().
- * fixed memory leaks in the packet receiving handler.
- * fixed a memory leak in add_contacts_to_groups().
- * fixed memory leak with sending messages.
- * fixed memory leaks involving the extended and account type icon functions.
- * moved freeing of globally allocated strings to the unload function(should stop some hangings on exit).
- * addition of a first run dialog for entering a username and password(contributed by RiPOFF).
- * Temporary Contacts can now added permanently to the buddy list.
- * Contacts added to the list are now added to their actual server-side group.
- * Fix for a hang in the aim keepalive thread(contributed by borkra).
- * The option title and user info dialogs now use the dll name as the title(use to be hardcoded as 'AimOSCAR').
- * Build time now included in the plugin description.
- * Now idles the user according the idle settings.
- * fixed a memory leak in the proxy file transfer handler.
- * fixed a buffer overrun in the way default away messages are handled.
- * changed the default away message to be the same in all cases.
- * An away message is no longer sent as an autoreply if 'Do not reply to request for this message' is set.
-
-------------------------
-
-AimOSCAR Beta 2
-
- * Doesn't send utf8 text to buddies who don't support it.
- * Contacts are now temporary contacts if they aren't on your buddy list.
- * Doesn't send your away message when a buddy just sent theirs.
- * doesn't add "aolsystemmsg" to your buddy list cause it's a useless piece of crap of a buddy.
- * cleaned up and functionized the code that offlines contacts.
- * cleaned up defines.h.
- * added an option to disable sending autoreplies.
- * some additional code cleaning somewhere.
-
-------------------------
-
-AimOSCAR Beta 1
-
- * Fixed a bug that caused garbage to appear instead of a recieved message.
- * Multiple threads should no longer attempt to close the direct port causing miranda to hang.
- * Added the ability to add buddies back in.
- * Ichat and trillian detection modifications.
- * Added the critical status section back in- I apparently deleted it?
- * Only adds groups to the db if there are db contacts in them.
- * No longer warns you if the username and password are not in the db if you aren't attempting to connect.
- * Now strips away message linebreaks and replaces with html linebreaks.
- * '/r' now removed correctly when stripping linebreaks.
-
-------------------------
-
- AimOSCAR Alpha 8.3
-
- * Ability to send and recieve unicode messages.
- * html characters are stripped from unicode messages.
- * Conversion of greater than and less than symbols to their escape character counterparts for unicode messages.
- * The 'disable extended status icons' now stays checked.
- * 'AimOCAR must be reconnected for this option to take effect' changed to 'AimOSCAR must be...'
- * Additional client detection: Qip, micq, im2, and sim.
- * fixed the aimoscar folders everywhere bug in the profile saving code.
- * connection now only waits a second and up to three seconds for the buddylist to be received
- * removed the on demand server-side group handling because it was a *giant* bottleneck.
- * there should be no more crappy hanging because of server-side handling slowness. Going to have to rehack the whole thing in a better way or something.
- * away message is now sent to buddies when they message.
- * modified the direct port to shutdown before the aol connection- So hopefully that solves the hangs.
- * moved most message box errors over to another thread to stop the blocking behavior.
-
-------------------------
-
-AimOSCAR Alpha 8.2
-
-+Group changes are now modularized - hopefully resulting in a smaller dll.
-+Server now set back to default if set to blank
-+New option to change the default group that contacts are added to in some cases.
-+Now one space instead of two spaces between 'Disable' and 'account' for the "Disable account type icon" option.
-+all additions and deletions of extra icons occur in different threads now
-+removed the 'sleep one second' code I accidently left in along with the old extra icon deletion code.
-+new default for keepalive packets- sent every 1 minute instead of every 7 minutes.
-+option to change the default time keepalive packets are sent.
-+added the ability to change one's profile
-+%n now codes for the user's name in both receiving profiles & away messages.
-+removed useless conversion to text for profiles(for now).
-+carrots now changed into escape character counterparts on send- so that offical clients don't get confused.
-+modified trillian detection to reduce false positives.
-+added ichat detection- no icon
-+Client information is deleted when going offline now.
-+Extended status icons are removed when a buddy goes offline now.
-+Fixed a bug that caused a user to be removed from your list if you changed a group name's case(apparently AOL considers two groups with the same name the same group even if they have case variations)
-+All group comparisions are now case insensitive. In other words, the server-side group doesn't change if you change the group name.
-
--------------------------
-
-AimOSCAR Alpha 8.1(7.2 for Goons)
-
-+icq's set extra status icon works correctly now(clist bug!)
-+changed the hiptop icon to a better one
-+file receiving shouldn't memory leak anymore
-+receiver now knows if a file transfer was cancelled
-+typing notifications(for you bitchy Goons)
-+moved the setting of extra icons to a different thread; so their creation service isn't bogged down causing some to not appear.
-
--------------------------
-
-Alpha 8.0
-
-+AimOSCAR no longer handles any type of rendervous connection as a file transfer connection
-+Added extended status icons to designate unconfirmed, confirmed, AOL, ICQ, and Admin users
-+added extended status icons to designate hiptop and bot users
-+AimOSCAR now identifies Miranda ICQ, Miranda AimOSCAR, Trillian, and Kopete users
-+Direct Connection port is now set to zero after being unaquired.
-+file transfers should now crash less or NEVER, but we'll see.
-+binding to the direct port no longer occurs until you are successfully connected.
-+Added option to disable account type icons.
-+added option to disable extended status icons.
-+added option to masquerade as a hiptop user.
-
--------------------------
-
-AimOSCAR Alpha 7.1
-
--changed main connection to a different thread so that it doesn't cause miranda to hang while AimOSCAR connects.
--moved peer and proxy connection attempts to a different thread to stop freezing.
--fixed a bug that caused hanging if miranda was exited suddenly right after starting.
--AimOSCAR no longer attempts to connect if there is no username or password specified
--AimOSCAR no longer deletes the away message of a contact when one trys to view the contact's profile if that contact doesn't have a profile.
--AimOSCAR Now adds "No Profile" when attempting to view a profile of someone who does not have one.
--fixed a bug that caused viewing html away messages not to work on buddies with spaces in their name.
--If the a user does not send the port tlv with a file transfer request- AimOSCAR no-longer attempts to save the port to the db.
--When cancelling a file AimOSCAR now correctly attempts to grab a byte from the db instead of a word.
--AimOSCAR No longer keeps the direct connection listening port open while disconnected.
--AimOSCAR Now free's all malloc'd memory.
--When connecting to aol's proxy- the connection no longer timesout after the grace period has ended.
--When a file transfer is initiated with a contact and another is attempted- AimOSCAR no longer continues to attempt the second transfer even though it says it won't.
--The File Transfer Key is now removed from the db when a proxy file transfer fails(caused attempts future file transfer attempts to fail).
-
--------------------------
-
-AimOSCAR Alpha 7.0
-
--added display name to the options dialog.
--file transfering added.
--fixed bug that causes process hanging(*ahem* file transfer bug).
--added a 'force proxy transfers' option to the options dialog.
--fixed bug that removed a user's status message from the database when their profile was requested
--added a option to specify grace period or file transfer time out(default-60 seconds, min-15 seconds, max-0xffff seconds)
--caught a bug right before the release; which, caused file transfers to fail in some cases.
--caught another bug that caused Uppercase characters to not be able to be entered in the display name box.
-
--------------------------
-
-Alpha 6.9 -Bug Fix release.
-
--Chatting with Triton users should work(probably AOL users also)
--fixed bug that causes away messages to stay when a user previously was away.
--added online time(feature)
-
--------------------------
-
-Alpha 6.8
-
--no more phantom contacts, and the contact list snac works again.... and brings your ????? groups back again! woohoo!
-
--------------------------
-
-Alpha 6.7
-
--Now sends keepalive packets every 7 minutes. See if this fixes peoples disconnection problems.:-)
-
--------------------------
-
-Alpha 6.6
-
--Changed AimOSCAR to wait five seconds before sending the ssi version to AOL if the contact list snac has not been sent by aol yet.
-
--------------------------
-
-Alpha 6.5
--fixed default group deletion if removing a user from it.
--added a check to see if a group exist before adding it
--fixed the elusive snac_contact_list bug. Apparently, aol sends an extra tlv containing the server-side list version(0x03) if the client already specified it. Because, Miranda is threaded it would sometimes specify it before the contact list was received; and because the extra data was not accounted for a buffer overrun would occur.
--Fixed some group bugs. AimOSCAR would attempt adjust groups after receiving one snac_contact_list packet before; however, AOL apparently can send multiple- so, some buddies would not have group id's specified, etc and madness would happen.
--Added some SNACs that tell the errors aol is giving via msgboxes.
--Status messages are now removed from the database if the contact isn't away anymore.
--Status messages are only retrieved if they are requested by the user now. Via, a call implemented in the core or via the HTML version I implemented. This should resolve issues were AimOSCAR was unable to request any away messages, because it already requested it's limit.
--General group handling improvements.
-
--------------------------
-
-alpha 6.4
-
--checks to see whether a group id exist before deleting a group
--fixed all contacts deletion bug
--forgot to mention in the last version dynamic creation of some module names now occurs on start up so that duplicate code could be removed
-
--------------------------
-
-AimOSCAR alpha 6.3
-
--changes to get groups working correctly again.
--changes to fix connection problems and hanging that can occur-(added some critical sections to prevent duplicate connection threads and restructured some of the code)
--created the SNAc for group deletion.(apparently i forgot to create it....no wonder groups were never deleted)
--Automatically removes empty server-side groups on log in(they will be added to your list before the server-side one is deleted-so expect them add once, but not after that)
--Removes any groups that become empty during the course of the connection to aol.
--Creates groups on the fly when users are added to them... for clarification(this isn't a new feature)
-
--------------------------
-
-Alpha 6.2 release:
-
--Utf Group support- and probably bugs.
--AimOSCAR now tells if no away message is provided by the server(Some contacts do not provide one for some reason on some occasions? I checked this on gaim, and aim 5.9 and they both did not show one either. The away message is apparently absent in the packet sent by AOL even after it is requested.)
--Fixed html appearing in away messages on the buddy list.
--fixed crash that occured when changing status to away if "do not reply to request for this message" was set in the options.
--Message Delivery Confirmation is now disabled by default
--Restructured the code for saving away messages and profiles- it is now contained in the write_away_message and write_profile functions; which, makes reading the SNACs code easier and helps reduce executable size.
-
--------------------------
-
-Alpha 6.1
-
--Now grabs the away message directly from the database if miranda hasn't aquired it yet.
--Removed some check that obviously didn't fix the random connection crashes on the buddy list SNAC.
-
--------------------------
-
-Alpha 6.0
-
--dynamic creation and deletion of cookie, away message storage, protocol name, and current working directory
--Module deletion functions added
--Fixed some bugs with group handling(module deletion fixed these bugs)
--Group deletion added. All buddies in the group that is deleted are moved to the 'Buddies' group.
--Changed group handling to not delete buddies in the 'Buddies' group when that group is deleted.
--'auto response' messages now indicate that they are auto response messages.
--added unique id return capablity to make AimOSCAR compatible with metacontacts.(hopefully)
--turned the the away message handler into a CRITICALSECTION so that it doesn't screw up and not set an away message.(Hopefully)
-
--------------------------
-
-Alpha 5.2 released.
-
--Fixed a nasty bug that caused crashes when attempting to view html away messages.
-
--------------------------
-
-Alpha 5.1
-
--Fixed a bug that caused the search dialog to display garbage names after searching.
-
--------------------------
-
-Alpha 5.0
-
--G++ Compilation
--Idle time now shows correctly
--Doesn't use 16MB of virtual memory anymore
--Added an option to remove message confirmation
--Buddy Addition/Deletion implemented
--Group Addition(Server-side)
--Implemented all backend snacks(or SNACs;-) ) for group/buddy addition/deletion
--Made a small modification to the buddylist SNAC anaylsis to catch(perhaps) a random bug that occurs when retrieving the buddy list after login.
-
--------------------------
-
-Alpha 4.3
-
--Fixed Wireless buddies to show as online(Don't be surprised when you get the two bots that AOL auto add's to your buddy list now... The change I made in the id string-e.g. emulated the offical client id string- caused aol to have THAT spectacular effect)
--And those damnedable directories should be gone for good. Hopefully.
-
--------------------------
-
-Alpha 4.2
-
--Can now see that contacts are idle.(Turn dim idle contacts on)
--Fixed SNAC(03,0B) analysis(see: http://iserverd.khstu.ru/oscar/snac_03_0b.html)- multiple tlv's can now be read.
--On the phone status no longer shows up in the aim menu.
--Now "Is Connecting" status is now shown while AimOSCAR is connecting.
--On the phone, DnD, NA, Occupied, and out to lunch are now linked to away status.
--Free for chat is now linked to Online status.
--In certain circumstances AimOSCAR would become stuck on "Is Connecting"; and would not reconnect until Miranda was restarted.- This should not happen anymore.
-
--------------------------
-
-Alpha 4.1
-
--Users appear in their actual aim groups.(No add, deletion, changing yet.)
-
--------------------------
-
-Alpha 4.0
-
--added groups
--fixed nonworking outgoing messages
-
--------------------------
-
-Alpha 3
-
--Converted to c++, so that I could clean up some of the code
--Away messages should change even if you are already away
--rogue AimOSCAR directories should no longer be created
--'to' was changed to 'too' somewhere in the code
--You should no longer appear as Unknown contact when typing(Re-apply the options)
--mobile people should have mobile status now.
-
--------------------------
-
-Alpha 2(Alpha 1.1)
--?
-
--------------------------
-
-Alpha 1
--initial release
-
diff --git a/protocols/AimOscar/docs/readme.txt b/protocols/AimOscar/docs/readme.txt
deleted file mode 100644
index 7713b18ec8..0000000000
--- a/protocols/AimOscar/docs/readme.txt
+++ /dev/null
@@ -1,104 +0,0 @@
-AIM protocol plugin for Miranda IM
-
-About:
-
-This Miranda IM plugin allows you to connect with AIM
-instant messenger network and communicate with other AIM users.
-It also allows you to connect with other linked AOL networks
-such as, iChat and ICQ.
-
-Supported Statuses:
- -Online
- -Away
- -Invisible
- -Offline
- -idle
-
- Features:
- -Send/Receive messages
- -Addition/Deletion of buddies.
- -File Transfer
- -AOL Mail Checking
- -Instant Message Formatting(With Appropriate Plugins)
- -Away Message & Profile Viewing
- -Aim Links Handling on Websites
-
-Options Overview:
- AIM User Details:
- Screenname- Your account name.
- Display Name- The name you want to show up in your IM conversations.
- Password- Your account password.
- Login Server- The server you are going to login to.(Remove it to reset it).
- AIM Options:
- Message Delivery Confirmation- Whether to have notifications of your message reaching other buddies.
- Do Not Autoreply When Away- Whether to send an away message to a buddy if they message you.
- Convert Incoming Messages to BBCode- Enable if you want to see some formating from your buddies.
- Convert Outgoing Messages to HTML- Enable if you want some formating to be sent to your buddies.
- Disable Account Type Icons-Removes some extra clist icons that are only visible on clist_modern and clist_nicer.
- Disable Extended Status Icons-Removes some extra clist icons that are only visible on clist_modern and clist_nicer.
- Handle aim: links on websites- Enable to allow handling of goim links.
- Check Mail on Login- Enable to have your account email automatically checked on login.
- Advanced Options:
- Keep Alive Timer- The amount of time between each keepalive packet that aim sends.
- File Transfer Grace Period- The amount of time before an inactive connection is disconnected for file transfers.
- Instant Idle on Login- Idles you on login.
- Force Proxy File Transfers- Makes all file transfers go through AOL's proxy server.
- Masquerade as a Sidekick/Hiptop User- Enable to 'fake' that you are on an aim mobile sidekick device.
-
-Main Menu Options Overview:
- Manage Account- Opens the manage your account link on AOL's website.
- Check Mail- Checks your mail for new messages.
- Instant Idle- Let's you specify the amount of hours and minutes you want to set yourself to idle as.
-
-Context Menu Options Overview:
- Add To Server List- Adds a buddy to your server-side buddy list if they aren't already on it.
- File- Let's you send files to the particular buddy.
- Read Profile- Opens a browser window with the specified buddy's profile.
- Read Away Message- Opens a dialog with a text version of the specified buddy's away message.
- Read HTML Away Message- Opens a browser window the the specified buddy's away message.
-
-Contact:
-
-Current developer:
- Boris Krasnovskiy
- Email: borkra@miranda-im.org
-
-Former developer and creator:
- Aaron Myles Landwehr
- Email: aaron@miranda-im.org
- AIM: thegermanaaron
- ICQ: 197688952
- IRC: snaphat @ #miranda @ irc.freenode.net
- JABBER: snaphat@gmail.com
- MSN: whitehata_zz@hotmail.com
- YAHOO: snapdaemon
-
-Thanks (by Aaron Myles Lendwehr):
- -To the numerous bug testers who make it possible for me to code badly and get away with it.
- -To My kitten Mew for typing on the keyboard everytime I try to do something.
- -To the Project members for making the plugin possible to code.
- -To AOL for a badly designed protocol.
- -To Koobs for keeping me smiling(he made me put it).
- -To Kimberly Myers who I love a great deal more than Anything else.
- -To Elise Bader for being the greatest secret holder and friend ever.
-
-License and Copyright
-_____________________
-
-Copyright (C) 2008-2009 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- \ No newline at end of file
diff --git a/protocols/AimOscar/proto_aim/CMakeLists.txt b/protocols/AimOscar/proto_aim/CMakeLists.txt
deleted file mode 100644
index 883d656e17..0000000000
--- a/protocols/AimOscar/proto_aim/CMakeLists.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-set(TARGET Proto_AIM)
-include(${CMAKE_SOURCE_DIR}/cmake/icons.cmake) \ No newline at end of file
diff --git a/protocols/AimOscar/proto_aim/res/Away.ico b/protocols/AimOscar/proto_aim/res/Away.ico
deleted file mode 100644
index 9f668b4fe7..0000000000
--- a/protocols/AimOscar/proto_aim/res/Away.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/proto_aim/res/Invisible.ico b/protocols/AimOscar/proto_aim/res/Invisible.ico
deleted file mode 100644
index 5c298d2e4e..0000000000
--- a/protocols/AimOscar/proto_aim/res/Invisible.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/proto_aim/res/Offline.ico b/protocols/AimOscar/proto_aim/res/Offline.ico
deleted file mode 100644
index 54fabffaa7..0000000000
--- a/protocols/AimOscar/proto_aim/res/Offline.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/proto_aim/res/Online.ico b/protocols/AimOscar/proto_aim/res/Online.ico
deleted file mode 100644
index 429afcc9ff..0000000000
--- a/protocols/AimOscar/proto_aim/res/Online.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/proto_aim/res/Phone.ico b/protocols/AimOscar/proto_aim/res/Phone.ico
deleted file mode 100644
index 5c568d67bf..0000000000
--- a/protocols/AimOscar/proto_aim/res/Phone.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/proto_aim/res/Proto_AIM.rc b/protocols/AimOscar/proto_aim/res/Proto_AIM.rc
deleted file mode 100644
index 14e5082d07..0000000000
--- a/protocols/AimOscar/proto_aim/res/Proto_AIM.rc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "..\src\resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// Russian (Russia) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
-LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "..\\src\\resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""afxres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Icon
-//
-
-// Icon with lowest ID value placed first to ensure application icon
-// remains consistent on all systems.
-IDI_ICON1 ICON "Online.ico"
-IDI_ICON2 ICON "Offline.ico"
-IDI_ICON3 ICON "Away.ico"
-IDI_ICON4 ICON "Invisible.ico"
-IDI_ICON5 ICON "Phone.ico"
-#endif // Russian (Russia) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
diff --git a/protocols/AimOscar/proto_aim/src/resource.h b/protocols/AimOscar/proto_aim/src/resource.h
deleted file mode 100644
index d63bb1cdec..0000000000
--- a/protocols/AimOscar/proto_aim/src/resource.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by Proto_AIM.rc
-//
-#define IDI_ICON1 104
-#define IDI_ICON2 105
-#define IDI_ICON3 128
-#define IDI_ICON4 130
-#define IDI_ICON5 1002
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 106
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1001
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
diff --git a/protocols/AimOscar/res/add.ico b/protocols/AimOscar/res/add.ico
deleted file mode 100644
index fcfa03a6ad..0000000000
--- a/protocols/AimOscar/res/add.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/admin.ico b/protocols/AimOscar/res/admin.ico
deleted file mode 100644
index b788d40de6..0000000000
--- a/protocols/AimOscar/res/admin.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/aim.rc b/protocols/AimOscar/res/aim.rc
deleted file mode 100755
index dbef88d58a..0000000000
--- a/protocols/AimOscar/res/aim.rc
+++ /dev/null
@@ -1,403 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "..\src\resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// Englisch (USA) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "..\\src\\resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""afxres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Dialog
-//
-
-IDD_AIM DIALOGEX 0, 0, 305, 212
-STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
-EXSTYLE WS_EX_CONTROLPARENT
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- GROUPBOX "AIM user details",IDC_DETAILS,3,7,147,72,WS_GROUP
- RTEXT "Screen name:",IDC_STATIC,8,20,50,11
- EDITTEXT IDC_SN,60,17,87,15,ES_LOWERCASE | ES_AUTOHSCROLL
- RTEXT "Display name:",IDC_STATIC,8,39,50,9
- EDITTEXT IDC_NK,60,37,87,15,ES_AUTOHSCROLL
- RTEXT "Password:",IDC_STATIC,8,59,50,11
- EDITTEXT IDC_PW,60,57,87,15,ES_PASSWORD | ES_AUTOHSCROLL
- GROUPBOX "AIM options",IDC_OPTIONS,3,83,147,120,WS_GROUP
- CONTROL "Message delivery confirmation",IDC_DC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,93,139,13
- CONTROL "Do not autoreply when away",IDC_DM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,105,139,13
- CONTROL "Convert incoming messages to BBCode",IDC_FI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,117,139,13
- CONTROL "Convert outgoing messages to HTML",IDC_FO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,129,139,13
- CONTROL "Disable avatars",IDC_DA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,141,139,13
- CONTROL "Disable account type icons",IDC_AT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,153,139,13
- CONTROL "Disable extended status icons",IDC_ES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,165,139,13
- CONTROL "Notify about new mail",IDC_CM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,177,139,13
- CONTROL "Manage server groups",IDC_MG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,188,139,13
- GROUPBOX "Advanced options",IDC_EXPERT,154,7,145,72,WS_GROUP
- CONTROL "Instant idle on login",IDC_II,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,18,138,15
- CONTROL "Force proxy file transfers",IDC_FP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,33,138,11
- CONTROL "Masquerade as a Sidekick/Hiptop user",IDC_HF,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,46,138,13
- GROUPBOX "Connection",IDC_STATIC,154,83,145,80
- RTEXT "Login server:",IDC_STATIC,157,98,52,12
- EDITTEXT IDC_HN,212,96,83,13,ES_AUTOHSCROLL
- RTEXT "Port:",IDC_STATIC,157,115,52,12
- EDITTEXT IDC_PN,212,113,38,13,ES_AUTOHSCROLL
- PUSHBUTTON "Reset",IDC_SVRRESET,260,112,35,14
- CONTROL "Disable SSL",IDC_DSSL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,129,138,10
- CONTROL "Force single client",IDC_FSC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,149,138,10
- CONTROL "Use ""clientlogin"" (recommended)",IDC_CLIENTLOGIN,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,139,138,10
- CTEXT "* Some changes will take effect the next time you connect to the AIM network",IDC_MASQ,157,168,138,28,NOT WS_VISIBLE
-END
-
-IDD_INFO DIALOGEX 0, 0, 227, 165
-STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
-EXSTYLE WS_EX_CONTROLPARENT | WS_EX_APPWINDOW
-FONT 8, "MS Shell Dlg", 0, 0, 0x0
-BEGIN
- PUSHBUTTON "Save profile",IDC_SETPROFILE,157,4,60,30,WS_DISABLED
- CONTROL "",IDC_PROFILE,"RichEdit50W",WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP | 0x11c4,4,36,213,112
- CONTROL "",IDC_BOLD,"Button",BS_OWNERDRAW,4,4,16,14,WS_EX_RIGHT
- CONTROL "",IDC_ITALIC,"Button",BS_OWNERDRAW,20,4,16,14,WS_EX_RIGHT
- CONTROL "",IDC_UNDERLINE,"Button",BS_OWNERDRAW,36,4,16,14,WS_EX_RIGHT
- CONTROL "",IDC_SUPERSCRIPT,"Button",BS_OWNERDRAW,52,4,16,14,WS_EX_RIGHT
- CONTROL "",IDC_SUBSCRIPT,"Button",BS_OWNERDRAW,84,4,16,14,WS_EX_RIGHT
- CONTROL "",IDC_FOREGROUNDCOLOR,"Button",BS_OWNERDRAW,100,4,16,14,WS_EX_RIGHT
- CONTROL "",IDC_FOREGROUNDCOLORPICKER,"Button",BS_OWNERDRAW,116,4,10,14,WS_EX_RIGHT
- CONTROL "",IDC_BACKGROUNDCOLOR,"Button",BS_OWNERDRAW,126,4,16,14,WS_EX_RIGHT
- CONTROL "",IDC_BACKGROUNDCOLORPICKER,"Button",BS_OWNERDRAW,142,4,10,14,WS_EX_RIGHT
- COMBOBOX IDC_TYPEFACE,4,21,112,117,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
- COMBOBOX IDC_FONTSIZE,126,21,26,117,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
- CONTROL "",IDC_NORMALSCRIPT,"Button",BS_OWNERDRAW,68,4,16,14,WS_EX_RIGHT
-END
-
-IDD_AIMACCOUNT DIALOGEX 0, 0, 186, 134
-STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
-EXSTYLE WS_EX_CONTROLPARENT
-FONT 8, "MS Shell Dlg", 0, 0, 0x0
-BEGIN
- LTEXT "Screen name:",IDC_STATIC,0,0,53,12
- EDITTEXT IDC_SN,54,0,131,12,ES_AUTOHSCROLL
- LTEXT "Password:",IDC_STATIC,0,16,53,12
- EDITTEXT IDC_PW,54,16,131,12,ES_PASSWORD | ES_AUTOHSCROLL
- CONTROL "Create a new AIM account",IDC_NEWAIMACCOUNTLINK,
- "Hyperlink",WS_TABSTOP,0,40,174,12
-END
-
-IDD_IDLE DIALOGEX 0, 0, 173, 74
-STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
-EXSTYLE WS_EX_TOPMOST
-CAPTION "AIM instant idler"
-FONT 8, "MS Shell Dlg", 0, 0, 0x0
-BEGIN
- EDITTEXT IDC_IIH,86,11,28,12,ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
- LTEXT "Number of hours:",IDC_STATIC,18,13,62,12
- LTEXT "Number of minutes:",IDC_STATIC,12,29,64,12
- EDITTEXT IDC_IIM,86,28,28,12,ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
- DEFPUSHBUTTON "Set idle",IDOK,78,50,46,14
- PUSHBUTTON "Unset idle",IDCANCEL,129,50,39,14
-END
-
-IDD_PRIVACY DIALOGEX 0, 0, 305, 220
-STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
-EXSTYLE WS_EX_CONTROLPARENT
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- LTEXT "Users who can contact me:",IDC_STATIC,14,14,282,8
- CONTROL "Allow all users",IDC_ALLOWALL,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,14,29,159,10
- CONTROL "Allow only users on contact list",IDC_ALLOWCONT,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,14,40,159,10
- CONTROL "Allow only users below",IDC_ALLOWBELOW,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,14,51,159,10
- CONTROL "Block all users",IDC_BLOCKALL,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,177,40,121,10
- CONTROL "Block only users below",IDC_BLOCKBELOW,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,177,51,121,10
- EDITTEXT IDC_ALLOWEDIT,16,67,82,14,ES_AUTOHSCROLL,WS_EX_CLIENTEDGE | WS_EX_STATICEDGE
- PUSHBUTTON "Add",IDC_ALLOWADD,98,67,38,14
- LISTBOX IDC_ALLOWLIST,16,81,119,86,LBS_SORT | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP,WS_EX_STATICEDGE
- PUSHBUTTON "Remove",IDC_ALLOWREMOVE,16,167,119,12
- EDITTEXT IDC_BLOCKEDIT,177,66,82,14,ES_AUTOHSCROLL,WS_EX_STATICEDGE
- PUSHBUTTON "Add",IDC_BLOCKADD,259,66,37,14
- LISTBOX IDC_BLOCKLIST,177,80,119,86,LBS_SORT | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP,WS_EX_STATICEDGE
- PUSHBUTTON "Remove",IDC_BLOCKREMOVE,177,166,119,12
- CONTROL "Idle",IDC_SIS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,197,119,9
- LTEXT "Allow contacts to be notified of:",IDC_STATIC,14,185,284,8
-END
-
-IDD_CHAT DIALOGEX 0, 0, 162, 82
-STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
-EXSTYLE WS_EX_TOPMOST
-CAPTION "Join chat room"
-FONT 8, "MS Shell Dlg", 0, 0, 0x0
-BEGIN
- LTEXT "Chat room",IDC_STATIC,7,10,86,9
- EDITTEXT IDC_ROOM,6,26,96,12,ES_LOWERCASE | ES_AUTOHSCROLL
- DEFPUSHBUTTON "&Join",IDOK,110,6,46,14
- PUSHBUTTON "&Cancel",IDCANCEL,110,24,45,14
- LTEXT "This allows access to user defined chat rooms. To access predefined chat rooms use web links",IDC_STATIC,5,49,150,25
-END
-
-IDD_ADMIN DIALOGEX 0, 0, 224, 147
-STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | DS_CENTER | WS_CHILD
-EXSTYLE WS_EX_CONTROLPARENT
-FONT 8, "MS Shell Dlg", 0, 0, 0x0
-BEGIN
- GROUPBOX "Change password",IDC_STATIC,2,2,101,103
- LTEXT "Original",IDC_STATIC,8,14,87,8
- EDITTEXT IDC_CPW,5,23,90,14,ES_PASSWORD | ES_AUTOHSCROLL
- LTEXT "New",IDC_STATIC,7,40,87,8
- EDITTEXT IDC_NPW1,5,49,90,14,ES_PASSWORD | ES_AUTOHSCROLL
- LTEXT "Repeat",IDC_STATIC,7,65,88,8
- EDITTEXT IDC_NPW2,5,74,90,14,ES_PASSWORD | ES_AUTOHSCROLL
- LTEXT "*Passwords don't match.",IDC_PINFO,7,92,82,9,NOT WS_VISIBLE
- LTEXT "Screen name",IDC_STATIC,118,15,92,8
- EDITTEXT IDC_FNAME,117,23,93,14,ES_AUTOHSCROLL
- LTEXT "E-mail",IDC_STATIC,118,41,92,8
- EDITTEXT IDC_CEMAIL,117,49,93,14,ES_AUTOHSCROLL
- PUSHBUTTON "Confirm account",IDC_CONFIRM,5,122,86,16,BS_MULTILINE
- LTEXT "*Applied upon reconnect",IDC_STATIC,127,109,80,8
- PUSHBUTTON "Save changes",IDC_SAVECHANGES,131,122,79,16
-END
-
-IDD_CHATROOM_INVITE DIALOGEX 0, 0, 302, 125
-STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
-EXSTYLE WS_EX_TOPMOST
-CAPTION "Invite buddy to chat room"
-FONT 8, "MS Shell Dlg", 0, 0, 0x0
-BEGIN
- LTEXT "Screen name",IDC_STATIC,154,31,43,9
- PUSHBUTTON "&Invite",IDOK,165,107,46,14
- PUSHBUTTON "&Cancel",IDCANCEL,234,107,45,14
- LTEXT "Invitation reason",IDC_STATIC,155,58,60,9
- EDITTEXT IDC_MSG,154,68,140,32,ES_MULTILINE | ES_LOWERCASE | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL
- CONTROL "",IDC_CCLIST,"CListControl",WS_TABSTOP | 0x16f,7,4,141,117,WS_EX_CLIENTEDGE
- EDITTEXT IDC_EDITSCR,154,41,93,12,ES_AUTOHSCROLL
- PUSHBUTTON "Add",IDC_ADDSCR,247,40,49,14
- CTEXT "",IDC_ROOMNAME,154,10,140,11,0,WS_EX_STATICEDGE
-END
-
-IDD_CHATROOM_INVITE_REQ DIALOGEX 0, 0, 177, 116
-STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION
-EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
-CAPTION "Chat room invitation request"
-FONT 8, "MS Shell Dlg", 0, 0, 0x0
-BEGIN
- DEFPUSHBUTTON "&Join",IDOK,77,97,46,14
- PUSHBUTTON "&Deny",IDCANCEL,125,97,45,14
- LTEXT "Message",IDC_STATIC,6,40,60,9
- CTEXT "",IDC_ROOMNAME,80,4,93,12,SS_SUNKEN
- EDITTEXT IDC_MSG,6,50,166,40,ES_MULTILINE | ES_LOWERCASE | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | WS_HSCROLL
- LTEXT "Room",IDC_STATIC,5,6,73,8
- LTEXT "Screen name",IDC_STATIC,5,24,73,8
- CTEXT "",IDC_SCREENNAME,80,22,93,12,SS_SUNKEN
-END
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// DESIGNINFO
-//
-
-#ifdef APSTUDIO_INVOKED
-GUIDELINES DESIGNINFO
-BEGIN
- IDD_AIM, DIALOG
- BEGIN
- RIGHTMARGIN, 299
- VERTGUIDE, 8
- VERTGUIDE, 58
- VERTGUIDE, 60
- VERTGUIDE, 147
- VERTGUIDE, 154
- VERTGUIDE, 157
- VERTGUIDE, 209
- VERTGUIDE, 212
- VERTGUIDE, 295
- BOTTOMMARGIN, 206
- END
-
- IDD_INFO, DIALOG
- BEGIN
- END
-
- IDD_AIMACCOUNT, DIALOG
- BEGIN
- RIGHTMARGIN, 183
- BOTTOMMARGIN, 72
- END
-
- IDD_IDLE, DIALOG
- BEGIN
- RIGHTMARGIN, 172
- BOTTOMMARGIN, 73
- END
-
- IDD_PRIVACY, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 298
- VERTGUIDE, 14
- VERTGUIDE, 173
- VERTGUIDE, 177
- VERTGUIDE, 296
- TOPMARGIN, 7
- BOTTOMMARGIN, 213
- END
-
- IDD_CHAT, DIALOG
- BEGIN
- RIGHTMARGIN, 155
- BOTTOMMARGIN, 80
- END
-
- IDD_ADMIN, DIALOG
- BEGIN
- RIGHTMARGIN, 223
- BOTTOMMARGIN, 146
- END
-
- IDD_CHATROOM_INVITE, DIALOG
- BEGIN
- RIGHTMARGIN, 300
- TOPMARGIN, 4
- BOTTOMMARGIN, 121
- END
-
- IDD_CHATROOM_INVITE_REQ, DIALOG
- BEGIN
- BOTTOMMARGIN, 111
- END
-END
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Icon
-//
-
-// Icon with lowest ID value placed first to ensure application icon
-// remains consistent on all systems.
-IDI_AIM ICON "oscar.ico"
-
-IDI_ADD ICON "add.ico"
-
-IDI_ICQ ICON "icq.ico"
-
-IDI_AOL ICON "aol.ico"
-
-IDI_HIPTOP ICON "hiptop.ico"
-
-IDI_BOT ICON "bot.ico"
-
-IDI_ADMIN ICON "admin.ico"
-
-IDI_CONFIRMED ICON "confirmed.ico"
-
-IDI_UNCONFIRMED ICON "unconfirmed.ico"
-
-IDI_AWAY ICON "away.ico"
-
-IDI_IDLE ICON "idle.ico"
-
-IDI_PROFILE ICON "profile.ico"
-
-IDI_MAIL ICON "inbox.ico"
-
-IDI_BOLD ICON "bold.ico"
-
-IDI_NBOLD ICON "nbold.ico"
-
-IDI_NITALIC ICON "nitalic.ico"
-
-IDI_ITALIC ICON "italic.ico"
-
-IDI_NUNDERLINE ICON "nunderline.ico"
-
-IDI_UNDERLINE ICON "underline.ico"
-
-IDI_NSUPERSCRIPT ICON "nsuperscript.ico"
-
-IDI_NSUBSCRIPT ICON "nsubscript.ico"
-
-IDI_FOREGROUNDCOLOR ICON "foregroundcolor.ico"
-
-IDI_BACKGROUNDCOLOR ICON "backgroundcolor.ico"
-
-IDI_NNORMALSCRIPT ICON "nnormalscript.ico"
-
-IDI_NORMALSCRIPT ICON "normalscript.ico"
-
-IDI_SUBSCRIPT ICON "subscript.ico"
-
-IDI_SUPERSCRIPT ICON "superscript.ico"
-
-IDI_BLOCK ICON "block.ico"
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// AFX_DIALOG_LAYOUT
-//
-
-IDD_AIM AFX_DIALOG_LAYOUT
-BEGIN
- 0
-END
-
-IDD_PRIVACY AFX_DIALOG_LAYOUT
-BEGIN
- 0
-END
-
-#endif // Englisch (USA) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
diff --git a/protocols/AimOscar/res/aol.ico b/protocols/AimOscar/res/aol.ico
deleted file mode 100644
index 7d63eb3ad5..0000000000
--- a/protocols/AimOscar/res/aol.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/away.ico b/protocols/AimOscar/res/away.ico
deleted file mode 100644
index 1b0a10ac26..0000000000
--- a/protocols/AimOscar/res/away.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/backgroundcolor.ico b/protocols/AimOscar/res/backgroundcolor.ico
deleted file mode 100644
index ae4c4d25de..0000000000
--- a/protocols/AimOscar/res/backgroundcolor.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/block.ico b/protocols/AimOscar/res/block.ico
deleted file mode 100644
index 6e7becdd69..0000000000
--- a/protocols/AimOscar/res/block.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/bold.ico b/protocols/AimOscar/res/bold.ico
deleted file mode 100644
index 63810159f9..0000000000
--- a/protocols/AimOscar/res/bold.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/bot.ico b/protocols/AimOscar/res/bot.ico
deleted file mode 100644
index e9dd0c14e1..0000000000
--- a/protocols/AimOscar/res/bot.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/confirmed.ico b/protocols/AimOscar/res/confirmed.ico
deleted file mode 100644
index c33fc0317d..0000000000
--- a/protocols/AimOscar/res/confirmed.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/foregroundcolor.ico b/protocols/AimOscar/res/foregroundcolor.ico
deleted file mode 100644
index b75015154a..0000000000
--- a/protocols/AimOscar/res/foregroundcolor.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/hiptop.ico b/protocols/AimOscar/res/hiptop.ico
deleted file mode 100644
index 266c9d1ecc..0000000000
--- a/protocols/AimOscar/res/hiptop.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/icq.ico b/protocols/AimOscar/res/icq.ico
deleted file mode 100644
index d3a9597771..0000000000
--- a/protocols/AimOscar/res/icq.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/idle.ico b/protocols/AimOscar/res/idle.ico
deleted file mode 100644
index 19be9acb30..0000000000
--- a/protocols/AimOscar/res/idle.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/inbox.ico b/protocols/AimOscar/res/inbox.ico
deleted file mode 100644
index 7a5e461f6f..0000000000
--- a/protocols/AimOscar/res/inbox.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/italic.ico b/protocols/AimOscar/res/italic.ico
deleted file mode 100644
index 42d3fea61b..0000000000
--- a/protocols/AimOscar/res/italic.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/nbold.ico b/protocols/AimOscar/res/nbold.ico
deleted file mode 100644
index dcdd5ce175..0000000000
--- a/protocols/AimOscar/res/nbold.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/nitalic.ico b/protocols/AimOscar/res/nitalic.ico
deleted file mode 100644
index 6fd9fc46af..0000000000
--- a/protocols/AimOscar/res/nitalic.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/nnormalscript.ico b/protocols/AimOscar/res/nnormalscript.ico
deleted file mode 100644
index b4bc629440..0000000000
--- a/protocols/AimOscar/res/nnormalscript.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/normalscript.ico b/protocols/AimOscar/res/normalscript.ico
deleted file mode 100644
index a7e17f28c3..0000000000
--- a/protocols/AimOscar/res/normalscript.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/nsubscript.ico b/protocols/AimOscar/res/nsubscript.ico
deleted file mode 100644
index f4921ec32d..0000000000
--- a/protocols/AimOscar/res/nsubscript.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/nsuperscript.ico b/protocols/AimOscar/res/nsuperscript.ico
deleted file mode 100644
index 554ec49bac..0000000000
--- a/protocols/AimOscar/res/nsuperscript.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/nunderline.ico b/protocols/AimOscar/res/nunderline.ico
deleted file mode 100644
index a67fc3219b..0000000000
--- a/protocols/AimOscar/res/nunderline.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/oscar.ico b/protocols/AimOscar/res/oscar.ico
deleted file mode 100644
index 429afcc9ff..0000000000
--- a/protocols/AimOscar/res/oscar.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/profile.ico b/protocols/AimOscar/res/profile.ico
deleted file mode 100644
index 2056f57798..0000000000
--- a/protocols/AimOscar/res/profile.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/subscript.ico b/protocols/AimOscar/res/subscript.ico
deleted file mode 100644
index c7b2240b98..0000000000
--- a/protocols/AimOscar/res/subscript.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/superscript.ico b/protocols/AimOscar/res/superscript.ico
deleted file mode 100644
index a1a282bba8..0000000000
--- a/protocols/AimOscar/res/superscript.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/unconfirmed.ico b/protocols/AimOscar/res/unconfirmed.ico
deleted file mode 100644
index 102d481687..0000000000
--- a/protocols/AimOscar/res/unconfirmed.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/underline.ico b/protocols/AimOscar/res/underline.ico
deleted file mode 100644
index 646d58456d..0000000000
--- a/protocols/AimOscar/res/underline.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/AimOscar/res/version.rc b/protocols/AimOscar/res/version.rc
deleted file mode 100644
index fdeb14668c..0000000000
--- a/protocols/AimOscar/res/version.rc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#ifdef APSTUDIO_INVOKED
-#error this file is not editable by Microsoft Visual C++
-#endif //APSTUDIO_INVOKED
-
-#include "..\src\version.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-#include "afxres.h"
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION __FILEVERSION_STRING
- PRODUCTVERSION __FILEVERSION_STRING
- FILEFLAGSMASK 0x17L
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x4L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "000004b0"
- BEGIN
- VALUE "Author", __AUTHOR
- VALUE "FileDescription", __DESCRIPTION
- VALUE "FileVersion", __VERSION_STRING
- VALUE "InternalName", __PLUGIN_NAME
- VALUE "LegalCopyright", __COPYRIGHT
- VALUE "OriginalFilename", __FILENAME
- VALUE "ProductName", __PLUGIN_NAME
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x0, 1200
- END
-END
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/AimOscar/src/aim.cpp b/protocols/AimOscar/src/aim.cpp
deleted file mode 100644
index c169e47aa4..0000000000
--- a/protocols/AimOscar/src/aim.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2012 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-char AIM_CAP_MIRANDA[16] = "MirandaA";
-
-int hLangpack;
-
-CLIST_INTERFACE *pcli;
-HINSTANCE hInstance;
-
-/////////////////////////////////////////////////////////////////////////////
-// Protocol instances
-static int sttCompareProtocols(const CAimProto *p1, const CAimProto *p2)
-{
- return mir_wstrcmp(p1->m_tszUserName, p2->m_tszUserName);
-}
-
-OBJLIST<CAimProto> g_Instances(1, sttCompareProtocols);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Dll entry point
-
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD /*fdwReason*/, LPVOID /*lpvReserved*/)
-{
- hInstance = hinstDLL;
- return TRUE;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Plugin information
-
-static const PLUGININFOEX pluginInfo =
-{
- sizeof(PLUGININFOEX),
- __PLUGIN_NAME,
- PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
- __DESCRIPTION,
- __AUTHOR,
- __AUTHOREMAIL,
- __COPYRIGHT,
- __AUTHORWEB,
- UNICODE_AWARE,
- // {3750A5A3-BF0D-490E-B65D-41AC4D29AEB3}
- {0x3750a5a3, 0xbf0d, 0x490e, {0xb6, 0x5d, 0x41, 0xac, 0x4d, 0x29, 0xae, 0xb3}}
-};
-
-extern "C" __declspec(dllexport) const PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
-{
- *(unsigned long*)(&AIM_CAP_MIRANDA[8]) = _htonl(mirandaVersion);
- *(unsigned long*)(&AIM_CAP_MIRANDA[12]) = _htonl(PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM));
- return &pluginInfo;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Interface information
-
-extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_PROTOCOL, MIID_LAST };
-
-////////////////////////////////////////////////////////////////////////////////////////
-// OnModulesLoaded - finalizes plugin's configuration on load
-
-static int OnModulesLoaded(WPARAM, LPARAM)
-{
- aim_links_init();
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Load
-
-static PROTO_INTERFACE* protoInit(const char* pszProtoName, const wchar_t* tszUserName)
-{
- CAimProto *ppro = new CAimProto(pszProtoName, tszUserName);
- g_Instances.insert(ppro);
- return ppro;
-}
-
-static int protoUninit(PROTO_INTERFACE* ppro)
-{
- g_Instances.remove((CAimProto*)ppro);
- return 0;
-}
-
-extern "C" int __declspec(dllexport) Load(void)
-{
- mir_getLP(&pluginInfo);
- pcli = Clist_GetInterface();
-
- HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded);
-
- PROTOCOLDESCRIPTOR pd = { 0 };
- pd.cbSize = sizeof(pd);
- pd.szName = "AIM";
- pd.type = PROTOTYPE_PROTOCOL;
- pd.fnInit = protoInit;
- pd.fnUninit = protoUninit;
- Proto_RegisterModule(&pd);
-
- InitIcons();
- InitExtraIcons();
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Unload
-
-extern "C" int __declspec(dllexport) Unload(void)
-{
- return 0;
-}
diff --git a/protocols/AimOscar/src/avatars.cpp b/protocols/AimOscar/src/avatars.cpp
deleted file mode 100644
index 0c8143aa4a..0000000000
--- a/protocols/AimOscar/src/avatars.cpp
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2012 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-void __cdecl CAimProto::avatar_request_thread(void* param)
-{
- MCONTACT hContact = (UINT_PTR)param;
-
- char *sn = getStringA(hContact, AIM_KEY_SN);
- debugLogA("Starting avatar request thread for %s)", sn);
-
- if (wait_conn(m_hAvatarConn, m_hAvatarEvent, 0x10)) {
- char *hash_str = getStringA(hContact, AIM_KEY_AH);
- if (!hash_str) {
- mir_free(sn);
- return;
- }
- char type = getByte(hContact, AIM_KEY_AHT, 1);
-
- size_t len = (mir_strlen(hash_str) + 1) / 2;
- char *hash = (char*)alloca(len);
- string_to_bytes(hash_str, hash);
- debugLogA("Requesting an Avatar: %s (Hash: %s)", sn, hash_str);
- aim_request_avatar(m_hAvatarConn, m_avatar_seqno, sn, type, hash, (unsigned short)len);
-
- mir_free(hash_str);
- }
-
- mir_free(sn);
-}
-
-void __cdecl CAimProto::avatar_upload_thread(void* param)
-{
- avatar_up_req* req = (avatar_up_req*)param;
-
- if (wait_conn(m_hAvatarConn, m_hAvatarEvent, 0x10)) {
- if (req->size2) {
- aim_upload_avatar(m_hAvatarConn, m_avatar_seqno, 1, req->data2, req->size2);
- aim_upload_avatar(m_hAvatarConn, m_avatar_seqno, 12, req->data1, req->size1);
- }
- else aim_upload_avatar(m_hAvatarConn, m_avatar_seqno, 1, req->data1, req->size1);
- }
- delete req;
-}
-
-void CAimProto::avatar_request_handler(MCONTACT hContact, char* hash, unsigned char type)//checks to see if the avatar needs requested
-{
- if (hContact == NULL) {
- hash = m_hash_lg ? m_hash_lg : m_hash_sm;
- type = m_hash_lg ? 12 : 1;
- }
-
- char *saved_hash = getStringA(hContact, AIM_KEY_AH);
- if (hash && _stricmp(hash, "0201d20472") && _stricmp(hash, "2b00003341")) //gaim default icon fix- we don't want their blank icon displaying.
- {
- if (mir_strcmp(saved_hash, hash)) {
- setByte(hContact, AIM_KEY_AHT, type);
- setString(hContact, AIM_KEY_AH, hash);
-
- ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, nullptr, 0);
- }
- }
- else {
- if (saved_hash) {
- delSetting(hContact, AIM_KEY_AHT);
- delSetting(hContact, AIM_KEY_AH);
-
- ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, nullptr, 0);
- }
- }
- mir_free(saved_hash);
-}
-
-void CAimProto::avatar_retrieval_handler(const char* sn, const char* /*hash*/, const char* data, int data_len)
-{
- bool res = false;
- PROTO_AVATAR_INFORMATION ai = { 0 };
- ai.hContact = contact_from_sn(sn);
-
- if (data_len > 0) {
- const wchar_t *type;
- ai.format = ProtoGetBufferFormat(data, &type);
- get_avatar_filename(ai.hContact, ai.filename, _countof(ai.filename), type);
-
- int fileId = _wopen(ai.filename, _O_CREAT | _O_TRUNC | _O_WRONLY | O_BINARY, _S_IREAD | _S_IWRITE);
- if (fileId >= 0) {
- _write(fileId, data, data_len);
- _close(fileId);
- res = true;
-
- char *my_sn = getStringA(AIM_KEY_SN);
- if (!mir_strcmp(sn, my_sn))
- CallService(MS_AV_REPORTMYAVATARCHANGED, (WPARAM)m_szModuleName, 0);
- mir_free(my_sn);
- }
- }
- else debugLogA("AIM sent avatar of zero length for %s.(Usually caused by repeated request for the same icon)", sn);
-
- ProtoBroadcastAck(ai.hContact, ACKTYPE_AVATAR, res ? ACKRESULT_SUCCESS : ACKRESULT_FAILED, &ai, 0);
-}
-
-int CAimProto::get_avatar_filename(MCONTACT hContact, wchar_t* pszDest, size_t cbLen, const wchar_t *ext)
-{
- int tPathLen = mir_snwprintf(pszDest, cbLen, L"%s\\%S", VARSW(L"%miranda_avatarcache%"), m_szModuleName);
-
- if (ext && _waccess(pszDest, 0))
- CreateDirectoryTreeW(pszDest);
-
- size_t tPathLen2 = tPathLen;
-
- DBVARIANT dbv;
- if (getWString(hContact, AIM_KEY_AH, &dbv)) return GAIR_NOAVATAR;
- tPathLen += mir_snwprintf(pszDest + tPathLen, cbLen - tPathLen, L"\\%s", dbv.ptszVal);
- db_free(&dbv);
-
- bool found = false;
- if (ext == nullptr) {
- mir_snwprintf(pszDest + tPathLen, cbLen - tPathLen, L".*");
-
- _tfinddata_t c_file;
- long hFile = _tfindfirst(pszDest, &c_file);
- if (hFile > -1L) {
- do {
- if (wcsrchr(c_file.name, '.')) {
- mir_snwprintf(pszDest + tPathLen2, cbLen - tPathLen2, L"\\%s", c_file.name);
- found = true;
- }
- } while (_tfindnext(hFile, &c_file) == 0);
- _findclose(hFile);
- }
-
- if (!found) pszDest[0] = 0;
- }
- else {
- mir_snwprintf(pszDest + tPathLen, cbLen - tPathLen, ext);
- found = _waccess(pszDest, 0) == 0;
- }
-
- return found ? GAIR_SUCCESS : GAIR_WAITFOR;
-}
-
-bool get_avatar_hash(const wchar_t* file, char* hash, char** data, unsigned short &size)
-{
- int fileId = _wopen(file, _O_RDONLY | _O_BINARY, _S_IREAD);
- if (fileId == -1) return false;
-
- long lAvatar = _filelength(fileId);
- if (lAvatar <= 0) {
- _close(fileId);
- return false;
- }
-
- char* pResult = (char*)mir_alloc(lAvatar);
- int res = _read(fileId, pResult, lAvatar);
- _close(fileId);
-
- if (res <= 0) {
- mir_free(pResult);
- return false;
- }
-
- mir_md5_state_t state;
- mir_md5_init(&state);
- mir_md5_append(&state, (unsigned char*)pResult, lAvatar);
- mir_md5_finish(&state, (unsigned char*)hash);
-
- if (data) {
- *data = pResult;
- size = (unsigned short)lAvatar;
- }
- else
- mir_free(pResult);
-
- return true;
-}
-
-void rescale_image(char *data, unsigned short size, char *&data1, unsigned short &size1)
-{
- FI_INTERFACE *fei = nullptr;
- CallService(MS_IMG_GETINTERFACE, FI_IF_VERSION, (LPARAM)&fei);
- if (fei == nullptr) return;
-
- FIMEMORY *hmem = fei->FI_OpenMemory((BYTE *)data, size);
- FREE_IMAGE_FORMAT fif = fei->FI_GetFileTypeFromMemory(hmem, 0);
- FIBITMAP *dib = fei->FI_LoadFromMemory(fif, hmem, 0);
- fei->FI_CloseMemory(hmem);
-
- if (fei->FI_GetWidth(dib) > 64) {
- FIBITMAP *dib1 = fei->FI_Rescale(dib, 64, 64, FILTER_BSPLINE);
-
- FIMEMORY *hmem2 = fei->FI_OpenMemory(nullptr, 0);
- fei->FI_SaveToMemory(fif, dib1, hmem2, 0);
-
- BYTE *data2; DWORD size2;
- fei->FI_AcquireMemory(hmem2, &data2, &size2);
- data1 = (char*)mir_alloc(size2);
- memcpy(data1, data2, size2);
- size1 = size2;
-
- fei->FI_CloseMemory(hmem2);
- fei->FI_Unload(dib1);
- }
- fei->FI_Unload(dib);
-}
diff --git a/protocols/AimOscar/src/avatars.h b/protocols/AimOscar/src/avatars.h
deleted file mode 100644
index 647e897f3f..0000000000
--- a/protocols/AimOscar/src/avatars.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef AVATARS_H
-#define AVATARS_H
-
-struct avatar_req
-{
- char* sn;
- char* hash;
- unsigned char type;
-
- avatar_req(char* sn, char* hash, unsigned char type)
- : sn(sn), hash(mir_strdup(hash)), type(type) {}
-
- ~avatar_req()
- { mir_free(sn); mir_free(hash); }
-};
-
-struct avatar_up_req
-{
- char* data1;
- char* data2;
- unsigned short size1;
- unsigned short size2;
-
- avatar_up_req(char* data1, unsigned short size1, char* data2, unsigned short size2)
- : data1(data1), size1(size1), data2(data2), size2(size2) {}
-
- ~avatar_up_req()
- { mir_free(data1); mir_free(data2); }
-};
-
-bool get_avatar_hash(const wchar_t* file, char* hash, char** data, unsigned short &size);
-void rescale_image(char *data, unsigned short size, char *&data1, unsigned short &size1);
-
-#endif
diff --git a/protocols/AimOscar/src/away.cpp b/protocols/AimOscar/src/away.cpp
deleted file mode 100644
index 96d4847d9b..0000000000
--- a/protocols/AimOscar/src/away.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2012 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-static const int modes[] =
-{
- ID_STATUS_ONLINE,
- ID_STATUS_AWAY,
- ID_STATUS_DND,
- ID_STATUS_NA,
- ID_STATUS_OCCUPIED,
- ID_STATUS_FREECHAT,
- ID_STATUS_INVISIBLE,
- ID_STATUS_ONTHEPHONE,
- ID_STATUS_OUTTOLUNCH,
-};
-
-char** CAimProto::get_status_msg_loc(int status)
-{
- for (int i = 0; i < _countof(modes); i++)
- if (modes[i] == status)
- return &m_modeMsgs[i];
-
- return nullptr;
-}
-
-int CAimProto::aim_set_away(HNETLIBCONN hServerConn, unsigned short &seqno, const char *amsg, bool set)//user info
-{
- unsigned short offset = 0;
- char *html_msg = nullptr;
- size_t msg_size = 0;
- if (set) {
- if (!amsg) return -1;
- setDword(AIM_KEY_LA, (DWORD)time(nullptr));
- html_msg = html_encode(amsg && amsg[0] ? amsg : DEFAULT_AWAY_MSG);
- msg_size = mir_strlen(html_msg);
- }
-
- aimString str(html_msg);
- const char *charset = str.isUnicode() ? AIM_MSG_TYPE_UNICODE : AIM_MSG_TYPE;
- const unsigned short charset_len = (unsigned short)mir_strlen(charset);
-
- const char *msg = str.getBuf();
- const unsigned short msg_len = str.getSize();
-
- char *buf = (char*)alloca(SNAC_SIZE + TLV_HEADER_SIZE * 3 + charset_len + msg_len + 1);
-
- aim_writesnac(0x02, 0x04, offset, buf);
- aim_writetlv(0x03, charset_len, charset, offset, buf);
- aim_writetlv(0x04, (unsigned short)msg_len, msg, offset, buf);
-
- mir_free(html_msg);
-
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_set_status(HNETLIBCONN hServerConn, unsigned short &seqno, unsigned long status_type)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE + TLV_HEADER_SIZE * 2];
- aim_writesnac(0x01, 0x1E, offset, buf);
- aim_writetlvlong(0x06, status_type, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_set_statusmsg(HNETLIBCONN hServerConn, unsigned short &seqno, const char *msg)//user info
-{
- size_t msg_size = mir_strlen(msg);
-
- unsigned short msgoffset = 0;
- char *msgbuf = (char*)alloca(10 + msg_size);
- if (msg_size) {
- char *msgb = (char*)alloca(4 + msg_size);
- msgb[0] = (unsigned char)(msg_size >> 8);
- msgb[1] = (unsigned char)(msg_size & 0xff);
- memcpy(&msgb[2], msg, msg_size);
- msgb[msg_size + 2] = 0;
- msgb[msg_size + 3] = 0;
-
- aim_writebartid(2, 4, (unsigned short)(msg_size + 4), msgb, msgoffset, msgbuf);
- }
- else aim_writebartid(2, 0, 0, nullptr, msgoffset, msgbuf);
-
- unsigned short offset = 0;
- char* buf = (char*)alloca(SNAC_SIZE + TLV_HEADER_SIZE + msgoffset + 8);
- aim_writesnac(0x01, 0x1e, offset, buf);
- aim_writetlv(0x1d, msgoffset, msgbuf, offset, buf);
-
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_query_away_message(HNETLIBCONN hServerConn, unsigned short &seqno, const char* sn)
-{
- unsigned short offset = 0;
- unsigned short sn_length = (unsigned short)mir_strlen(sn);
- char *buf = (char*)alloca(SNAC_SIZE + 5 + sn_length);
- aim_writesnac(0x02, 0x15, offset, buf);
- aim_writegeneric(4, "\0\0\0\x02", offset, buf);
- aim_writegeneric(1, (char*)&sn_length, offset, buf);
- aim_writegeneric(sn_length, sn, offset, buf);
- int res = aim_sendflap(hServerConn, 0x02, offset, buf, seqno) == 0;
- return res;
-}
diff --git a/protocols/AimOscar/src/chat.cpp b/protocols/AimOscar/src/chat.cpp
deleted file mode 100644
index b084f6ca02..0000000000
--- a/protocols/AimOscar/src/chat.cpp
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-void CAimProto::chat_register(void)
-{
- GCREGISTER gcr = {};
- gcr.dwFlags = GC_TYPNOTIF | GC_CHANMGR;
- gcr.ptszDispName = m_tszUserName;
- gcr.pszModule = m_szModuleName;
- Chat_Register(&gcr);
-
- HookProtoEvent(ME_GC_EVENT, &CAimProto::OnGCEvent);
- HookProtoEvent(ME_GC_BUILDMENU, &CAimProto::OnGCMenuHook);
-}
-
-void CAimProto::chat_start(const char *id, unsigned short exchange)
-{
- wchar_t *idt = mir_a2u(id);
- Chat_NewSession(GCW_CHATROOM, m_szModuleName, idt, idt);
-
- Chat_AddGroup(m_szModuleName, idt, TranslateT("Me"));
- Chat_AddGroup(m_szModuleName, idt, TranslateT("Others"));
-
- Chat_Control(m_szModuleName, idt, SESSION_INITDONE);
- Chat_Control(m_szModuleName, idt, SESSION_ONLINE);
- Chat_Control(m_szModuleName, idt, WINDOW_VISIBLE);
-
- setWord(find_chat_contact(id), "Exchange", exchange);
-
- mir_free(idt);
-}
-
-void CAimProto::chat_event(const char* id, const char* sn, int evt, const wchar_t* msg)
-{
- ptrW idt(mir_a2u(id));
- ptrW snt(mir_a2u(sn));
-
- MCONTACT hContact = contact_from_sn(sn);
- wchar_t *nick = hContact ? (wchar_t*)pcli->pfnGetContactDisplayName(hContact, 0) : snt;
-
- GCEVENT gce = { m_szModuleName, idt, evt };
- gce.dwFlags = GCEF_ADDTOLOG;
- gce.ptszNick = nick;
- gce.ptszUID = snt;
- gce.bIsMe = _stricmp(sn, m_username) == 0;
- gce.ptszStatus = gce.bIsMe ? TranslateT("Me") : TranslateT("Others");
- gce.ptszText = msg;
- gce.time = time(nullptr);
- Chat_Event(&gce);
-}
-
-void CAimProto::chat_leave(const char* id)
-{
- ptrW idt(mir_a2u(id));
- Chat_Control(m_szModuleName, idt, SESSION_OFFLINE);
- Chat_Terminate(m_szModuleName, idt);
-}
-
-int CAimProto::OnGCEvent(WPARAM, LPARAM lParam)
-{
- GCHOOK *gch = (GCHOOK*)lParam;
- if (!gch) return 1;
-
- if (mir_strcmp(gch->pszModule, m_szModuleName))
- return 0;
-
- char *id = mir_u2a(gch->ptszID);
- chat_list_item* item = find_chat_by_id(id);
- if (item == nullptr)
- return 0;
-
- switch (gch->iType) {
- case GC_SESSION_TERMINATE:
- aim_sendflap(item->hconn, 0x04, 0, nullptr, item->seqno);
- Netlib_Shutdown(item->hconn);
- break;
-
- case GC_USER_MESSAGE:
- if (gch->ptszText && mir_wstrlen(gch->ptszText))
- aim_chat_send_message(item->hconn, item->seqno, T2Utf(gch->ptszText));
- break;
-
- case GC_USER_CHANMGR:
- DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_CHATROOM_INVITE), nullptr, invite_to_chat_dialog,
- LPARAM(new invite_chat_param(item->id, this)));
- break;
-
- case GC_USER_PRIVMESS:
- {
- char* sn = mir_u2a(gch->ptszUID);
- MCONTACT hContact = contact_from_sn(sn);
- mir_free(sn);
- CallService(MS_MSG_SENDMESSAGE, hContact, 0);
- }
- break;
-
- case GC_USER_LOGMENU:
- switch (gch->dwData) {
- case 10:
- DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_CHATROOM_INVITE), nullptr, invite_to_chat_dialog,
- LPARAM(new invite_chat_param(item->id, this)));
- break;
-
- case 20:
- chat_leave(id);
- break;
- }
- break;
-
- case GC_USER_NICKLISTMENU:
- {
- char *sn = mir_u2a(gch->ptszUID);
- MCONTACT hContact = contact_from_sn(sn);
- mir_free(sn);
-
- switch (gch->dwData) {
- case 10:
- CallService(MS_USERINFO_SHOWDIALOG, hContact, 0);
- break;
-
- case 20:
- CallService(MS_HISTORY_SHOWCONTACTHISTORY, hContact, 0);
- break;
-
- case 110:
- chat_leave(id);
- break;
- }
- }
- break;
-
- case GC_USER_TYPNOTIFY:
- break;
- }
- mir_free(id);
-
- return 0;
-}
-
-int CAimProto::OnGCMenuHook(WPARAM, LPARAM lParam)
-{
- GCMENUITEMS *gcmi = (GCMENUITEMS*)lParam;
- if (mir_strcmp(gcmi->pszModule, m_szModuleName))
- return 0;
-
- if (gcmi->Type == MENU_ON_LOG) {
- static const struct gc_item Items[] = {
- { LPGENW("&Invite user..."), 10, MENU_ITEM, FALSE },
- { LPGENW("&Leave chat session"), 20, MENU_ITEM, FALSE }
- };
- Chat_AddMenuItems(gcmi->hMenu, _countof(Items), Items);
- }
- else if (gcmi->Type == MENU_ON_NICKLIST) {
- char* sn = mir_u2a(gcmi->pszUID);
- if (!mir_strcmp(m_username, sn)) {
- static const struct gc_item Items[] = {
- { LPGENW("User &details"), 10, MENU_ITEM, FALSE },
- { LPGENW("User &history"), 20, MENU_ITEM, FALSE },
- { L"", 100, MENU_SEPARATOR, FALSE },
- { LPGENW("&Leave chat session"), 110, MENU_ITEM, FALSE }
- };
- Chat_AddMenuItems(gcmi->hMenu, _countof(Items), Items);
- }
- else {
- static const struct gc_item Items[] = {
- { LPGENW("User &details"), 10, MENU_ITEM, FALSE },
- { LPGENW("User &history"), 20, MENU_ITEM, FALSE }
- };
- Chat_AddMenuItems(gcmi->hMenu, _countof(Items), Items);
- }
- mir_free(sn);
- }
-
- return 0;
-}
-
-
-void __cdecl CAimProto::chatnav_request_thread(void* param)
-{
- chatnav_param *par = (chatnav_param*)param;
-
- if (wait_conn(m_hChatNavConn, m_hChatNavEvent, 0x0d)) {
- if (par->isroom)
- aim_chatnav_create(m_hChatNavConn, m_chatnav_seqno, par->id, par->exchange);
- else
- aim_chatnav_room_info(m_hChatNavConn, m_chatnav_seqno, par->id, par->exchange, par->instance);
- }
- delete par;
-}
-
-chat_list_item* CAimProto::find_chat_by_cid(unsigned short cid)
-{
- for (int i = 0; i < m_chat_rooms.getCount(); ++i)
- if (m_chat_rooms[i].cid == cid)
- return &m_chat_rooms[i];
-
- return nullptr;
-}
-
-chat_list_item* CAimProto::find_chat_by_id(char* id)
-{
- for (int i = 0; i < m_chat_rooms.getCount(); ++i)
- if (mir_strcmp(m_chat_rooms[i].id, id) == 0)
- return &m_chat_rooms[i];
-
- return nullptr;
-}
-
-chat_list_item* CAimProto::find_chat_by_conn(HANDLE conn)
-{
- for (int i = 0; i < m_chat_rooms.getCount(); ++i)
- if (m_chat_rooms[i].hconn == conn)
- return &m_chat_rooms[i];
-
- return nullptr;
-}
-
-void CAimProto::remove_chat_by_ptr(chat_list_item *item)
-{
- for (int i = 0; i < m_chat_rooms.getCount(); ++i) {
- if (&m_chat_rooms[i] == item) {
- m_chat_rooms.remove(i);
- break;
- }
- }
-}
-
-void CAimProto::shutdown_chat_conn(void)
-{
- for (int i = 0; i < m_chat_rooms.getCount(); ++i) {
- chat_list_item &item = m_chat_rooms[i];
- if (item.hconn) {
- aim_sendflap(item.hconn, 0x04, 0, nullptr, item.seqno);
- Netlib_Shutdown(item.hconn);
- }
- }
-}
-
-void CAimProto::close_chat_conn(void)
-{
- for (int i = 0; i < m_chat_rooms.getCount(); ++i) {
- chat_list_item &item = m_chat_rooms[i];
- if (item.hconn) {
- Netlib_CloseHandle(item.hconn);
- item.hconn = nullptr;
- }
- }
-}
diff --git a/protocols/AimOscar/src/chat.h b/protocols/AimOscar/src/chat.h
deleted file mode 100644
index c10d0265da..0000000000
--- a/protocols/AimOscar/src/chat.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef CHAT_H
-#define CHAT_H
-
-struct chatnav_param
-{
- char* id;
- unsigned short exchange;
- unsigned short instance;
-
- char* message;
- char* sn;
- char* icbm_cookie;
-
- bool isroom;
-
- chatnav_param(char* tid, unsigned short ex, unsigned short in, char* msg, char* nm, char* icki)
- { id = tid; exchange = ex; instance = in; isroom = false;
- message = mir_strdup(msg); sn = mir_strdup(nm); icbm_cookie = (char*)mir_alloc(8); memcpy(icbm_cookie, icki, 8); }
-
- chatnav_param(char* tid, unsigned short ex)
- { id = mir_strdup(tid); exchange = ex; isroom = true;
- message = NULL; sn = NULL; icbm_cookie = NULL; }
-
- ~chatnav_param()
- {
- mir_free(id);
- mir_free(message);
- mir_free(sn);
- mir_free(icbm_cookie);
- }
-};
-
-struct chat_list_item
-{
- char* id;
- char* cookie;
- HNETLIBCONN hconn;
- unsigned short cid;
- unsigned short seqno;
- unsigned short exchange;
- unsigned short instance;
- char* CHAT_COOKIE;
- int CHAT_COOKIE_LENGTH;
-
- chat_list_item(char* tid, char* tcookie, unsigned short ex, unsigned short in)
- {
- id = mir_strdup(tid); cid = get_random(); seqno = 0; hconn = NULL;
- cookie = mir_strdup(tcookie); exchange = ex; instance = in;
- }
-
- ~chat_list_item()
- {
- mir_free(id); mir_free(cookie);
- }
-};
-
-#endif \ No newline at end of file
diff --git a/protocols/AimOscar/src/client.cpp b/protocols/AimOscar/src/client.cpp
deleted file mode 100755
index 8299cc5a32..0000000000
--- a/protocols/AimOscar/src/client.cpp
+++ /dev/null
@@ -1,985 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2012 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-int CAimProto::aim_send_connection_packet(HNETLIBCONN hServerConn, unsigned short &seqno, char *buf)
-{
- return aim_sendflap(hServerConn, 0x01, 4, buf, seqno);
-}
-
-int CAimProto::aim_authkey_request(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char *buf = (char*)alloca(SNAC_SIZE + TLV_HEADER_SIZE * 3 + mir_strlen(m_username));
- aim_writesnac(0x17, 0x06, offset, buf);
- aim_writetlv(0x01, (unsigned short)mir_strlen(m_username), m_username, offset, buf);
- aim_writetlv(0x4B, 0, nullptr, offset, buf);
- aim_writetlv(0x5A, 0, nullptr, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_auth_request(HNETLIBCONN hServerConn, unsigned short &seqno, const char* key, const char* language,
- const char* country, const char* username, const char* password)
-{
- unsigned short offset = 0;
- BYTE pass_hash[16];
- BYTE auth_hash[16];
- mir_md5_state_t state;
-
- mir_md5_init(&state);
- mir_md5_append(&state, (const BYTE *)password, (int)mir_strlen(password));
- mir_md5_finish(&state, pass_hash);
- mir_md5_init(&state);
- mir_md5_append(&state, (BYTE*)key, (int)mir_strlen(key));
- mir_md5_append(&state, (BYTE*)pass_hash, MD5_HASH_LENGTH);
- mir_md5_append(&state, (BYTE*)AIM_MD5_STRING, sizeof(AIM_MD5_STRING) - 1);
- mir_md5_finish(&state, auth_hash);
-
- char client_id[64], mirver[64];
- Miranda_GetVersionText(mirver, sizeof(mirver));
- int client_id_len = mir_snprintf(client_id, "Miranda AIM, version %s", mirver);
-
- char* buf = (char*)alloca(SNAC_SIZE + TLV_HEADER_SIZE * 13 + MD5_HASH_LENGTH + mir_strlen(username) + client_id_len + 30 + mir_strlen(language) + mir_strlen(country));
-
- aim_writesnac(0x17, 0x02, offset, buf);
- aim_writetlv(0x01, (unsigned short)mir_strlen(username), username, offset, buf);
- aim_writetlv(0x25, MD5_HASH_LENGTH, (char*)auth_hash, offset, buf);
- aim_writetlv(0x4C, 0, nullptr, offset, buf);//signifies new password hash instead of old method
- aim_writetlv(0x03, (unsigned short)client_id_len, client_id, offset, buf);
-
- aim_writetlvshort(0x16, AIM_CLIENT_ID_NUMBER, offset, buf); //in pidgin it's first
- aim_writetlvshort(0x17, AIM_CLIENT_MAJOR_VERSION, offset, buf);
- aim_writetlvshort(0x18, AIM_CLIENT_MINOR_VERSION, offset, buf);
- aim_writetlvshort(0x19, AIM_CLIENT_LESSER_VERSION, offset, buf);
- aim_writetlvshort(0x1A, AIM_CLIENT_BUILD_NUMBER, offset, buf);
- aim_writetlvlong(0x14, AIM_CLIENT_DISTRIBUTION_NUMBER, offset, buf);
- aim_writetlv(0x0F, (unsigned short)mir_strlen(language), language, offset, buf);
- aim_writetlv(0x0E, (unsigned short)mir_strlen(country), country, offset, buf);
- aim_writetlvchar(0x4A, getByte(AIM_KEY_FSC, 0) ? 3 : 1, offset, buf);
- // aim_writetlvchar(0x94,0,offset,buf);
-/* if (!getByte(AIM_KEY_DSSL, 0))
- aim_writetlv(0x8c, 0, NULL, offset, buf); // Request SSL connection */
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_send_cookie(HNETLIBCONN hServerConn, unsigned short &seqno, int cookie_size, char * cookie)
-{
- unsigned short offset = 0;
- char* buf = (char*)alloca(TLV_HEADER_SIZE * 2 + cookie_size);
- aim_writelong(0x01, offset, buf);//protocol version number
- aim_writetlv(0x06, (unsigned short)cookie_size, cookie, offset, buf);
- return aim_sendflap(hServerConn, 0x01, offset, buf, seqno);
-}
-
-int CAimProto::aim_send_service_request(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE + TLV_HEADER_SIZE * 12];
- aim_writesnac(0x01, 0x17, offset, buf);
- aim_writefamily(AIM_SERVICE_GENERIC, offset, buf);
- aim_writefamily(AIM_SERVICE_SSI, offset, buf);
- aim_writefamily(AIM_SERVICE_LOCATION, offset, buf);
- aim_writefamily(AIM_SERVICE_BUDDYLIST, offset, buf);
- aim_writefamily(AIM_SERVICE_MESSAGING, offset, buf);
- aim_writefamily(AIM_SERVICE_ICQ, offset, buf);
- aim_writefamily(AIM_SERVICE_INVITATION, offset, buf);
- aim_writefamily(AIM_SERVICE_POPUP, offset, buf);
- aim_writefamily(AIM_SERVICE_BOS, offset, buf);
- aim_writefamily(AIM_SERVICE_USERLOOKUP, offset, buf);
- aim_writefamily(AIM_SERVICE_STATS, offset, buf);
- aim_writefamily(AIM_SERVICE_UNKNOWN, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_new_service_request(HNETLIBCONN hServerConn, unsigned short &seqno, unsigned short service)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE + 2 + TLV_HEADER_SIZE];
- aim_writesnac(0x01, 0x04, offset, buf);
- aim_writeshort(service, offset, buf);
-/* if (!getByte(AIM_KEY_DSSL, 0))
- aim_writetlv(0x8c, 0, NULL, offset, buf); */
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_request_rates(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE];
- aim_writesnac(0x01, 0x06, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_accept_rates(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE * 2];
- aim_writesnac(0x01, 0x08, offset, buf);
- aim_writegeneric(10, AIM_SERVICE_RATES, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_request_icbm(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE];
- aim_writesnac(0x04, 0x04, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_set_icbm(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- const unsigned icbm_flags = ICBM_CHANNEL_MSGS_ALLOWED | ICBM_MISSED_CALLS_ENABLED |
- ICBM_EVENTS_ALLOWED | ICBM_SMS_SUPPORTED | ICBM_OFFLINE_MSGS_ALLOWED;
- // const unsigned icbm_flags = 0x3db;
-
- unsigned short offset = 0;
- char buf[SNAC_SIZE + 16];
- aim_writesnac(0x04, 0x02, offset, buf);
- aim_writeshort(0, offset, buf); //channel
- aim_writelong(icbm_flags, offset, buf); //flags
- aim_writeshort(0x1f40, offset, buf); //max snac size 8000
- aim_writeshort(0x03e7, offset, buf); //max sender warning level 999 (0-1000) WinAim default
- aim_writeshort(0x03e7, offset, buf); //max receiver warning level 999 (0-1000) WinAim default
- aim_writelong(0, offset, buf); //min message interval, ms 0
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_request_offline_msgs(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE];
- aim_writesnac(0x04, 0x10, offset, buf); // Subtype for offline messages 0x10
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_request_list(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE];
- aim_writesnac(0x13, 0x04, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_activate_list(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE];
- aim_writesnac(0x13, 0x07, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-/*
-0000 00 05 00 02 00 17 00 06 00 03 00 00 00 00 07 00 ................
-0010 01 00 00 08 00 01 01 00 0a 00 14 00 02 00 08 66 ...............f
-0020 61 63 65 62 6f 6f 6b 00 06 67 6f 6f 67 6c 65 acebook..google
-
-int CAimProto::aim_request_rights(HNETLIBCONN hServerConn,unsigned short &seqno)
-{
- unsigned short offset=0;
- char buf[SNAC_SIZE+50];
- aim_writesnac(0x03,0x02,offset,buf);
- aim_writetlvshort(0x05,0x17,offset,buf);
- aim_writetlv(0x06,3,"\x0\x0",offset,buf);
- aim_writetlvchar(0x07,0x01,offset,buf);
- aim_writetlvshort(0x05,0x17,offset,buf);
- aim_writetlvshort(0x05,0x17,offset,buf);
- return aim_sendflap(hServerConn,0x02,offset,buf,seqno);
-}
-*/
-int CAimProto::aim_set_caps(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- int i = 1;
- char buf[SNAC_SIZE + TLV_HEADER_SIZE * 3 + AIM_CAPS_LENGTH * 50 + sizeof(AIM_MSG_TYPE)];
- char temp[AIM_CAPS_LENGTH * 20];
- memcpy(temp, AIM_CAP_SHORT_CAPS, AIM_CAPS_LENGTH);
- memcpy(&temp[AIM_CAPS_LENGTH*i++], AIM_CAP_HOST_STATUS_TEXT_AWARE, AIM_CAPS_LENGTH);
- memcpy(&temp[AIM_CAPS_LENGTH*i++], AIM_CAP_SMART_CAPS, AIM_CAPS_LENGTH);
- memcpy(&temp[AIM_CAPS_LENGTH*i++], AIM_CAP_FILE_TRANSFER, AIM_CAPS_LENGTH);
- // memcpy(&temp[AIM_CAPS_LENGTH*i++],AIM_CAP_HAS_MICROPHONE,AIM_CAPS_LENGTH);
- // memcpy(&temp[AIM_CAPS_LENGTH*i++],AIM_CAP_RTCAUDIO,AIM_CAPS_LENGTH);
- // memcpy(&temp[AIM_CAPS_LENGTH*i++],AIM_CAP_HAS_CAMERA,AIM_CAPS_LENGTH);
- // memcpy(&temp[AIM_CAPS_LENGTH*i++],AIM_CAP_RTCVIDEO,AIM_CAPS_LENGTH);
- memcpy(&temp[AIM_CAPS_LENGTH*i++], AIM_CAP_BUDDY_ICON, AIM_CAPS_LENGTH);
- memcpy(&temp[AIM_CAPS_LENGTH*i++], AIM_CAP_CHAT, AIM_CAPS_LENGTH);
- memcpy(&temp[AIM_CAPS_LENGTH*i++], AIM_CAP_SUPPORT_ICQ, AIM_CAPS_LENGTH);
- // memcpy(&temp[AIM_CAPS_LENGTH*i++],AIM_CAP_ICQ_SERVER_RELAY,AIM_CAPS_LENGTH);
- memcpy(&temp[AIM_CAPS_LENGTH*i++], AIM_CAP_UTF8, AIM_CAPS_LENGTH);
- memcpy(&temp[AIM_CAPS_LENGTH*i++], AIM_CAP_MIRANDA, AIM_CAPS_LENGTH);
- if (getByte(AIM_KEY_HF, 0))
- memcpy(&temp[AIM_CAPS_LENGTH*i++], AIM_CAP_HIPTOP, AIM_CAPS_LENGTH);
- aim_writesnac(0x02, 0x04, offset, buf);
- aim_writetlv(0x05, (unsigned short)(AIM_CAPS_LENGTH*i), temp, offset, buf);
-
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_set_profile(HNETLIBCONN hServerConn, unsigned short &seqno, char* amsg)//user info
-{
- aimString str(amsg);
- const char *charset = str.isUnicode() ? AIM_MSG_TYPE_UNICODE : AIM_MSG_TYPE;
- const unsigned short charset_len = (unsigned short)mir_strlen(charset);
-
- const char* msg = str.getBuf();
- const unsigned short msg_len = str.getSize();
-
- char* buf = (char*)alloca(SNAC_SIZE + TLV_HEADER_SIZE * 3 + 1 + charset_len + msg_len);
- unsigned short offset = 0;
-
- aim_writesnac(0x02, 0x04, offset, buf);
- aim_writetlvchar(0x0c, 1, offset, buf);
- aim_writetlv(0x01, charset_len, charset, offset, buf);
- aim_writetlv(0x02, msg_len, msg, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_client_ready(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
-
- NETLIBCONNINFO connInfo = {};
- Netlib_GetConnectionInfo(hServerConn, &connInfo);
-
- m_internal_ip = connInfo.dwIpv4;
-
- char buf[SNAC_SIZE + TLV_HEADER_SIZE * 22];
- aim_writesnac(0x01, 0x02, offset, buf);
- aim_writefamily(AIM_SERVICE_GENERIC, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- aim_writefamily(AIM_SERVICE_SSI, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- aim_writefamily(AIM_SERVICE_LOCATION, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- aim_writefamily(AIM_SERVICE_BUDDYLIST, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- aim_writefamily(AIM_SERVICE_MESSAGING, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- aim_writefamily(AIM_SERVICE_ICQ, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- aim_writefamily(AIM_SERVICE_INVITATION, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- //removed extra generic server
- aim_writefamily(AIM_SERVICE_POPUP, offset, buf);
- aim_writegeneric(4, "\x01\x04\0\x01", offset, buf);//different version number like trillian 3.1
- aim_writefamily(AIM_SERVICE_BOS, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- aim_writefamily(AIM_SERVICE_USERLOOKUP, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- aim_writefamily(AIM_SERVICE_STATS, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_mail_ready(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE + TLV_HEADER_SIZE * 4];
- aim_writesnac(0x01, 0x02, offset, buf);
- aim_writefamily(AIM_SERVICE_GENERIC, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- aim_writefamily(AIM_SERVICE_MAIL, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_avatar_ready(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE + TLV_HEADER_SIZE * 4];
- aim_writesnac(0x01, 0x02, offset, buf);
- aim_writefamily(AIM_SERVICE_GENERIC, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- aim_writefamily(AIM_SERVICE_AVATAR, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_chatnav_ready(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE + TLV_HEADER_SIZE * 4];
- aim_writesnac(0x01, 0x02, offset, buf);
- aim_writefamily(AIM_SERVICE_GENERIC, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- aim_writefamily(AIM_SERVICE_CHATNAV, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_chat_ready(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE + TLV_HEADER_SIZE * 4];
- aim_writesnac(0x01, 0x02, offset, buf);
- aim_writefamily(AIM_SERVICE_GENERIC, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- aim_writefamily(AIM_SERVICE_CHAT, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_send_message(HNETLIBCONN hServerConn, unsigned short &seqno, const char* sn, char* amsg, bool auto_response, bool blast)
-{
- aimString str(amsg);
-
- const char* msg = str.getBuf();
- const unsigned short msg_len = str.getSize();
-
- unsigned short tlv_offset = 0;
- char* tlv_buf = (char*)alloca(5 + msg_len + 8);
-
- char icbm_cookie[8];
- Utils_GetRandom(icbm_cookie, sizeof(icbm_cookie));
-
- aim_writegeneric(5, "\x05\x01\x00\x01\x01", tlv_offset, tlv_buf); // icbm im capabilities
- aim_writeshort(0x0101, tlv_offset, tlv_buf); // icbm im text tag
- aim_writeshort(msg_len + 4, tlv_offset, tlv_buf); // icbm im text tag length
- aim_writeshort(str.isUnicode() ? 2 : 0, tlv_offset, tlv_buf); // character set
- aim_writeshort(0, tlv_offset, tlv_buf); // language
-
- aim_writegeneric(msg_len, msg, tlv_offset, tlv_buf); // message text
-
- unsigned short offset = 0;
- unsigned short sn_length = (unsigned short)mir_strlen(sn);
- char* buf = (char*)alloca(SNAC_SIZE + 8 + 3 + sn_length + TLV_HEADER_SIZE * 3 + tlv_offset);
-
- aim_writesnac(0x04, 0x06, offset, buf, get_random());
- aim_writegeneric(8, icbm_cookie, offset, buf); // icbm cookie
- aim_writeshort(0x01, offset, buf); // channel
- aim_writechar((unsigned char)sn_length, offset, buf); // screen name len
- aim_writegeneric(sn_length, sn, offset, buf); // screen name
-
- aim_writetlv(0x02, tlv_offset, tlv_buf, offset, buf);
-
- if (!blast) {
- if (auto_response)
- aim_writetlv(0x04, 0, nullptr, offset, buf); // auto-response message
- else {
- aim_writetlv(0x03, 0, nullptr, offset, buf); // message ack request
- aim_writetlv(0x06, 0, nullptr, offset, buf); // offline message storage
- }
- }
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno) ? 0 : *(int*)icbm_cookie & 0x7fffffff;
-}
-
-int CAimProto::aim_query_profile(HNETLIBCONN hServerConn, unsigned short &seqno, char* sn)
-{
- unsigned short offset = 0;
- unsigned short sn_length = (unsigned short)mir_strlen(sn);
- char* buf = (char*)alloca(SNAC_SIZE + 5 + sn_length);
- aim_writesnac(0x02, 0x15, offset, buf);
- aim_writelong(0x01, offset, buf);
- aim_writechar((unsigned char)sn_length, offset, buf);
- aim_writegeneric(sn_length, sn, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno) == 0;
-}
-
-int CAimProto::aim_delete_contact(HNETLIBCONN hServerConn, unsigned short &seqno, char* sn, unsigned short item_id,
- unsigned short group_id, unsigned short list, bool nil)
-{
- unsigned short offset = 0;
- unsigned short sn_length = (unsigned short)mir_strlen(sn);
- char* buf = (char*)alloca(SNAC_SIZE + sn_length + 10);
- aim_writesnac(0x13, 0x0a, offset, buf, get_random()); // SSI Delete
- aim_writeshort(sn_length, offset, buf); // screen name length
- aim_writegeneric(sn_length, sn, offset, buf); // screen name
- aim_writeshort(group_id, offset, buf); // group id
- aim_writeshort(item_id, offset, buf); // buddy id
- aim_writeshort(list, offset, buf); // buddy type
- aim_writeshort(nil ? 4 : 0, offset, buf); // length of extra data
- if (nil) aim_writetlv(0x6a, 0, nullptr, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_add_contact(HNETLIBCONN hServerConn, unsigned short &seqno, const char* sn, unsigned short item_id,
- unsigned short group_id, unsigned short list, char* nick, char* note)
-{
- unsigned short offset = 0;
- unsigned short sn_length = (unsigned short)mir_strlen(sn);
- unsigned short nick_length = (unsigned short)mir_strlen(nick);
- unsigned short note_length = (unsigned short)mir_strlen(note);
- unsigned short tlv_len = nick || note ? TLV_HEADER_SIZE * 2 + nick_length + note_length : 0;
-
- char* buf = (char*)alloca(SNAC_SIZE + sn_length + 10 + tlv_len);
- aim_writesnac(0x13, 0x08, offset, buf, get_random()); // SSI Add
- aim_writeshort(sn_length, offset, buf); // screen name length
- aim_writegeneric(sn_length, sn, offset, buf); // screen name
- aim_writeshort(group_id, offset, buf); // group id
- aim_writeshort(item_id, offset, buf); // buddy id
- aim_writeshort(list, offset, buf); // buddy type
- aim_writeshort(tlv_len, offset, buf); // length of extra data
-
- if (nick || note) {
- aim_writetlv(0x13c, note_length, note, offset, buf);
- aim_writetlv(0x131, nick_length, nick, offset, buf);
- }
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_mod_group(HNETLIBCONN hServerConn, unsigned short &seqno, const char* name, unsigned short group_id,
- char* members, unsigned short members_length)
-{
- unsigned short offset = 0;
- unsigned short name_length = (unsigned short)mir_strlen(name);
- char* buf = (char*)alloca(SNAC_SIZE + TLV_HEADER_SIZE + name_length + members_length + 10);
- aim_writesnac(0x13, 0x09, offset, buf, get_random()); // SSI Edit
- aim_writeshort(name_length, offset, buf); // group name length
- aim_writegeneric(name_length, name, offset, buf); // group name
- aim_writeshort(group_id, offset, buf); // group id
- aim_writeshort(0, offset, buf); // buddy id
- aim_writeshort(1, offset, buf); // buddy type: Group
- aim_writeshort(TLV_HEADER_SIZE + members_length, offset, buf); // length of extra data
- aim_writetlv(0xc8, members_length, members, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_mod_buddy(HNETLIBCONN hServerConn, unsigned short &seqno, const char* sn,
- unsigned short buddy_id, unsigned short group_id,
- char* nick, char* note)
-{
- unsigned short offset = 0;
- unsigned short sn_length = (unsigned short)mir_strlen(sn);
- unsigned short nick_length = (unsigned short)mir_strlen(nick);
- unsigned short note_length = (unsigned short)mir_strlen(note);
- unsigned short tlv_len = TLV_HEADER_SIZE * 2 + nick_length + note_length;
-
- char* buf = (char*)alloca(SNAC_SIZE + sn_length + 10 + tlv_len);
- aim_writesnac(0x13, 0x09, offset, buf, get_random()); // SSI Edit
- aim_writeshort(sn_length, offset, buf); // screen name length
- aim_writegeneric(sn_length, sn, offset, buf); // screen name
- aim_writeshort(buddy_id, offset, buf); // buddy id
- aim_writeshort(group_id, offset, buf); // group id
- aim_writeshort(0, offset, buf); // buddy type: Buddy
- aim_writeshort(tlv_len, offset, buf); // length of extra data
-
- aim_writetlv(0x13c, note_length, note, offset, buf);
- aim_writetlv(0x131, nick_length, nick, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_set_pd_info(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE + TLV_HEADER_SIZE * 3 + 20];
- unsigned short req = 0x09;
- if (m_pd_info_id == 0) {
- m_pd_info_id = get_random();
- req = 0x08;
- }
- aim_writesnac(0x13, req, offset, buf, get_random()); // SSI Edit/Add
- aim_writeshort(0, offset, buf); // name length
- aim_writeshort(0, offset, buf); // group id (root)
- aim_writeshort(m_pd_info_id, offset, buf); // buddy id
- aim_writeshort(0x4, offset, buf); // pd info id
- aim_writeshort(0x15, offset, buf); // size
- aim_writetlvchar(0xca, m_pd_mode, offset, buf); // pd mode
- aim_writetlvlong(0xcb, 0xffffffff, offset, buf); // pd mask
- aim_writetlvlong(0xcc, m_pd_flags, offset, buf); // pd flags
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_ssi_update_preferences(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE + TLV_HEADER_SIZE * 4 + 100];
- unsigned short req = 0x09;
- if (m_pref1_id == 0) {
- m_pref1_id = get_random();
- req = 0x08;
- }
- aim_writesnac(0x13, req, offset, buf, get_random()); // SSI Edit/Add
- aim_writeshort(0, offset, buf); // group name length
- aim_writeshort(0, offset, buf); // group id (root)
- aim_writeshort(m_pref1_id, offset, buf); // buddy id
- aim_writeshort(5, offset, buf); // buddy type: Presence
-
- unsigned short tlv_len = TLV_HEADER_SIZE * 2 + 8;
- if (m_pref2_len) tlv_len += TLV_HEADER_SIZE + m_pref2_len;
- if (m_pref2_set_len) tlv_len += TLV_HEADER_SIZE + m_pref2_set_len;
-
- aim_writeshort(tlv_len, offset, buf); // length of extra data
- aim_writetlvlong(0xc9, m_pref1_flags, offset, buf); // Update Buddy preferences 1
- aim_writetlvlong(0xd6, m_pref1_set_flags, offset, buf); // Update Buddy preferences 1
- if (m_pref2_len)
- aim_writetlv(0xd7, m_pref2_len, m_pref2_flags, offset, buf); // Update Buddy preferences 2
- if (m_pref2_set_len)
- aim_writetlv(0xd8, m_pref2_set_len, m_pref2_set_flags, offset, buf); // Update Buddy preferences 2
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_ssi_update(HNETLIBCONN hServerConn, unsigned short &seqno, bool start)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE];
- aim_writesnac(0x13, start ? 0x11 : 0x12, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno) == 0;
-}
-
-int CAimProto::aim_keepalive(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- return aim_sendflap(hServerConn, 0x05, 4, "\x0\x0\x0\xEE", seqno);
-}
-
-// used when requesting a regular file transfer
-int CAimProto::aim_send_file(HNETLIBCONN hServerConn, unsigned short &seqno,
- unsigned long ip, unsigned short port,
- bool force_proxy, file_transfer *ft)
-{
- char msg_frag[2048];
- unsigned short frag_offset = 0;
-
- aim_writeshort(0, frag_offset, msg_frag); // request type
- aim_writegeneric(8, ft->icbm_cookie, frag_offset, msg_frag); // icbm cookie
- aim_writegeneric(AIM_CAPS_LENGTH, AIM_CAP_FILE_TRANSFER,
- frag_offset, msg_frag); // uuid
- aim_writetlvshort(0x0a, ++ft->req_num, frag_offset, msg_frag); // request number
-
- aim_writetlvlong(0x02, ip, frag_offset, msg_frag); // ip
- aim_writetlvlong(0x16, ~ip, frag_offset, msg_frag); // ip check
-
- aim_writetlvshort(0x05, port, frag_offset, msg_frag); // port
- aim_writetlvshort(0x17, ~port, frag_offset, msg_frag); // port ip check
-
- if (force_proxy)
- aim_writetlv(0x10, 0, nullptr, frag_offset, msg_frag); // request proxy transfer
- else
- aim_writetlvlong(0x03, m_internal_ip, frag_offset, msg_frag); // ip
-
- if (ft->req_num == 1) {
- if (ft->message) {
- aimString dscr(ft->message);
-
- const char* charset = dscr.isUnicode() ? "unicode-2-0" : "us-ascii";
- const unsigned short charset_len = (unsigned short)mir_strlen(charset);
-
- const char* desc_msg = dscr.getBuf();
- const unsigned short desc_len = dscr.getSize();
-
- aim_writetlv(0x0e, 2, "en", frag_offset, msg_frag); // language used by the data
- aim_writetlv(0x0d, charset_len, charset, frag_offset, msg_frag);// charset used by the data
- aim_writetlv(0x0c, desc_len, desc_msg, frag_offset, msg_frag); // invitaion text
- }
-
- aim_writetlv(0x0f, 0, nullptr, frag_offset, msg_frag); // request host check
-
- const char* fname = get_fname(ft->file);
- const unsigned short fnlen = (unsigned short)mir_strlen(fname);
-
- char* fblock = (char*)alloca(9 + fnlen);
- *(unsigned short*)&fblock[0] = _htons(ft->pfts.totalFiles > 1 ? 2 : 1); // single file transfer
- *(unsigned short*)&fblock[2] = _htons(ft->pfts.totalFiles); // number of files
- *(unsigned long*)&fblock[4] = _htonl(ft->pfts.totalBytes); // total bytes in files
- memcpy(&fblock[8], fname, fnlen + 1);
-
- const char* enc = is_utf(fname) ? "utf-8" : "us-ascii";
- aim_writetlv(0x2711, 9 + fnlen, fblock, frag_offset, msg_frag); // extra data, file names, size
- aim_writetlv(0x2712, 8, enc, frag_offset, msg_frag); // character set used by data
-// aim_writetlvlong64(0x2713,ft->pfts.totalBytes,frag_offset,msg_frag); // file length
-
- debugLogA("Attempting to Send a file to a buddy.");
- }
- else {
- aim_writetlvshort(0x14, 0x0a, frag_offset, msg_frag); // Counter proposal reason
- }
-
- unsigned short offset = 0;
- unsigned short sn_length = (unsigned short)mir_strlen(ft->sn);
- char* buf = (char*)alloca(SNAC_SIZE + TLV_HEADER_SIZE * 2 + 12 + frag_offset + sn_length);
- aim_writesnac(0x04, 0x06, offset, buf); // msg to host
- aim_writegeneric(8, ft->icbm_cookie, offset, buf); // icbm cookie
- aim_writeshort(2, offset, buf); // icbm channel
- aim_writechar((unsigned char)sn_length, offset, buf); // screen name length
- aim_writegeneric(sn_length, ft->sn, offset, buf); // screen name
- aim_writetlv(0x05, frag_offset, msg_frag, offset, buf); // icbm tags
- aim_writetlv(0x03, 0, nullptr, offset, buf); // request ack
-
- char cip[20];
- long_ip_to_char_ip(ip, cip);
- debugLogA("IP for Buddy to connect to: %s:%u", cip, port);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno) == 0;
-}
-
-
-int CAimProto::aim_file_ad(HNETLIBCONN hServerConn, unsigned short &seqno, char* sn, char* icbm_cookie, bool deny, unsigned short)
-{
- unsigned short frag_offset = 0;
- char msg_frag[10 + AIM_CAPS_LENGTH + TLV_HEADER_SIZE * 2 + 6];
- aim_writeshort(deny ? 1 : 2, frag_offset, msg_frag); // icbm accept / deny
- aim_writegeneric(8, icbm_cookie, frag_offset, msg_frag); // icbm cookie
- aim_writegeneric(AIM_CAPS_LENGTH,
- AIM_CAP_FILE_TRANSFER, frag_offset, msg_frag); // uuid
-
-// if (max_ver > 1)
-// aim_writetlvshort(0x12,2,frag_offset,msg_frag); // max protocol version
-
- unsigned short sn_length = (unsigned short)mir_strlen(sn);
- unsigned short offset = 0;
- char* buf = (char*)alloca(SNAC_SIZE + TLV_HEADER_SIZE + 21 + frag_offset + sn_length);
- aim_writesnac(0x04, 0x06, offset, buf); // msg to host
- aim_writegeneric(8, icbm_cookie, offset, buf); // icbm cookie
- aim_writeshort(2, offset, buf); // icbm channel
- aim_writechar((unsigned char)sn_length, offset, buf); // screen name length
- aim_writegeneric(sn_length, sn, offset, buf); // screen name
- aim_writetlv(0x05, frag_offset, msg_frag, offset, buf); // icbm tags
-
- debugLogA("%s a file transfer.", deny ? "Denying" : "Accepting");
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno) == 0;
-}
-
-int CAimProto::aim_typing_notification(HNETLIBCONN hServerConn, unsigned short &seqno, char* sn, unsigned short type)
-{
- unsigned short offset = 0;
- unsigned short sn_length = (unsigned short)mir_strlen(sn);
- char* buf = (char*)alloca(SNAC_SIZE + sn_length + 13);
- aim_writesnac(0x04, 0x14, offset, buf);
- aim_writegeneric(8, "\0\0\0\0\0\0\0\0", offset, buf); // icbm cookie
- aim_writeshort(1, offset, buf); // icbm channel
- aim_writechar((unsigned char)sn_length, offset, buf); // screen name length
- aim_writegeneric(sn_length, sn, offset, buf); // screen name
- aim_writeshort(type, offset, buf); // typing event
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_set_idle(HNETLIBCONN hServerConn, unsigned short &seqno, unsigned long seconds)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE + 4];
- aim_writesnac(0x01, 0x11, offset, buf);
- aim_writelong(seconds, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_request_mail(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE + 34];
- aim_writesnac(0x18, 0x06, offset, buf);
- aim_writegeneric(34,
- "\x00\x02"
- "\xb3\x80\x9a\xd8\x0d\xba\x11\xd5\x9f\x8a\x00\x60\xb0\xee\x06\x31"
- "\x5d\x5e\x17\x08\x55\xaa\x11\xd3\xb1\x43\x00\x60\xb0\xfb\x1e\xcb",
- offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_activate_mail(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE + 17];
- aim_writesnac(0x18, 0x16, offset, buf);
- aim_writegeneric(17, "\x02\x04\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00", offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_request_avatar(HNETLIBCONN hServerConn, unsigned short &seqno, const char* sn, unsigned short bart_type, const char* hash, unsigned short hash_size)
-{
- unsigned short offset = 0;
- unsigned char sn_length = (unsigned char)mir_strlen(sn);
- char* buf = (char*)alloca(SNAC_SIZE + sn_length + hash_size + 12);
- aim_writesnac(0x10, 0x06, offset, buf);
- aim_writechar(sn_length, offset, buf); // screen name length
- aim_writegeneric(sn_length, sn, offset, buf); // screen name
- aim_writechar(1, offset, buf); // number of BART ID
- aim_writebartid(bart_type, 0, hash_size, hash, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_set_avatar_hash(HNETLIBCONN hServerConn, unsigned short &seqno, char flags, unsigned short bart_type, unsigned short &id, char size, const char* hash)
-{
- unsigned short offset = 0;
-
- char bart_type_txt[8];
- ultoa(bart_type, bart_type_txt, 10);
- unsigned short bart_type_len = (unsigned short)mir_strlen(bart_type_txt);
-
- unsigned short req = 0x09;
- if (id == 0) {
- id = get_random();
- req = 0x08;
- }
-
- char* buf = (char*)alloca(SNAC_SIZE + TLV_HEADER_SIZE * 2 + 20 + size + bart_type_len);
- aim_writesnac(0x13, req, offset, buf, get_random()); // SSI Edit/Add
- aim_writeshort(bart_type_len, offset, buf); // name length
- aim_writegeneric(bart_type_len, bart_type_txt, offset, buf); // name
- aim_writeshort(0, offset, buf); // group id
- aim_writeshort(id, offset, buf); // buddy id
- aim_writeshort(0x14, offset, buf); // buddy type: Buddy Icon
- aim_writeshort(2 + size + TLV_HEADER_SIZE, offset, buf); // length of extra data
-
- char* buf2 = (char*)alloca(2 + size);
- buf2[0] = flags;
- buf2[1] = (char)size;
- memcpy(&buf2[2], hash, size);
- aim_writetlv(0xd5, 2 + size, buf2, offset, buf); // BART
-
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_delete_avatar_hash(HNETLIBCONN hServerConn, unsigned short &seqno, char /*flags*/, unsigned short bart_type, unsigned short & id)
-{
- unsigned short offset = 0;
-
- if (id == 0) return -1;
- id = 0;
-
- char bart_type_txt[8];
- ultoa(bart_type, bart_type_txt, 10);
- unsigned short bart_type_len = (unsigned short)mir_strlen(bart_type_txt);
-
- char* buf = (char*)alloca(SNAC_SIZE + 20 + bart_type_len);
- aim_writesnac(0x13, 0x0a, offset, buf, get_random()); // SSI Delete
- aim_writeshort(bart_type_len, offset, buf); // name length
- aim_writegeneric(bart_type_len, bart_type_txt, offset, buf); // name
- aim_writeshort(0, offset, buf); // group id
- aim_writeshort(id, offset, buf); // buddy id
- aim_writeshort(0x14, offset, buf); // buddy type: Buddy Icon
- aim_writeshort(0, offset, buf); // length of extra data
-
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_upload_avatar(HNETLIBCONN hServerConn, unsigned short &seqno, unsigned short bart_type, const char* avatar, unsigned short avatar_size)
-{
- unsigned short offset = 0;
- char* buf = (char*)alloca(SNAC_SIZE + 22 + avatar_size);
- aim_writesnac(0x10, 0x02, offset, buf);
- aim_writeshort(bart_type, offset, buf); // BART id
- aim_writeshort(avatar_size, offset, buf);
- aim_writegeneric(avatar_size, avatar, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_search_by_email(HNETLIBCONN hServerConn, unsigned short &seqno, const char* email)
-{
- unsigned short offset = 0;
- char em_length = (char)mir_strlen(email);
- char* buf = (char*)alloca(SNAC_SIZE + em_length);
- aim_writesnac(0x0a, 0x02, offset, buf); // Email search
- aim_writegeneric(em_length, email, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_chatnav_request_limits(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE];
- aim_writesnac(0x0d, 0x02, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno) ? -1 : 0;
-}
-
-int CAimProto::aim_chatnav_create(HNETLIBCONN hServerConn, unsigned short &seqno, char* room, unsigned short exchage)
-{
- //* Join Pseudo Room (Get's the info we need for the real connection)
- unsigned short room_len = (unsigned short)mir_strlen(room);
-
- unsigned short offset = 0;
- char* buf = (char*)alloca(SNAC_SIZE + 10 + room_len + 26);
- aim_writesnac(0x0d, 0x08, offset, buf);
- aim_writeshort(exchage, offset, buf); // Exchange
- aim_writechar(6, offset, buf); // Command Length
- aim_writegeneric(6, "create", offset, buf); // Command
- aim_writeshort(0xffff, offset, buf); // Last Instance
- aim_writechar(1, offset, buf); // Detail
- aim_writeshort(3, offset, buf); // Number of TLVs
- aim_writetlv(0xd3, room_len, room, offset, buf); // Room Name
- aim_writetlv(0xd6, 8, "us-ascii", offset, buf); // Character Set
- aim_writetlv(0xd7, 2, "en", offset, buf); // Language Encoding
-
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_chatnav_room_info(HNETLIBCONN hServerConn, unsigned short &seqno, char* chat_cookie, unsigned short exchange, unsigned short instance)
-{
- unsigned short offset = 0;
- unsigned short chat_cookie_len = (unsigned short)mir_strlen(chat_cookie);
- char* buf = (char*)alloca(SNAC_SIZE + 7 + chat_cookie_len);
- aim_writesnac(0x0d, 0x04, offset, buf);
- aim_writeshort(exchange, offset, buf); // Exchange
- aim_writechar((unsigned char)chat_cookie_len, offset, buf); // Chat Cookie Length
- aim_writegeneric(chat_cookie_len, chat_cookie, offset, buf); // Chat Cookie
- aim_writeshort(instance, offset, buf); // Last Instance
- aim_writechar(1, offset, buf); // Detail
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_chat_join_room(HNETLIBCONN hServerConn, unsigned short &seqno, char* chat_cookie,
- unsigned short exchange, unsigned short instance, unsigned short id)
-{
- unsigned short offset = 0;
- unsigned short cookie_len = (unsigned short)mir_strlen(chat_cookie);
- char* buf = (char*)alloca(SNAC_SIZE + TLV_HEADER_SIZE * 2 + cookie_len + 8);
- aim_writesnac(0x01, 0x04, offset, buf, id);
- aim_writeshort(0x0e, offset, buf); // Service request for Chat
-
- aim_writeshort(0x01, offset, buf); // Tag
- aim_writeshort(cookie_len + 5, offset, buf); // Length
- aim_writeshort(exchange, offset, buf); // Value - Exchange
- aim_writechar((unsigned char)cookie_len, offset, buf); // Value - Cookie Length
- aim_writegeneric(cookie_len, chat_cookie, offset, buf); // Value - Cookie
- aim_writeshort(instance, offset, buf); // Value - Instance
-
-/* if (!getByte(AIM_KEY_DSSL, 0))
- aim_writetlv(0x8c, 0, NULL, offset, buf); // Request SSL connection */
-
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_chat_send_message(HNETLIBCONN hServerConn, unsigned short &seqno, char *amsg)
-{
- aimString str(amsg);
-
- const char* charset = str.isUnicode() ? "unicode-2-0" : "us-ascii";
- const unsigned short chrset_len = (unsigned short)mir_strlen(charset);
-
- const char* msg = str.getBuf();
- const unsigned short msg_len = str.getSize();
-
- unsigned short tlv_offset = 0;
- char* tlv_buf = (char*)alloca(TLV_HEADER_SIZE * 4 + chrset_len + msg_len + 20);
- aim_writetlv(0x04, 13, "text/x-aolrtf", tlv_offset, tlv_buf); // Format
- aim_writetlv(0x02, chrset_len, charset, tlv_offset, tlv_buf); // Character Set
- aim_writetlv(0x03, 2, "en", tlv_offset, tlv_buf); // Language Encoding
- aim_writetlv(0x01, msg_len, msg, tlv_offset, tlv_buf); // Message
-
- unsigned short offset = 0;
- char* buf = (char*)alloca(SNAC_SIZE + 8 + 2 + TLV_HEADER_SIZE * 3 + tlv_offset);
- aim_writesnac(0x0e, 0x05, offset, buf);
- aim_writegeneric(8, "\0\0\0\0\0\0\0\0", offset, buf); // Message Cookie (can be random)
- aim_writeshort(0x03, offset, buf); // Message Channel (Always 3 for chat)
- aim_writetlv(0x01, 0, nullptr, offset, buf); // Public/Whisper flag
- aim_writetlv(0x06, 0, nullptr, offset, buf); // Enable Reflection flag
- aim_writetlv(0x05, tlv_offset, tlv_buf, offset, buf); // Message Information TLV
-
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_chat_invite(HNETLIBCONN hServerConn, unsigned short &seqno, char* chat_cookie, unsigned short exchange, unsigned short instance, char* sn, char* msg)
-{
- unsigned short offset = 0;
- unsigned short chat_cookie_len = (unsigned short)mir_strlen(chat_cookie);
- unsigned short sn_len = (unsigned short)mir_strlen(sn);
- unsigned short msg_len = (unsigned short)mir_strlen(msg);
- char* buf = (char*)alloca(SNAC_SIZE + 64 + chat_cookie_len + sn_len + msg_len);
- aim_writesnac(0x04, 0x06, offset, buf);
- aim_writegeneric(8, "\0\0\0\0\0\0\0\0", offset, buf); // ICBM Cookie
- aim_writeshort(2, offset, buf); // ICBM Channel
- aim_writechar((unsigned char)sn_len, offset, buf); // Screen Name Length
- aim_writegeneric(sn_len, sn, offset, buf); // Screen Name
-
- aim_writeshort(0x05, offset, buf); // Rendezvous Message Data TLV
- aim_writeshort(49 + msg_len + chat_cookie_len, offset, buf); // TLV size
-
- aim_writeshort(0, offset, buf); // Message Type (0) - Request
- aim_writegeneric(8, "\0\0\0\0\0\0\0\0", offset, buf); // ICBM Cookie (same as above)
- aim_writegeneric(16, AIM_CAP_CHAT, offset, buf); // Capability
-
- aim_writetlvshort(0x0a, 1, offset, buf); // Sequence Number TLV
- aim_writetlv(0x0f, 0, nullptr, offset, buf); // Request Host Caps Check TLV
- aim_writetlv(0x0c, msg_len, msg, offset, buf); // Invitation Message TLV
-
- aim_writeshort(0x2711, offset, buf); // Capability TLV
- aim_writeshort(chat_cookie_len + 5, offset, buf); // Length
- aim_writeshort(exchange, offset, buf); // Value - Exchange
- aim_writechar((unsigned char)chat_cookie_len, offset, buf); // Value - Cookie Length
- aim_writegeneric(chat_cookie_len, chat_cookie, offset, buf); // Value - Cookie
- aim_writeshort(instance, offset, buf); // Value - Instance
-
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_chat_deny(HNETLIBCONN hServerConn, unsigned short &seqno, char* sn, char* icbm_cookie)
-{
- unsigned short offset = 0;
- unsigned short sn_length = (unsigned short)mir_strlen(sn);
- char* buf = (char*)alloca(SNAC_SIZE + 20 + sn_length);
- aim_writesnac(0x04, 0x0b, offset, buf);
- aim_writegeneric(8, icbm_cookie, offset, buf); // ICBM Cookie
- aim_writeshort(2, offset, buf); // Channel
- aim_writechar((unsigned char)sn_length, offset, buf); // Screen Name length
- aim_writegeneric(sn_length, sn, offset, buf); // Screen Name
- aim_writeshort(3, offset, buf); // Error code
- aim_writeshort(2, offset, buf); // Error code
- aim_writeshort(1, offset, buf); // Error code
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno) == 0;
-}
-
-int CAimProto::aim_admin_ready(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE + TLV_HEADER_SIZE * 4];
- aim_writesnac(0x01, 0x02, offset, buf);
- aim_writefamily(AIM_SERVICE_GENERIC, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- aim_writefamily(AIM_SERVICE_ADMIN, offset, buf);
- aim_writegeneric(4, AIM_TOOL_VERSION, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_admin_format_name(HNETLIBCONN hServerConn, unsigned short &seqno, const char* sn)
-{
- unsigned short offset = 0;
- unsigned short sn_len = (unsigned short)mir_strlen(sn);
- char* buf = (char*)alloca(SNAC_SIZE + TLV_HEADER_SIZE + sn_len);
- aim_writesnac(0x07, 0x04, offset, buf);
- aim_writetlv(0x01, sn_len, sn, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_admin_change_email(HNETLIBCONN hServerConn, unsigned short &seqno, const char* email)
-{
- unsigned short offset = 0;
- unsigned short email_len = (unsigned short)mir_strlen(email);
- char* buf = (char*)alloca(SNAC_SIZE + TLV_HEADER_SIZE + email_len);
- aim_writesnac(0x07, 0x04, offset, buf);
- aim_writetlv(0x11, email_len, email, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_admin_change_password(HNETLIBCONN hServerConn, unsigned short &seqno, const char* cur_pw, const char* new_pw)
-{
- unsigned short offset = 0;
- unsigned short cur_pw_len = (unsigned short)mir_strlen(cur_pw);
- unsigned short new_pw_len = (unsigned short)mir_strlen(new_pw);
- char* buf = (char*)alloca(SNAC_SIZE + 2 * TLV_HEADER_SIZE + cur_pw_len + new_pw_len);
- aim_writesnac(0x07, 0x04, offset, buf);
- aim_writetlv(0x02, new_pw_len, new_pw, offset, buf);
- aim_writetlv(0x12, cur_pw_len, cur_pw, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_admin_request_info(HNETLIBCONN hServerConn, unsigned short &seqno, const unsigned short &type)
-{
- // types: 0x01 - nickname, 0x11 - email info, 0x13 - registration status
- unsigned short offset = 0;
- char buf[SNAC_SIZE + TLV_HEADER_SIZE];
- aim_writesnac(0x07, 0x02, offset, buf);
- aim_writetlv(type, 0, nullptr, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
-
-int CAimProto::aim_admin_account_confirm(HNETLIBCONN hServerConn, unsigned short &seqno)
-{
- unsigned short offset = 0;
- char buf[SNAC_SIZE + TLV_HEADER_SIZE];
- aim_writesnac(0x07, 0x06, offset, buf);
- return aim_sendflap(hServerConn, 0x02, offset, buf, seqno);
-}
diff --git a/protocols/AimOscar/src/connection.cpp b/protocols/AimOscar/src/connection.cpp
deleted file mode 100755
index 42b69e9f3d..0000000000
--- a/protocols/AimOscar/src/connection.cpp
+++ /dev/null
@@ -1,784 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-HNETLIBCONN CAimProto::aim_connect(const char* server, unsigned short port, bool use_ssl, const char* host)
-{
- NETLIBOPENCONNECTION ncon = { 0 };
- ncon.cbSize = sizeof(ncon);
- ncon.szHost = server;
- ncon.wPort = port;
- ncon.timeout = 6;
- ncon.flags = NLOCF_V2;
- debugLogA("%s:%u", server, port);
- HNETLIBCONN con = Netlib_OpenConnection(m_hNetlibUser, &ncon);
- if (con && use_ssl) {
- if (!Netlib_StartSsl(con, host)) {
- Netlib_CloseHandle(con);
- con = nullptr;
- }
- }
- return con;
-}
-
-HNETLIBCONN CAimProto::aim_peer_connect(const char* ip, unsigned short port)
-{
- NETLIBOPENCONNECTION ncon = { 0 };
- ncon.cbSize = sizeof(ncon);
- ncon.flags = NLOCF_V2;
- ncon.szHost = ip;
- ncon.wPort = port;
- ncon.timeout = 3;
- return Netlib_OpenConnection(m_hNetlibPeer, &ncon);
-}
-
-HNETLIBCONN CAimProto::aim_peer_connect(unsigned long ip, unsigned short port)
-{
- char ips[20];
- long_ip_to_char_ip(ip, ips);
-
- return aim_peer_connect(ips, port);
-}
-
-void CAimProto::aim_connection_authorization(void)
-{
- if (m_iDesiredStatus != ID_STATUS_OFFLINE) {
- char *password = getStringA(AIM_KEY_PW);
- if (password != nullptr) {
- mir_free(m_username);
- m_username = getStringA(AIM_KEY_SN);
- if (m_username != nullptr) {
- HANDLE hServerPacketRecver = Netlib_CreatePacketReceiver(m_hServerConn, 2048 * 4);
-
- NETLIBPACKETRECVER packetRecv = {};
- packetRecv.dwTimeout = 5000;
- for (;;) {
- int recvResult = Netlib_GetMorePackets(hServerPacketRecver, &packetRecv);
- if (recvResult == 0) {
- debugLogA("Connection Closed: No Error? during Connection Authorization");
- break;
- }
- else if (recvResult < 0) {
- debugLogA("Connection Closed: Socket Error during Connection Authorization %d", WSAGetLastError());
- break;
- }
- else {
- unsigned short flap_length = 0;
- for (; packetRecv.bytesUsed < packetRecv.bytesAvailable; packetRecv.bytesUsed = flap_length) {
- if (!packetRecv.buffer)
- break;
-
- FLAP flap((char*)&packetRecv.buffer[packetRecv.bytesUsed], (unsigned short)(packetRecv.bytesAvailable - packetRecv.bytesUsed));
- if (!flap.len())
- break;
-
- flap_length += FLAP_SIZE + flap.len();
- if (flap.cmp(0x01)) {
- if (aim_send_connection_packet(m_hServerConn, m_seqno, flap.val()) == 0) // cookie challenge
- aim_authkey_request(m_hServerConn, m_seqno); // md5 authkey request
- }
- else if (flap.cmp(0x02)) {
- SNAC snac(flap.val(), flap.snaclen());
- if (snac.cmp(0x0017)) {
- snac_md5_authkey(snac, m_hServerConn, m_seqno, m_username, password);
- int authres = snac_authorization_reply(snac);
- switch (authres) {
- case 1:
- mir_free(password);
- Netlib_CloseHandle(hServerPacketRecver);
- debugLogA("Connection Authorization Thread Ending: Negotiation Beginning");
- return;
-
- case 2:
- ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, nullptr, LOGINERR_WRONGPASSWORD);
- goto exit;
-
- case 3:
- ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, nullptr, LOGINERR_NOSERVER);
- goto exit;
- }
- }
- }
- else if (flap.cmp(0x04)) {
- debugLogA("Connection Authorization Thread Ending: Flap 0x04");
- goto exit;
- }
- }
- }
- }
- exit:
- if (hServerPacketRecver)
- Netlib_CloseHandle(hServerPacketRecver);
- }
- }
- mir_free(password);
- }
- if (m_iStatus != ID_STATUS_OFFLINE)
- broadcast_status(ID_STATUS_OFFLINE);
- Netlib_CloseHandle(m_hServerConn);
- m_hServerConn = nullptr;
- debugLogA("Connection Authorization Thread Ending: End of Thread");
-}
-
-bool parse_clientlogin_response(NETLIBHTTPREQUEST *nlhr, NETLIBHTTPHEADER *my_headers, CMStringA &token, CMStringA &secret, time_t &hosttime)
-{
- //TODO: validate response
- //TODO: return false on errors
- //TODO: extract token, secret, hosttime from response
-
- int datalen = 0;
- for (int i = 0; i < nlhr->headersCount; i++) {
- if (!mir_strcmp(nlhr->headers[i].szName, "Set-Cookie")) {
- my_headers[0].szName = "Cookie";
- my_headers[0].szValue = mir_strdup(nlhr->headers[i].szValue);
- }
- }
-
- ptrW buf_w(mir_utf8decodeW(nlhr->pData));
- HXML root = xmlParseString(buf_w, &datalen, L"");
- if (!root)
- return false;
-
- HXML status = xmlGetChildByPath(root, L"response/statusCode", 0);
- if (!status)
- return false;
-
- LPCTSTR status_text = xmlGetText(status);
- // TODO: check other than 200 codes and print some debug info on errors
- if (wcscmp(status_text, L"200"))
- return false;
-
- HXML secret_node = xmlGetChildByPath(root, L"response/data/sessionSecret", 0);
- HXML hosttime_node = xmlGetChildByPath(root, L"response/data/hostTime", 0);
- if (!secret_node || !hosttime_node)
- return false;
-
- HXML token_node = xmlGetChildByPath(root, L"response/data/token/a", 0);
- if (!token_node)
- return false;
-
- LPCTSTR secret_w = xmlGetText(secret_node), token_w = xmlGetText(token_node), hosttime_w = xmlGetText(hosttime_node);
- if (!secret_w || !token_w || !hosttime_w)
- return false;
-
- secret = _T2A(secret_w);
- token = _T2A(token_w);
- hosttime = strtol(_T2A(hosttime_w), nullptr, 10);
- return true;
-}
-
-void generate_signature(BYTE *signature, const char *method, const char *url, const char *parameters, char *session_key)
-{
- CMStringA sig_base(FORMAT, "%s&%s&%s", method, ptrA(mir_urlEncode(url)), ptrA(mir_urlEncode(parameters)));
- mir_hmac_sha256(signature, (BYTE*)session_key, mir_strlen(session_key), (BYTE*)sig_base.GetString(), sig_base.GetLength());
-}
-
-void fill_session_url(CMStringA &buf, CMStringA &token, CMStringA &secret, time_t &hosttime, const char *password, bool encryption)
-{
- /*
- AIM_SESSION_URL?query_string?sig_sha256=signature
- */
-
- CMStringA query_string;
- query_string.Format("a=%s&distId=%s&f=xml&k=%s&ts=%llu&useTLS=%d", token.c_str(), AIM_DEFAULT_DISTID, AIM_DEFAULT_CLIENT_KEY, hosttime, (int)encryption);
-
- BYTE session_key[MIR_SHA256_HASH_SIZE], signature[MIR_SHA256_HASH_SIZE];
- mir_hmac_sha256(session_key, (BYTE*)password, mir_strlen(password), (BYTE*)secret.GetString(), secret.GetLength());
-
- ptrA szKey(mir_base64_encode(session_key, sizeof(session_key)));
-
- generate_signature(signature, "GET", AIM_SESSION_URL, query_string, szKey);
-
- ptrA szEncoded(mir_base64_encode(signature, sizeof(signature)));
- buf.Format("%s?%s&sig_sha256=%s", AIM_SESSION_URL, query_string.c_str(), (char*)szEncoded);
-}
-
-bool parse_start_socar_session_response(const char *response, CMStringA &bos_host, unsigned short &bos_port, CMStringA &cookie, CMStringA &tls_cert_name, bool encryption = true)
-{
- //TODO: extract bos_host, bos_port, cookie, tls_cert_name
-
- int datalen = 0;
- ptrW buf_w(mir_utf8decodeW(response));
- HXML root = xmlParseString(buf_w, &datalen, L"");
- if (!root)
- return false;
-
- HXML status = xmlGetChildByPath(root, L"response/statusCode", 0);
- if (!status)
- return false;
-
- LPCTSTR status_text = xmlGetText(status);
- //TODO: check other than 200 codes and print some debug info on errors
- if (wcscmp(status_text, L"200"))
- return false;
-
- HXML host_node = xmlGetChildByPath(root, L"response/data/host", 0);
- HXML port_node = xmlGetChildByPath(root, L"response/data/port", 0);
- HXML cookie_node = xmlGetChildByPath(root, L"response/data/cookie", 0);
- if (!host_node || !port_node || !cookie_node)
- return false;
-
- LPCTSTR host_w = xmlGetText(host_node), port_w = xmlGetText(port_node), cookie_w = xmlGetText(cookie_node);
- if (!host_w || !port_w || !cookie_w)
- return false;
-
- bos_host = _T2A(host_w);
- bos_port = atoi(_T2A(port_w));
- cookie = _T2A(cookie_w);
-
- if (encryption) {
- HXML tls_node = xmlGetChildByPath(root, L"response/data/tlsCertName", 0); //tls is optional, so this is not fatal error
- if (tls_node) {
- LPCTSTR certname_w = xmlGetText(tls_node);
- if (certname_w)
- tls_cert_name = _T2A(certname_w);
- }
- }
-
- return true;
-}
-
-void CAimProto::aim_connection_clientlogin(void)
-{
- pass_ptrA password(getStringA(AIM_KEY_PW));
- replaceStr(m_username, ptrA(getStringA(AIM_KEY_SN)));
-
- CMStringA buf;
- buf.Format("devId=%s&f=xml&pwd=%s&s=%s", AIM_DEFAULT_CLIENT_KEY, ptrA(mir_urlEncode(password)), ptrA(mir_urlEncode(m_username)));
-
- NETLIBHTTPHEADER headers[] = {
- { "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8" }
- };
-
- NETLIBHTTPREQUEST req = { 0 };
- req.cbSize = sizeof(req);
- req.flags = NLHRF_SSL;
- req.requestType = REQUEST_POST;
- req.szUrl = AIM_LOGIN_URL;
- req.headers = headers;
- req.headersCount = _countof(headers);
- req.pData = buf.GetBuffer();
- req.dataLength = buf.GetLength();
-
- NLHR_PTR resp(Netlib_HttpTransaction(m_hNetlibUser, &req));
- if (!resp || !resp->dataLength) {
- broadcast_status(ID_STATUS_OFFLINE);
- return;
- }
-
- time_t hosttime;
- CMStringA token, secret;
- if (!parse_clientlogin_response(resp, headers, token, secret, hosttime)) {
- //TODO: handle error
- broadcast_status(ID_STATUS_OFFLINE);
- mir_free(headers[0].szValue);
- return;
- }
-
- bool encryption = !getByte(AIM_KEY_DSSL, 0);
- CMStringA url;
- fill_session_url(url, token, secret, hosttime, password, encryption);
-
- // reuse NETLIBHTTPREQUEST
- req.requestType = REQUEST_GET;
- req.pData = nullptr;
- req.flags |= NLHRF_MANUALHOST;
- req.dataLength = 0;
- req.headersCount = 1;
- req.szUrl = url.GetBuffer();
- {
- NETLIBHTTPHEADER headers2[] = {
- { "Host", "api.oscar.aol.com" },
- };
- req.headers = headers2;
-
- resp = Netlib_HttpTransaction(m_hNetlibUser, &req);
- }
-
- if (!resp || !resp->dataLength) {
- // TODO: handle error
- broadcast_status(ID_STATUS_OFFLINE);
- return;
- }
-
- CMStringA bos_host, cookie, tls_cert_name; //TODO: find efficient buf size
- unsigned short bos_port = 0;
- if (!parse_start_socar_session_response(resp->pData, bos_host, bos_port, cookie, tls_cert_name, encryption)) {
- // TODO: handle error
- broadcast_status(ID_STATUS_OFFLINE);
- return;
- }
- if(COOKIE)
- mir_free(COOKIE);
- COOKIE = (char*)mir_base64_decode(cookie, (unsigned int*)&COOKIE_LENGTH);
-
-
- m_hServerConn = aim_connect(bos_host, bos_port, (tls_cert_name[0] && encryption) ? true : false, bos_host);
- if (!m_hServerConn) {
- // TODO: handle error
- broadcast_status(ID_STATUS_OFFLINE);
- return;
- }
-
-
-
- ForkThread(&CAimProto::aim_protocol_negotiation, nullptr);
-}
-
-void __cdecl CAimProto::aim_protocol_negotiation(void*)
-{
- HANDLE hServerPacketRecver = Netlib_CreatePacketReceiver(m_hServerConn, 2048 * 8);
-
- NETLIBPACKETRECVER packetRecv = {};
- packetRecv.dwTimeout = DEFAULT_KEEPALIVE_TIMER * 1000;
- for (;;) {
- int recvResult = Netlib_GetMorePackets(hServerPacketRecver, &packetRecv);
- if (recvResult == 0) {
- debugLogA("Connection Closed: No Error during Connection Negotiation?");
- break;
- }
- else if (recvResult == SOCKET_ERROR) {
- if (WSAGetLastError() == ERROR_TIMEOUT) {
- if (aim_keepalive(m_hServerConn, m_seqno) < 0)
- break;
- }
- else {
- debugLogA("Connection Closed: Socket Error during Connection Negotiation %d", WSAGetLastError());
- break;
- }
- }
- else if (recvResult > 0) {
- unsigned short flap_length = 0;
- for (; packetRecv.bytesUsed < packetRecv.bytesAvailable; packetRecv.bytesUsed = flap_length) {
- if (!packetRecv.buffer)
- break;
- FLAP flap((char*)&packetRecv.buffer[packetRecv.bytesUsed], packetRecv.bytesAvailable - packetRecv.bytesUsed);
- if (!flap.len())
- break;
- flap_length += FLAP_SIZE + flap.len();
- if (flap.cmp(0x01)) {
- if (getByte(AIM_KEY_CLIENTLOGIN, 1) != 1)
- {
- aim_send_cookie(m_hServerConn, m_seqno, COOKIE_LENGTH, COOKIE);//cookie challenge
- mir_free(COOKIE);
- COOKIE = nullptr;
- COOKIE_LENGTH = 0;
- }
- else
- {
- unsigned short offset = 0;
- char client_id[64], mirver[64];
- Miranda_GetVersionText(mirver, sizeof(mirver));
- int client_id_len = mir_snprintf(client_id, "Miranda AIM, version %s", mirver);
-
- char* buf_ = (char*)alloca(SNAC_SIZE + TLV_HEADER_SIZE * 8 + COOKIE_LENGTH + client_id_len + 30); //TODO: correct length
-
- aim_writelong(0x01, offset, buf_);//protocol version number
-
- aim_writetlv(0x06, (unsigned short)COOKIE_LENGTH, COOKIE, offset, buf_);
-
- aim_writetlv(0x03, (unsigned short)client_id_len, client_id, offset, buf_);
-
- aim_writetlvshort(0x17, AIM_CLIENT_MAJOR_VERSION, offset, buf_);
- aim_writetlvshort(0x18, AIM_CLIENT_MINOR_VERSION, offset, buf_);
- aim_writetlvshort(0x19, AIM_CLIENT_LESSER_VERSION, offset, buf_);
- aim_writetlvshort(0x1A, AIM_CLIENT_BUILD_NUMBER, offset, buf_);
- aim_writetlvchar(0x4A, getByte(AIM_KEY_FSC, 0) ? 3 : 1, offset, buf_);
-
- aim_sendflap(m_hServerConn, 0x01, offset, buf_, m_seqno);
- mir_free(COOKIE);
- COOKIE = nullptr;
- COOKIE_LENGTH = 0;
-
- }
- }
- else if (flap.cmp(0x02)) {
- SNAC snac(flap.val(), flap.snaclen());
- if (snac.cmp(0x0001)) {
- snac_supported_families(snac, m_hServerConn, m_seqno);
- snac_supported_family_versions(snac, m_hServerConn, m_seqno);
- snac_rate_limitations(snac, m_hServerConn, m_seqno);
- snac_service_redirect(snac);
- snac_self_info(snac);
- snac_error(snac);
- }
- else if (snac.cmp(0x0002)) {
- snac_received_info(snac);
- snac_error(snac);
- }
- else if (snac.cmp(0x0003)) {
- snac_user_online(snac);
- snac_user_offline(snac);
- snac_error(snac);
- }
- else if (snac.cmp(0x0004)) {
- snac_icbm_limitations(snac, m_hServerConn, m_seqno);
- snac_message_accepted(snac);
- snac_received_message(snac, m_hServerConn, m_seqno);
- snac_typing_notification(snac);
- snac_error(snac);
- snac_file_decline(snac);
- }
- else if (snac.cmp(0x000A)) {
- snac_email_search_results(snac);
- /*
- If there's no match (error 0x14), AIM will pop up a message.
- Since it's annoying and there's no other errors that'll get
- generated, I just assume leave this commented out. It's here
- for consistency.
- */
- //snac_error(snac);
- }
- else if (snac.cmp(0x0013)) {
- snac_contact_list(snac, m_hServerConn, m_seqno);
- snac_list_modification_ack(snac);
- snac_error(snac);
- }
- }
- else if (flap.cmp(0x04)) {
- ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, nullptr, LOGINERR_OTHERLOCATION);
- debugLogA("Connection Negotiation Thread Ending: Flap 0x04");
- goto exit;
- }
- }
- }
- }
-
-exit:
- if (m_iStatus != ID_STATUS_OFFLINE) broadcast_status(ID_STATUS_OFFLINE);
- Netlib_CloseHandle(hServerPacketRecver); hServerPacketRecver = nullptr;
- Netlib_CloseHandle(m_hServerConn); m_hServerConn = nullptr;
- debugLogA("Connection Negotiation Thread Ending: End of Thread");
- offline_contacts();
-}
-
-void __cdecl CAimProto::aim_mail_negotiation(void*)
-{
- HANDLE hServerPacketRecver = Netlib_CreatePacketReceiver(m_hMailConn, 2048 * 8);
-
- NETLIBPACKETRECVER packetRecv = { 0 };
- packetRecv.dwTimeout = DEFAULT_KEEPALIVE_TIMER * 1000;
-
- while (m_iStatus != ID_STATUS_OFFLINE) {
- int recvResult = Netlib_GetMorePackets(hServerPacketRecver, &packetRecv);
- if (recvResult == 0)
- break;
-
- if (recvResult == SOCKET_ERROR) {
- if (WSAGetLastError() == ERROR_TIMEOUT) {
- if (aim_keepalive(m_hMailConn, m_mail_seqno) < 0)
- break;
- }
- else
- break;
- }
- if (recvResult > 0) {
- unsigned short flap_length = 0;
- for (; packetRecv.bytesUsed < packetRecv.bytesAvailable; packetRecv.bytesUsed = flap_length) {
- if (!packetRecv.buffer)
- break;
-
- FLAP flap((char*)&packetRecv.buffer[packetRecv.bytesUsed], packetRecv.bytesAvailable - packetRecv.bytesUsed);
- if (!flap.len())
- break;
-
- flap_length += FLAP_SIZE + flap.len();
- if (flap.cmp(0x01)) {
- aim_send_cookie(m_hMailConn, m_mail_seqno, MAIL_COOKIE_LENGTH, MAIL_COOKIE);//cookie challenge
- mir_free(MAIL_COOKIE);
- MAIL_COOKIE = nullptr;
- MAIL_COOKIE_LENGTH = 0;
- }
- else if (flap.cmp(0x02)) {
- SNAC snac(flap.val(), flap.snaclen());
- if (snac.cmp(0x0001)) {
- snac_supported_families(snac, m_hMailConn, m_mail_seqno);
- snac_supported_family_versions(snac, m_hMailConn, m_mail_seqno);
- snac_mail_rate_limitations(snac, m_hMailConn, m_mail_seqno);
- snac_error(snac);
- }
- else if (snac.cmp(0x0018)) {
- snac_mail_response(snac);
- }
- }
- else if (flap.cmp(0x04))
- goto exit;
- }
- }
- }
-
-exit:
- debugLogA("Mail Server Connection has ended");
- Netlib_CloseHandle(hServerPacketRecver);
- Netlib_CloseHandle(m_hMailConn);
- m_hMailConn = nullptr;
-}
-
-void __cdecl CAimProto::aim_avatar_negotiation(void*)
-{
- HANDLE hServerPacketRecver = Netlib_CreatePacketReceiver(m_hAvatarConn, 2048 * 8);
-
- NETLIBPACKETRECVER packetRecv = { 0 };
- packetRecv.dwTimeout = 300000;//5 minutes connected
-
- for (;;) {
- int recvResult = Netlib_GetMorePackets(hServerPacketRecver, &packetRecv);
- if (recvResult == 0)
- break;
-
- if (recvResult == SOCKET_ERROR)
- break;
-
- if (recvResult > 0) {
- unsigned short flap_length = 0;
- for (; packetRecv.bytesUsed < packetRecv.bytesAvailable; packetRecv.bytesUsed = flap_length) {
- if (!packetRecv.buffer)
- break;
-
- FLAP flap((char*)&packetRecv.buffer[packetRecv.bytesUsed], packetRecv.bytesAvailable - packetRecv.bytesUsed);
- if (!flap.len())
- break;
-
- flap_length += FLAP_SIZE + flap.len();
- if (flap.cmp(0x01)) {
- aim_send_cookie(m_hAvatarConn, m_avatar_seqno, AVATAR_COOKIE_LENGTH, AVATAR_COOKIE); // cookie challenge
- mir_free(AVATAR_COOKIE);
- AVATAR_COOKIE = nullptr;
- AVATAR_COOKIE_LENGTH = 0;
- }
- else if (flap.cmp(0x02)) {
- SNAC snac(flap.val(), flap.snaclen());
- if (snac.cmp(0x0001)) {
- snac_supported_families(snac, m_hAvatarConn, m_avatar_seqno);
- snac_supported_family_versions(snac, m_hAvatarConn, m_avatar_seqno);
- snac_avatar_rate_limitations(snac, m_hAvatarConn, m_avatar_seqno);
- snac_error(snac);
- }
- if (snac.cmp(0x0010)) {
- snac_retrieve_avatar(snac);
- snac_upload_reply_avatar(snac);
- }
- }
- else if (flap.cmp(0x04))
- goto exit;
- }
- }
- }
-
-exit:
- Netlib_CloseHandle(hServerPacketRecver);
- Netlib_CloseHandle(m_hAvatarConn);
- m_hAvatarConn = nullptr;
- ResetEvent(m_hAvatarEvent);
- debugLogA("Avatar Server Connection has ended");
-}
-
-void __cdecl CAimProto::aim_chatnav_negotiation(void*)
-{
- unsigned idle_chat = 0;
- HANDLE hServerPacketRecver = Netlib_CreatePacketReceiver(m_hChatNavConn, 2048 * 8);
-
- NETLIBPACKETRECVER packetRecv = { 0 };
- packetRecv.dwTimeout = DEFAULT_KEEPALIVE_TIMER * 1000;
-
- for (;;) {
- int recvResult = Netlib_GetMorePackets(hServerPacketRecver, &packetRecv);
- if (recvResult == 0)
- break;
-
- if (recvResult == SOCKET_ERROR) {
- if (WSAGetLastError() == ERROR_TIMEOUT) {
- if (m_chat_rooms.getCount())
- idle_chat = 0;
- else if (++idle_chat >= 6)
- break;
-
- if (aim_keepalive(m_hChatNavConn, m_chatnav_seqno) < 0)
- break;
- }
- else
- break;
- }
-
- if (recvResult > 0) {
- unsigned short flap_length = 0;
- for (; packetRecv.bytesUsed < packetRecv.bytesAvailable; packetRecv.bytesUsed = flap_length) {
- if (!packetRecv.buffer)
- break;
- FLAP flap((char*)&packetRecv.buffer[packetRecv.bytesUsed], packetRecv.bytesAvailable - packetRecv.bytesUsed);
- if (!flap.len())
- break;
- flap_length += FLAP_SIZE + flap.len();
- if (flap.cmp(0x01)) {
- aim_send_cookie(m_hChatNavConn, m_chatnav_seqno, CHATNAV_COOKIE_LENGTH, CHATNAV_COOKIE);//cookie challenge
- mir_free(CHATNAV_COOKIE);
- CHATNAV_COOKIE = nullptr;
- CHATNAV_COOKIE_LENGTH = 0;
- }
- else if (flap.cmp(0x02)) {
- SNAC snac(flap.val(), flap.snaclen());
- if (snac.cmp(0x0001)) {
- snac_supported_families(snac, m_hChatNavConn, m_chatnav_seqno);
- snac_supported_family_versions(snac, m_hChatNavConn, m_chatnav_seqno);
- snac_chatnav_rate_limitations(snac, m_hChatNavConn, m_chatnav_seqno);
- snac_error(snac);
- }
- if (snac.cmp(0x000D)) {
- snac_chatnav_info_response(snac, m_hChatNavConn, m_chatnav_seqno);
- snac_error(snac);
- }
- }
- else if (flap.cmp(0x04))
- goto exit;
- }
- }
- }
-
-exit:
- Netlib_CloseHandle(hServerPacketRecver);
- Netlib_CloseHandle(m_hChatNavConn);
- m_hChatNavConn = nullptr;
- ResetEvent(m_hChatNavEvent);
- debugLogA("Chat Navigation Server Connection has ended");
-}
-
-void __cdecl CAimProto::aim_chat_negotiation(void* param)
-{
- chat_list_item *item = (chat_list_item*)param;
- HANDLE hServerPacketRecver = Netlib_CreatePacketReceiver(item->hconn, 2048 * 8);
-
- NETLIBPACKETRECVER packetRecv = { 0 };
- packetRecv.dwTimeout = DEFAULT_KEEPALIVE_TIMER * 1000;
-
- for (;;) {
- int recvResult = Netlib_GetMorePackets(hServerPacketRecver, &packetRecv);
- if (recvResult == 0)
- break;
-
- if (recvResult == SOCKET_ERROR) {
- if (WSAGetLastError() == ERROR_TIMEOUT) {
- if (aim_keepalive(item->hconn, item->seqno) < 0)
- break;
- }
- else
- break;
- }
-
- if (recvResult > 0) {
- unsigned short flap_length = 0;
- for (; packetRecv.bytesUsed < packetRecv.bytesAvailable; packetRecv.bytesUsed = flap_length) {
- if (!packetRecv.buffer)
- break;
- FLAP flap((char*)&packetRecv.buffer[packetRecv.bytesUsed], packetRecv.bytesAvailable - packetRecv.bytesUsed);
- if (!flap.len())
- break;
- flap_length += FLAP_SIZE + flap.len();
- if (flap.cmp(0x01)) {
- aim_send_cookie(item->hconn, item->seqno, item->CHAT_COOKIE_LENGTH, item->CHAT_COOKIE);//cookie challenge
- mir_free(item->CHAT_COOKIE);
- item->CHAT_COOKIE = nullptr;
- item->CHAT_COOKIE_LENGTH = 0;
- }
- else if (flap.cmp(0x02)) {
- SNAC snac(flap.val(), flap.snaclen());
- if (snac.cmp(0x0001)) {
- snac_supported_families(snac, item->hconn, item->seqno);
- snac_supported_family_versions(snac, item->hconn, item->seqno);
- snac_chat_rate_limitations(snac, item->hconn, item->seqno);
- snac_error(snac);
-
- }
- if (snac.cmp(0x000E)) {
- snac_chat_received_message(snac, item);
- snac_chat_joined_left_users(snac, item);
- snac_error(snac);
- }
- }
- else if (flap.cmp(0x04))
- goto exit;
- }
- }
- }
-
-exit:
- Netlib_CloseHandle(hServerPacketRecver);
- Netlib_CloseHandle(item->hconn);
- chat_leave(item->id);
- remove_chat_by_ptr(item);
- debugLogA("Chat Server Connection has ended");
-}
-
-void __cdecl CAimProto::aim_admin_negotiation(void*)
-{
- HANDLE hServerPacketRecver = Netlib_CreatePacketReceiver(m_hAdminConn, 2048 * 8);
-
- NETLIBPACKETRECVER packetRecv = {};
- packetRecv.dwTimeout = 300000; // 5 minutes connected
-
- for (;;) {
- int recvResult = Netlib_GetMorePackets(hServerPacketRecver, &packetRecv);
- if (recvResult == 0)
- break;
-
- if (recvResult == SOCKET_ERROR)
- break;
-
- if (recvResult > 0) {
- unsigned short flap_length = 0;
- for (; packetRecv.bytesUsed < packetRecv.bytesAvailable; packetRecv.bytesUsed = flap_length) {
- if (!packetRecv.buffer)
- break;
- FLAP flap((char*)&packetRecv.buffer[packetRecv.bytesUsed], packetRecv.bytesAvailable - packetRecv.bytesUsed);
- if (!flap.len())
- break;
- flap_length += FLAP_SIZE + flap.len();
- if (flap.cmp(0x01)) {
- aim_send_cookie(m_hAdminConn, m_admin_seqno, ADMIN_COOKIE_LENGTH, ADMIN_COOKIE);//cookie challenge
- mir_free(ADMIN_COOKIE);
- ADMIN_COOKIE = nullptr;
- ADMIN_COOKIE_LENGTH = 0;
- }
- else if (flap.cmp(0x02)) {
- SNAC snac(flap.val(), flap.snaclen());
- if (snac.cmp(0x0001)) {
- snac_supported_families(snac, m_hAdminConn, m_admin_seqno);
- snac_supported_family_versions(snac, m_hAdminConn, m_admin_seqno);
- snac_admin_rate_limitations(snac, m_hAdminConn, m_admin_seqno);
- snac_error(snac);
- }
- if (snac.cmp(0x0007)) {
- snac_admin_account_infomod(snac);
- snac_admin_account_confirm(snac);
- snac_error(snac);
- }
- }
- else if (flap.cmp(0x04))
- goto exit;
- }
- }
- }
-
-exit:
- Netlib_CloseHandle(hServerPacketRecver);
- Netlib_CloseHandle(m_hAdminConn);
- m_hAdminConn = nullptr;
- ResetEvent(m_hAdminEvent);
- debugLogA("Admin Server Connection has ended");
-}
diff --git a/protocols/AimOscar/src/conv.cpp b/protocols/AimOscar/src/conv.cpp
deleted file mode 100644
index cca0c668ac..0000000000
--- a/protocols/AimOscar/src/conv.cpp
+++ /dev/null
@@ -1,758 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2012 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-#pragma warning( disable: 4706 )
-
-char* process_status_msg(const char *str, const char* sn)
-{
- const char *src = str;
- size_t size = mir_strlen(src) + 1;
- char* res = (char*)mir_alloc(size);
- char* dest = res;
- size_t len = mir_strlen(sn);
-
- for (; *src; ++src) {
- if (src[0] == '\n' && (src == str || src[-1] != '\r')) {
- int off = dest - res;
- res = (char*)mir_realloc(res, ++size);
- dest = res + off;
- *(dest++) = '\r';
- *(dest++) = *src;
- }
- else if (src[0] == '%' && src[1] == 'n') {
- int off = dest - res;
- res = (char*)mir_realloc(res, size + len);
- dest = res + off;
- size += len;
- memcpy(dest, sn, len);
- dest += len;
- ++src;
- }
- else if (src[0] == '%' && src[1] == 'd') {
- int off = dest - res;
- res = (char*)mir_realloc(res, size + 20);
- dest = res + off;
- size += 20;
- dest += GetDateFormatA(LOCALE_USER_DEFAULT, 0, nullptr, nullptr, dest, 20) - 1;
- ++src;
- }
- else if (src[0] == '%' && src[1] == 't') {
- int off = dest - res;
- res = (char*)mir_realloc(res, size + 20);
- dest = res + off;
- size += 20;
- dest += GetTimeFormatA(LOCALE_USER_DEFAULT, 0, nullptr, nullptr, dest, 20) - 1;
- ++src;
- }
- else *(dest++) = *src;
- }
- *dest = '\0';
- return res;
-}
-
-
-void html_decode(char* str)
-{
- char *p, *q;
-
- if (str == nullptr) return;
-
- for (p = q = str; *p != '\0'; p++, q++) {
- if (*p == '&') {
- if (!strnicmp(p, "&amp;", 5)) { *q = '&'; p += 4; }
- else if (!strnicmp(p, "&apos;", 6)) { *q = '\''; p += 5; }
- else if (!strnicmp(p, "&gt;", 4)) { *q = '>'; p += 3; }
- else if (!strnicmp(p, "&lt;", 4)) { *q = '<'; p += 3; }
- else if (!strnicmp(p, "&quot;", 6)) { *q = '"'; p += 5; }
- else if (*(p + 1) == '#') {
- char *s = strchr(p, ';');
- if (s) {
- wchar_t t[2] = { (wchar_t)atoi(p + 2), 0 };
- char *t1 = mir_utf8encodeW(t);
- if (t1 && *t1) {
- mir_strcpy(q, t1);
- q += mir_strlen(t1) - 1;
- }
- mir_free(t1);
- p = s;
- }
- else
- *q = *p;
- }
- else { *q = *p; }
- }
- else if (*p == '<') {
- if (!strnicmp(p, "<p>", 3)) { mir_strcpy(q, "\r\n\r\n"); q += 3; p += 2; }
- else if (!strnicmp(p, "</p>", 4)) { mir_strcpy(q, "\r\n\r\n"); q += 3; p += 3; }
- else if (!strnicmp(p, "<br>", 4)) { mir_strcpy(q, "\r\n"); ++q; p += 3; }
- else if (!strnicmp(p, "<br />", 6)) { mir_strcpy(q, "\r\n"); ++q; p += 5; }
- else if (!strnicmp(p, "<hr>", 4)) { mir_strcpy(q, "\r\n"); ++q; p += 3; }
- else if (!strnicmp(p, "<hr />", 6)) { mir_strcpy(q, "\r\n"); ++q; p += 5; }
- else {
- char *l = strchr(p, '>');
- if (l) { p = l; --q; }
- else *q = *p;
- }
- }
- else *q = *p;
- }
- *q = '\0';
-}
-
-
-char* html_encode(const char* str)
-{
- char *s, *q;
- const char *p;
- int c;
-
- if (str == nullptr) return nullptr;
-
- for (c = 0, p = str; *p != '\0'; p++) {
- switch (*p) {
- case '&': c += 5; break;
- case '\'': c += 6; break;
- case '>': c += 4; break;
- case '<': c += 4; break;
- case '"': c += 6; break;
- case '\n': c += 4; break;
- default: c++; break;
- }
- }
-
- s = (char*)mir_alloc(c + 27);
- mir_strcpy(s, "<HTML><BODY>");
- for (p = str, q = s + 12; *p != '\0'; p++) {
- switch (*p) {
- case '&': memcpy(q, "&amp;", 5); q += 5; break;
- case '>': memcpy(q, "&gt;", 4); q += 4; break;
- case '<': memcpy(q, "&lt;", 4); q += 4; break;
- case '"': memcpy(q, "&quot;", 6); q += 6; break;
- case '\r': break;
- case '\n': memcpy(q, "<BR>", 4); q += 4; break;
- default: *q = *p; ++q; break;
- }
- }
- mir_strcpy(q, "</BODY></HTML>");
-
- return s;
-}
-
-char* html_to_bbcodes(char *src)
-{
- char *ptr;
- char *ptrl;
- char *rptr;
- char* dest = mir_strdup(src);
- while ((ptr = strstr(dest, "<B>")) != nullptr || (ptr = strstr(dest, "<b>")) != nullptr) {
- *ptr = '[';
- *(ptr + 1) = 'b';
- *(ptr + 2) = ']';
- if ((ptr = strstr(dest, "</B>")) != nullptr || (ptr = strstr(dest, "</b>")) != nullptr) {
- *ptr = '[';
- *(ptr + 2) = 'b';
- *(ptr + 3) = ']';
- }
- else {
- dest = (char*)mir_realloc(dest, mir_strlen(dest) + 6);
- memcpy(&dest[mir_strlen(dest)], "[/b]", 5);
- }
- }
- while ((ptr = strstr(dest, "<I>")) != nullptr || (ptr = strstr(dest, "<i>")) != nullptr) {
- *ptr = '[';
- *(ptr + 1) = 'i';
- *(ptr + 2) = ']';
- if ((ptr = strstr(dest, "</I>")) != nullptr || (ptr = strstr(dest, "</i>")) != nullptr) {
- *ptr = '[';
- *(ptr + 2) = 'i';
- *(ptr + 3) = ']';
- }
- else {
- dest = (char*)mir_realloc(dest, mir_strlen(dest) + 6);
- memcpy(&dest[mir_strlen(dest)], "[/i]", 5);
- }
- }
- while ((ptr = strstr(dest, "<U>")) != nullptr || (ptr = strstr(dest, "<u>")) != nullptr) {
- *ptr = '[';
- *(ptr + 1) = 'u';
- *(ptr + 2) = ']';
- if ((ptr = strstr(dest, "</U>")) != nullptr || (ptr = strstr(dest, "</u>")) != nullptr) {
- *ptr = '[';
- *(ptr + 2) = 'u';
- *(ptr + 3) = ']';
- }
- else {
- dest = (char*)mir_realloc(dest, mir_strlen(dest) + 6);
- memcpy(&dest[mir_strlen(dest)], "[/u]", 5);
- }
- }
- while ((ptr = strstr(dest, "<S>")) != nullptr || (ptr = strstr(dest, "<s>")) != nullptr) {
- *ptr = '[';
- *(ptr + 1) = 's';
- *(ptr + 2) = ']';
- if ((ptr = strstr(dest, "</S>")) != nullptr || (ptr = strstr(dest, "</s>")) != nullptr) {
- *ptr = '[';
- *(ptr + 2) = 's';
- *(ptr + 3) = ']';
- }
- else {
- dest = (char*)mir_realloc(dest, mir_strlen(dest) + 6);
- memcpy(&dest[mir_strlen(dest)], "[/s]", 5);
- }
- }
- rptr = dest;
- while (ptr = strstr(rptr, "<A HREF")) {
- char* begin = ptr;
- ptrl = ptr + 4;
- memcpy(ptrl, "[url=", 5);
- memmove(ptr, ptrl, mir_strlen(ptrl) + 1);
- if ((ptr = strstr(ptrl, ">"))) {
- ptr -= 1;
- memmove(ptr, ptr + 1, mir_strlen(ptr + 1) + 1);
- *(ptr) = ']';
- ptrl -= 1;
- char* s1 = strstr(ptrl, "</A");
- char* s2 = strstr(rptr, "<A HREF");
- if (s1&&s1 < s2 || s1&&!s2) {
- ptr = s1;
- ptr = strip_tag_within(begin, ptr);
- memmove(ptr + 2, ptr, mir_strlen(ptr) + 1);
- memcpy(ptr, "[/url]", 6);
- }
- else if (s2&&s2 < s1 || s2&&!s1) {
- ptr = s2;
- ptr = strip_tag_within(begin, ptr);
- int addr = ptr - rptr;
- dest = (char*)mir_realloc(dest, mir_strlen(dest) + 8);
- rptr = dest;
- ptr = rptr + addr;
- memmove(ptr + 6, ptr, mir_strlen(ptr) + 1);
- memcpy(ptr, "[/url]", 6);
- }
- else {
- strip_tag_within(begin, &dest[mir_strlen(dest)]);
- //int addr=ptr-rptr;
- dest = (char*)mir_realloc(dest, mir_strlen(dest) + 8);
- rptr = dest;
- ptr = dest;
- memcpy(&ptr[mir_strlen(ptr)], "[/url]", 7);
- }
- }
- else rptr++;
- }
- rptr = dest;
- while (ptr = strstr(rptr, "<a href")) {
- char* begin = ptr;
- ptrl = ptr + 4;
- memcpy(ptrl, "[url=", 5);
- memmove(ptr, ptrl, mir_strlen(ptrl) + 1);
- if ((ptr = strstr(ptrl, ">"))) {
- ptr -= 1;
- memmove(ptr, ptr + 1, mir_strlen(ptr + 1) + 1);
- *(ptr) = ']';
- ptrl -= 1;
- char* s1 = strstr(ptrl, "</a");
- char* s2 = strstr(ptrl, "<a href");
- if (s1&&s1 < s2 || s1&&!s2) {
- ptr = s1;
- ptr = strip_tag_within(begin, ptr);
- memmove(ptr + 2, ptr, mir_strlen(ptr) + 1);
- memcpy(ptr, "[/url]", 6);
- }
- else if (s2&&s2 < s1 || s2&&!s1) {
- ptr = s2;
- ptr = strip_tag_within(begin, ptr);
- int addr = ptr - rptr;
- dest = (char*)mir_realloc(dest, mir_strlen(dest) + 8);
- rptr = dest;
- ptr = rptr + addr;
- memmove(ptr + 6, ptr, mir_strlen(ptr) + 1);
- memcpy(ptr, "[/url]", 6);
- }
- else {
- strip_tag_within(begin, &dest[mir_strlen(dest)]);
- //int addr=ptr-rptr;
- dest = (char*)mir_realloc(dest, mir_strlen(dest) + 8);
- rptr = dest;
- ptr = dest;
- memcpy(&ptr[mir_strlen(ptr)], "[/url]", 7);
- }
- }
- else rptr++;
- }
- rptr = dest;
- while (ptr = strstr(rptr, "<FONT COLOR=\"")) {
- int addr = ptr - rptr;
- dest = (char*)mir_realloc(dest, mir_strlen(dest) + 8);
- rptr = dest;
- ptr = rptr + addr;
- ptrl = ptr + 6;
- memcpy(ptrl, "[color=", 7);
- memmove(ptr, ptrl, mir_strlen(ptrl) + 1);
- if ((ptr = strstr(ptrl, ">"))) {
- memmove(ptrl + 7, ptr, mir_strlen(ptr) + 1);
- *(ptrl + 7) = ']';
- ptr = ptrl + 7;
- char* s1 = strstr(ptr, "</FONT");
- char* s2 = strstr(ptr, "<FONT COLOR=\"");
- if (s1&&s1 < s2 || s1&&!s2) {
- ptr = s1;
- memmove(ptr + 1, ptr, mir_strlen(ptr) + 1);
- memcpy(ptr, "[/color]", 8);
- }
- else if (s2&&s2 < s1 || s2&&!s1) {
- ptr = s2;
- memmove(ptr + 8, ptr, mir_strlen(ptr) + 1);
- memcpy(ptr, "[/color]", 8);
- }
- else {
- ptr = dest;
- memcpy(&ptr[mir_strlen(ptr)], "[/color]", 9);
- }
- }
- else rptr++;
- }
- rptr = dest;
- while (ptr = strstr(rptr, "<font color=\"")) {
- int addr = ptr - rptr;
- dest = (char*)mir_realloc(dest, mir_strlen(dest) + 8);
- rptr = dest;
- ptr = rptr + addr;
- ptrl = ptr + 6;
- memcpy(ptrl, "[color=", 7);
- memmove(ptr, ptrl, mir_strlen(ptrl) + 1);
- if ((ptr = strstr(ptrl, ">"))) {
- memmove(ptrl + 7, ptr, mir_strlen(ptr) + 1);
- *(ptrl + 7) = ']';
- ptr = ptrl + 7;
- char* s1 = strstr(ptr, "</font");
- char* s2 = strstr(ptr, "<font color=\"");
- if (s1&&s1 < s2 || s1&&!s2) {
- ptr = s1;
- memmove(ptr + 1, ptr, mir_strlen(ptr) + 1);
- memcpy(ptr, "[/color]", 8);
- }
- else if (s2&&s2 < s1 || s2&&!s1) {
- ptr = s2;
- memmove(ptr + 8, ptr, mir_strlen(ptr) + 1);
- memcpy(ptr, "[/color]", 8);
- }
- else {
- ptr = dest;
- memcpy(&ptr[mir_strlen(ptr)], "[/color]", 9);
- }
- }
- else rptr++;
- }
- rptr = dest;
- while ((ptr = strstr(rptr, "<FONT COLOR=")) || (ptr = strstr(rptr, "<font color="))) {
- int addr = ptr - rptr;
- dest = (char*)mir_realloc(dest, mir_strlen(dest) + 8);
- rptr = dest;
- ptr = rptr + addr;
- ptrl = ptr + 5;
- memcpy(ptrl, "[color=", 7);
- memmove(ptr, ptrl, mir_strlen(ptrl) + 1);
- if ((ptr = strstr(ptrl, ">"))) {
- *(ptr) = ']';
- if ((ptrl = strstr(ptr, "</FONT")) || (ptrl = strstr(ptr, "</font"))) {
- memmove(ptrl + 1, ptrl, mir_strlen(ptrl) + 1);
- memcpy(ptrl, "[/color]", 8);
- }
- else memcpy(&dest[mir_strlen(dest)], "[/color]", 9);
- }
- else rptr++;
- }
-
- return dest;
-}
-
-char* bbcodes_to_html(const char *src)
-{
- char *ptr;
- char *rptr;
- char* dest = mir_strdup(src);
- while ((ptr = strstr(dest, "[b]")) != nullptr) {
- *ptr = '<';
- *(ptr + 1) = 'b';
- *(ptr + 2) = '>';
- }
- while ((ptr = strstr(dest, "[/b]")) != nullptr) {
- *ptr = '<';
- *(ptr + 2) = 'b';
- *(ptr + 3) = '>';
- }
- while ((ptr = strstr(dest, "[i]")) != nullptr) {
- *ptr = '<';
- *(ptr + 1) = 'i';
- *(ptr + 2) = '>';
- }
- while ((ptr = strstr(dest, "[/i]")) != nullptr) {
- *ptr = '<';
- *(ptr + 2) = 'i';
- *(ptr + 3) = '>';
- }
- while ((ptr = strstr(dest, "[u]")) != nullptr) {
- *ptr = '<';
- *(ptr + 1) = 'u';
- *(ptr + 2) = '>';
- }
- while ((ptr = strstr(dest, "[/u]")) != nullptr) {
- *ptr = '<';
- *(ptr + 2) = 'u';
- *(ptr + 3) = '>';
- }
- while ((ptr = strstr(dest, "[s]")) != nullptr) {
- *ptr = '<';
- *(ptr + 1) = 's';
- *(ptr + 2) = '>';
- }
- while ((ptr = strstr(dest, "[/s]")) != nullptr) {
- *ptr = '<';
- *(ptr + 2) = 's';
- *(ptr + 3) = '>';
- }
- rptr = dest;
- while ((ptr = strstr(rptr, "[color="))) {
- int addr = ptr - rptr;
- dest = (char*)mir_realloc(dest, mir_strlen(dest) + 8);
- rptr = dest;
- ptr = rptr + addr;
- memmove(ptr + 5, ptr, mir_strlen(ptr) + 1);
- memcpy(ptr, "<font ", 6);
- if ((ptr = strstr(ptr, "]"))) {
- *(ptr) = '>';
- if ((ptr = strstr(ptr, "[/color]"))) {
- memcpy(ptr, "</font>", 7);
- memmove(ptr + 7, ptr + 8, mir_strlen(ptr + 8) + 1);
- }
- }
- else
- rptr++;
- }
- while ((ptr = strstr(rptr, "[url="))) {
- int addr = ptr - rptr;
- dest = (char*)mir_realloc(dest, mir_strlen(dest) + 8);
- rptr = dest;
- ptr = rptr + addr;
- memmove(ptr + 3, ptr, mir_strlen(ptr) + 1);
- memcpy(ptr, "<a href", 7);
- if ((ptr = strstr(ptr, "]"))) {
- *(ptr) = '>';
- if ((ptr = strstr(ptr, "[/url]"))) {
- memcpy(ptr, "</a>", 4);
- memmove(ptr + 4, ptr + 6, mir_strlen(ptr + 6) + 1);
- }
- }
- else
- rptr++;
- }
- return dest;
-}
-
-void strip_tag(char* begin, char* end)
-{
- memmove(begin, end + 1, mir_strlen(end + 1) + 1);
-}
-
-//strip a tag within a string
-char* strip_tag_within(char* begin, char* end)
-{
- while (char *sub_begin = strchr(begin, '<')) {
- if (sub_begin < end)//less than the original ending
- {
- char *sub_end = strchr(begin, '>');
- strip_tag(sub_begin, sub_end);
- end = end - (sub_end - sub_begin) - 1;
- }
- else
- break;
- }
- return end;
-}
-
-char* rtf_to_html(HWND hwndDlg, int DlgItem)
-{
- char* buf = (char*)mir_alloc(4024);
- size_t pos = 0;
- int start = 0;
- int end = 1;
- BOOL Bold = false;
- BOOL Italic = false;
- BOOL Underline = false;
- char Face[32] = "";
- COLORREF Color = 0;
- COLORREF BackColor = 0;
- int Size = 0;
- GETTEXTLENGTHEX tl;
- tl.flags = GTL_DEFAULT;
- tl.codepage = CP_ACP;
-
- int oldstart = 0, oldend = 0;
- SendDlgItemMessage(hwndDlg, DlgItem, EM_GETSEL, (WPARAM)&oldstart, (LPARAM)&oldend);
-
- int length = SendDlgItemMessage(hwndDlg, DlgItem, EM_GETTEXTLENGTHEX, (WPARAM)&tl, 0);
- while (start < length) {
- SendDlgItemMessage(hwndDlg, DlgItem, EM_SETSEL, start, end);
- CHARFORMAT2A cfOld;
- cfOld.cbSize = sizeof(cfOld);
- cfOld.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_SIZE | CFM_COLOR | CFM_BACKCOLOR | CFM_FACE;
- SendDlgItemMessageA(hwndDlg, DlgItem, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfOld);
- BOOL isBold = (cfOld.dwEffects & CFE_BOLD) && (cfOld.dwMask & CFM_BOLD);
- BOOL isItalic = (cfOld.dwEffects & CFE_ITALIC) && (cfOld.dwMask & CFM_ITALIC);
- BOOL isUnderline = (cfOld.dwEffects & CFE_UNDERLINE) && (cfOld.dwMask & CFM_UNDERLINE);
- COLORREF isColor = cfOld.crTextColor;
- COLORREF isBackColor = cfOld.crBackColor;
- int isSize;
- if (cfOld.yHeight == 38 * 20)
- isSize = 7;
- else if (cfOld.yHeight == 24 * 20)
- isSize = 6;
- else if (cfOld.yHeight == 18 * 20)
- isSize = 5;
- else if (cfOld.yHeight == 14 * 20)
- isSize = 4;
- else if (cfOld.yHeight == 12 * 20)
- isSize = 3;
- else if (cfOld.yHeight == 10 * 20)
- isSize = 2;
- else if (cfOld.yHeight == 8 * 20)
- isSize = 1;
- else
- isSize = 3;
- wchar_t text[3] = L"";
- SendDlgItemMessage(hwndDlg, DlgItem, EM_GETSELTEXT, 0, (LPARAM)&text);
- if (Bold != isBold) {
- Bold = isBold;
- if (isBold) {
- mir_strcpy(&buf[pos], "<b>");
- pos += 3;
- }
- else {
- if (start != 0) {
- mir_strcpy(&buf[pos], "</b>");
- pos += 4;
- }
- }
- }
- if (Italic != isItalic) {
- Italic = isItalic;
- if (isItalic) {
- mir_strcpy(&buf[pos], "<i>");
- pos += 3;
- }
- else {
- if (start != 0) {
- mir_strcpy(&buf[pos], "</i>");
- pos += 4;
- }
- }
- }
- if (Underline != isUnderline) {
- Underline = isUnderline;
- if (isUnderline) {
- mir_strcpy(&buf[pos], "<u>");
- pos += 3;
- }
- else {
- if (start != 0) {
- mir_strcpy(&buf[pos], "</u>");
- pos += 4;
- }
- }
- }
- if (Size != isSize || Color != isColor || BackColor != isBackColor || mir_strcmp(Face, cfOld.szFaceName)) {
- Size = isSize;
- Color = isColor;
- BackColor = isBackColor;
- mir_strcpy(Face, cfOld.szFaceName);
- if (start != 0) {
- mir_strcpy(&buf[pos], "</font>");
- pos += 7;
- }
- mir_strcpy(&buf[pos], "<font");
- pos += 5;
- mir_strcpy(&buf[pos], " face=\"");
- pos += 7;
- mir_strcpy(&buf[pos], Face);
- pos += mir_strlen(Face);
- mir_strcpy(&buf[pos], "\"");
- pos++;
- if (!(cfOld.dwEffects & CFE_AUTOBACKCOLOR)) {
- mir_strcpy(&buf[pos], " back=#");
- pos += 6;
- char chBackColor[7];
- _itoa((_htonl(BackColor) >> 8), chBackColor, 16);
- size_t len = mir_strlen(chBackColor);
- if (len < 6) {
- memmove(chBackColor + (6 - len), chBackColor, len + 1);
- for (int i = 0; i < 6; i++)
- chBackColor[i] = '0';
- }
- mir_strcpy(&buf[pos], chBackColor);
- pos += 6;
- }
- if (!(cfOld.dwEffects & CFE_AUTOCOLOR)) {
- mir_strcpy(&buf[pos], " color=#");
- pos += 8;
- char chColor[7];
- _itoa((_htonl(Color) >> 8), chColor, 16);
- size_t len = mir_strlen(chColor);
- if (len < 6) {
- memmove(chColor + (6 - len), chColor, len + 1);
- for (int i = 0; i < 6; i++)
- chColor[i] = '0';
- }
- mir_strcpy(&buf[pos], chColor);
- pos += 6;
- }
- mir_strcpy(&buf[pos], " size=");
- pos += 6;
- char chSize[2];
- _itoa(Size, chSize, 10);
- mir_strcpy(&buf[pos], chSize);
- pos++;
-
- mir_strcpy(&buf[pos], ">");
- pos++;
- }
- if (text[0] == '\r') {
- mir_strcpy(&buf[pos], "<br>");
- pos += 4;
- }
- else {
- T2Utf txt(text);
- mir_strcpy(&buf[pos], txt);
- pos += mir_strlen(txt);
- }
- start++;
- end++;
- }
- if (Bold) {
- mir_strcpy(&buf[pos], "</b>");
- pos += 4;
- }
- if (Italic) {
- mir_strcpy(&buf[pos], "</i>");
- pos += 4;
- }
- if (Underline) {
- mir_strcpy(&buf[pos], "</u>");
- pos += 4;
- }
- mir_strcpy(&buf[pos], "</font>");
- pos += 7;
-
- SendDlgItemMessage(hwndDlg, DlgItem, EM_SETSEL, oldstart, oldend);
-
- return buf;
-}
-
-void wcs_htons(wchar_t *ch)
-{
- if (ch == nullptr) return;
- for (size_t i = 0; i < mir_wstrlen(ch); i++)
- ch[i] = _htons(ch[i]);
-}
-
-char* bytes_to_string(char *bytes, int num_bytes)
-{
- if (num_bytes == 0) return nullptr;
-
- char *string = (char*)mir_alloc(num_bytes * 2 + 1);
- for (int i = 0; i < num_bytes; i++) {
- char store[2];
- unsigned char bit = (bytes[i] & 0xF0) >> 4;
- _itoa(bit, store, 16);
- memcpy(&string[i * 2], store, 1);
- bit = (bytes[i] & 0x0F);
- _itoa(bit, store, 16);
- memcpy(&string[i * 2 + 1], store, 1);
- }
- string[num_bytes * 2] = '\0';
- return string;
-}
-
-void string_to_bytes(char *string, char *bytes)
-{
- char sbyte[3];
- sbyte[2] = '\0';
- size_t length = mir_strlen(string);
- for (size_t i = 0; i < length; i += 2) {
- sbyte[0] = string[i];
- sbyte[1] = string[i + 1];
- bytes[i / 2] = (char)strtol(sbyte, nullptr, 16);
- }
-}
-
-bool is_utf(const char *msg)
-{
- bool res = false;
- if (msg) {
- for (unsigned i = 0; !res; ++i) {
- char c = msg[i];
- if (c == 0) break;
- res = (c & 0x80) != 0;
- }
- }
- return res;
-}
-
-char* get_fname(char *path)
-{
- char *pszFile = strrchr(path, '\\');
- if (pszFile) pszFile++; else pszFile = path;
-
- return pszFile;
-}
-
-wchar_t* get_dir(wchar_t *path)
-{
- wchar_t *cpath = mir_wstrdup(path);
-
- wchar_t *swd = wcsrchr(cpath, '\\');
- if (swd) swd[1] = 0; else cpath[0] = 0;
-
- return cpath;
-}
-
-aimString::aimString(char *str)
-{
- if (str == nullptr) {
- szString = nullptr;
- size = 0;
- unicode = false;
- }
- else {
- unicode = is_utf(str);
- if (unicode) {
- wszString = mir_utf8decodeW(str);
- wcs_htons(wszString);
- size = mir_wstrlen(wszString) * sizeof(wchar_t);
- }
- else {
- szString = mir_utf8decodeA(str);
- size = mir_strlen(szString);
- }
- }
-}
-
-#pragma warning( default: 4706 )
diff --git a/protocols/AimOscar/src/conv.h b/protocols/AimOscar/src/conv.h
deleted file mode 100644
index d12506189b..0000000000
--- a/protocols/AimOscar/src/conv.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef CONV_H
-#define CONV_H
-
-char* process_status_msg (const char *src, const char* sn);
-void html_decode(char* str);
-char* html_encode(const char *src);
-char* html_to_bbcodes(char *src);
-char* bbcodes_to_html(const char *src);
-void strip_tag(char* begin, char* end);
-char* strip_tag_within(char* begin, char* end);
-char* rtf_to_html(HWND hwndDlg,int DlgItem);
-void wcs_htons(wchar_t * ch);
-char* bytes_to_string(char* bytes, int num_bytes);
-void string_to_bytes(char* string, char* bytes);
-bool is_utf(const char* msg);
-char* get_fname(char* path);
-wchar_t* get_dir(wchar_t* path);
-
-struct aimString
-{
- union
- {
- char* szString;
- wchar_t* wszString;
- };
- size_t size;
- bool unicode;
-
- aimString(char* str);
- ~aimString() { mir_free(szString); }
-
- bool isUnicode(void) { return unicode; }
- unsigned short getSize(void) { return (unsigned short)size; }
- unsigned short getTermSize(void) { return (unsigned short)(size + (unicode ? sizeof(wchar_t) : sizeof(char))); }
- char* getBuf(void) { return szString; }
-};
-
-#endif
diff --git a/protocols/AimOscar/src/defines.h b/protocols/AimOscar/src/defines.h
deleted file mode 100644
index 11126ac2fb..0000000000
--- a/protocols/AimOscar/src/defines.h
+++ /dev/null
@@ -1,353 +0,0 @@
-#ifndef DEFINES_H
-#define DEFINES_H
-#if defined __GNUC__
-#pragma GCC system_header
-#endif
-#define _CRT_SECURE_NO_DEPRECATE
-#pragma warning (disable : 4996)
-//System includes
-#include <windows.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <io.h>
-#include <malloc.h>
-#include <process.h>
-#include <prsht.h>
-#include <richedit.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <vssym32.h>
-#include <winuser.h>
-//Miranda IM includes
-#pragma warning( disable: 4100 )
-#pragma warning( disable: 4244 )
-#pragma warning( disable: 4201 )
-#include <newpluginapi.h>
-#include <statusmodes.h>
-#include <m_button.h>
-#include <m_clist.h>
-#include <m_clui.h>
-#include "m_cluiframes.h"
-#include <m_database.h>
-#include <m_idle.h>
-#include <m_langpack.h>
-#include <m_message.h>
-#include <m_netlib.h>
-#include <m_options.h>
-#include <m_popup.h>
-#include <m_protocols.h>
-#include <m_protomod.h>
-#include <m_protosvc.h>
-#include <m_skin.h>
-#include <statusmodes.h>
-#include <m_system.h>
-#include <m_userinfo.h>
-#include <m_addcontact.h>
-#include <m_icolib.h>
-#pragma warning( default: 4100 )
-#pragma warning( default: 4244 )
-#pragma warning( default: 4201 )
-//independent includes
-#include "strl.h"
-#include "flap.h"
-#include "snac.h"
-#include "tlv.h"
-//rest o includes
-#include "avatars.h"
-#include "away.h"
-#include "utility.h"
-#include "client.h"
-#include "connection.h"
-#include "conv.h"
-#include "direct_connect.h"
-#include "error.h"
-#include "file.h"
-#include "links.h"
-#include "packets.h"
-#include "popup.h"
-#include "proxy.h"
-#include "resource.h"
-#include "services.h"
-#include "server.h"
-#include "theme.h"
-#include "thread.h"
-#include "windows.h"
-//Packet Stuff
-#define MSG_LEN 4089
-//Extended Status Icon Numbers
-#define ACCOUNT_TYPE_UNCONFIRMED 1
-#define ACCOUNT_TYPE_CONFIRMED 2
-#define ACCOUNT_TYPE_ICQ 3
-#define ACCOUNT_TYPE_AOL 4
-#define ACCOUNT_TYPE_ADMIN 5
-#define EXTENDED_STATUS_BOT 1
-#define EXTENDED_STATUS_HIPTOP 2
-//Popup flags
-#define MAIL_POPUP 4
-//Main Option Window Keys
-#define AIM_KEY_SN "SN"
-#define AIM_KEY_NK "Nick"
-#define AIM_KEY_PW "Password"
-#define AIM_KEY_HN "hostname"
-#define AIM_KEY_DC "DelConf"//delivery confirmation
-#define AIM_KEY_FP "ForceProxyTransfer"
-#define AIM_KEY_GP "FileTransferGracePeriod"//in seconds default 60
-#define AIM_KEY_KA "KeepAlive"//in seconds default 60
-#define AIM_KEY_HF "HiptopFake"
-#define AIM_KEY_AT "DisableATIcons"
-#define AIM_KEY_ES "DisableESIcons"
-#define AIM_KEY_DM "DisableModeMsg"
-#define AIM_KEY_FI "FormatIncoming"//html->bbcodes
-#define AIM_KEY_FO "FormatOutgoing"//bbcodes->html
-#define AIM_KEY_FR "FirstRun"
-#define AIM_KEY_II "InstantIdle"
-#define AIM_KEY_IIT "InstantIdleTS"
-#define AIM_KEY_CM "CheckMail"
-#define AIM_KEY_DA "DisableAvatars"
-
-//Other plugin Option Keys
-#define OTH_KEY_AI "AwayIgnore"
-#define OTH_KEY_AD "AwayDefault"
-#define OTH_KEY_AM "AwayMsg"
-#define OTH_KEY_OI "OccupiedIgnore"
-#define OTH_KEY_OD "OccupiedDefault"
-#define OTH_KEY_OM "OccupiedMsg"
-#define OTH_KEY_NI "NaIgnore"
-#define OTH_KEY_ND "NaDefault"
-#define OTH_KEY_NM "NaMsg"
-#define OTH_KEY_DI "DndIgnore"
-#define OTH_KEY_DD "DndDefault"
-#define OTH_KEY_DM "DndMsg"
-#define OTH_KEY_PI "OtpIgnore"
-#define OTH_KEY_PD "OtpDefault"
-#define OTH_KEY_PM "OtpMsg"
-#define OTH_KEY_LI "OtlIgnore"
-#define OTH_KEY_LD "OtlDefault"
-#define OTH_KEY_LM "OtlMsg"
-
-#define OTH_KEY_SM "StatusMsg"
-#define OTH_KEY_GP "Group"
-//Module Name Key
-#define MOD_KEY_SA "SRAway"
-#define MOD_KEY_CL "CList"
-//Settings Keys
-#define AIM_KEY_PR "Profile"
-#define AIM_KEY_LA "LastAwayChange"
-#define AIM_MOD_IG "ID2Group"
-#define AIM_MOD_GI "Group2ID"
-#define AIM_KEY_AL "AIMLinks"// aim: links support
-//Contact Keys
-#define AIM_KEY_BI "BuddyId"
-#define AIM_KEY_GI "GroupId"
-#define AIM_KEY_ST "Status"
-#define AIM_KEY_IT "IdleTS"
-#define AIM_KEY_OT "LogonTS"
-#define AIM_KEY_AC "AccType"//account type
-#define AIM_KEY_ET "ESType"//Extended Status type
-#define AIM_KEY_MV "MirVer"
-#define AIM_KEY_US "Utf8Support"
-#define AIM_KEY_NL "NotOnList"
-#define AIM_KEY_LM "LastMessage"
-#define AIM_KEY_NC "NewContact"
-#define AIM_KEY_AH "AvatarHash"
-//File Transfer Keys
-#define AIM_KEY_FT "FileTransfer"//1= sending 0=receiving
-#define AIM_KEY_CK "Cookie"
-#define AIM_KEY_CK2 "Cookie2"
-#define AIM_KEY_FN "FileName"
-#define AIM_KEY_FS "FileSize"
-#define AIM_KEY_FD "FileDesc"
-#define AIM_KEY_IP "IP"
-#define AIM_KEY_PS "ProxyStage"
-#define AIM_KEY_PC "PortCheck"
-#define AIM_KEY_DH "DCHandle"
-//Old Keys
-#define OLD_KEY_PW "password"
-#define OLD_KEY_DM "AutoResponse"
-
-//Some Defaults for various things
-#define DEFAULT_KEEPALIVE_TIMER 60// 1000 milliseconds * 60 = 60 secs
-#define DEFAULT_GRACE_PERIOD 60
-#define AIM_DEFAULT_GROUP "miranda merged"
-#define AIM_DEFAULT_SERVER "login.oscar.aol.com:5190"
-#define SYSTEM_BUDDY "aolsystemmsg"
-#define DEFAULT_AWAY_MSG "I am away from my computer right now."
-//Md5 Roasting stuff
-#define AIM_MD5_STRING "AOL Instant Messenger (SM)"
-#define MD5_HASH_LENGTH 16
-//Aim Version Stuff
-#define AIM_CLIENT_ID_NUMBER "\x01\x09"
-#define AIM_CLIENT_MAJOR_VERSION "\0\x05"
-#define AIM_CLIENT_MINOR_VERSION "\0\x09"
-#define AIM_CLIENT_LESSER_VERSION "\0\0"
-#define AIM_CLIENT_BUILD_NUMBER "\x0b\xdc"
-#define AIM_CLIENT_DISTRIBUTION_NUMBER "\0\0\0\xd2"
-#define AIM_LANGUAGE "en"
-#define AIM_COUNTRY "us"
-#define AIM_MSG_TYPE "text/x-aolrtf; charset=\"us-ascii\""
-#define AIM_TOOL_VERSION "\x01\x10\x08\xf1"
-extern char* AIM_CLIENT_ID_STRING; //Client id EXTERN
-//Supported Clients
-#define CLIENT_UNKNOWN "?"
-#define CLIENT_AIM5 "AIM 5.x"
-#define CLIENT_AIM4 "AIM 4.x"
-#define CLIENT_AIMEXPRESS "AIM Express"
-#define CLIENT_AIM_TRITON "AIM Triton"
-#define CLIENT_AIMTOC "AIM TOC"
-#define CLIENT_GAIM "Gaim"
-#define CLIENT_ADIUM "Adium X"
-#define CLIENT_GPRS "GPRS"
-#define CLIENT_ICHAT "iChat"
-#define CLIENT_IM2 "IM2"
-#define CLIENT_KOPETE "Kopete"
-#define CLIENT_MEEBO "Meebo"
-#define CLIENT_MICQ "mICQ"
-#define CLIENT_AIMOSCAR "Miranda IM %d.%d.%d.%d(AimOSCAR v%d.%d.%d.%d)"
-#define CLIENT_OSCARJ "Miranda IM %d.%d.%d.%d(ICQ v0.%d.%d.%d)"
-#define CLIENT_NAIM "naim"
-#define CLIENT_QIP "qip"
-#define CLIENT_SIM "SIM"
-#define CLIENT_SMS "SMS"
-#define CLIENT_TERRAIM "TerraIM"
-#define CLIENT_TRILLIAN_PRO "Trillian Pro"
-#define CLIENT_TRILLIAN "Trillian"
-//Aim Caps
-#define AIM_CAPS_LENGTH 16
-#define AIM_CAP_ICHAT "\x09\x46\x00\x00\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_UNKNOWN3 "\x09\x46\x01\x03\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_UNKNOWNA "\x09\x46\x01\x05\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_UNKNOWNB "\x09\x46\x01\xff\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_HIPTOP "\x09\x46\x13\x23\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_VOICE_CHAT "\x09\x46\x13\x41\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_DIRECT_PLAY "\x09\x46\x13\x42\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_SEND_FILES "\x09\x46\x13\x43\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_ROUTER_FIND "\x09\x46\x13\x44\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"//icq?
-#define AIM_CAP_DIRECT_IM "\x09\x46\x13\x45\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_AVATARS "\x09\x46\x13\x46\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_ADDINS "\x09\x46\x13\x47\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_RECEIVE_FILES "\x09\x46\x13\x48\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_CHANNEL_TWO "\x09\x46\x13\x49\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"//icq? channel 2 extended, TLV(0x2711) based messages
-#define AIM_CAP_GAMES "\x09\x46\x13\x4A\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_LIST_TRANSFER "\x09\x46\x13\x4B\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_ICQ_SUPPORT "\x09\x46\x13\x4D\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_UTF8 "\x09\x46\x13\x4E\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_UNKNOWN4 "\x09\x46\xf0\x03\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_UNKNOWN1 "\x09\x46\xf0\x04\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_UNKNOWNC "\x09\x46\xf0\x05\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_CHAT "\x74\x8F\x24\x20\x62\x87\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_IM2 "\x74\xed\xc3\x36\x44\xdf\x48\x5b\x8b\x1c\x67\x1a\x1f\x86\x09\x9f"
-#define AIM_CAP_TRILLIAN "\xF2\xE7\xC7\xF4\xFE\xAD\x4D\xFB\xB2\x35\x36\x79\x8B\xDF\0\0"
-extern char AIM_CAP_MIRANDA[]; //Miranda cap EXTERN
-//Aim Services
-#define AIM_SERVICE_GENERIC "\0\x01\0\x04"//version 4
-#define AIM_SERVICE_SSI "\0\x13\0\x03"//version 3
-#define AIM_SERVICE_LOCATION "\0\x02\0\x01"//version 1
-#define AIM_SERVICE_BUDDYLIST "\0\x03\0\x01"//version 1
-#define AIM_SERVICE_MESSAGING "\0\x04\0\x01"//version 1
-#define AIM_SERVICE_INVITATION "\0\x06\0\x01"//version 1
-#define AIM_SERVICE_POPUP "\0\x08\0\x01"//version 1
-#define AIM_SERVICE_BOS "\0\x09\0\x01"//version 1
-#define AIM_SERVICE_AVATAR "\0\x10\0\x01"//version 1
-#define AIM_SERVICE_USERLOOKUP "\0\x0A\0\x01"//version 1
-#define AIM_SERVICE_STATS "\0\x0B\0\x01"//version 1
-#define AIM_SERVICE_MAIL "\0\x18\0\x01"//version 1
-#define AIM_SERVICE_RATES "\0\x01\0\x02\0\x03\0\x04\0\x05"
-//Aim Statuses
-#define AIM_STATUS_WEBAWARE "\0\x01"
-#define AIM_STATUS_SHOWIP "\0\x02"
-#define AIM_STATUS_BIRTHDAY "\0\x08"
-#define AIM_STATUS_WEBFRONT "\0\x20"
-#define AIM_STATUS_DCAUTH "\x10\0"
-#define AIM_STATUS_DCCONT "\x20\0"
-#define AIM_STATUS_NULL "\0\0"
-#define AIM_STATUS_ONLINE "\0\0"
-#define AIM_STATUS_AWAY "\0\x01"
-#define AIM_STATUS_DND "\0\x02"
-#define AIM_STATUS_NA "\0\x04"
-#define AIM_STATUS_OCCUPIED "\0\x10"
-#define AIM_STATUS_FREE4CHAT "\0\x20"
-#define AIM_STATUS_INVISIBLE "\x01\0"
-
-#define HOOKEVENT_SIZE 10
-#define SERVICES_SIZE 30
-class oscar_data
-{
-public:
- char *username;
- char *password;
- unsigned short seqno;//main connection sequence number
- int state;//status of the connection; e.g. whether connected or not
- int packet_offset;//current offset of main connection client to server packet
- unsigned int status;//current status
- int initial_status;//start up status
- char* szModeMsg;//away message
- unsigned short port;
-
- //Some bools to keep track of different things
- bool request_HTML_profile;
- bool extra_icons_loaded;
- bool freeing_DirectBoundPort;
- bool shutting_down;
- bool idle;
- bool instantidle;
- bool checking_mail;
- bool list_received;
- HANDLE hKeepAliveEvent;
-
- HINSTANCE hInstance;//plugin handle instance
-
- //Some main connection stuff
- HANDLE hServerConn;//handle to the main connection
- HANDLE hServerPacketRecver;//handle to the listening device
- HANDLE hNetlib;//handle to netlib
- unsigned long InternalIP;// our ip
- unsigned short LocalPort;// our port
-
- //Peer connection stuff
- HNETLIBUSER m_hNetlibPeer;//handle to the peer netlib
- HANDLE hDirectBoundPort;//direct connection listening port
- HANDLE current_rendezvous_accept_user;//hack
-
- //Handles for the context menu items
- HANDLE hHTMLAwayContextMenuItem;
- HANDLE hAddToServerListContextMenuItem;
-
- //hook event size stuff
- HANDLE hookEvent[HOOKEVENT_SIZE];
- unsigned int hookEvent_size;//current hookevent size
-
- //services size stuff
- HANDLE services[SERVICES_SIZE];
- unsigned int services_size;//current services size
-
- //Some mail connection stuff
- HANDLE m_hMailConn;
- unsigned short mail_seqno;
- int mail_packet_offset;
-
- //avatar connection stuff
- HANDLE m_hAvatarConn;
- unsigned short avatar_seqno;
- HANDLE hAvatarEvent;
- bool AvatarLimitThread;
-
- //away message retrieval stuff
- HANDLE hAwayMsgEvent;
-
- //Some Icon handles
- HANDLE bot_icon;
- HANDLE icq_icon;
- HANDLE aol_icon;
- HANDLE hiptop_icon;
- HANDLE admin_icon;
- HANDLE confirmed_icon;
- HANDLE unconfirmed_icon;
-} extern conn;
-
-void InitIcons(void);
-HICON LoadIconEx(const char* name);
-HANDLE GetIconHandle(const char* name);
-void ReleaseIconEx(const char* name);
-
-#endif
diff --git a/protocols/AimOscar/src/direct_connect.cpp b/protocols/AimOscar/src/direct_connect.cpp
deleted file mode 100644
index e79a0f1d9a..0000000000
--- a/protocols/AimOscar/src/direct_connect.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2012 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-void __cdecl CAimProto::aim_dc_helper(void* param) //only called when we are initiating a direct connection with someone else
-{
- file_transfer *ft = (file_transfer*)param;
-
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, ft, 0);
-
- NETLIBPACKETRECVER packetRecv = {};
- packetRecv.dwTimeout = 350000;
-
- HANDLE hServerPacketRecver = Netlib_CreatePacketReceiver(ft->hConn, 2048 * 4);
-
- int result;
- if (ft->sending)//we are sending
- result = sending_file(ft, hServerPacketRecver, packetRecv);
- else
- result = receiving_file(ft, hServerPacketRecver, packetRecv);
-
- Netlib_CloseHandle(hServerPacketRecver);
- Netlib_CloseHandle(ft->hConn);
- ft->hConn = nullptr;
-
- if (result == 0)
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0);
- else {
- if (!ft->requester && result == 1 && !Miranda_IsTerminated()) {
- ft->accepted = false;
- HNETLIBCONN hConn = aim_peer_connect(AIM_PROXY_SERVER, get_default_port());
- if (hConn) {
- debugLogA("Connected to proxy ip because we want to use a proxy for the file transfer.");
- ft->requester = true;
- ft->hConn = hConn;
- ForkThread(&CAimProto::aim_proxy_helper, ft);
- return;
- }
- }
- aim_file_ad(m_hServerConn, m_seqno, ft->sn, ft->icbm_cookie, true, 0);
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
- }
-
- m_ft_list.remove_by_ft(ft);
-}
-
-void aim_direct_connection_initiated(HNETLIBCONN hNewConnection, DWORD, void* extra)//for receiving stuff via dc
-{
- CAimProto *ppro = (CAimProto*)extra;
-
- NETLIBCONNINFO connInfo = {};
- Netlib_GetConnectionInfo(hNewConnection, &connInfo);
-
- ppro->debugLogA("Buddy connected: %s", connInfo.szIpPort);
-
- // okay someone connected to us or we initiated the connection- we need to figure out who they are and if they belong
- file_transfer *ft = ppro->m_ft_list.find_by_port(connInfo.wPort);
- if (ft) {
- ft->hConn = hNewConnection;
- ppro->aim_dc_helper(ft);
- }
- else Netlib_CloseHandle(hNewConnection);
-}
diff --git a/protocols/AimOscar/src/direct_connect.h b/protocols/AimOscar/src/direct_connect.h
deleted file mode 100644
index 4bdcab6a4d..0000000000
--- a/protocols/AimOscar/src/direct_connect.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2012 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef DIRECT_CONNECT_H
-#define DIRECT_CONNECT_H
-
-void aim_direct_connection_initiated(HNETLIBCONN hNewConnection, DWORD dwRemoteIP, void* extra);
-
-#endif
diff --git a/protocols/AimOscar/src/error.cpp b/protocols/AimOscar/src/error.cpp
deleted file mode 100644
index e0988f5170..0000000000
--- a/protocols/AimOscar/src/error.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-void CAimProto::login_error(unsigned short error)
-{
- switch (error) {
- case 0x0004:
- ShowPopup(LPGEN("Invalid screen name or password."), ERROR_POPUP);
- break;
-
- case 0x0005:
- ShowPopup(LPGEN("Mismatched screen name or password."), ERROR_POPUP);
- break;
-
- case 0x0018:
- ShowPopup(LPGEN("You are connecting too frequently. Try waiting 10 minutes to reconnect."), ERROR_POPUP);
- break;
-
- default:
- ShowPopup(LPGEN("Unknown error occurred when attempting to connect."), ERROR_POPUP);
- break;
- }
-}
-
-void CAimProto::get_error(unsigned short error)
-{
- switch (error) {
- case 0x01:
- ShowPopup(LPGEN("Invalid SNAC header."), ERROR_POPUP);
- break;
-
- case 0x02:
- ShowPopup(LPGEN("Server rate limit exceeded."), ERROR_POPUP);
- break;
-
- case 0x03:
- ShowPopup(LPGEN("Client rate limit exceeded"), ERROR_POPUP);
- break;
-
- case 0x04:
- ShowPopup(LPGEN("Recipient is not logged in."), ERROR_POPUP);
- break;
-
- case 0x05:
- ShowPopup(LPGEN("Requested service is unavailable."), ERROR_POPUP);
- break;
-
- case 0x06:
- ShowPopup(LPGEN("Requested service is not defined."), ERROR_POPUP);
- break;
-
- case 0x07:
- ShowPopup(LPGEN("You sent obsolete SNAC."), ERROR_POPUP);
- break;
-
- case 0x08:
- ShowPopup(LPGEN("Not supported by server."), ERROR_POPUP);
- break;
-
- case 0x09:
- ShowPopup(LPGEN("Not supported by the client."), ERROR_POPUP);
- break;
-
- case 0x0a:
- ShowPopup(LPGEN("Refused by client."), ERROR_POPUP);
- break;
-
- case 0x0b:
- ShowPopup(LPGEN("Reply too big."), ERROR_POPUP);
- break;
-
- case 0x0c:
- ShowPopup(LPGEN("Response lost."), ERROR_POPUP);
- break;
-
- case 0x0d:
- ShowPopup(LPGEN("Request denied."), ERROR_POPUP);
- break;
-
- case 0x0e:
- ShowPopup(LPGEN("Incorrect SNAC format."), ERROR_POPUP);
- break;
-
- case 0x0f:
- ShowPopup(LPGEN("Insufficient rights."), ERROR_POPUP);
- break;
-
- case 0x10:
- ShowPopup(LPGEN("Recipient blocked."), ERROR_POPUP);
- break;
-
- case 0x11:
- ShowPopup(LPGEN("Sender too evil."), ERROR_POPUP);
- break;
-
- case 0x12:
- ShowPopup(LPGEN("Receiver too evil."), ERROR_POPUP);
- break;
-
- case 0x13:
- ShowPopup(LPGEN("User temporarily unavailable."), ERROR_POPUP);
- break;
-
- case 0x14:
- ShowPopup(LPGEN("No match."), ERROR_POPUP);
- break;
-
- case 0x15:
- ShowPopup(LPGEN("List overflow."), ERROR_POPUP);
- break;
-
- case 0x16:
- ShowPopup(LPGEN("Request ambiguous."), ERROR_POPUP);
- break;
-
- case 0x17:
- ShowPopup(LPGEN("Server queue full."), ERROR_POPUP);
- break;
-
- case 0x18:
- ShowPopup(LPGEN("Not while on AOL."), ERROR_POPUP);
- break;
- }
-}
-
-void CAimProto::admin_error(unsigned short error)
-{
- switch (error) {
- case 0x01:
- ShowPopup(LPGEN("Check your screen name."), ERROR_POPUP);
- break;
-
- case 0x02:
- ShowPopup(LPGEN("Check your password."), ERROR_POPUP);
- break;
-
- case 0x03:
- ShowPopup(LPGEN("Check your email address."), ERROR_POPUP);
- break;
-
- case 0x04:
- ShowPopup(LPGEN("Service temporarily unavailable."), ERROR_POPUP);
- break;
-
- case 0x05:
- ShowPopup(LPGEN("Field change temporarily unavailable."), ERROR_POPUP);
- break;
-
- case 0x06:
- ShowPopup(LPGEN("Invalid screen name."), ERROR_POPUP);
- break;
-
- case 0x07:
- ShowPopup(LPGEN("Invalid password."), ERROR_POPUP);
- break;
-
- case 0x08:
- ShowPopup(LPGEN("Invalid email."), ERROR_POPUP);
- break;
-
- case 0x09:
- ShowPopup(LPGEN("Invalid registration preference."), ERROR_POPUP);
- break;
-
- case 0x0a:
- ShowPopup(LPGEN("Invalid old password."), ERROR_POPUP);
- break;
-
- case 0x0b:
- ShowPopup(LPGEN("Invalid screen name Length."), ERROR_POPUP);
- break;
-
- case 0x0c:
- ShowPopup(LPGEN("Invalid password length."), ERROR_POPUP);
- break;
-
- case 0x0d:
- ShowPopup(LPGEN("Invalid email length."), ERROR_POPUP);
- break;
-
- case 0x0e:
- ShowPopup(LPGEN("Invalid old password length."), ERROR_POPUP);
- break;
-
- case 0x0f:
- ShowPopup(LPGEN("Need old password."), ERROR_POPUP);
- break;
-
- case 0x10:
- ShowPopup(LPGEN("Read only field."), ERROR_POPUP);
- break;
-
- case 0x11:
- ShowPopup(LPGEN("Write only field."), ERROR_POPUP);
- break;
-
- case 0x12:
- ShowPopup(LPGEN("Unsupported type."), ERROR_POPUP);
- break;
-
- case 0x13:
- ShowPopup(LPGEN("An error has occurred."), ERROR_POPUP);
- break;
-
- case 0x14:
- ShowPopup(LPGEN("Incorrect SNAC format."), ERROR_POPUP);
- break;
-
- case 0x15:
- ShowPopup(LPGEN("Invalid account."), ERROR_POPUP);
- break;
-
- case 0x16:
- ShowPopup(LPGEN("Deleted account."), ERROR_POPUP);
- break;
-
- case 0x17:
- ShowPopup(LPGEN("Expired account."), ERROR_POPUP);
- break;
-
- case 0x18:
- ShowPopup(LPGEN("No database access."), ERROR_POPUP);
- break;
-
- case 0x19:
- ShowPopup(LPGEN("Invalid database fields."), ERROR_POPUP);
- break;
-
- case 0x1a:
- ShowPopup(LPGEN("Bad database status."), ERROR_POPUP);
- break;
-
- case 0x1b:
- ShowPopup(LPGEN("Migration cancel."), ERROR_POPUP);
- break;
-
- case 0x1c:
- ShowPopup(LPGEN("Internal error."), ERROR_POPUP);
- break;
-
- case 0x1d:
- ShowPopup(LPGEN("There is already a pending request for this screen name."), ERROR_POPUP);
- break;
-
- case 0x1e:
- ShowPopup(LPGEN("Not DT status."), ERROR_POPUP);
- break;
-
- case 0x1f:
- ShowPopup(LPGEN("Outstanding confirmation."), ERROR_POPUP);
- break;
-
- case 0x20:
- ShowPopup(LPGEN("No email address."), ERROR_POPUP);
- break;
-
- case 0x21:
- ShowPopup(LPGEN("Over limit."), ERROR_POPUP);
- break;
-
- case 0x22:
- ShowPopup(LPGEN("Email host fail."), ERROR_POPUP);
- break;
-
- case 0x23:
- ShowPopup(LPGEN("DNS fail."), ERROR_POPUP);
- break;
- }
-}
diff --git a/protocols/AimOscar/src/file.cpp b/protocols/AimOscar/src/file.cpp
deleted file mode 100644
index 2f8e93f907..0000000000
--- a/protocols/AimOscar/src/file.cpp
+++ /dev/null
@@ -1,546 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2012 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-#pragma pack(push, 1)
-
-// oscar file transfer 2 class- See On_Sending_Files_via_OSCAR.pdf
-struct oft2
-{
- char protocol_version[4];//4
- unsigned short length;//6
- unsigned short type;//8
- unsigned char icbm_cookie[8];//16
- unsigned short encryption;//18
- unsigned short compression;//20
- unsigned short total_files;//22
- unsigned short num_files_left;//24
- unsigned short total_parts;//26
- unsigned short parts_left;//28
- unsigned long total_size;//32
- unsigned long size;//36
- unsigned long mod_time;//40
- unsigned long checksum;//44
- unsigned long recv_RFchecksum;//48
- unsigned long RFsize;//52
- unsigned long creation_time;//56
- unsigned long RFchecksum;//60
- unsigned long recv_bytes;//64
- unsigned long recv_checksum;//68
- unsigned char idstring[32];//100
- unsigned char flags;//101
- unsigned char list_name_offset;//102
- unsigned char list_size_offset;//103
- unsigned char dummy[69];//172
- unsigned char mac_info[16];//188
- unsigned short encoding;//190
- unsigned short sub_encoding;//192
- unsigned char filename[64];//256
- };
-
-#pragma pack(pop)
-
-bool send_init_oft2(file_transfer *ft, char* file)
-{
- aimString astr(file);
-
- unsigned short len = max(0x100, 0xc0 + astr.getTermSize());
-
- oft2 *oft = (oft2*)alloca(len);
- memset(oft, 0, len);
-
- memcpy(oft->protocol_version, "OFT2", 4);
- oft->length = _htons(len);
- oft->type = 0x0101;
- oft->total_files = _htons(ft->pfts.totalFiles);
- oft->num_files_left = _htons(ft->pfts.totalFiles - ft->pfts.currentFileNumber);
- oft->total_parts = _htons(1);
- oft->parts_left = _htons(1);
- oft->total_size = _htonl(ft->pfts.totalBytes);
- oft->size = _htonl(ft->pfts.currentFileSize);
- oft->mod_time = _htonl(ft->pfts.currentFileTime);
- oft->checksum = _htonl(aim_oft_checksum_file(ft->pfts.tszCurrentFile));
- oft->recv_RFchecksum = 0x0000FFFF;
- oft->RFchecksum = 0x0000FFFF;
- oft->recv_checksum = 0x0000FFFF;
- memcpy(oft->idstring, "Cool FileXfer", 13);
- oft->flags = 0x20;
- oft->list_name_offset = 0x1c;
- oft->list_size_offset = 0x11;
- oft->encoding = _htons(astr.isUnicode() ? 2 : 0);
- memcpy(oft->filename, astr.getBuf(), astr.getTermSize());
-
- if (!ft->requester || ft->pfts.currentFileNumber)
- memcpy(oft->icbm_cookie, ft->icbm_cookie, 8);
-
- return Netlib_Send(ft->hConn, (char*)oft, len, 0) > 0;
-}
-
-void CAimProto::report_file_error(wchar_t *fname)
-{
- wchar_t errmsg[512];
- wchar_t* error = mir_a2u(_strerror(nullptr));
- mir_snwprintf(errmsg, TranslateT("Failed to open file: %s : %s"), fname, error);
- mir_free(error);
- ShowPopup((char*)errmsg, ERROR_POPUP | TCHAR_POPUP);
-}
-
-bool setup_next_file_send(file_transfer *ft)
-{
- wchar_t *file;
- struct _stati64 statbuf;
- for (;;) {
- file = ft->pfts.ptszFiles[ft->cf];
- if (file == nullptr) return false;
-
- if (_wstat64(file, &statbuf) == 0 && (statbuf.st_mode & _S_IFDIR) == 0)
- break;
-
- ++ft->cf;
- }
-
- ft->pfts.tszCurrentFile = file;
- ft->pfts.currentFileSize = statbuf.st_size;
- ft->pfts.currentFileTime = statbuf.st_mtime;
- ft->pfts.currentFileProgress = 0;
-
- char* fnamea;
- T2Utf fname(file);
- if (ft->pfts.totalFiles > 1 && ft->file[0]) {
- size_t dlen = mir_strlen(ft->file);
- if (strncmp(fname, ft->file, dlen) == 0 && fname.get()[dlen] == '\\') {
- fnamea = &fname.get()[dlen + 1];
- for (char *p = fnamea; *p; ++p)
- if (*p == '\\')
- *p = 1;
- }
- else fnamea = get_fname(fname);
- }
- else fnamea = get_fname(fname);
-
- send_init_oft2(ft, fnamea);
- return true;
-}
-
-int CAimProto::sending_file(file_transfer *ft, HANDLE hServerPacketRecver, NETLIBPACKETRECVER &packetRecv)
-{
- debugLogA("P2P: Entered file sending thread.");
-
- bool failed = true;
- bool failed_conn = false;
-
- if (!setup_next_file_send(ft)) return 2;
-
- debugLogA("Sent file information to buddy.");
- //start listen for packets stuff
-
- for (;;) {
- int recvResult = packetRecv.bytesAvailable - packetRecv.bytesUsed;
- if (recvResult <= 0)
- recvResult = Netlib_GetMorePackets(hServerPacketRecver, &packetRecv);
- if (recvResult == 0) {
- debugLogA("P2P: File transfer connection Error: 0");
- break;
- }
- if (recvResult == SOCKET_ERROR) {
- failed_conn = true;
- debugLogA("P2P: File transfer connection Error: -1");
- break;
- }
- if (recvResult > 0) {
- if (recvResult < 0x100) continue;
-
- oft2* recv_ft = (oft2*)&packetRecv.buffer[packetRecv.bytesUsed];
-
- unsigned short pkt_len = _htons(recv_ft->length);
- if (recvResult < pkt_len) continue;
-
- packetRecv.bytesUsed += pkt_len;
- unsigned short type = _htons(recv_ft->type);
- if (type == 0x0202 || type == 0x0207) {
- debugLogA("P2P: Buddy Accepts our file transfer.");
-
- int fid = _wopen(ft->pfts.tszCurrentFile, _O_RDONLY | _O_BINARY, _S_IREAD);
- if (fid < 0) {
- report_file_error(ft->pfts.tszCurrentFile);
- return 2;
- }
-
- if (ft->pfts.currentFileProgress) _lseeki64(fid, ft->pfts.currentFileProgress, SEEK_SET);
-
- NETLIBSELECT tSelect = { 0 };
- tSelect.hReadConns[0] = ft->hConn;
-
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, (LPARAM)&ft->pfts);
-
- clock_t lNotify = clock();
- for (;;) {
- char buffer[4096];
- int bytes = _read(fid, buffer, sizeof(buffer));
- if (bytes <= 0) break;
-
- if (Netlib_Send(ft->hConn, buffer, bytes, MSG_NODUMP) <= 0) break;
- ft->pfts.currentFileProgress += bytes;
- ft->pfts.totalProgress += bytes;
-
- if (clock() >= lNotify) {
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, (LPARAM)&ft->pfts);
- if (Netlib_Select(&tSelect))
- break;
-
- lNotify = clock() + 500;
- }
- }
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, (LPARAM)&ft->pfts);
- debugLogA("P2P: Finished sending file bytes.");
- _close(fid);
- }
- else if (type == 0x0204) {
- // Handle file skip case
- if (ft->pfts.currentFileProgress == 0) {
- ft->pfts.totalProgress += ft->pfts.currentFileSize;
- }
-
- debugLogA("P2P: Buddy says they got the file successfully");
- if ((ft->pfts.currentFileNumber + 1) < ft->pfts.totalFiles) {
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0);
- ++ft->pfts.currentFileNumber; ++ft->cf;
-
- if (!setup_next_file_send(ft)) {
- report_file_error(ft->pfts.tszCurrentFile);
- return 2;
- }
- }
- else {
- failed = _htonl(recv_ft->recv_bytes) != ft->pfts.currentFileSize;
- break;
- }
- }
- else if (type == 0x0205) {
- recv_ft = (oft2*)packetRecv.buffer;
- recv_ft->type = _htons(0x0106);
-
- ft->pfts.currentFileProgress = _htonl(recv_ft->recv_bytes);
- if (aim_oft_checksum_file(ft->pfts.tszCurrentFile, ft->pfts.currentFileProgress) != _htonl(recv_ft->recv_checksum)) {
- ft->pfts.currentFileProgress = 0;
- recv_ft->recv_bytes = 0;
- }
-
- debugLogA("P2P: Buddy wants us to start sending at a specified file point. (%I64u)", ft->pfts.currentFileProgress);
- if (Netlib_Send(ft->hConn, (char*)recv_ft, _htons(recv_ft->length), 0) <= 0) break;
-
- ft->pfts.totalProgress += ft->pfts.currentFileProgress;
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, (LPARAM)&ft->pfts);
- }
- }
- }
-
- ft->success = !failed;
- return failed ? (failed_conn ? 1 : 2) : 0;
-}
-
-int CAimProto::receiving_file(file_transfer *ft, HANDLE hServerPacketRecver, NETLIBPACKETRECVER &packetRecv)
-{
- debugLogA("P2P: Entered file receiving thread.");
- bool failed = true;
- bool failed_conn = false;
- bool accepted_file = false;
- int fid = -1;
-
- oft2 *oft = nullptr;
-
- ft->pfts.tszWorkingDir = mir_utf8decodeW(ft->file);
-
- //start listen for packets stuff
- for (;;) {
- int recvResult = packetRecv.bytesAvailable - packetRecv.bytesUsed;
- if (recvResult <= 0)
- recvResult = Netlib_GetMorePackets(hServerPacketRecver, &packetRecv);
- if (recvResult == 0) {
- debugLogA("P2P: File transfer connection Error: 0");
- break;
- }
- if (recvResult == SOCKET_ERROR) {
- failed_conn = true;
- debugLogA("P2P: File transfer connection Error: -1");
- break;
- }
- if (recvResult > 0) {
- if (!accepted_file) {
- if (recvResult < 0x100) continue;
-
- oft2* recv_ft = (oft2*)&packetRecv.buffer[packetRecv.bytesUsed];
- unsigned short pkt_len = _htons(recv_ft->length);
-
- if (recvResult < pkt_len) continue;
- packetRecv.bytesUsed += pkt_len;
-
- unsigned short type = _htons(recv_ft->type);
- if (type == 0x0101) {
- debugLogA("P2P: Buddy Ready to begin transfer.");
- oft = (oft2*)mir_realloc(oft, pkt_len);
- memcpy(oft, recv_ft, pkt_len);
- memcpy(oft->icbm_cookie, ft->icbm_cookie, 8);
-
- int buflen = pkt_len - 0x100 + 64;
- char *buf = (char*)mir_calloc(buflen + 2);
- unsigned short enc;
-
- ft->pfts.currentFileSize = _htonl(recv_ft->size);
- ft->pfts.totalBytes = _htonl(recv_ft->total_size);
- ft->pfts.currentFileTime = _htonl(recv_ft->mod_time);
- memcpy(buf, recv_ft->filename, buflen);
- enc = _htons(recv_ft->encoding);
-
- wchar_t *name;
- if (enc == 2) {
- wchar_t* wbuf = (wchar_t*)buf;
- wcs_htons(wbuf);
- for (wchar_t *p = wbuf; *p; ++p) { if (*p == 1) *p = '\\'; }
- name = mir_wstrdup(wbuf);
- }
- else {
- for (char *p = buf; *p; ++p) { if (*p == 1) *p = '\\'; }
- name = mir_a2u(buf);
- }
-
- mir_free(buf);
-
- wchar_t fname[256];
- mir_snwprintf(fname, L"%s%s", ft->pfts.tszWorkingDir, name);
- mir_free(name);
- mir_free(ft->pfts.tszCurrentFile);
- ft->pfts.tszCurrentFile = mir_wstrdup(fname);
-
- ResetEvent(ft->hResumeEvent);
- if (ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FILERESUME, ft, (LPARAM)&ft->pfts))
- WaitForSingleObject(ft->hResumeEvent, INFINITE);
-
- if (ft->pfts.tszCurrentFile) {
- wchar_t* dir = get_dir(ft->pfts.tszCurrentFile);
- CreateDirectoryTreeW(dir);
- mir_free(dir);
-
- oft->type = _htons(ft->pfts.currentFileProgress ? 0x0205 : 0x0202);
-
- const int flag = ft->pfts.currentFileProgress ? 0 : _O_TRUNC;
- fid = _wopen(ft->pfts.tszCurrentFile, _O_CREAT | _O_WRONLY | _O_BINARY | flag, _S_IREAD | _S_IWRITE);
-
- if (fid < 0) {
- report_file_error(fname);
- break;
- }
-
- accepted_file = ft->pfts.currentFileProgress == 0;
-
- if (ft->pfts.currentFileProgress) {
- bool the_same;
- oft->recv_bytes = _htonl(ft->pfts.currentFileProgress);
- oft->recv_checksum = _htonl(aim_oft_checksum_file(ft->pfts.tszCurrentFile));
- the_same = oft->size == oft->recv_bytes && oft->checksum == oft->recv_checksum;
- if (the_same) {
- ft->pfts.totalProgress += ft->pfts.currentFileProgress;
- oft->type = _htons(0x0204);
- _close(fid);
-
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0);
- ++ft->pfts.currentFileNumber;
- ft->pfts.currentFileProgress = 0;
- }
- }
- }
- else {
- oft->type = _htons(0x0204);
-
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0);
- ++ft->pfts.currentFileNumber;
- ft->pfts.currentFileProgress = 0;
- }
-
- if (Netlib_Send(ft->hConn, (char*)oft, pkt_len, 0) == SOCKET_ERROR)
- break;
-
- if (ft->pfts.currentFileNumber >= ft->pfts.totalFiles && _htons(oft->type) == 0x0204) {
- failed = false;
- break;
- }
- }
- else if (type == 0x0106) {
- oft = (oft2*)mir_realloc(oft, pkt_len);
- memcpy(oft, recv_ft, pkt_len);
-
- ft->pfts.currentFileProgress = _htonl(oft->recv_bytes);
- ft->pfts.totalProgress += ft->pfts.currentFileProgress;
-
- _lseeki64(fid, ft->pfts.currentFileProgress, SEEK_SET);
- accepted_file = true;
-
- oft->type = _htons(0x0207);
- if (Netlib_Send(ft->hConn, (char*)oft, pkt_len, 0) == SOCKET_ERROR)
- break;
- }
- else break;
- }
- else {
- packetRecv.bytesUsed = packetRecv.bytesAvailable;
- _write(fid, packetRecv.buffer, packetRecv.bytesAvailable);
- ft->pfts.currentFileProgress += packetRecv.bytesAvailable;
- ft->pfts.totalProgress += packetRecv.bytesAvailable;
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, (LPARAM)&ft->pfts);
- if (ft->pfts.currentFileSize == ft->pfts.currentFileProgress) {
- oft->type = _htons(0x0204);
- oft->recv_bytes = _htonl(ft->pfts.currentFileProgress);
- oft->recv_checksum = _htonl(aim_oft_checksum_file(ft->pfts.tszCurrentFile));
-
- debugLogA("P2P: We got the file successfully");
- Netlib_Send(ft->hConn, (char*)oft, _htons(oft->length), 0);
- if (_htons(oft->num_files_left) == 1) {
- failed = false;
- break;
- }
- else {
- accepted_file = false;
- _close(fid);
-
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0);
- ++ft->pfts.currentFileNumber;
- ft->pfts.currentFileProgress = 0;
- }
- }
- }
- }
- }
-
- if (accepted_file) _close(fid);
- mir_free(oft);
-
- ft->success = !failed;
- return failed ? (failed_conn ? 1 : 2) : 0;
-}
-
-void CAimProto::shutdown_file_transfers(void)
-{
- for (int i = 0; i < m_ft_list.getCount(); ++i) {
- file_transfer& ft = m_ft_list[i];
- if (ft.hConn)
- Netlib_Shutdown(ft.hConn);
- }
-}
-
-ft_list_type::ft_list_type() : OBJLIST <file_transfer>(10) {};
-
-file_transfer* ft_list_type::find_by_cookie(char* cookie, MCONTACT hContact)
-{
- for (int i = 0; i < getCount(); ++i) {
- file_transfer *ft = items[i];
- if (ft->hContact == hContact && memcmp(ft->icbm_cookie, cookie, 8) == 0)
- return ft;
- }
- return nullptr;
-}
-
-file_transfer* ft_list_type::find_by_port(unsigned short port)
-{
- for (int i = getCount(); i--; ) {
- file_transfer *ft = items[i];
- if (ft->requester && ft->local_port == port)
- return ft;
- }
- return nullptr;
-}
-
-
-bool ft_list_type::find_by_ft(file_transfer *ft)
-{
- for (int i = 0; i < getCount(); ++i)
- if (items[i] == ft)
- return true;
-
- return false;
-}
-
-void ft_list_type::remove_by_ft(file_transfer *ft)
-{
- for (int i = 0; i < getCount(); ++i) {
- if (items[i] == ft) {
- remove(i);
- break;
- }
- }
-}
-
-file_transfer::file_transfer(MCONTACT hCont, char* nick, char* cookie)
-{
- memset(this, 0, sizeof(*this));
-
- pfts.cbSize = sizeof(pfts);
- pfts.flags = PFTS_UNICODE;
- pfts.hContact = hCont;
-
- hContact = hCont;
- sn = mir_strdup(nick);
-
- if (cookie)
- memcpy(icbm_cookie, cookie, 8);
- else
- Utils_GetRandom(icbm_cookie, 8);
-
- hResumeEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
-}
-
-file_transfer::~file_transfer()
-{
- stop_listen();
-
- mir_free(file);
- mir_free(message);
- mir_free(sn);
-
- mir_free(pfts.tszWorkingDir);
- if (!sending) mir_free(pfts.tszCurrentFile);
-
- if (success && pfts.ptszFiles) {
- for (int i = 0; pfts.ptszFiles[i]; i++)
- mir_free(pfts.ptszFiles[i]);
-
- mir_free(pfts.ptszFiles);
- }
- CloseHandle(hResumeEvent);
-}
-
-void file_transfer::listen(CAimProto* ppro)
-{
- if (hDirectBoundPort) return;
-
- NETLIBBIND nlb = {};
- nlb.pfnNewConnectionV2 = aim_direct_connection_initiated;
- nlb.pExtra = ppro;
- hDirectBoundPort = Netlib_BindPort(ppro->m_hNetlibPeer, &nlb);
- local_port = hDirectBoundPort ? nlb.wPort : 0;
-}
-
-void file_transfer::stop_listen(void)
-{
- if (hDirectBoundPort) {
- Netlib_CloseHandle(hDirectBoundPort);
- hDirectBoundPort = nullptr;
- local_port = 0;
- }
-}
diff --git a/protocols/AimOscar/src/file.h b/protocols/AimOscar/src/file.h
deleted file mode 100644
index faf6714284..0000000000
--- a/protocols/AimOscar/src/file.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2012 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef FILE_H
-#define FILE_H
-
-struct CAimProto;
-
-struct file_transfer
-{
- MCONTACT hContact;
- char* sn;
-
- char icbm_cookie[8];
-
- HNETLIBCONN hConn;
- HANDLE hResumeEvent;
- HNETLIBBIND hDirectBoundPort;
-
- char* file;
- char* message;
-
- PROTOFILETRANSFERSTATUS pfts;
-
- unsigned long cf;
-
- //below is for when receiving only
- unsigned long local_ip;
- unsigned long verified_ip;
- unsigned long proxy_ip;
- unsigned short port;
- unsigned short max_ver;
-
- unsigned short req_num;
- unsigned short local_port;
-
- bool peer_force_proxy;
- bool me_force_proxy;
- bool sending;
- bool accepted;
- bool requester;
- bool success;
-
- file_transfer(MCONTACT hCont, char* nick, char* cookie);
- ~file_transfer();
-
- void listen(CAimProto* ppro);
- void stop_listen(void);
-
-};
-
-struct ft_list_type : OBJLIST <file_transfer>
-{
- ft_list_type();
-
- file_transfer* find_by_handle(MCONTACT hContact);
- file_transfer* find_by_cookie(char* cookie, MCONTACT hContact);
- file_transfer* find_by_port(unsigned short port);
-
- bool find_by_ft(file_transfer *ft);
-
- void remove_by_ft(file_transfer *ft);
-};
-
-
-#endif
diff --git a/protocols/AimOscar/src/flap.cpp b/protocols/AimOscar/src/flap.cpp
deleted file mode 100644
index 960034d8a0..0000000000
--- a/protocols/AimOscar/src/flap.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#include "stdafx.h"
-
-FLAP::FLAP(char* buf, int num_bytes)
-{
- if (FLAP_SIZE > num_bytes)
- length_ = 0;
- else {
- length_ = _htons((*(unsigned short*)&buf[4]));
- if (FLAP_SIZE + length_ > num_bytes)
- length_ = 0;
- else {
- type_ = buf[1];
- value_ = &buf[FLAP_SIZE];
- }
- }
-}
-unsigned short FLAP::len()
-{
- return length_;
-}
-
-unsigned short FLAP::snaclen()
-{
- return length_ - 10;
-}
-
-int FLAP::cmp(unsigned short type)
-{
- return (type_ == type);
-}
-
-char* FLAP::val()
-{
- return value_;
-}
diff --git a/protocols/AimOscar/src/flap.h b/protocols/AimOscar/src/flap.h
deleted file mode 100644
index 190d668537..0000000000
--- a/protocols/AimOscar/src/flap.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef FLAP_H
-#define FLAP_H
-
-#define FLAP_SIZE 6
-
-class FLAP
-{
-private:
- unsigned char type_;
- unsigned short length_;
- char* value_;
-public:
- FLAP(char* buf,int num_bytes);
- unsigned short len();
- unsigned short snaclen();
- int cmp(unsigned short type);
- char* val();
-};
-
-#endif
diff --git a/protocols/AimOscar/src/links.cpp b/protocols/AimOscar/src/links.cpp
deleted file mode 100644
index b9235bde99..0000000000
--- a/protocols/AimOscar/src/links.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2010 Boris Krasnovskiy
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-extern OBJLIST<CAimProto> g_Instances;
-
-static int SingleHexToDecimal(wchar_t c)
-{
- if (c >= '0' && c <= '9') return c - '0';
- if (c >= 'a' && c <= 'f') return c - 'a' + 10;
- if (c >= 'A' && c <= 'F') return c - 'A' + 10;
- return -1;
-}
-
-static wchar_t* url_decode(wchar_t* str)
-{
- wchar_t* s = str, *d = str;
-
- while (*s) {
- if (*s == '%') {
- int digit1 = SingleHexToDecimal(s[1]);
- if (digit1 != -1) {
- int digit2 = SingleHexToDecimal(s[2]);
- if (digit2 != -1) {
- s += 3;
- *d++ = (wchar_t)((digit1 << 4) | digit2);
- continue;
- }
- }
- }
- *d++ = *s++;
- }
-
- *d = 0;
- return str;
-}
-
-static INT_PTR ServiceParseAimLink(WPARAM, LPARAM lParam)
-{
- if (lParam == 0) return 1; /* sanity check */
-
- wchar_t *arg = (wchar_t*)lParam;
-
- /* skip leading prefix */
- arg = wcschr(arg, ':');
- if (arg == nullptr) return 1; /* parse failed */
-
- for (++arg; *arg == '/'; ++arg);
-
- arg = NEWWSTR_ALLOCA(arg);
-
- if (g_Instances.getCount() == 0) return 0;
-
- CAimProto *proto = &g_Instances[0];
- for (int i = 0; i < g_Instances.getCount(); ++i) {
- if (g_Instances[i].m_iStatus != ID_STATUS_OFFLINE && !IsStatusConnecting(g_Instances[i].m_iStatus)) {
- proto = &g_Instances[i];
- break;
- }
- }
- if (proto == nullptr) return 1;
-
- /*
- add user: aim:addbuddy?screenname=NICK&groupname=GROUP
- send message: aim:goim?screenname=NICK&message=MSG
- open chatroom: aim:gochat?roomname=ROOM&exchange=NUM
- */
- /* add a contact to the list */
- if (!wcsnicmp(arg, L"addbuddy?", 9)) {
- wchar_t *tok, *tok2;
- char *sn = nullptr, *group = nullptr;
-
- for (tok = arg + 8; tok != nullptr; tok = tok2) {
- tok2 = wcschr(++tok, '&'); /* first token */
- if (tok2) *tok2 = 0;
- if (!wcsnicmp(tok, L"screenname=", 11) && *(tok + 11) != 0)
- sn = mir_u2a(url_decode(tok + 11));
- if (!wcsnicmp(tok, L"groupname=", 10) && *(tok + 10) != 0)
- group = mir_utf8encodeW(url_decode(tok + 10)); /* group is currently ignored */
- }
- if (sn == nullptr) {
- mir_free(group);
- return 1;
- }
-
- if (!proto->contact_from_sn(sn)) /* does not yet check if sn is current user */
- {
- MCONTACT hContact = proto->contact_from_sn(sn, true);
- proto->add_contact_to_group(hContact, group && group[0] ? group : AIM_DEFAULT_GROUP);
- }
- mir_free(group);
- mir_free(sn);
- return 0;
- }
- /* send a message to a contact */
- else if (!wcsnicmp(arg, L"goim?", 5)) {
- wchar_t *tok, *tok2, *msg = nullptr;
- char *sn = nullptr;
-
- for (tok = arg + 4; tok != nullptr; tok = tok2) {
- tok2 = wcschr(++tok, '&'); /* first token */
- if (tok2) *tok2 = 0;
- if (!wcsnicmp(tok, L"screenname=", 11) && *(tok + 11) != 0)
- sn = mir_u2a(url_decode(tok + 11));
- if (!wcsnicmp(tok, L"message=", 8) && *(tok + 8) != 0)
- msg = url_decode(tok + 8);
- }
- if (sn == nullptr) return 1; /* parse failed */
-
- MCONTACT hContact = proto->contact_from_sn(sn, true, true);
- if (hContact)
- CallService(MS_MSG_SENDMESSAGEW, hContact, (LPARAM)msg);
-
- mir_free(sn);
- return 0;
- }
-
- /* open a chatroom */
- else if (!wcsnicmp(arg, L"gochat?", 7)) {
- wchar_t *tok, *tok2;
- char *rm = nullptr;
- int exchange = 0;
-
- for (tok = arg + 6; tok != nullptr; tok = tok2) {
- tok2 = wcschr(++tok, '&'); /* first token */
- if (tok2) *tok2 = 0;
- if (!wcsnicmp(tok, L"roomname=", 9) && *(tok + 9) != 0) {
- rm = mir_u2a(url_decode(tok + 9));
- for (char *ch = rm; *ch; ++ch)
- if (*ch == '+') *ch = ' ';
- }
- if (!wcsnicmp(tok, L"exchange=", 9))
- exchange = _wtoi(tok + 9);
- }
- if (rm == nullptr || exchange <= 0) {
- mir_free(rm);
- return 1;
- }
-
- chatnav_param* par = new chatnav_param(rm, (unsigned short)exchange);
- proto->ForkThread(&CAimProto::chatnav_request_thread, par);
-
- mir_free(rm);
- return 0;
- }
- return 1; /* parse failed */
-}
-
-void aim_links_init(void)
-{
- static const char szService[] = "AIM/ParseAimLink";
-
- CreateServiceFunction(szService, ServiceParseAimLink);
- AssocMgr_AddNewUrlTypeT("aim:", TranslateT("AIM link protocol"), hInstance, IDI_AOL, szService, 0);
-}
diff --git a/protocols/AimOscar/src/links.h b/protocols/AimOscar/src/links.h
deleted file mode 100644
index 5eb95a9eab..0000000000
--- a/protocols/AimOscar/src/links.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef LINKS_H
-#define LINKS_H
-
-void aim_links_init();
-
-#endif
diff --git a/protocols/AimOscar/src/packets.cpp b/protocols/AimOscar/src/packets.cpp
deleted file mode 100644
index dc77c6a41e..0000000000
--- a/protocols/AimOscar/src/packets.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#include "stdafx.h"
-
-int aim_writesnac(unsigned short service, unsigned short subgroup,unsigned short &offset, char* out, unsigned short id)
-{
- snac_header *snac = (snac_header*)&out[offset];
- snac->service=_htons(service);
- snac->subgroup=_htons(subgroup);
- snac->flags=0;
- snac->request_id[0]=_htons(id);
- snac->request_id[1]=_htons(subgroup);
- offset+=sizeof(snac_header);
- return 0;
-}
-
-int aim_writetlv(unsigned short type,unsigned short length, const char* value,unsigned short &offset,char* out)
-{
- TLV tlv(type,length,value);
- offset += tlv.whole(&out[offset]);
- return 0;
-}
-
-int aim_writetlvchar(unsigned short type, unsigned char value, unsigned short &offset, char* out)
-{
- return aim_writetlv(type, sizeof(value), (char*)&value, offset, out);
-}
-
-
-int aim_writetlvshort(unsigned short type, unsigned short value, unsigned short &offset, char* out)
-{
- value = _htons(value);
- return aim_writetlv(type, sizeof(value), (char*)&value, offset, out);
-}
-
-
-int aim_writetlvlong(unsigned short type, unsigned long value, unsigned short &offset, char* out)
-{
- value = _htonl(value);
- return aim_writetlv(type, sizeof(value), (char*)&value, offset, out);
-}
-
-int aim_writetlvlong64(unsigned short type, unsigned __int64 value, unsigned short &offset, char* out)
-{
- value = _htonl64(value);
- return aim_writetlv(type, sizeof(value), (char*)&value, offset, out);
-}
-
-
-int CAimProto::aim_sendflap(HNETLIBCONN hServerConn, char type, unsigned short length, const char *buf, unsigned short &seqno)
-{
- mir_cslock lck(SendingMutex);
- const int slen = FLAP_SIZE + length;
- char* obuf = (char*)alloca(slen);
- flap_header *flap = (flap_header*)obuf;
- flap->ast = '*';
- flap->type = type;
- flap->seqno = _htons(seqno++);
- flap->len = _htons(length);
- memcpy(&obuf[FLAP_SIZE], buf, length);
- int rlen= Netlib_Send(hServerConn, obuf, slen, 0);
- if (rlen == SOCKET_ERROR) seqno--;
- return rlen >= 0 ? 0 : -1;
-}
-
-void aim_writefamily(const char *buf,unsigned short &offset,char* out)
-{
- memcpy(&out[offset],buf,4);
- offset+=4;
-}
-
-void aim_writechar(unsigned char val, unsigned short &offset,char* out)
-{
- out[offset++] = val;
-}
-
-void aim_writeshort(unsigned short val, unsigned short &offset,char* out)
-{
- out[offset++] = (char)(val >> 8);
- out[offset++] = (char)(val & 0xFF);
-}
-
-void aim_writelong(unsigned long val, unsigned short &offset,char* out)
-{
- out[offset++] = (char)(val >> 24);
- out[offset++] = (char)((val >> 16) & 0xFF);
- out[offset++] = (char)((val >> 8) & 0xFF);
- out[offset++] = (char)(val & 0xFF);
-}
-
-void aim_writegeneric(unsigned short size,const char *buf,unsigned short &offset,char* out)
-{
- memcpy(&out[offset],buf,size);
- offset+=size;
-}
-
-void aim_writebartid(unsigned short type, unsigned char flags, unsigned short size,const char *buf,unsigned short &offset,char* out)
-{
- out[offset++]=(unsigned char)(type >> 8);
- out[offset++]=(unsigned char)(type & 0xff);
- out[offset++]=flags;
- out[offset++]=(char)size;
- memcpy(&out[offset],buf,size);
- offset+=size;
-}
diff --git a/protocols/AimOscar/src/packets.h b/protocols/AimOscar/src/packets.h
deleted file mode 100644
index e7c4de6cf0..0000000000
--- a/protocols/AimOscar/src/packets.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2010 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef PACKETS_H
-#define PACKETS_H
-
-struct flap_header
-{
- unsigned char ast;
- unsigned char type;
- unsigned short seqno;
- unsigned short len;
-};
-struct snac_header
-{
- unsigned short service;
- unsigned short subgroup;
- unsigned short flags;
- unsigned short request_id[2];
-};
-
-inline unsigned short _htons(unsigned short s)
-{
- return s>>8|s<<8;
-}
-
-inline unsigned long _htonl(unsigned long s)
-{
- return s<<24|(s&0xff00)<<8|((s>>8)&0xff00)|s>>24;
-}
-
-inline unsigned __int64 _htonl64(unsigned __int64 s)
-{
- return (unsigned __int64)_htonl(s & 0xffffffff) << 32 | _htonl(s >> 32);
-}
-
-
-int aim_writesnac(unsigned short service, unsigned short subgroup,unsigned short &offset,char* out, unsigned short id=0);
-int aim_writetlv(unsigned short type,unsigned short size, const char* value,unsigned short &offset,char* out);
-int aim_writetlvchar(unsigned short type, unsigned char value, unsigned short &offset, char* out);
-int aim_writetlvshort(unsigned short type, unsigned short value, unsigned short &offset, char* out);
-int aim_writetlvlong(unsigned short type, unsigned long value, unsigned short &offset, char* out);
-int aim_writetlvlong64(unsigned short type, unsigned __int64 value, unsigned short &offset, char* out);
-void aim_writefamily(const char *buf,unsigned short &offset,char* out);
-void aim_writegeneric(unsigned short size,const char *buf,unsigned short &offset,char* out);
-void aim_writebartid(unsigned short type, unsigned char flags, unsigned short size,const char *buf,unsigned short &offset,char* out);
-void aim_writechar(unsigned char val, unsigned short &offset,char* out);
-void aim_writeshort(unsigned short val, unsigned short &offset,char* out);
-void aim_writelong(unsigned long val, unsigned short &offset,char* out);
-
-#endif
diff --git a/protocols/AimOscar/src/popup.cpp b/protocols/AimOscar/src/popup.cpp
deleted file mode 100644
index c6ad5624fd..0000000000
--- a/protocols/AimOscar/src/popup.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#include "stdafx.h"
-
-struct CAimPopupData
-{
- CAimPopupData(CAimProto* _ppro, char* _url) :
- ppro(_ppro),
- url(mir_strdup(_url))
- {}
-
- ~CAimPopupData()
- { mir_free(url); }
-
- CAimProto* ppro;
- char* url;
-};
-
-LRESULT CALLBACK PopupWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- switch(message)
- {
- case WM_COMMAND:
- if (HIWORD(wParam) == STN_CLICKED)
- {
- CAimPopupData* p = (CAimPopupData*)PUGetPluginData(hWnd);
- if (p->url != nullptr)
- ShellExecuteA(nullptr, "open", p->url, nullptr, nullptr, SW_SHOW);
-
- PUDeletePopup(hWnd);
- return 0;
- }
- break;
-
- case WM_CONTEXTMENU:
- PUDeletePopup(hWnd);
- break;
-
- case UM_FREEPLUGINDATA:
- CAimPopupData* p = (CAimPopupData*)PUGetPluginData(hWnd);
- ReleaseIconEx("aim");
- delete p;
- break;
- }
- return DefWindowProc(hWnd, message, wParam, lParam);
-}
-
-void CAimProto::ShowPopup(const char* msg, int flags, char* url)
-{
- POPUPDATAT ppd = {0};
-
- mir_snwprintf(ppd.lptzContactName, TranslateT("%s protocol"), m_tszUserName);
-
- if (flags & ERROR_POPUP)
- {
- if (flags & TCHAR_POPUP)
- {
- char* errmsg = mir_u2a((wchar_t*)msg);
- debugLogA(errmsg);
- mir_free(errmsg);
- }
- else
- debugLogA(msg);
- }
-
- wchar_t *msgt = (flags & TCHAR_POPUP) ? mir_wstrdup((wchar_t*)msg) : mir_a2u(msg);
- wcsncpy_s(ppd.lptzText, TranslateW(msgt), _TRUNCATE);
- mir_free(msgt);
-
- if (!ServiceExists(MS_POPUP_ADDPOPUPT))
- {
- if (flags & MAIL_POPUP)
- {
- size_t len = mir_wstrlen(ppd.lptzText);
- mir_snwprintf(&ppd.lptzText[len], _countof(ppd.lptzText) - len, L" %s", TranslateT("Open mail account?"));
- if (MessageBox(nullptr, ppd.lptzText, ppd.lptzContactName, MB_YESNO | MB_ICONINFORMATION) == IDYES)
- ShellExecuteA(nullptr, "open", url, nullptr, nullptr, SW_SHOW);
- }
- else
- {
- MessageBox(nullptr, ppd.lptzText, ppd.lptzContactName, MB_OK | MB_ICONINFORMATION);
- }
- }
- else
- {
- ppd.PluginWindowProc = PopupWindowProc;
- ppd.lchIcon = LoadIconEx("aim");
- if (flags & MAIL_POPUP)
- {
- ppd.PluginData = new CAimPopupData(this, url);
- ppd.iSeconds = -1;
- }
- else
- ppd.PluginData = new CAimPopupData(this, nullptr);
-
- CallService(MS_POPUP_ADDPOPUPT, (WPARAM)&ppd, 0);
- }
-}
diff --git a/protocols/AimOscar/src/proto.cpp b/protocols/AimOscar/src/proto.cpp
deleted file mode 100644
index 5857be9f50..0000000000
--- a/protocols/AimOscar/src/proto.cpp
+++ /dev/null
@@ -1,685 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2012 Boris Krasnovskiy
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#include "stdafx.h"
-
-CAimProto::CAimProto(const char* aProtoName, const wchar_t* aUserName) :
- PROTO<CAimProto>(aProtoName, aUserName),
- m_chat_rooms(5)
-{
- debugLogA("Setting protocol/module name to '%s'", m_szModuleName);
-
- //create some events
- m_hAvatarEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
- m_hChatNavEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
- m_hAdminEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
-
- CreateProtoService(PS_CREATEACCMGRUI, &CAimProto::SvcCreateAccMgrUI);
-
- CreateProtoService(PS_GETMYAWAYMSG, &CAimProto::GetMyAwayMsg);
-
- CreateProtoService(PS_GETAVATARINFO, &CAimProto::GetAvatarInfo);
- CreateProtoService(PS_GETMYAVATAR, &CAimProto::GetAvatar);
- CreateProtoService(PS_SETMYAVATAR, &CAimProto::SetAvatar);
- CreateProtoService(PS_GETAVATARCAPS, &CAimProto::GetAvatarCaps);
-
- CreateProtoService(PS_JOINCHAT, &CAimProto::OnJoinChat);
- CreateProtoService(PS_LEAVECHAT, &CAimProto::OnLeaveChat);
-
- HookProtoEvent(ME_CLIST_PREBUILDCONTACTMENU, &CAimProto::OnPreBuildContactMenu);
- HookProtoEvent(ME_CLIST_GROUPCHANGE, &CAimProto::OnGroupChange);
- HookProtoEvent(ME_OPT_INITIALISE, &CAimProto::OnOptionsInit);
-
- offline_contacts();
-
- wchar_t descr[MAX_PATH];
-
- NETLIBUSER nlu = {};
- nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS | NUF_UNICODE;
- nlu.szSettingsModule = m_szModuleName;
- mir_snwprintf(descr, TranslateT("%s server connection"), m_tszUserName);
- nlu.szDescriptiveName.w = descr;
- m_hNetlibUser = Netlib_RegisterUser(&nlu);
-
- char szP2P[128];
- mir_snprintf(szP2P, "%sP2P", m_szModuleName);
- nlu.flags = NUF_OUTGOING | NUF_INCOMING | NUF_UNICODE;
- mir_snwprintf(descr, TranslateT("%s client-to-client connections"), m_tszUserName);
- nlu.szSettingsModule = szP2P;
- nlu.minIncomingPorts = 1;
- m_hNetlibPeer = Netlib_RegisterUser(&nlu);
-}
-
-CAimProto::~CAimProto()
-{
- if (m_hServerConn)
- Netlib_CloseHandle(m_hServerConn);
- if (m_hAvatarConn && m_hAvatarConn != (HANDLE)1)
- Netlib_CloseHandle(m_hAvatarConn);
- if (m_hChatNavConn && m_hChatNavConn != (HANDLE)1)
- Netlib_CloseHandle(m_hChatNavConn);
- if (m_hAdminConn && m_hAdminConn != (HANDLE)1)
- Netlib_CloseHandle(m_hAdminConn);
-
- close_chat_conn();
-
- Netlib_CloseHandle(m_hNetlibUser);
- Netlib_CloseHandle(m_hNetlibPeer);
-
- CloseHandle(m_hAvatarEvent);
- CloseHandle(m_hChatNavEvent);
- CloseHandle(m_hAdminEvent);
-
- for (int i = 0; i < 9; ++i)
- mir_free(m_modeMsgs[i]);
-
- mir_free(m_pref2_flags);
- mir_free(m_pref2_set_flags);
-
- mir_free(COOKIE);
- mir_free(MAIL_COOKIE);
- mir_free(AVATAR_COOKIE);
- mir_free(CHATNAV_COOKIE);
- mir_free(ADMIN_COOKIE);
- mir_free(m_username);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// OnModulesLoadedEx - performs hook registration
-
-int CAimProto::OnModulesLoaded(WPARAM, LPARAM)
-{
- HookProtoEvent(ME_IDLE_CHANGED, &CAimProto::OnIdleChanged);
- HookProtoEvent(ME_MSG_WINDOWEVENT, &CAimProto::OnWindowEvent);
- HookProtoEvent(ME_USERINFO_INITIALISE, &CAimProto::OnUserInfoInit);
-
- chat_register();
- InitContactMenus();
-
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// AddToList - adds a contact to the contact list
-
-MCONTACT CAimProto::AddToList(int flags, PROTOSEARCHRESULT* psr)
-{
- if (m_state != 1)
- return 0;
-
- wchar_t *id = psr->id.w ? psr->id.w : psr->nick.w;
- char *sn = psr->flags & PSR_UNICODE ? mir_u2a((wchar_t*)id) : mir_strdup((char*)id);
- MCONTACT hContact = contact_from_sn(sn, true, (flags & PALF_TEMPORARY) != 0);
- mir_free(sn);
- return hContact; //See authrequest for serverside addition
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// PSS_AUTHREQUEST
-
-int __cdecl CAimProto::AuthRequest(MCONTACT hContact, const wchar_t*)
-{
- //Not a real authrequest- only used b/c we don't know the group until now.
- if (m_state != 1)
- return 1;
-
- DBVARIANT dbv;
- if (!db_get_utf(hContact, MOD_KEY_CL, OTH_KEY_GP, &dbv) && dbv.pszVal[0]) {
- add_contact_to_group(hContact, dbv.pszVal);
- db_free(&dbv);
- }
- else add_contact_to_group(hContact, AIM_DEFAULT_GROUP);
-
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// FileAllow - starts a file transfer
-
-HANDLE __cdecl CAimProto::FileAllow(MCONTACT, HANDLE hTransfer, const wchar_t *szPath)
-{
- file_transfer *ft = (file_transfer*)hTransfer;
- if (ft && m_ft_list.find_by_ft(ft)) {
- char *path = mir_utf8encodeW(szPath);
-
- if (ft->pfts.totalFiles > 1 && ft->file[0]) {
- size_t path_len = mir_strlen(path);
- size_t len = mir_strlen(ft->file) + 2;
-
- path = (char*)mir_realloc(path, path_len + len);
- mir_snprintf(&path[path_len], len, "%s\\", ft->file);
- }
-
- mir_free(ft->file);
- ft->file = path;
-
- ForkThread(&CAimProto::accept_file_thread, ft);
- return ft;
- }
- return nullptr;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// FileCancel - cancels a file transfer
-
-int __cdecl CAimProto::FileCancel(MCONTACT, HANDLE hTransfer)
-{
- file_transfer *ft = (file_transfer*)hTransfer;
- if (!m_ft_list.find_by_ft(ft))
- return 0;
-
- debugLogA("We are cancelling a file transfer.");
-
- aim_chat_deny(m_hServerConn, m_seqno, ft->sn, ft->icbm_cookie);
-
- if (ft->hConn) {
- Netlib_Shutdown(ft->hConn);
- SetEvent(ft->hResumeEvent);
- }
- else m_ft_list.remove_by_ft(ft);
-
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// FileDeny - denies a file transfer
-
-int __cdecl CAimProto::FileDeny(MCONTACT, HANDLE hTransfer, const wchar_t* /*szReason*/)
-{
- file_transfer *ft = (file_transfer*)hTransfer;
- if (!m_ft_list.find_by_ft(ft))
- return 0;
-
- debugLogA("We are denying a file transfer.");
-
- aim_chat_deny(m_hServerConn, m_seqno, ft->sn, ft->icbm_cookie);
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// FileResume - processes file renaming etc
-
-int __cdecl CAimProto::FileResume(HANDLE hTransfer, int* action, const wchar_t** szFilename)
-{
- file_transfer *ft = (file_transfer*)hTransfer;
- if (!m_ft_list.find_by_ft(ft))
- return 0;
-
- switch (*action) {
- case FILERESUME_RESUME:
- {
- struct _stati64 statbuf;
- _wstat64(ft->pfts.tszCurrentFile, &statbuf);
- ft->pfts.currentFileProgress = statbuf.st_size;
- }
- break;
-
- case FILERESUME_RENAME:
- mir_free(ft->pfts.tszCurrentFile);
- ft->pfts.tszCurrentFile = mir_wstrdup(*szFilename);
- break;
-
- case FILERESUME_OVERWRITE:
- ft->pfts.currentFileProgress = 0;
- break;
-
- case FILERESUME_SKIP:
- mir_free(ft->pfts.tszCurrentFile);
- ft->pfts.tszCurrentFile = nullptr;
- break;
-
- default:
- aim_file_ad(m_hServerConn, m_seqno, ft->sn, ft->icbm_cookie, true, ft->max_ver);
- break;
- }
- SetEvent(ft->hResumeEvent);
-
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// GetCaps - return protocol capabilities bits
-
-DWORD_PTR __cdecl CAimProto::GetCaps(int type, MCONTACT)
-{
- switch (type) {
- case PFLAGNUM_1:
- return PF1_IM | PF1_MODEMSG | PF1_BASICSEARCH | PF1_SEARCHBYEMAIL | PF1_FILE;
-
- case PFLAGNUM_2:
- #ifdef ALLOW_BUSY
- return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_ONTHEPHONE | PF2_LIGHTDND;
- #else
- return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_ONTHEPHONE;
- #endif
-
- case PFLAGNUM_3:
- #ifdef ALLOW_BUSY
- return PF2_ONLINE | PF2_SHORTAWAY | PF2_INVISIBLE | PF2_LIGHTDND;
- #else
- return PF2_ONLINE | PF2_SHORTAWAY | PF2_INVISIBLE;
- #endif
-
- case PFLAGNUM_4:
- return PF4_SUPPORTTYPING | PF4_FORCEAUTH | PF4_NOCUSTOMAUTH | PF4_FORCEADDED |
- PF4_SUPPORTIDLE | PF4_AVATARS | PF4_IMSENDOFFLINE;
-
- case PFLAGNUM_5:
- return PF2_ONTHEPHONE;
-
- case PFLAG_MAXLENOFMESSAGE:
- return MAX_MESSAGE_LENGTH;
-
- case PFLAG_UNIQUEIDTEXT:
- return (DWORD_PTR) "Screen Name";
-
- case PFLAG_UNIQUEIDSETTING:
- return (DWORD_PTR)AIM_KEY_SN;
- }
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// SearchBasic - searches the contact by JID
-
-void __cdecl CAimProto::basic_search_ack_success(void *p)
-{
- char *sn = normalize_name((char*)p);
- if (sn) { // normalize it
- if (mir_strlen(sn) > 32)
- ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)1, 0);
- else {
- PROTOSEARCHRESULT psr = { 0 };
- psr.cbSize = sizeof(psr);
- psr.id.w = (wchar_t*)sn;
- ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)1, (LPARAM)& psr);
- ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)1, 0);
- }
- }
- mir_free(sn);
- mir_free(p);
-}
-
-HANDLE __cdecl CAimProto::SearchBasic(const wchar_t *szId)
-{
- if (m_state != 1)
- return nullptr;
-
- //duplicating the parameter so that it isn't deleted before it's needed- e.g. this function ends before it's used
- ForkThread(&CAimProto::basic_search_ack_success, mir_u2a(szId));
- return (HANDLE)1;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// SearchByEmail - searches the contact by its e-mail
-
-HANDLE __cdecl CAimProto::SearchByEmail(const wchar_t *email)
-{
- // Maximum email size should really be 320, but the char string is limited to 255.
- if (m_state != 1 || email == nullptr || mir_wstrlen(email) >= 254)
- return nullptr;
-
- char *szEmail = mir_u2a(email);
- aim_search_by_email(m_hServerConn, m_seqno, szEmail);
- mir_free(szEmail);
- return (HANDLE)1;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// RecvMsg
-
-int __cdecl CAimProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT *pre)
-{
- char *omsg = pre->szMessage;
- char *bbuf = nullptr;
- if (getByte(AIM_KEY_FI, 1)) {
- debugLogA("Converting from html to bbcodes then stripping leftover html.");
- pre->szMessage = bbuf = html_to_bbcodes(pre->szMessage);
- }
- debugLogA("Stripping html.");
- html_decode(pre->szMessage);
-
- INT_PTR res = Proto_RecvMessage(hContact, pre);
- mir_free(bbuf);
- pre->szMessage = omsg;
- return (int)res;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// SendFile - sends a file
-
-HANDLE __cdecl CAimProto::SendFile(MCONTACT hContact, const wchar_t* szDescription, wchar_t** ppszFiles)
-{
- if (m_state != 1)
- return nullptr;
-
- if (hContact && szDescription && ppszFiles) {
- DBVARIANT dbv;
- if (!getString(hContact, AIM_KEY_SN, &dbv)) {
- file_transfer *ft = new file_transfer(hContact, dbv.pszVal, nullptr);
-
- bool isDir = false;
- int count = 0;
- while (ppszFiles[count] != nullptr) {
- struct _stati64 statbuf;
- if (_wstat64(ppszFiles[count++], &statbuf) == 0) {
- if (statbuf.st_mode & _S_IFDIR) {
- if (ft->pfts.totalFiles == 0) isDir = true;
- }
- else {
- ft->pfts.totalBytes += statbuf.st_size;
- ++ft->pfts.totalFiles;
- }
- }
- }
-
- if (ft->pfts.totalFiles == 0) {
- delete ft;
- return nullptr;
- }
-
- ft->pfts.flags |= PFTS_SENDING;
- ft->pfts.ptszFiles = ppszFiles;
-
- ft->file = ft->pfts.totalFiles == 1 || isDir ? mir_utf8encodeW(ppszFiles[0]) : (char*)mir_calloc(1);
- ft->sending = true;
- ft->message = szDescription[0] ? mir_utf8encodeW(szDescription) : nullptr;
- ft->me_force_proxy = getByte(AIM_KEY_FP, 0) != 0;
- ft->requester = true;
-
- m_ft_list.insert(ft);
-
- if (ft->me_force_proxy) {
- debugLogA("We are forcing a proxy file transfer.");
- ForkThread(&CAimProto::accept_file_thread, ft);
- }
- else {
- ft->listen(this);
- aim_send_file(m_hServerConn, m_seqno, m_detected_ip, ft->local_port, false, ft);
- }
-
- db_free(&dbv);
- return ft;
- }
- }
-
- return nullptr;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// SendMessage - sends a message
-
-void __cdecl CAimProto::msg_ack_success(void* param)
-{
- msg_ack_param *msg_ack = (msg_ack_param*)param;
-
- Sleep(150);
- ProtoBroadcastAck(msg_ack->hContact, ACKTYPE_MESSAGE,
- msg_ack->success ? ACKRESULT_SUCCESS : ACKRESULT_FAILED,
- (HANDLE)msg_ack->id, (LPARAM)msg_ack->msg);
-
- mir_free(msg_ack);
-}
-
-
-int __cdecl CAimProto::SendMsg(MCONTACT hContact, int, const char* pszSrc)
-{
- if (pszSrc == nullptr)
- return 0;
-
- if (m_state != 1) {
- msg_ack_param *msg_ack = (msg_ack_param*)mir_calloc(sizeof(msg_ack_param));
- msg_ack->hContact = hContact;
- msg_ack->msg = "Message cannot be sent, when protocol offline";
- ForkThread(&CAimProto::msg_ack_success, msg_ack);
- }
-
- char *sn = getStringA(hContact, AIM_KEY_SN);
- if (sn == nullptr) {
- msg_ack_param *msg_ack = (msg_ack_param*)mir_calloc(sizeof(msg_ack_param));
- msg_ack->hContact = hContact;
- msg_ack->msg = "Screen Name for the contact not available";
- ForkThread(&CAimProto::msg_ack_success, msg_ack);
- }
-
- char *smsg = html_encode(pszSrc), *msg;
- if (getByte(AIM_KEY_FO, 1)) {
- msg = bbcodes_to_html(smsg);
- mir_free(smsg);
- }
- else msg = smsg;
-
- bool blast = getBool(hContact, AIM_KEY_BLS, false);
- int res = aim_send_message(m_hServerConn, m_seqno, sn, msg, false, blast);
-
- mir_free(msg);
- mir_free(sn);
-
- if (!res || blast || 0 == getByte(AIM_KEY_DC, 1)) {
- msg_ack_param *msg_ack = (msg_ack_param*)mir_alloc(sizeof(msg_ack_param));
- msg_ack->hContact = hContact;
- msg_ack->msg = nullptr;
- msg_ack->id = res;
- msg_ack->success = res != 0;
- ForkThread(&CAimProto::msg_ack_success, msg_ack);
- }
-
- return res;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// SetStatus - sets the protocol m_iStatus
-
-int __cdecl CAimProto::SetStatus(int iNewStatus)
-{
- switch (iNewStatus) {
- case ID_STATUS_FREECHAT:
- iNewStatus = ID_STATUS_ONLINE;
- break;
-
- case ID_STATUS_DND:
- case ID_STATUS_OCCUPIED:
- case ID_STATUS_ONTHEPHONE:
- #ifdef ALLOW_BUSY
- iNewStatus = ID_STATUS_OCCUPIED;
- break;
- #endif
-
- case ID_STATUS_OUTTOLUNCH:
- case ID_STATUS_NA:
- iNewStatus = ID_STATUS_AWAY;
- break;
- }
-
- if (iNewStatus == m_iStatus)
- return 0;
-
- if (iNewStatus == ID_STATUS_OFFLINE) {
- broadcast_status(ID_STATUS_OFFLINE);
- return 0;
- }
-
- m_iDesiredStatus = iNewStatus;
- if (m_iStatus == ID_STATUS_OFFLINE) {
- broadcast_status(ID_STATUS_CONNECTING);
- ForkThread(&CAimProto::start_connection, (void*)iNewStatus);
- }
- else if (m_iStatus > ID_STATUS_OFFLINE) {
- switch (iNewStatus) {
- case ID_STATUS_ONLINE:
- aim_set_status(m_hServerConn, m_seqno, AIM_STATUS_ONLINE);
- broadcast_status(ID_STATUS_ONLINE);
- break;
-
- case ID_STATUS_INVISIBLE:
- aim_set_status(m_hServerConn, m_seqno, AIM_STATUS_INVISIBLE);
- broadcast_status(ID_STATUS_INVISIBLE);
- break;
-
- case ID_STATUS_OCCUPIED:
- aim_set_status(m_hServerConn, m_seqno, AIM_STATUS_BUSY | AIM_STATUS_AWAY);
- broadcast_status(ID_STATUS_OCCUPIED);
- break;
-
- case ID_STATUS_AWAY:
- aim_set_status(m_hServerConn, m_seqno, AIM_STATUS_AWAY);
- broadcast_status(ID_STATUS_AWAY);
- break;
- }
- }
-
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// GetAwayMsg - returns a contact's away message
-
-void __cdecl CAimProto::get_online_msg_thread(void* arg)
-{
- Sleep(150);
-
- MCONTACT hContact = (UINT_PTR)arg;
- DBVARIANT dbv;
- if (!db_get_ws(hContact, MOD_KEY_CL, OTH_KEY_SM, &dbv)) {
- ProtoBroadcastAck(hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)dbv.ptszVal);
- db_free(&dbv);
- }
- else ProtoBroadcastAck(hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, 0);
-}
-
-HANDLE __cdecl CAimProto::GetAwayMsg(MCONTACT hContact)
-{
- if (m_state != 1)
- return nullptr;
-
- int status = getWord(hContact, AIM_KEY_ST, ID_STATUS_OFFLINE);
- switch (status) {
- case ID_STATUS_AWAY:
- case ID_STATUS_ONLINE:
- ForkThread(&CAimProto::get_online_msg_thread, (void*)hContact);
- break;
-
- default:
- return nullptr;
- }
-
- return (HANDLE)1;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// PSR_AWAYMSG
-
-int __cdecl CAimProto::RecvAwayMsg(MCONTACT hContact, int, PROTORECVEVENT* pre)
-{
- ProtoBroadcastAck(hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)pre->szMessage);
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// SetAwayMsg - sets the away m_iStatus message
-
-int __cdecl CAimProto::SetAwayMsg(int status, const wchar_t* msg)
-{
- char **msgptr = get_status_msg_loc(status);
- if (msgptr == nullptr) return 1;
-
- char *nmsg = mir_utf8encodeW(msg);
- mir_free(*msgptr); *msgptr = nmsg;
-
- switch (status) {
- case ID_STATUS_FREECHAT:
- status = ID_STATUS_ONLINE;
- break;
-
- case ID_STATUS_DND:
- case ID_STATUS_OCCUPIED:
- case ID_STATUS_ONTHEPHONE:
- #ifdef ALLOW_BUSY
- status = ID_STATUS_OCCUPIED;
- break;
- #endif
-
- case ID_STATUS_OUTTOLUNCH:
- case ID_STATUS_NA:
- status = ID_STATUS_AWAY;
- break;
- }
-
- if (m_state == 1 && status == m_iStatus) {
- if (!mir_strcmp(m_last_status_msg, nmsg))
- return 0;
-
- replaceStr(m_last_status_msg, nmsg);
- aim_set_statusmsg(m_hServerConn, m_seqno, nmsg);
- aim_set_away(m_hServerConn, m_seqno, nmsg,
- status == ID_STATUS_AWAY || status == ID_STATUS_OCCUPIED);
- }
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// UserIsTyping - sends a UTN notification
-
-int __cdecl CAimProto::UserIsTyping(MCONTACT hContact, int type)
-{
- if (m_state != 1)
- return 0;
-
- if (getWord(hContact, AIM_KEY_ST, ID_STATUS_OFFLINE) == ID_STATUS_ONTHEPHONE)
- return 0;
-
- DBVARIANT dbv;
- if (!getBool(hContact, AIM_KEY_BLS, false) && !getString(hContact, AIM_KEY_SN, &dbv)) {
- if (type == PROTOTYPE_SELFTYPING_ON)
- aim_typing_notification(m_hServerConn, m_seqno, dbv.pszVal, 0x0002);
- else if (type == PROTOTYPE_SELFTYPING_OFF)
- aim_typing_notification(m_hServerConn, m_seqno, dbv.pszVal, 0x0000);
- db_free(&dbv);
- }
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// OnEvent - maintain protocol events
-
-int __cdecl CAimProto::OnEvent(PROTOEVENTTYPE eventType, WPARAM wParam, LPARAM lParam)
-{
- switch (eventType) {
- case EV_PROTO_ONLOAD:
- return OnModulesLoaded(0, 0);
-
- case EV_PROTO_ONMENU:
- InitMainMenus();
- break;
-
- case EV_PROTO_ONOPTIONS:
- return OnOptionsInit(wParam, lParam);
-
- case EV_PROTO_ONERASE:
- char szDbsettings[64];
- mir_snprintf(szDbsettings, "%sP2P", m_szModuleName);
- db_delete_module(0, szDbsettings);
- break;
-
- case EV_PROTO_ONCONTACTDELETED:
- return OnContactDeleted(wParam, lParam);
-
- case EV_PROTO_DBSETTINGSCHANGED:
- return OnDbSettingChanged(wParam, lParam);
- }
- return 1;
-}
diff --git a/protocols/AimOscar/src/proto.h b/protocols/AimOscar/src/proto.h
deleted file mode 100755
index da05270f3d..0000000000
--- a/protocols/AimOscar/src/proto.h
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2012 Boris Krasnovskiy
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _AIM_PROTO_H_
-#define _AIM_PROTO_H_
-
-struct CAimProto : public PROTO<CAimProto>
-{
- CAimProto(const char*, const wchar_t*);
- ~CAimProto();
-
- //====================================================================================
- // PROTO_INTERFACE
- //====================================================================================
-
- virtual MCONTACT __cdecl AddToList( int flags, PROTOSEARCHRESULT* psr );
-
- virtual int __cdecl AuthRequest(MCONTACT hContact, const wchar_t* szMessage );
-
- virtual HANDLE __cdecl FileAllow(MCONTACT hContact, HANDLE hTransfer, const wchar_t* szPath );
- virtual int __cdecl FileCancel(MCONTACT hContact, HANDLE hTransfer );
- virtual int __cdecl FileDeny(MCONTACT hContact, HANDLE hTransfer, const wchar_t* szReason );
- virtual int __cdecl FileResume( HANDLE hTransfer, int* action, const wchar_t** szFilename );
-
- virtual DWORD_PTR __cdecl GetCaps( int type, MCONTACT hContact = NULL );
-
- virtual HANDLE __cdecl SearchBasic( const wchar_t* id );
- virtual HANDLE __cdecl SearchByEmail( const wchar_t* email );
-
- virtual int __cdecl RecvMsg(MCONTACT hContact, PROTORECVEVENT* );
-
- virtual HANDLE __cdecl SendFile(MCONTACT hContact, const wchar_t* szDescription, wchar_t** ppszFiles);
- virtual int __cdecl SendMsg(MCONTACT hContact, int flags, const char* msg );
-
- virtual int __cdecl SetStatus( int iNewStatus );
-
- virtual HANDLE __cdecl GetAwayMsg(MCONTACT hContact );
- virtual int __cdecl RecvAwayMsg(MCONTACT hContact, int mode, PROTORECVEVENT* evt );
- virtual int __cdecl SetAwayMsg( int m_iStatus, const wchar_t* msg );
-
- virtual int __cdecl UserIsTyping(MCONTACT hContact, int type );
-
- virtual int __cdecl OnEvent( PROTOEVENTTYPE eventType, WPARAM wParam, LPARAM lParam );
-
- //====| Services |====================================================================
- INT_PTR __cdecl SvcCreateAccMgrUI(WPARAM wParam, LPARAM lParam);
-
- INT_PTR __cdecl GetAvatarInfo(WPARAM wParam, LPARAM lParam);
- INT_PTR __cdecl GetMyAwayMsg(WPARAM wParam,LPARAM lParam);
-
- INT_PTR __cdecl GetAvatar(WPARAM wParam, LPARAM lParam);
- INT_PTR __cdecl SetAvatar(WPARAM wParam, LPARAM lParam);
- INT_PTR __cdecl GetAvatarCaps(WPARAM wParam, LPARAM lParam);
-
- INT_PTR __cdecl ManageAccount(WPARAM wParam, LPARAM lParam);
- INT_PTR __cdecl InstantIdle(WPARAM wParam, LPARAM lParam);
- INT_PTR __cdecl JoinChatUI(WPARAM wParam, LPARAM lParam);
- INT_PTR __cdecl GetHTMLAwayMsg(WPARAM wParam, LPARAM lParam);
- INT_PTR __cdecl GetProfile(WPARAM wParam, LPARAM lParam);
- INT_PTR __cdecl EditProfile(WPARAM wParam, LPARAM lParam);
- INT_PTR __cdecl AddToServerList(WPARAM wParam, LPARAM lParam);
- INT_PTR __cdecl BlockBuddy(WPARAM wParam, LPARAM lParam);
-
- INT_PTR __cdecl OnJoinChat(WPARAM wParam, LPARAM lParam);
- INT_PTR __cdecl OnLeaveChat(WPARAM wParam, LPARAM lParam);
-
- //====| Events |======================================================================
- int __cdecl OnContactDeleted(WPARAM wParam,LPARAM lParam);
- int __cdecl OnGroupChange(WPARAM wParam,LPARAM lParam);
- int __cdecl OnIdleChanged(WPARAM wParam, LPARAM lParam);
- int __cdecl OnWindowEvent(WPARAM wParam, LPARAM lParam);
- int __cdecl OnModulesLoaded( WPARAM wParam, LPARAM lParam );
- int __cdecl OnOptionsInit(WPARAM wParam,LPARAM lParam);
- int __cdecl OnPreBuildContactMenu(WPARAM wParam,LPARAM lParam);
-// int __cdecl OnPreShutdown(WPARAM wParam,LPARAM lParam);
- int __cdecl OnDbSettingChanged(WPARAM wParam,LPARAM lParam);
- int __cdecl OnUserInfoInit(WPARAM wParam,LPARAM lParam);
- int __cdecl OnGCEvent(WPARAM wParam,LPARAM lParam);
- int __cdecl OnGCMenuHook(WPARAM wParam,LPARAM lParam);
-
- //====| Data |========================================================================
- mir_cs SendingMutex;
- mir_cs connMutex;
-
- char* COOKIE;
- int COOKIE_LENGTH;
- char* MAIL_COOKIE;
- int MAIL_COOKIE_LENGTH;
- char* AVATAR_COOKIE;
- int AVATAR_COOKIE_LENGTH;
- char* CHATNAV_COOKIE;
- int CHATNAV_COOKIE_LENGTH;
- char* ADMIN_COOKIE;
- int ADMIN_COOKIE_LENGTH;
-
- char *m_username;
- unsigned short m_seqno;//main connection sequence number
- int m_state;//m_iStatus of the connection; e.g. whether connected or not
- unsigned short m_port;
-
- //Some bools to keep track of different things
- bool m_request_HTML_profile;
- bool m_request_away_message;
- bool m_extra_icons_loaded;
- bool m_idle;
- bool m_instantidle;
- bool m_list_received;
-
- //Some main connection stuff
- HNETLIBCONN m_hServerConn; // handle to the main connection
-
- unsigned long m_internal_ip; // our ip
- unsigned long m_detected_ip; // our ip
- unsigned short m_local_port; // our port
-
- //Peer connection stuff
- HNETLIBUSER m_hNetlibPeer;//handle to the peer netlib
- HANDLE m_hDirectBoundPort;//direct connection listening port
-
- //Handles for the context menu items
- HGENMENU m_hHTMLAwayContextMenuItem;
- HGENMENU m_hAddToServerListContextMenuItem;
- HGENMENU m_hBlockContextMenuItem;
- HGENMENU m_hMainMenu[3];
-
- //Some mail connection stuff
- HNETLIBCONN m_hMailConn;
- unsigned short m_mail_seqno;
-
- //avatar connection stuff
- unsigned short m_avatar_seqno;
- unsigned short m_avatar_id_sm;
- unsigned short m_avatar_id_lg;
- HNETLIBCONN m_hAvatarConn;
- HANDLE m_hAvatarEvent;
-
- ft_list_type m_ft_list;
-
- //chatnav connection stuff
- unsigned short m_chatnav_seqno;
- HNETLIBCONN m_hChatNavConn;
- HANDLE m_hChatNavEvent;
- char MAX_ROOMS;
-
- OBJLIST<chat_list_item> m_chat_rooms;
-
- //admin connection stuff
- unsigned short m_admin_seqno;
- HNETLIBCONN m_hAdminConn;
- HANDLE m_hAdminEvent;
-
- // privacy settings
- unsigned long m_pd_flags;
- unsigned short m_pd_info_id;
- char m_pd_mode;
-
- // prefernces
- unsigned short m_pref1_id;
- unsigned long m_pref1_flags;
- unsigned long m_pref1_set_flags;
- unsigned long m_pref2_len;
- unsigned long m_pref2_set_len;
- char *m_pref2_flags;
- char *m_pref2_set_flags;
-
- BdList m_allow_list;
- BdList m_block_list;
- BdList m_group_list;
-
- //away message retrieval stuff
- char *m_modeMsgs[9];
- char *m_last_status_msg;
-
- //////////////////////////////////////////////////////////////////////////////////////
- // avatars.cpp
-
- char *m_hash_sm, *m_hash_lg;
-
- void __cdecl avatar_request_thread( void* param );
- void __cdecl avatar_upload_thread( void* param );
-
- void avatar_request_handler(MCONTACT hContact, char* hash, unsigned char type);
- void avatar_retrieval_handler(const char* sn, const char* hash, const char* data, int data_len);
- int get_avatar_filename(MCONTACT hContact, wchar_t* pszDest, size_t cbLen, const wchar_t *ext);
-
- //////////////////////////////////////////////////////////////////////////////////////
- // away.cpp
-
- void __cdecl get_online_msg_thread( void* arg );
-
- int aim_set_away(HNETLIBCONN hServerConn, unsigned short &seqno, const char *msg, bool set);//user info
- int aim_set_statusmsg(HNETLIBCONN hServerConn,unsigned short &seqno,const char *msg);//user info
- int aim_set_status(HNETLIBCONN hServerConn,unsigned short &seqno,unsigned long status_type);
- int aim_query_away_message(HNETLIBCONN hServerConn,unsigned short &seqno,const char* sn);
-
- char** get_status_msg_loc(int status);
-
- //////////////////////////////////////////////////////////////////////////////////////
- // chat.cpp
-
- void __cdecl chatnav_request_thread( void* param );
-
- void chat_register(void);
- void chat_start(const char* id, unsigned short exchange);
- void chat_event(const char* id, const char* sn, int evt, const wchar_t* msg = NULL);
- void chat_leave(const char* id);
-
- chat_list_item* find_chat_by_cid(unsigned short cid);
- chat_list_item* find_chat_by_id(char* id);
- chat_list_item* find_chat_by_conn(HANDLE conn);
- void remove_chat_by_ptr(chat_list_item* item);
- void shutdown_chat_conn(void);
- void close_chat_conn(void);
-
- //////////////////////////////////////////////////////////////////////////////////////
- // client.cpp
-
- int aim_send_connection_packet(HNETLIBCONN hServerConn, unsigned short &seqno, char *buf);
- int aim_authkey_request(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_auth_request(HNETLIBCONN hServerConn, unsigned short &seqno, const char* key, const char* language, const char* country, const char* username, const char* password);
- int aim_send_cookie(HNETLIBCONN hServerConn, unsigned short &seqno, int cookie_size, char * cookie);
- int aim_send_service_request(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_new_service_request(HNETLIBCONN hServerConn, unsigned short &seqno, unsigned short service);
- int aim_request_rates(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_request_icbm(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_request_offline_msgs(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_set_icbm(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_set_profile(HNETLIBCONN hServerConn, unsigned short &seqno, char* amsg);//user info
- int aim_request_list(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_activate_list(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_accept_rates(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_set_caps(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_client_ready(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_mail_ready(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_avatar_ready(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_chatnav_ready(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_chat_ready(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_send_message(HNETLIBCONN hServerConn, unsigned short &seqno, const char* sn, char* amsg, bool auto_response, bool blast);
- int aim_query_profile(HNETLIBCONN hServerConn, unsigned short &seqno, char* sn);
- int aim_delete_contact(HNETLIBCONN hServerConn, unsigned short &seqno, char* sn, unsigned short item_id, unsigned short group_id, unsigned short list, bool nil);
- int aim_add_contact(HNETLIBCONN hServerConn, unsigned short &seqno, const char* sn, unsigned short item_id, unsigned short group_id, unsigned short list, char* nick = NULL, char* note = NULL);
- int aim_mod_group(HNETLIBCONN hServerConn, unsigned short &seqno, const char* name, unsigned short group_id, char* members, unsigned short members_length);
- int aim_mod_buddy(HNETLIBCONN hServerConn, unsigned short &seqno, const char* sn, unsigned short buddy_id, unsigned short group_id, char* nick, char* note);
- int aim_ssi_update(HNETLIBCONN hServerConn, unsigned short &seqno, bool start);
- int aim_ssi_update_preferences(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_keepalive(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_send_file(HNETLIBCONN hServerConn, unsigned short &seqno, unsigned long ip, unsigned short port, bool force_proxy, file_transfer *ft);//used when requesting a regular file transfer
- int aim_file_ad(HNETLIBCONN hServerConn, unsigned short &seqno, char* sn, char* icbm_cookie, bool deny, unsigned short max_ver);
- int aim_typing_notification(HNETLIBCONN hServerConn, unsigned short &seqno, char* sn, unsigned short type);
- int aim_set_idle(HNETLIBCONN hServerConn, unsigned short &seqno, unsigned long seconds);
- int aim_request_mail(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_activate_mail(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_request_avatar(HNETLIBCONN hServerConn, unsigned short &seqno, const char* sn, unsigned short bart_type, const char* hash, unsigned short hash_size);//family 0x0010
- int aim_set_avatar_hash(HNETLIBCONN hServerConn, unsigned short &seqno, char flags, unsigned short bart_type, unsigned short &id, char size, const char* hash);
- int aim_delete_avatar_hash(HNETLIBCONN hServerConn, unsigned short &seqno, char flags, unsigned short bart_type, unsigned short &id);
- int aim_upload_avatar(HNETLIBCONN hServerConn, unsigned short &seqno, unsigned short bart_type, const char* avatar, unsigned short avatar_size);
- int aim_search_by_email(HNETLIBCONN hServerConn, unsigned short &seqno, const char* email);
- int aim_set_pd_info(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_block_buddy(HNETLIBCONN hServerConn, unsigned short &seqno, bool remove, const char* sn, unsigned short item_id);
- int aim_chatnav_request_limits(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_chatnav_create(HNETLIBCONN hServerConn, unsigned short &seqno, char* room, unsigned short exchage);
- int aim_chatnav_room_info(HNETLIBCONN hServerConn, unsigned short &seqno, char* chat_cookie, unsigned short exchange, unsigned short instance);
- int aim_chat_join_room(HNETLIBCONN hServerConn, unsigned short &seqno, char* chat_cookie, unsigned short exchange, unsigned short instance, unsigned short id);
- int aim_chat_send_message(HNETLIBCONN hServerConn, unsigned short &seqno, char *amsg);
- int aim_chat_invite(HNETLIBCONN hServerConn, unsigned short &seqno, char* chat_cookie, unsigned short exchange, unsigned short instance, char* sn, char* msg);
- int aim_chat_deny(HNETLIBCONN hServerConn, unsigned short &seqno, char* sn, char* icbm_cookie);
- int aim_admin_ready(HNETLIBCONN hServerConn, unsigned short &seqno);
- int aim_admin_format_name(HNETLIBCONN hServerConn, unsigned short &seqno, const char* sn);
- int aim_admin_change_password(HNETLIBCONN hServerConn, unsigned short &seqno, const char* cur_pw, const char* new_pw);
- int aim_admin_change_email(HNETLIBCONN hServerConn, unsigned short &seqno, const char* email);
- int aim_admin_request_info(HNETLIBCONN hServerConn, unsigned short &seqno, const unsigned short &type);
- int aim_admin_account_confirm(HNETLIBCONN hServerConn, unsigned short &seqno);
-
- //////////////////////////////////////////////////////////////////////////////////////
- // connection.cpp
-
- void aim_connection_authorization(void);
- void aim_connection_clientlogin(void);
-
- void __cdecl aim_protocol_negotiation(void*);
- void __cdecl aim_mail_negotiation(void*);
- void __cdecl aim_avatar_negotiation(void*);
- void __cdecl aim_chatnav_negotiation(void*);
- void __cdecl aim_chat_negotiation(void*);
- void __cdecl aim_admin_negotiation(void*);
-
- HNETLIBCONN aim_connect(const char* server, unsigned short port, bool use_ssl, const char* host = NULL);
- HNETLIBCONN aim_peer_connect(const char* ip, unsigned short port);
- HNETLIBCONN aim_peer_connect(unsigned long ip, unsigned short port);
-
- //////////////////////////////////////////////////////////////////////////////////////
- // direct_connect.cpp
-
- void __cdecl aim_dc_helper( void* );
-
- //////////////////////////////////////////////////////////////////////////////////////
- // error.cpp
-
- void login_error(unsigned short error);
- void get_error(unsigned short error);
- void admin_error(unsigned short error);
-
- //////////////////////////////////////////////////////////////////////////////////////
- // file.cpp
-
- int sending_file(file_transfer *ft, HANDLE hServerPacketRecver, NETLIBPACKETRECVER &packetRecv);
- int receiving_file(file_transfer *ft, HANDLE hServerPacketRecver, NETLIBPACKETRECVER &packetRecv);
- void report_file_error(wchar_t* fname);
- void shutdown_file_transfers(void);
-
- //////////////////////////////////////////////////////////////////////////////////////
- // packets.cpp
-
- int aim_sendflap(HNETLIBCONN conn, char type, unsigned short length, const char *buf, unsigned short &seqno);
-
- //////////////////////////////////////////////////////////////////////////////////////
- // proto.cpp
-
- void __cdecl basic_search_ack_success( void* p );
- void __cdecl email_search_ack_success( void* p );
-
- //////////////////////////////////////////////////////////////////////////////////////
- // proxy.cpp
-
- void __cdecl aim_proxy_helper( void* );
-
- //////////////////////////////////////////////////////////////////////////////////////
- // server.cpp
-
- void snac_md5_authkey(SNAC &snac,HNETLIBCONN hServerConn,unsigned short &seqno, const char* username, const char* password);
- int snac_authorization_reply(SNAC &snac);
- void snac_supported_families(SNAC &snac, HNETLIBCONN hServerConn,unsigned short &seqno);
- void snac_supported_family_versions(SNAC &snac,HNETLIBCONN hServerConn,unsigned short &seqno);//family 0x0001
- void snac_rate_limitations(SNAC &snac,HNETLIBCONN hServerConn,unsigned short &seqno);//family 0x0001
- void snac_mail_rate_limitations(SNAC &snac,HNETLIBCONN hServerConn,unsigned short &seqno);// family 0x0001
- void snac_avatar_rate_limitations(SNAC &snac,HNETLIBCONN hServerConn,unsigned short &seqno);// family 0x0001
- void snac_chatnav_rate_limitations(SNAC &snac,HNETLIBCONN hServerConn,unsigned short &seqno);// family 0x0001
- void snac_chat_rate_limitations(SNAC &snac,HNETLIBCONN hServerConn,unsigned short &seqno);// family 0x0001
- void snac_admin_rate_limitations(SNAC &snac,HNETLIBCONN hServerConn,unsigned short &seqno);// family 0x0001
- void snac_service_redirect(SNAC &snac);// family 0x0001
- void snac_self_info(SNAC &snac);//family 0x0001
- void snac_icbm_limitations(SNAC &snac,HNETLIBCONN hServerConn,unsigned short &seqno);//family 0x0004
- void snac_user_online(SNAC &snac);
- void snac_user_offline(SNAC &snac);
- void snac_error(SNAC &snac);//family 0x0003 or x0004
- void snac_contact_list(SNAC &snac,HNETLIBCONN hServerConn,unsigned short &seqno);
- void snac_message_accepted(SNAC &snac);//family 0x004
- void snac_received_message(SNAC &snac,HNETLIBCONN hServerConn,unsigned short &seqno);//family 0x0004
- void snac_file_decline(SNAC &snac);//family 0x0004
- void snac_received_info(SNAC &snac);//family 0x0002
- void snac_typing_notification(SNAC &snac);//family 0x004
- void snac_list_modification_ack(SNAC &snac);//family 0x0013
- void snac_mail_response(SNAC &snac);//family 0x0018
- void snac_retrieve_avatar(SNAC &snac);//family 0x0010
- void snac_upload_reply_avatar(SNAC &snac);//family 0x0010
- void snac_email_search_results(SNAC &snac);//family 0x000A
- void snac_chatnav_info_response(SNAC &snac,HNETLIBCONN hServerConn,unsigned short &seqno);//family 0x000D
- void snac_chat_joined_left_users(SNAC &snac,chat_list_item* item);//family 0x000E
- void snac_chat_received_message(SNAC &snac,chat_list_item* item);//family 0x000E
- void snac_admin_account_infomod(SNAC &snac);//family 0x0007
- void snac_admin_account_confirm(SNAC &snac);//family 0x0007
-
- void process_ssi_list(SNAC &snac, int &offset);
- void modify_ssi_list(SNAC &snac, int &offset);
- void delete_ssi_list(SNAC &snac, int &offset);
-
- //////////////////////////////////////////////////////////////////////////////////////
- // themes.cpp
-
- void InitMainMenus(void);
- void InitContactMenus(void);
-
- //////////////////////////////////////////////////////////////////////////////////////
- // thread.cpp
-
- void __cdecl accept_file_thread( void* );
-
- //////////////////////////////////////////////////////////////////////////////////////
- // utilities.cpp
-
- struct msg_ack_param { MCONTACT hContact; const char *msg; int id; bool success; };
-
- void __cdecl msg_ack_success(void*);
- void __cdecl start_connection(void*);
-
- MCONTACT find_chat_contact(const char * room);
- MCONTACT contact_from_sn(const char* sn, bool addIfNeeded = false, bool temporary = false);
-
- void broadcast_status(int status);
- bool wait_conn(HNETLIBCONN& hConn, HANDLE& hEvent, unsigned short service);
- bool is_my_contact(MCONTACT hContact);
- void add_contact_to_group(MCONTACT hContact, const char* group);
- void set_local_nick(MCONTACT hContact, char* nick, char* note);
- void upload_nicks(void);
- void update_server_group(const char* group, unsigned short group_id);
- void offline_contacts(void);
- void offline_contact(MCONTACT hContact, bool remove_settings);
- unsigned short get_default_port(void);
-
- int open_contact_file(const char* sn, const wchar_t* file, const char* mode, wchar_t* &path, bool contact_dir);
- void write_away_message(const char* sn, const char* msg, bool utf);
- void write_profile(const char* sn, const char* msg, bool utf);
-
- unsigned short getBuddyId(MCONTACT hContact, int i);
- unsigned short getGroupId(MCONTACT hContact, int i);
- void setBuddyId(MCONTACT hContact, int i, unsigned short id);
- void setGroupId(MCONTACT hContact, int i, unsigned short id);
- int deleteBuddyId(MCONTACT hContact, int i);
- int deleteGroupId(MCONTACT hContact, int i);
-
- unsigned short search_for_free_item_id(MCONTACT hbuddy);
- unsigned short* get_members_of_group(unsigned short group_id, unsigned short& size);
-
- void ShowPopup( const char* msg, int flags, char* url = 0 );
-};
-
-#endif
diff --git a/protocols/AimOscar/src/proxy.cpp b/protocols/AimOscar/src/proxy.cpp
deleted file mode 100644
index 2b7fdb0f77..0000000000
--- a/protocols/AimOscar/src/proxy.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#include "stdafx.h"
-
-void __cdecl CAimProto::aim_proxy_helper(void* param)
-{
- file_transfer *ft = (file_transfer*)param;
-
- if (ft->requester)
- {
- if (proxy_initialize_send(ft->hConn, m_username, ft->icbm_cookie))
- return;//error
- }
- else
- {
- if (proxy_initialize_recv(ft->hConn, m_username, ft->icbm_cookie, ft->port))
- return;//error
- }
-
- //start listen for packets stuff
- NETLIBPACKETRECVER packetRecv = {};
- packetRecv.dwTimeout = INFINITE;
-
- HANDLE hServerPacketRecver = Netlib_CreatePacketReceiver(ft->hConn, 2048 * 4);
- for (;;)
- {
- int recvResult = Netlib_GetMorePackets(hServerPacketRecver, &packetRecv);
- if (recvResult == 0)
- {
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
- break;
- }
- if (recvResult == SOCKET_ERROR)
- {
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
- break;
- }
- if (recvResult > 0)
- {
- unsigned short length = _htons(*(unsigned short*)&packetRecv.buffer[0]);
- packetRecv.bytesUsed = length + 2;
- unsigned short type = _htons(*(unsigned short*)&packetRecv.buffer[4]);
- if (type == 0x0001)
- {
- unsigned short error = _htons(*(unsigned short*)&packetRecv.buffer[12]);
- switch (error)
- {
- case 0x000D:
- ShowPopup("Proxy Server File Transfer Error: Bad Request.", ERROR_POPUP);
- break;
-
- case 0x0010:
- ShowPopup("Proxy Server File Transfer Error: Initial Request Timed Out.", ERROR_POPUP);
- break;
-
- case 0x001A:
- ShowPopup("Proxy Server File Transfer Error: Accept Period Timed Out.", ERROR_POPUP);
- break;
-
- case 0x000e:
- ShowPopup("Proxy Server File Transfer Error: Incorrect command syntax.", ERROR_POPUP);
- break;
-
- case 0x0016:
- ShowPopup("Proxy Server File Transfer Error: Unknown command issued.", ERROR_POPUP);
- break;
- }
-
- }
- else if (type == 0x0003)
- {
- unsigned short port = _htons(*(unsigned short*)&packetRecv.buffer[12]);
- unsigned long ip = _htonl(*(unsigned long*)&packetRecv.buffer[14]);
-
- aim_send_file(m_hServerConn, m_seqno, ip, port, true, ft);
- debugLogA("Stage %d Proxy ft and we are not the sender.", ft->req_num);
- }
- else if (type == 0x0005)
- {
- if (!ft->requester)
- {
- aim_file_ad(m_hServerConn, m_seqno, ft->sn, ft->icbm_cookie, false, ft->max_ver);
- ft->accepted = true;
- }
-
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, ft, 0);
-
- int i;
- for (i = 21; --i; )
- {
- if (Miranda_IsTerminated()) return;
- Sleep(100);
- if (ft->accepted) break;
- }
- if (i == 0)
- {
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
- break;
- }
-
- packetRecv.dwTimeout = 350000;
-
- int result;
- if (ft->sending)//we are sending
- result = sending_file(ft, hServerPacketRecver, packetRecv);
- else
- result = receiving_file(ft, hServerPacketRecver, packetRecv);
-
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, result ? ACKRESULT_FAILED : ACKRESULT_SUCCESS, ft, 0);
- break;
- }
- }
- }
- Netlib_CloseHandle(hServerPacketRecver);
- Netlib_CloseHandle(ft->hConn);
-
- m_ft_list.remove_by_ft(ft);
-}
-
-
-int proxy_initialize_send(HNETLIBCONN connection, char* sn, char* cookie)
-{
- const char sn_length = (char)mir_strlen(sn);
- const int len = sn_length + 21 + TLV_HEADER_SIZE + AIM_CAPS_LENGTH;
-
- char* buf= (char*)alloca(len);
- unsigned short offset=0;
-
- aim_writeshort(len-2, offset, buf);
- aim_writegeneric(10, "\x04\x4a\0\x02\0\0\0\0\0\0", offset, buf);
- aim_writechar((unsigned char)sn_length, offset, buf); // screen name len
- aim_writegeneric(sn_length, sn, offset, buf); // screen name
- aim_writegeneric(8, cookie, offset, buf); // icbm cookie
- aim_writetlv(1, AIM_CAPS_LENGTH, AIM_CAP_FILE_TRANSFER, offset, buf);
-
- return Netlib_Send(connection, buf, offset, 0) >= 0 ? 0 : -1;
-}
-
-int proxy_initialize_recv(HNETLIBCONN connection, char* sn, char* cookie, unsigned short port_check)
-{
- const char sn_length = (char)mir_strlen(sn);
- const int len = sn_length + 23 + TLV_HEADER_SIZE + AIM_CAPS_LENGTH;
-
- char* buf= (char*)alloca(len);
- unsigned short offset=0;
-
- aim_writeshort(len-2, offset, buf);
- aim_writegeneric(10, "\x04\x4a\0\x04\0\0\0\0\0\0", offset, buf);
- aim_writechar((unsigned char)sn_length, offset, buf); // screen name len
- aim_writegeneric(sn_length, sn, offset, buf); // screen name
- aim_writeshort(port_check, offset, buf);
- aim_writegeneric(8, cookie, offset, buf); // icbm cookie
- aim_writetlv(1, AIM_CAPS_LENGTH, AIM_CAP_FILE_TRANSFER, offset, buf);
-
- return Netlib_Send(connection, buf, offset, 0) >= 0 ? 0 : -1;
-}
diff --git a/protocols/AimOscar/src/proxy.h b/protocols/AimOscar/src/proxy.h
deleted file mode 100644
index 83a03e2d0d..0000000000
--- a/protocols/AimOscar/src/proxy.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef PROXY_H
-#define PROXY_H
-
-int proxy_initialize_send(HNETLIBCONN connection, char* sn, char* cookie);
-int proxy_initialize_recv(HNETLIBCONN connection, char* sn, char* cookie, unsigned short port_check);
-
-#endif
diff --git a/protocols/AimOscar/src/resource.h b/protocols/AimOscar/src/resource.h
deleted file mode 100755
index c123194d8e..0000000000
--- a/protocols/AimOscar/src/resource.h
+++ /dev/null
@@ -1,125 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by X:\install\git\miranda\miranda_ng_svn\protocols\AimOscar\res\aim.rc
-//
-#define IDC_SAVECHANGES 3
-#define IDC_CONFIRM 4
-#define IDD_INFO 6
-#define IDD_AIMACCOUNT 7
-#define IDD_AIM 8
-#define IDD_IDLE 9
-#define IDI_AIM 10
-#define IDI_ICQ 11
-#define IDI_ADD 12
-#define IDI_PROFILE 13
-#define IDI_MAIL 14
-#define IDI_HIPTOP 21
-#define IDI_BOT 22
-#define IDI_ADMIN 23
-#define IDI_CONFIRMED 24
-#define IDI_UNCONFIRMED 25
-#define IDI_AWAY 26
-#define IDI_IDLE 27
-#define IDI_AOL 28
-#define IDI_FOREGROUNDCOLOR 31
-#define IDI_BACKGROUNDCOLOR 32
-#define IDD_PRIVACY 36
-#define IDD_CHAT 37
-#define IDI_BLOCK 38
-#define IDD_ADMIN 39
-#define IDD_CHATROOM_INVITE 40
-#define IDI_BOLD 41
-#define IDD_CHATROOM_INVITE_REQ 41
-#define IDI_NBOLD 42
-#define IDI_ITALIC 43
-#define IDI_NITALIC 44
-#define IDI_UNDERLINE 45
-#define IDI_NUNDERLINE 46
-#define IDI_SUBSCRIPT 53
-#define IDI_NSUBSCRIPT 54
-#define IDI_SUPERSCRIPT 55
-#define IDI_NSUPERSCRIPT 56
-#define IDI_NORMALSCRIPT 57
-#define IDI_NNORMALSCRIPT 58
-#define IDC_DETAILS 125
-#define IDC_OPTIONS 126
-#define IDC_EXPERT 127
-#define IDC_BOLD 129
-#define IDC_ITALIC 130
-#define IDC_UNDERLINE 131
-#define IDC_SUPERSCRIPT 132
-#define IDC_SUBSCRIPT 133
-#define IDC_NORMALSCRIPT 134
-#define IDC_FOREGROUNDCOLORPICKER 135
-#define IDC_FOREGROUNDCOLOR 136
-#define IDC_BACKGROUNDCOLORPICKER 137
-#define IDC_BACKGROUNDCOLOR 138
-#define IDC_TYPEFACE 139
-#define IDC_FONTSIZE 141
-#define IDC_SVRRESET 142
-#define IDC_NEWAIMACCOUNTLINK 143
-#define IDC_ALLOWALL 144
-#define IDC_ALLOWCONT 145
-#define IDC_ALLOWBELOW 146
-#define IDC_BLOCKALL 147
-#define IDC_BLOCKBELOW 148
-#define IDC_ALLOWLIST 149
-#define IDC_BLOCKLIST 150
-#define IDC_ALLOWEDIT 151
-#define IDC_ALLOWADD 152
-#define IDC_BLOCKEDIT 153
-#define IDC_BLOCKADD 154
-#define IDC_ALLOWREMOVE 155
-#define IDC_BLOCKREMOVE 156
-#define IDC_ROOM 157
-#define IDC_CEMAIL 158
-#define IDC_MSG 158
-#define IDC_FNAME 159
-#define IDC_NPW1 161
-#define IDC_NPW2 162
-#define IDC_CPW 164
-#define IDC_PINFO 165
-#define IDC_SCREENNAME 169
-#define IDC_CCLIST 173
-#define IDC_EDITSCR 174
-#define IDC_ADDSCR 175
-#define IDC_ROOMNAME 176
-#define IDC_CHECK1 178
-#define IDC_CLIENTLOGIN 178
-#define IDC_SN 1030
-#define IDC_NK 1040
-#define IDC_PW 1050
-#define IDC_HN 1060
-#define IDC_PN 1061
-#define IDC_DM 1100
-#define IDC_DC 1110
-#define IDC_FP 1120
-#define IDC_AT 1130
-#define IDC_ES 1140
-#define IDC_FI 1150
-#define IDC_FO 1160
-#define IDC_DA 1161
-#define IDC_DSSL 1162
-#define IDC_FSC 1163
-#define IDC_HF 1170
-#define IDC_SIS 1171
-#define IDC_MASQ 1180
-#define IDC_CM 1191
-#define IDC_MG 1192
-#define IDC_SETPROFILE 1200
-#define IDC_II 1210
-#define IDC_PROFILE 1220
-#define IDC_IIM 1230
-#define IDC_IIH 1240
-#define IDC_STATIC -1
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 41
-#define _APS_NEXT_COMMAND_VALUE 40002
-#define _APS_NEXT_CONTROL_VALUE 179
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
diff --git a/protocols/AimOscar/src/server.cpp b/protocols/AimOscar/src/server.cpp
deleted file mode 100644
index 96038aa8d1..0000000000
--- a/protocols/AimOscar/src/server.cpp
+++ /dev/null
@@ -1,1994 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2012 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-void CAimProto::snac_md5_authkey(SNAC &snac, HNETLIBCONN hServerConn, unsigned short &seqno, const char* username, const char* password)//family 0x0017
-{
- if (snac.subcmp(0x0007))//md5 authkey string
- {
- unsigned short length = snac.ushort();
- char* authkey = snac.part(2, length);
- aim_auth_request(hServerConn, seqno, authkey, AIM_LANGUAGE, AIM_COUNTRY, username, password);
- mir_free(authkey);
- }
-}
-
-int CAimProto::snac_authorization_reply(SNAC &snac)//family 0x0017
-{
- int res = 0;
-
- if (snac.subcmp(0x0003)) {
- char* server = nullptr;
- int address = 0;
- unsigned short port;
- unsigned char use_ssl = 0;
-
- while (address < snac.len()) {
- TLV tlv(snac.val(address));
- if (tlv.cmp(0x0005))
- server = tlv.dup();
- else if (tlv.cmp(0x0006)) {
- Netlib_CloseHandle(m_hServerConn);
-
- if (server == nullptr) return 3;
- char* delim = strchr(server, ':');
- port = delim ? (unsigned short)atoi(delim + 1) : get_default_port();
- if (delim) *delim = 0;
-
- m_hServerConn = aim_connect(server, port, use_ssl != 0, "bos.oscar.aol.com");
- if (m_hServerConn) {
- mir_free(COOKIE);
- COOKIE_LENGTH = tlv.len();
- COOKIE = tlv.dup();
- ForkThread(&CAimProto::aim_protocol_negotiation, nullptr);
- res = 1;
- }
- else
- res = 3;
- break;
- }
- else if (tlv.cmp(0x0008)) {
- login_error(tlv.ushort());
- res = 2;
- break;
- }
- else if (tlv.cmp(0x0011)) {
- char* email = tlv.dup();
- setString(AIM_KEY_EM, email);
- mir_free(email);
- }
- else if (tlv.cmp(0x008e)) {
- use_ssl = tlv.ubyte();
- }
- address += tlv.len() + 4;
- }
- mir_free(server);
- }
- return res;
-}
-void CAimProto::snac_supported_families(SNAC &snac, HNETLIBCONN hServerConn, unsigned short &seqno)//family 0x0001
-{
- if (snac.subcmp(0x0003))//server supported service list
- {
- aim_send_service_request(hServerConn, seqno);
- }
-}
-void CAimProto::snac_supported_family_versions(SNAC &snac, HNETLIBCONN hServerConn, unsigned short &seqno)//family 0x0001
-{
- if (snac.subcmp(0x0018))//service list okayed
- {
- aim_request_rates(hServerConn, seqno);//request some rate crap
- }
-}
-void CAimProto::snac_rate_limitations(SNAC &snac, HNETLIBCONN hServerConn, unsigned short &seqno)// family 0x0001
-{
- if (snac.subcmp(0x0007)) {
- aim_accept_rates(hServerConn, seqno);
- aim_request_icbm(hServerConn, seqno);
- }
-}
-void CAimProto::snac_mail_rate_limitations(SNAC &snac, HNETLIBCONN hServerConn, unsigned short &seqno)// family 0x0001
-{
- if (snac.subcmp(0x0007)) {
- aim_accept_rates(hServerConn, seqno);
- aim_request_mail(hServerConn, seqno);
- aim_activate_mail(hServerConn, seqno);
- aim_mail_ready(hServerConn, seqno);
- }
-}
-
-void CAimProto::snac_avatar_rate_limitations(SNAC &snac, HNETLIBCONN hServerConn, unsigned short &seqno)// family 0x0001
-{
- if (snac.subcmp(0x0007)) {
- aim_accept_rates(hServerConn, seqno);
- aim_avatar_ready(hServerConn, seqno);
- SetEvent(m_hAvatarEvent);
- }
-}
-
-void CAimProto::snac_chatnav_rate_limitations(SNAC &snac, HNETLIBCONN hServerConn, unsigned short &seqno)// family 0x0001
-{
- if (snac.subcmp(0x0007)) {
- aim_accept_rates(hServerConn, seqno);
- aim_chatnav_request_limits(m_hChatNavConn, m_chatnav_seqno); // Get the max number of rooms we're allowed in.
- }
-}
-
-void CAimProto::snac_chat_rate_limitations(SNAC &snac, HNETLIBCONN hServerConn, unsigned short &seqno)// family 0x0001
-{
- if (snac.subcmp(0x0007)) {
- aim_accept_rates(hServerConn, seqno);
- aim_chat_ready(hServerConn, seqno);
- }
-}
-
-void CAimProto::snac_icbm_limitations(SNAC &snac, HNETLIBCONN hServerConn, unsigned short &seqno)//family 0x0004
-{
- if (snac.subcmp(0x0005)) {
- switch (m_iDesiredStatus) {
- case ID_STATUS_ONLINE:
- broadcast_status(ID_STATUS_ONLINE);
- aim_set_status(hServerConn, seqno, AIM_STATUS_ONLINE);
- break;
-
- case ID_STATUS_INVISIBLE:
- broadcast_status(ID_STATUS_INVISIBLE);
- aim_set_status(hServerConn, seqno, AIM_STATUS_INVISIBLE);
- break;
-
- case ID_STATUS_OCCUPIED:
- broadcast_status(ID_STATUS_OCCUPIED);
- aim_set_status(hServerConn, seqno, AIM_STATUS_BUSY | AIM_STATUS_AWAY);
- break;
-
- case ID_STATUS_AWAY:
- broadcast_status(ID_STATUS_AWAY);
- aim_set_status(hServerConn, seqno, AIM_STATUS_AWAY);
- break;
- }
-
- char** msgptr = get_status_msg_loc(m_iDesiredStatus);
- replaceStr(m_last_status_msg, msgptr ? *msgptr: nullptr);
- aim_set_statusmsg(hServerConn, seqno, m_last_status_msg);
-
- if (m_iDesiredStatus == ID_STATUS_AWAY)
- aim_set_away(hServerConn, seqno, m_last_status_msg, true);
-
- if (getByte(AIM_KEY_II, 0)) {
- unsigned long time = getDword(AIM_KEY_IIT, 0);
- aim_set_idle(hServerConn, seqno, time * 60);
- m_instantidle = 1;
- }
- aim_request_list(hServerConn, seqno);
- }
-}
-
-void CAimProto::snac_self_info(SNAC &snac)//family 0x0001
-{
- if (snac.subcmp(0x000f)) {
- int offset = snac.flags() & 0x8000 ? snac.ushort(0) + 2 : 0;
-
- unsigned char sn_len = snac.ubyte(offset++);
- char* sn = snac.part(offset, sn_len);
- offset += sn_len + 2;
-
- int tlv_count = snac.ushort(offset);
- offset += 2;
-
- for (int i = 0; i < tlv_count; i++) {
- TLV tlv(snac.val(offset));
- offset += TLV_HEADER_SIZE + tlv.len();
-
- if (tlv.cmp(0x000a)) {
- m_detected_ip = tlv.ulong();
- }
- }
- mir_free(sn);
- }
-}
-
-void CAimProto::snac_user_online(SNAC &snac)//family 0x0003
-{
- if (snac.subcmp(0x000b)) {
- char client[100] = "";
- bool hiptop_user = false;
- bool bot_user = false;
- bool wireless_user = false;
- bool away_user = false;
- bool caps_included = false;
- unsigned long status_type = 0; // 0 = online
-
- char *hash_sm = nullptr, *hash_lg = nullptr;
-
- unsigned char sn_len = snac.ubyte();
- char* sn = snac.part(1, sn_len);
- MCONTACT hContact = contact_from_sn(sn, true);
-
- int offset = sn_len + 3;
- int tlv_count = snac.ushort(offset);
- offset += 2;
-
- for (int i = 0; i < tlv_count; i++) {
- TLV tlv(snac.val(offset));
- offset += TLV_HEADER_SIZE;
- if (tlv.cmp(0x0001)) { // user m_iStatus
- unsigned short status = tlv.ushort();
- int unconfirmed = status & 0x0001;
- int admin_aol = status & 0x0002;
- int aol = status & 0x0004;
- //int nonfree = status & 0x0008;
- //int aim = status & 0x0010;
- int away = status & 0x0020;
- int icq = status & 0x0040;
- int wireless = status & 0x0080;
- int bot = status & 0x0400;
- setString(hContact, AIM_KEY_NK, sn);
-
- if (icq)
- setString(hContact, "Transport", "ICQ");
- else
- delSetting(hContact, "Transport");
-
- if (admin_aol)
- setByte(hContact, AIM_KEY_AC, ACCOUNT_TYPE_ADMIN);
- else if (aol)
- setByte(hContact, AIM_KEY_AC, ACCOUNT_TYPE_AOL);
- else if (icq)
- setByte(hContact, AIM_KEY_AC, ACCOUNT_TYPE_ICQ);
- else if (unconfirmed)
- setByte(hContact, AIM_KEY_AC, ACCOUNT_TYPE_UNCONFIRMED);
- else
- setByte(hContact, AIM_KEY_AC, ACCOUNT_TYPE_CONFIRMED);
-
- if (bot) {
- mir_strcpy(client, CLIENT_BOT);
- bot_user = 1;
- }
- if (wireless) {
- mir_strcpy(client, CLIENT_SMS);
- wireless_user = 1;
- }
- else if (away) {
- away_user = 1;
- }
- setDword(hContact, AIM_KEY_IT, 0);//erase idle time
- setDword(hContact, AIM_KEY_OT, 0);//erase online time
- }
- else if (tlv.cmp(0x0006)) // Status
- {
- status_type = tlv.ulong() & 0x00000FFF;
- }
- else if (tlv.cmp(0x000d)) {
- caps_included = true;
-
- for (int k = 0; k < tlv.len(); k += 16) {
- char *cap = tlv.part(k, 16);
- if (memcmp(cap, "MirandaM", 8) == 0) {
- char a = cap[8];
- char b = cap[9];
- char c = cap[10];
- char d = cap[11];
- char e = cap[12];
- char f = cap[13];
- char g = cap[14];
- char h = cap[15];
- mir_snprintf(client, CLIENT_OSCARJ, a & 0x7f, b, c, d, alpha_cap_str(a), e & 0x7f, f, g, h, alpha_cap_str(e));
- }
- else if (memcmp(cap, "MirandaA", 8) == 0) {
- char a = cap[8];
- char b = cap[9];
- char c = cap[10];
- char d = cap[11];
- char e = cap[12];
- char f = cap[13];
- char g = cap[14];
- char h = cap[15];
- mir_snprintf(client, CLIENT_AIMOSCAR, a, b, c, d, e, f, g, h);
- }
- if (memcmp(cap, "sinj", 4) == 0) {
- char a = cap[4];
- char b = cap[5];
- char c = cap[6];
- char d = cap[7];
- char e = cap[8];
- char f = cap[9];
- char g = cap[10];
- char h = cap[11];
- mir_snprintf(client, CLIENT_OSCARSN, a & 0x7f, b, c, d, alpha_cap_str(a), e & 0x7f, f, g, h, alpha_cap_str(e), secure_cap_str(&cap[12]));
- }
- if (memcmp(cap, "icqp", 4) == 0) {
- char a = cap[4];
- char b = cap[5];
- char c = cap[6];
- char d = cap[7];
- char e = cap[8];
- char f = cap[9];
- char g = cap[10];
- char h = cap[11];
- mir_snprintf(client, CLIENT_OSCARPL, a & 0x7f, b, c, d, alpha_cap_str(a), e & 0x7f, f, g, h, alpha_cap_str(e), secure_cap_str(&cap[12]));
- }
- else if (memcmp(cap, "Kopete ICQ", 10) == 0) {
- mir_strcpy(client, CLIENT_KOPETE);
- }
- else if (memcmp(&cap[7], "QIP", 3) == 0) {
- mir_strcpy(client, CLIENT_QIP);
- }
- else if (memcmp(cap, "mICQ", 4) == 0) {
- mir_strcpy(client, CLIENT_MICQ);
- }
- else if (cap_cmp(cap, AIM_CAP_IM2) == 0) {
- mir_strcpy(client, CLIENT_IM2);
- }
- else if (memcmp(cap, "SIM client", 10) == 0) {
- mir_strcpy(client, CLIENT_SIM);
- }
- else if (memcmp(cap + 4, "naim", 4) == 0) {
- mir_strcpy(client, CLIENT_NAIM);
- }
- else if (memcmp(cap, "digsby", 6) == 0) {
- mir_strcpy(client, CLIENT_DIGSBY);
- }
- mir_free(cap);
- }
- }
- else if (tlv.cmp(0x0019)) { // new caps
- caps_included = 1;
- bool f002 = 0, f003 = 0, f004 = 0, f005 = 0, f007 = 0, f008 = 0,
- O101 = 0, O102 = 0, O103 = 0, O104 = 0, O105 = 0, O107 = 0, O1ff = 0,
- O10a = 0, O10c = 0, O10d = 0,
- l341 = 0, l343 = 0, l345 = 0, l346 = 0, l347 = 0, l348 = 0, l349 = 0, l34b = 0, l34e = 0;
-
- for (int k = 0; k < tlv.len(); k = k + 2) {
- unsigned short cap = tlv.ushort(k);
- if (cap == 0xf002)
- f002 = 1;
- if (cap == 0xf003)
- f003 = 1;
- if (cap == 0xf004)
- f004 = 1;
- if (cap == 0xf005)
- f005 = 1;
- if (cap == 0xf007)
- f007 = 1;
- if (cap == 0xf008)
- f008 = 1;
- if (cap == 0x0101)
- O101 = 1;
- if (cap == 0x0102)
- O102 = 1;
- if (cap == 0x0103)
- O103 = 1;
- if (cap == 0x0104)
- O104 = 1;
- if (cap == 0x0105)
- O105 = 1;
- if (cap == 0x0107)
- O107 = 1;
- if (cap == 0x010a)
- O10a = 1;
- if (cap == 0x010c)
- O10c = 1;
- if (cap == 0x010d)
- O10d = 1;
- if (cap == 0x01ff)
- O1ff = 1;
- if (cap == 0x1323) {
- mir_strcpy(client, CLIENT_GPRS);
- hiptop_user = 1;
- }
- if (cap == 0x1341)
- l341 = 1;
- if (cap == 0x1343)
- l343 = 1;
- if (cap == 0x1345)
- l345 = 1;
- if (cap == 0x1346)
- l346 = 1;
- if (cap == 0x1347)
- l347 = 1;
- if (cap == 0x1348)
- l348 = 1;
- if (cap == 0x1349)
- l349 = 1;
- if (cap == 0x134b)
- l34b = 1;
- if (cap == 0x134e)
- l34e = 1;
- }
-
- if (f002 && f003 && f004 && f005)
- mir_strcpy(client, CLIENT_TRILLIAN_PRO);
- else if ((f004 && f005 && f007 && f008) || (f004 && f005 && O104 && O105))
- mir_strcpy(client, CLIENT_ICHAT);
- else if (f003&f004&f005)
- mir_strcpy(client, CLIENT_TRILLIAN);
- else if (l343 && O1ff && tlv.len() == 4)
- mir_strcpy(client, CLIENT_TRILLIAN_ASTRA);
- else if (l343 && tlv.len() == 2)
- mir_strcpy(client, CLIENT_AIMTOC);
- else if (l343 && l345 && l346 && tlv.len() == 6)
- mir_strcpy(client, CLIENT_GAIM);
- else if (l343 && l345 && l346 && l34e && tlv.len() == 8)
- mir_strcpy(client, CLIENT_PURPLE);
- else if (l343 && l345 && l346 && l349 && l34e && tlv.len() == 10)
- mir_strcpy(client, CLIENT_PURPLE);
- else if (l343 && l345 && l34e && tlv.len() == 6)
- mir_strcpy(client, CLIENT_ADIUM);
- else if (l343 && l346 && l34e && tlv.len() == 6)
- mir_strcpy(client, CLIENT_TERRAIM);
- else if (tlv.len() == 0 && getWord(hContact, AIM_KEY_ST, 0) != ID_STATUS_ONTHEPHONE)
- mir_strcpy(client, CLIENT_AIMEXPRESS5);
- else if (l34b && l343 && O1ff && l345 && l346 && tlv.len() == 10)
- mir_strcpy(client, CLIENT_AIMEXPRESS6);
- else if (l34b && l341 && l343 && O1ff && l345 && l346 && l347)
- mir_strcpy(client, CLIENT_AIM5);
- else if (l34b && l341 && l343 && l345&l346 && l347 && l348)
- mir_strcpy(client, CLIENT_AIM4);
- else if (O1ff && l343 && O107 && l341 && O104 && O105 && O101 && l346) {
- if (O10d)
- mir_strcpy(client, CLIENT_AIM6_9);
- else if (O10c)
- mir_strcpy(client, CLIENT_AIM6_8);
- else if (O10a)
- mir_strcpy(client, CLIENT_AIM6_5);
- else
- mir_strcpy(client, CLIENT_AIM_TRITON);
- }
- else if (O1ff && l343 && l341 && O104 && O105 && O101 && l346)
- mir_strcpy(client, CLIENT_AIM7_0);
- else if (l346 && l34e && tlv.len() == 4)
- mir_strcpy(client, CLIENT_MEEBO);
- else if (l34e && tlv.len() == 2)
- mir_strcpy(client, CLIENT_BEEJIVE);
- else if (l34e && l343 && tlv.len() == 4)
- mir_strcpy(client, CLIENT_BEEJIVE);
- }
- else if (tlv.cmp(0x001d)) { // bart
- if (hContact) {
- bool msg_exist = false;
- for (int k = 0; k < tlv.len(); ) {
- // Bart header
- unsigned short type = tlv.ushort(k);
- unsigned char flags = tlv.ubyte(k + 2);
- unsigned char datalen = tlv.ubyte(k + 3);
-
- switch (type) {
- case 0x0001:
- hash_sm = bytes_to_string(tlv.val() + k + 4, datalen);
- break;
-
- case 0x000c:
- hash_lg = bytes_to_string(tlv.val() + k + 4, datalen);
- break;
-
- case 0x0002:
- if ((flags & 4) && datalen > 2) {
- unsigned short len = tlv.ushort(k + 4);
- if (len) {
- msg_exist = true;
- char* msg = tlv.part(k + 6, len);
- char* msg_s = process_status_msg(msg, sn);
- db_set_utf(hContact, MOD_KEY_CL, OTH_KEY_SM, msg_s);
-
- wchar_t* tszMsg = mir_utf8decodeW(msg_s);
- ProtoBroadcastAck(hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, nullptr, (LPARAM)tszMsg);
- mir_free(tszMsg);
- mir_free(msg);
- mir_free(msg_s);
- }
- }
- break;
- }
- k += 4 + datalen;
- }
-
- if (!msg_exist)
- db_unset(hContact, MOD_KEY_CL, OTH_KEY_SM);
- }
- }
- else if (tlv.cmp(0x0004)) { //idle tlv
- if (hContact) {
- time_t current_time;
- time(&current_time);
- setDword(hContact, AIM_KEY_IT, ((DWORD)current_time) - tlv.ushort() * 60);
- }
- }
- else if (tlv.cmp(0x0003)) { // online time tlv
- if (hContact)
- setDword(hContact, AIM_KEY_OT, tlv.ulong());
- }
- else if (tlv.cmp(0x0005)) { // member since
- if (hContact)
- setDword(hContact, AIM_KEY_MS, tlv.ulong());
- }
- offset += tlv.len();
- }
-
- if (status_type & AIM_STATUS_INVISIBLE)
- setWord(hContact, AIM_KEY_ST, ID_STATUS_INVISIBLE);
- else if (status_type & AIM_STATUS_BUSY)
- setWord(hContact, AIM_KEY_ST, ID_STATUS_OCCUPIED);
- else if (status_type & AIM_STATUS_AWAY || away_user)
- setWord(hContact, AIM_KEY_ST, ID_STATUS_AWAY);
- else if (wireless_user)
- setWord(hContact, AIM_KEY_ST, ID_STATUS_ONTHEPHONE);
- else
- setWord(hContact, AIM_KEY_ST, ID_STATUS_ONLINE);
-
- if (hash_lg)
- avatar_request_handler(hContact, hash_lg, 12);
- else
- avatar_request_handler(hContact, hash_sm, 1);
-
- if (bot_user)
- setByte(hContact, AIM_KEY_ET, EXTENDED_STATUS_BOT);
- else if (hiptop_user)
- setByte(hContact, AIM_KEY_ET, EXTENDED_STATUS_HIPTOP);
- if (caps_included)
- set_contact_icon(this, hContact);
-
- if (caps_included || client[0])
- setString(hContact, AIM_KEY_MV, client[0] ? client : "?");
- else if (atoi(sn))
- setString(hContact, AIM_KEY_MV, CLIENT_ICQ);
- else if (getBool(hContact, AIM_KEY_BLS, false))
- setString(hContact, AIM_KEY_MV, CLIENT_BLAST);
- else
- setString(hContact, AIM_KEY_MV, CLIENT_AIMEXPRESS7);
-
- mir_free(hash_lg);
- mir_free(hash_sm);
- mir_free(sn);
- }
-}
-
-void CAimProto::snac_user_offline(SNAC &snac)//family 0x0003
-{
- if (snac.subcmp(0x000c)) {
- unsigned char buddy_length = snac.ubyte();
- char* buddy = snac.part(1, buddy_length);
- MCONTACT hContact = contact_from_sn(buddy, true);
- if (hContact)
- offline_contact(hContact, 0);
- mir_free(buddy);
- }
-}
-void CAimProto::snac_error(SNAC &snac)//family 0x0003 or 0x0004
-{
- if (snac.subcmp(0x0001))
- get_error(snac.ushort());
-}
-
-void CAimProto::process_ssi_list(SNAC &snac, int &offset)
-{
- unsigned short name_length = snac.ushort(offset);
- char* name = snac.part(offset + 2, name_length);
- unsigned short group_id = snac.ushort(offset + 2 + name_length);
- unsigned short item_id = snac.ushort(offset + 4 + name_length);
- unsigned short type = snac.ushort(offset + 6 + name_length);
- unsigned short tlv_size = snac.ushort(offset + 8 + name_length);
- const int tlv_base = offset + name_length + 10;
-
- switch (type) {
- case 0x0000: //buddy record
- {
- MCONTACT hContact = contact_from_sn(name, true);
- if (hContact) {
- int i;
- for (i = 1;; i++) {
- if (!getBuddyId(hContact, i)) {
- setBuddyId(hContact, i, item_id);
- setGroupId(hContact, i, group_id);
- break;
- }
- }
- if (i == 1 && getByte(AIM_KEY_MG, 1)) {
- const char* group = m_group_list.find_name(group_id);
- if (group) {
- bool ok = false;
- DBVARIANT dbv;
- if (!db_get_utf(hContact, MOD_KEY_CL, OTH_KEY_GP, &dbv) && dbv.pszVal[0]) {
- ok = mir_strcmp(group, dbv.pszVal) == 0;
- db_free(&dbv);
- }
- else ok = mir_strcmp(group, AIM_DEFAULT_GROUP) == 0;
-
- if (!ok) {
- if (mir_strcmp(group, AIM_DEFAULT_GROUP))
- db_set_utf(hContact, MOD_KEY_CL, OTH_KEY_GP, group);
- else
- db_unset(hContact, MOD_KEY_CL, OTH_KEY_GP);
- }
- }
- }
- setWord(hContact, AIM_KEY_ST, ID_STATUS_OFFLINE);
-
- bool nickfound = false;
- for (int tlv_offset = 0; tlv_offset < tlv_size;) {
- TLV tlv(snac.val(tlv_base + tlv_offset));
-
- if (tlv.cmp(0x0131) && tlv.len()) {
- char* nick = tlv.dup();
- db_set_utf(hContact, MOD_KEY_CL, "MyHandle", nick);
- mir_free(nick);
- nickfound = true;
- }
- else if (tlv.cmp(0x7b))
- setByte(hContact, AIM_KEY_BLS, 1);
- else if (tlv.cmp(0x6a))
- setByte(hContact, AIM_KEY_NIL, 1);
-
- tlv_offset += TLV_HEADER_SIZE + tlv.len();
- }
- if (!nickfound && getDword(AIM_KEY_LV, 0) >= 0x80500)
- db_unset(hContact, MOD_KEY_CL, "MyHandle");
- }
- }
- break;
-
- case 0x0001: //group record
- if (group_id) {
- m_group_list.add(name, group_id);
- if (getByte(AIM_KEY_MG, 1))
- create_group(name);
- }
- break;
-
- case 0x0002: //permit record
- m_allow_list.add(name, item_id);
- break;
-
- case 0x0003: //deny record
- m_block_list.add(name, item_id);
- break;
-
- case 0x0004: //privacy record
- if (group_id == 0) {
- m_pd_info_id = item_id;
-
- for (int tlv_offset = 0; tlv_offset < tlv_size;) {
- TLV tlv(snac.val(tlv_base + tlv_offset));
-
- if (tlv.cmp(0x00ca))
- m_pd_mode = tlv.ubyte();
- else if (tlv.cmp(0x00cc))
- m_pd_flags = tlv.ulong();
-
- tlv_offset += TLV_HEADER_SIZE + tlv.len();
- }
- }
- break;
-
- case 0x0005: //prefernces record
- if (group_id == 0) {
- m_pref1_id = item_id;
-
- for (int tlv_offset = 0; tlv_offset < tlv_size;) {
- TLV tlv(snac.val(tlv_base + tlv_offset));
-
- if (tlv.cmp(0x00c9))
- m_pref1_flags = tlv.ulong();
- else if (tlv.cmp(0x00d6))
- m_pref1_set_flags = tlv.ulong();
- else if (tlv.cmp(0x00d7)) {
- mir_free(m_pref2_flags);
- m_pref2_flags = tlv.dup();
- m_pref2_len = tlv.len();
- }
- else if (tlv.cmp(0x00d8)) {
- mir_free(m_pref2_set_flags);
- m_pref2_set_flags = tlv.dup();
- m_pref2_set_len = tlv.len();
- }
-
- tlv_offset += TLV_HEADER_SIZE + tlv.len();
- }
- }
- break;
-
- case 0x0014: //avatar record
- if (!mir_strcmp(name, "1") || !mir_strcmp(name, "12")) {
- if (name_length == 1)
- m_avatar_id_sm = item_id;
- else
- m_avatar_id_lg = item_id;
-
- for (int tlv_offset = 0; tlv_offset < tlv_size;) {
- TLV tlv(snac.val(tlv_base + tlv_offset));
-
- if (tlv.cmp(0x00d5) && tlv.len() > 2) {
- if (name_length == 1) {
- mir_free(m_hash_sm);
- m_hash_sm = bytes_to_string(tlv.val() + 2, tlv.ubyte(1));
- }
- else {
- mir_free(m_hash_lg);
- m_hash_lg = bytes_to_string(tlv.val() + 2, tlv.ubyte(1));
- }
- }
-
- tlv_offset += TLV_HEADER_SIZE + tlv.len();
- }
- if (m_list_received)
- avatar_request_handler(NULL, nullptr, 0);
- }
- break;
-
- case 0x001D: // Vanity information
- if (group_id == 0) {
- for (int tlv_offset = 0; tlv_offset < tlv_size;) {
- TLV tlv(snac.val(tlv_base + tlv_offset));
-
- if (tlv.cmp(0x0150)) // Number of IMs sent
- setDword(AIM_KEY_TIS, tlv.ulong());
- else if (tlv.cmp(0x0151)) // Number of seconds a user is online
- setDword(AIM_KEY_TTO, tlv.ulong());
- else if (tlv.cmp(0x0152)) // Number of times a user has the away message set
- setDword(AIM_KEY_TAM, tlv.ulong());
- else if (tlv.cmp(0x0153)) // Number of IMs received
- setDword(AIM_KEY_TIR, tlv.ulong());
-
- tlv_offset += TLV_HEADER_SIZE + tlv.len();
- }
- }
- break;
- }
-
- mir_free(name);
-
- offset = tlv_base + tlv_size;
-}
-
-void CAimProto::modify_ssi_list(SNAC &snac, int &offset)
-{
- unsigned short name_length = snac.ushort(offset);
- char* name = snac.part(offset + 2, name_length);
- unsigned short group_id = snac.ushort(offset + 2 + name_length);
- unsigned short item_id = snac.ushort(offset + 4 + name_length);
- unsigned short type = snac.ushort(offset + 6 + name_length);
- unsigned short tlv_size = snac.ushort(offset + 8 + name_length);
- const int tlv_base = offset + name_length + 10;
-
- switch (type) {
- case 0x0000: //buddy record
- {
- MCONTACT hContact = contact_from_sn(name, true);
- if (hContact) {
- for (int tlv_offset = 0; tlv_offset < tlv_size; ) {
- TLV tlv(snac.val(tlv_base + tlv_offset));
-
- if (tlv.cmp(0x0131) && tlv.len()) {
- char* nick = tlv.dup();
- if (nick)
- db_set_utf(hContact, MOD_KEY_CL, "MyHandle", nick);
- else
- db_unset(hContact, MOD_KEY_CL, "MyHandle");
- mir_free(nick);
- }
-
- tlv_offset += TLV_HEADER_SIZE + tlv.len();
- }
- }
- break;
- }
-
- case 0x0004: //privacy record
- if (group_id == 0) {
- m_pd_info_id = item_id;
-
- for (int tlv_offset = 0; tlv_offset < tlv_size; ) {
- TLV tlv(snac.val(tlv_base + tlv_offset));
-
- if (tlv.cmp(0x00ca))
- m_pd_mode = tlv.ubyte();
- else if (tlv.cmp(0x00cc))
- m_pd_flags = tlv.ulong();
-
- tlv_offset += TLV_HEADER_SIZE + tlv.len();
- }
- }
- break;
-
- case 0x0005: //prefernces record
- if (group_id == 0) {
- m_pref1_id = item_id;
-
- for (int tlv_offset = 0; tlv_offset < tlv_size; ) {
- TLV tlv(snac.val(tlv_base + tlv_offset));
-
- if (tlv.cmp(0x00c9))
- m_pref1_flags = tlv.ulong();
- else if (tlv.cmp(0x00d6))
- m_pref1_set_flags = tlv.ulong();
- else if (tlv.cmp(0x00d7)) {
- mir_free(m_pref2_flags);
- m_pref2_flags = tlv.dup();
- m_pref2_len = tlv.len();
- }
- else if (tlv.cmp(0x00d8)) {
- mir_free(m_pref2_set_flags);
- m_pref2_set_flags = tlv.dup();
- m_pref2_set_len = tlv.len();
- }
-
- tlv_offset += TLV_HEADER_SIZE + tlv.len();
- }
- }
- break;
-
- case 0x0014: //avatar record
- if (!mir_strcmp(name, "1") || !mir_strcmp(name, "12")) {
- if (name_length == 1)
- m_avatar_id_sm = item_id;
- else
- m_avatar_id_lg = item_id;
-
- for (int tlv_offset = 0; tlv_offset < tlv_size; ) {
- TLV tlv(snac.val(tlv_base + tlv_offset));
-
- if (tlv.cmp(0x00d5) && tlv.len() > 2) {
- // unsigned char type = tlv.ubyte(0);
- if (name_length == 1) {
- mir_free(m_hash_sm);
- m_hash_sm = bytes_to_string(tlv.val() + 2, tlv.ubyte(1));
- }
- else {
- mir_free(m_hash_lg);
- m_hash_lg = bytes_to_string(tlv.val() + 2, tlv.ubyte(1));
- }
- }
- tlv_offset += TLV_HEADER_SIZE + tlv.len();
- }
- avatar_request_handler(NULL, nullptr, 0);
- }
- break;
- }
-
- mir_free(name);
-}
-
-void CAimProto::delete_ssi_list(SNAC &snac, int &offset)
-{
- int i;
-
- unsigned short name_length = snac.ushort(offset);
- char* name = snac.part(offset + 2, name_length);
- unsigned short group_id = snac.ushort(offset + 2 + name_length);
- unsigned short item_id = snac.ushort(offset + 4 + name_length);
- unsigned short type = snac.ushort(offset + 6 + name_length);
-
- MCONTACT hContact = contact_from_sn(name);
-
- switch (type) {
- case 0x0000: //buddy record
- for (i = 1;; ++i) {
- unsigned short item_id_st = getBuddyId(hContact, i);
- if (item_id_st == 0) break;
-
- if (item_id == item_id_st) {
- deleteBuddyId(hContact, i);
- deleteGroupId(hContact, i);
- --i;
- }
- }
- if (i == 1)
- db_delete_contact(hContact);
- break;
-
- case 0x0001: //group record
- m_group_list.remove_by_id(group_id);
- break;
-
- case 0x0014: //avatar record
- if (mir_strcmp(name, "1")) {
- m_avatar_id_sm = 0;
- mir_free(m_hash_sm);
- m_hash_sm = nullptr;
- }
- else if (!mir_strcmp(name, "12")) {
- m_avatar_id_lg = 0;
- mir_free(m_hash_lg);
- m_hash_lg = nullptr;
- }
- avatar_request_handler(NULL, nullptr, 0);
- break;
- }
- mir_free(name);
-}
-
-void CAimProto::snac_contact_list(SNAC &snac, HNETLIBCONN hServerConn, unsigned short &seqno)//family 0x0013
-{
- if (snac.subcmp(0x0006)) { //contact list
- debugLogA("Contact List Received");
- // unsigned char ver = snac.ubyte();
- int num_obj = snac.ushort(1);
-
- int offset = 3;
- for (int i = 0; i < num_obj; ++i)
- process_ssi_list(snac, offset);
-
- if (!m_list_received) { // because they can send us multiple buddy list packets
- // only want one finished connection
- m_list_received = 1;
- aim_activate_list(hServerConn, seqno);
- aim_set_caps(hServerConn, seqno);
- aim_set_icbm(hServerConn, seqno);
- aim_client_ready(hServerConn, seqno);
- aim_request_offline_msgs(hServerConn, seqno);
-
- DBVARIANT dbv;
- if (!db_get_utf(NULL, m_szModuleName, AIM_KEY_PR, &dbv)) {
- aim_set_profile(hServerConn, seqno, dbv.pszVal);
- db_free(&dbv);
- }
-
- if (getDword(AIM_KEY_LV, 0) < 0x80500) {
- upload_nicks();
- setDword(AIM_KEY_LV, Miranda_GetVersion());
- }
-
- if (getByte(AIM_KEY_CM, 0))
- aim_new_service_request(hServerConn, seqno, 0x0018);//mail
-
- avatar_request_handler(NULL, nullptr, 0);
-
- debugLogA("Connection Negotiation Finished");
- m_state = 1;
- }
- }
- else if (snac.subcmp(0x0008)) { // add buddy
- int offset = 8;
- process_ssi_list(snac, offset);
- }
- else if (snac.subcmp(0x0009)) { // modify buddy
- int offset = 8;
- modify_ssi_list(snac, offset);
- }
- else if (snac.subcmp(0x000a)) { // delete buddy
- int offset = 8;
- delete_ssi_list(snac, offset);
- }
-}
-
-void CAimProto::snac_message_accepted(SNAC &snac)//family 0x004
-{
- if (snac.subcmp(0x000c)) {
- char *icbm_cookie = snac.part(0, 8);
- unsigned char sn_length = snac.ubyte(10);
- char *sn = snac.part(11, sn_length);
-
- MCONTACT hContact = contact_from_sn(sn);
- if (hContact) {
- msg_ack_param *msg_ack = (msg_ack_param*)mir_alloc(sizeof(msg_ack_param));
- msg_ack->hContact = hContact;
- msg_ack->id = *(int*)icbm_cookie & 0x7fffffff;
- msg_ack->msg = nullptr;
- msg_ack->success = true;
- ForkThread(&CAimProto::msg_ack_success, msg_ack);
- }
-
- mir_free(sn);
- mir_free(icbm_cookie);
- }
-}
-void CAimProto::snac_received_message(SNAC &snac, HNETLIBCONN hServerConn, unsigned short &seqno)//family 0x0004
-{
- if (snac.subcmp(0x0007)) {
- unsigned short channel = snac.ushort(8);
- unsigned char sn_length = snac.ubyte(10);
- char *sn = snac.part(11, sn_length);
-
- MCONTACT hContact = contact_from_sn(sn, true, true), hMsgContact = NULL;
-
- int offset = 15 + sn_length;
-
- char *msg_buf = nullptr;
- unsigned long offline_timestamp = 0;
- bool is_offline = false;
- //file transfer stuff
- char *icbm_cookie = nullptr;
- char *filename = nullptr;
- unsigned __int64 file_size = 0;
- bool auto_response = false;
- bool force_proxy = false;
- bool descr_included = false;
- bool utf_fname = false;
- bool unicode_descr = false;
- short rdz_msg_type = -1;
- unsigned short request_num = 0;
- unsigned long local_ip = 0, verified_ip = 0, proxy_ip = 0;
- unsigned short port = 0;
- unsigned short max_ver = 0;
- unsigned short num_files = 0;
- //end file transfer stuff
-
- unsigned short tlv_head_num = snac.ushort(offset - 2);
- for (int i = 0; i < tlv_head_num; i++) { // skip server-added TLVs - prevent another problems with parsing
- TLV tlv(snac.val(offset));
- offset += TLV_HEADER_SIZE + tlv.len();
- // some extra sanity
- if (offset >= snac.len()) break;
- }
-
- while (offset < snac.len()) {
- TLV tlv(snac.val(offset));
- offset += TLV_HEADER_SIZE;
- if (tlv.cmp(0x0004) && !tlv.len())//auto response flag
- auto_response = 1;
-
- if (tlv.cmp(0x0002)) { // msg
- unsigned short caps_length = tlv.ushort(2);
- unsigned short msg_length = tlv.ushort(6 + caps_length) - 4;
- unsigned short encoding = tlv.ushort(8 + caps_length);
- char *buf = tlv.part(12 + caps_length, msg_length);
- if (hContact) {
- wchar_t* wbuf;
- hMsgContact = hContact;
- switch (encoding) {
- case 2:
- wbuf = (wchar_t*)buf;
- wcs_htons(wbuf);
-
- msg_buf = mir_utf8encodeW(wbuf);
- mir_free(wbuf);
- break;
-
- case 3:
- wbuf = mir_a2u_cp(buf, 28591);
-
- msg_buf = mir_utf8encodeW(wbuf);
- mir_free(wbuf);
- mir_free(buf);
- break;
-
- default:
- msg_buf = buf;
- break;
- }
- }
- }
-
- if (tlv.cmp(0x0004) && !tlv.len())//auto response flag
- auto_response = 1;
-
- if (channel == 2 && tlv.cmp(0x0005)) { //recv rendervous packet
- rdz_msg_type = snac.ushort(offset);
- icbm_cookie = snac.part(offset + 2, 8);
- if (cap_cmp(snac.val(offset + 10), AIM_CAP_FILE_TRANSFER) == 0) {
- for (int i = 26; i < tlv.len(); ) {
- TLV tlv2(snac.val(offset + i));
- if (tlv2.cmp(0x000A))
- request_num = tlv2.ushort();//for file transfer
- else if (tlv2.cmp(0x0002))//proxy ip
- proxy_ip = tlv2.ulong();
- else if (tlv2.cmp(0x0003))//client ip
- local_ip = tlv2.ulong();
- else if (tlv2.cmp(0x0004))//verified ip
- verified_ip = tlv2.ulong();
- else if (tlv2.cmp(0x0005))
- port = tlv2.ushort();
- else if (tlv2.cmp(0x0010))
- force_proxy = 1;
- else if (tlv2.cmp(0x0012))
- max_ver = tlv2.ushort();
- else if (tlv2.cmp(0x2711)) {
- num_files = tlv2.ushort(2);
- file_size = tlv2.ulong(4);
- filename = tlv2.part(8, tlv2.len() - 8);
- }
- else if (tlv2.cmp(0x2712)) {
- char *enc = tlv2.dup();
- utf_fname = mir_strcmp(enc, "utf-8") == 0;
- mir_free(enc);
- }
- else if (tlv2.cmp(0x2713)) {
- file_size = tlv2.u64();
- }
- else if (tlv2.cmp(0x000c)) {
- msg_buf = unicode_descr ? tlv2.dupw() : tlv2.dup();
- html_decode(msg_buf);
- descr_included = true;
- if (strstr(msg_buf, "<ICQ_COOL_FT>")) {
- char* beg = strstr(msg_buf, "<DESC>");
- char* end = strstr(msg_buf, "</DESC>");
- if (beg && end && beg < end) {
- beg += 6;
- end[0] = 0;
- memmove(msg_buf, beg, end - beg + 1);
- }
- else descr_included = false;
- }
- }
- else if (tlv2.cmp(0x000d)) {
- char* enc = tlv2.dup();
- unicode_descr = mir_strcmp(enc, "unicode-2-0") == 0;
- mir_free(enc);
- }
- i += TLV_HEADER_SIZE + tlv2.len();
- }
- }
- else if (cap_cmp(snac.val(offset + 10), AIM_CAP_RTCAUDIO) == 0 || cap_cmp(snac.val(offset + 10), AIM_CAP_RTCVIDEO) == 0) {
- for (int i = 26; i < tlv.len(); ) {
- TLV tlv2(snac.val(offset + i));
- if (tlv2.cmp(0x000A))
- request_num = tlv2.ushort();//for file transfer
- else if (tlv2.cmp(0x0002))//proxy ip
- proxy_ip = tlv2.ulong();
- else if (tlv2.cmp(0x0003))//client ip
- local_ip = tlv2.ulong();
- else if (tlv2.cmp(0x0004))//verified ip
- verified_ip = tlv2.ulong();
- else if (tlv2.cmp(0x0005))
- port = tlv2.ushort();
- }
- channel = 0;
- break;
- }
- else if (cap_cmp(snac.val(offset + 10), AIM_CAP_CHAT) == 0) { //it's a chat invite request
- for (int i = 26; i < tlv.len();) {
- TLV tlv2(snac.val(offset + i));
- if (tlv2.cmp(0x000c)) //optional message
- msg_buf = tlv2.dup();
- else if (tlv2.cmp(0x2711)) { //room information
- int cookie_len = tlv2.ubyte(2);
- chatnav_param* par =
- new chatnav_param(tlv2.part(3, cookie_len), tlv2.ushort(), tlv2.ushort(3 + cookie_len),
- msg_buf, sn, icbm_cookie);
-
- invite_chat_req_param* chat_rq = new invite_chat_req_param(par, this, msg_buf, sn, icbm_cookie);
- CallFunctionAsync(chat_request_cb, chat_rq);
- }
- i += TLV_HEADER_SIZE + tlv2.len();
- }
- }
- else {
- channel = 0;
- break;
- }
- }
-
- if (channel == 6 && tlv.cmp(0x0005))//audio/video tunnel
- msg_buf = tlv.dup();
-
- if (tlv.cmp(0x0006))//Offline message flag
- is_offline = true;
-
- if (tlv.cmp(0x0016))//Offline message timestamp
- offline_timestamp = tlv.ulong(0);
-
- offset += (tlv.len());
- }
-
- if (channel == 1) { //Message not file
- if (auto_response) { //this message must be an autoresponse
- T2Utf away(TranslateT("[Auto-response]:"));
- size_t len = mir_strlen(msg_buf) + mir_strlen(away) + 2;
- char* buf = (char*)mir_alloc(len);
- mir_snprintf(buf, len, "%s %s", away, msg_buf);
- mir_free(msg_buf);
- msg_buf = buf;
- }
-
- // Okay we are setting up the structure to give the message back to miranda's core
- CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hMsgContact, 0);
- {
- PROTORECVEVENT pre = { 0 };
- pre.timestamp = (is_offline) ? offline_timestamp : (DWORD)time(nullptr);
- pre.szMessage = msg_buf;
- ProtoChainRecvMsg(hMsgContact, &pre);
- }
-
- if (m_iStatus == ID_STATUS_AWAY && !auto_response && !getByte(AIM_KEY_DM, 0)) {
- unsigned long msg_time = getDword(hContact, AIM_KEY_LM, 0);
- unsigned long away_time = getDword(AIM_KEY_LA, 0);
- char** msgptr = get_status_msg_loc(m_iStatus);
- if (away_time > msg_time && *msgptr) {
- char* s_msg = process_status_msg(*msgptr, sn);
-
- T2Utf away(TranslateT("[Auto-response]:"));
- size_t len = mir_strlen(s_msg) + mir_strlen(away) + 2;
- char* buf = (char*)alloca(len);
- mir_snprintf(buf, len, "%s %s", away, s_msg);
-
- DBEVENTINFO dbei = {};
- dbei.szModule = m_szModuleName;
- dbei.timestamp = (DWORD)time(nullptr);
- dbei.flags = DBEF_SENT | DBEF_UTF;
- dbei.eventType = EVENTTYPE_MESSAGE;
- dbei.cbBlob = (int)len;
- dbei.pBlob = (PBYTE)buf;
- db_event_add(hContact, &dbei);
-
- aim_send_message(hServerConn, seqno, sn, s_msg, true, getBool(hContact, AIM_KEY_BLS, false));
- mir_free(s_msg);
- }
- setDword(hContact, AIM_KEY_LM, (DWORD)time(nullptr));
- }
- }
- else if (channel == 2) { // File Transfer
- if (rdz_msg_type == 0 && request_num == 1) { // buddy wants to send us a file
- debugLogA("Buddy Wants to Send us a file. Request 1");
- debugLogA(force_proxy ? "Forcing a Proxy File transfer." : "Not forcing Proxy File transfer.");
-
- file_transfer* ft = new file_transfer(hContact, sn, icbm_cookie);
-
- ft->me_force_proxy = getByte(AIM_KEY_FP, 0) != 0;
- ft->peer_force_proxy = force_proxy;
- ft->local_ip = local_ip;
- ft->verified_ip = verified_ip;
- ft->proxy_ip = proxy_ip;
- ft->port = port;
- ft->max_ver = max_ver;
- ft->req_num = request_num;
-
- ft->file = mir_strdup(filename);
-
- ft->pfts.totalBytes = file_size;
- ft->pfts.totalFiles = num_files;
-
- m_ft_list.insert(ft);
-
- if (!descr_included) msg_buf = nullptr;
-
- wchar_t* filenameT = mir_utf8decodeW(filename);
-
- PROTORECVFILET pre = { 0 };
- pre.dwFlags = PRFF_UNICODE;
- pre.fileCount = 1;
- pre.timestamp = time(nullptr);
- pre.descr.w = mir_utf8decodeW(msg_buf);
- pre.files.w = &filenameT;
- pre.lParam = (LPARAM)ft;
- ProtoChainRecvFile(hContact, &pre);
-
- mir_free(pre.descr.w);
- mir_free(filenameT);
-
- char cip[20];
- debugLogA("Local IP: %s:%u", long_ip_to_char_ip(local_ip, cip), port);
- debugLogA("Verified IP: %s:%u", long_ip_to_char_ip(verified_ip, cip), port);
- debugLogA("Proxy IP: %s:%u", long_ip_to_char_ip(proxy_ip, cip), port);
- }
- else if (rdz_msg_type == 0) {
- debugLogA("We are sending a file. Buddy wants us to connect to them. Request %d", request_num);
- debugLogA(force_proxy ? "Forcing a Proxy File transfer." : "Not forcing Proxy File transfer.");
-
- file_transfer* ft = m_ft_list.find_by_cookie(icbm_cookie, hContact);
- if (ft) {
- ft->hContact = hContact;
-
- ft->me_force_proxy |= (request_num > 2);
- ft->peer_force_proxy = force_proxy;
- ft->local_ip = local_ip;
- ft->verified_ip = verified_ip;
- ft->proxy_ip = proxy_ip;
- ft->port = port;
- ft->requester = false;
- ft->req_num = request_num;
- ft->max_ver = max_ver;
-
- char cip[20];
- debugLogA("Local IP: %s:%u", long_ip_to_char_ip(local_ip, cip), port);
- debugLogA("Verified IP: %s:%u", long_ip_to_char_ip(verified_ip, cip), port);
- debugLogA("Proxy IP: %s:%u", long_ip_to_char_ip(proxy_ip, cip), port);
-
- ForkThread(&CAimProto::accept_file_thread, ft);
- }
- else {
- debugLogA("Unknown File transfer, thus denied.");
- aim_file_ad(hServerConn, seqno, sn, icbm_cookie, true, 0);
- }
- }
- else if (rdz_msg_type == 1) { // buddy cancelled or denied file transfer
- debugLogA("File transfer cancelled or denied.");
-
- file_transfer *ft = m_ft_list.find_by_cookie(icbm_cookie, hContact);
- ProtoBroadcastAck(hContact, ACKTYPE_FILE, ACKRESULT_DENIED, ft, 0);
- m_ft_list.remove_by_ft(ft);
- }
- else if (rdz_msg_type == 2) { // buddy accepts our file transfer request
- debugLogA("File transfer accepted");
- file_transfer *ft = m_ft_list.find_by_cookie(icbm_cookie, hContact);
- if (ft) {
- ft->accepted = true;
- ft->max_ver = max_ver;
- }
- else aim_file_ad(hServerConn, seqno, sn, icbm_cookie, true, 0);
- }
- }
- else if (channel == 6) // Audio/Video call
- {
- aim_file_ad(hServerConn, seqno, sn, icbm_cookie, true, 0);
- ShowPopup(LPGEN("Contact tried to open an audio/video conference (not currently supported)"), ERROR_POPUP);
- }
-
- mir_free(sn);
- mir_free(msg_buf);
- mir_free(filename);
- mir_free(icbm_cookie);
- }
-}
-
-void CAimProto::snac_file_decline(SNAC &snac)//family 0x0004
-{
- if (snac.subcmp(0x000b)) {
- char *icbm_cookie = snac.part(0, 8);
- int channel = snac.ushort(8);
- if (channel == 0x01) {
- int sn_len = snac.ubyte(10);
- char *sn = snac.part(11, sn_len);
- MCONTACT hContact = contact_from_sn(sn);
-
- msg_ack_param *msg_ack = (msg_ack_param*)mir_alloc(sizeof(msg_ack_param));
- msg_ack->hContact = hContact;
- msg_ack->msg = nullptr;
- msg_ack->id = *(int*)icbm_cookie & 0x7fffffff;
- msg_ack->success = false;
- ForkThread(&CAimProto::msg_ack_success, msg_ack);
- }
-
- if (channel == 0x02) {
- int sn_len = snac.ubyte(10);
- char *sn = snac.part(11, sn_len);
- int reason = snac.ushort(11 + sn_len);
- if (reason == 0x03) {
- int error = snac.ushort(13 + sn_len);
- if (error == 0x02) {
- debugLogA("File Transfer declied");
- MCONTACT hContact = contact_from_sn(sn);
- file_transfer *ft = m_ft_list.find_by_cookie(icbm_cookie, hContact);
- if (ft) {
- ProtoBroadcastAck(hContact, ACKTYPE_FILE, ACKRESULT_DENIED, ft, 0);
- if (ft->hConn)
- Netlib_Shutdown(ft->hConn);
- else
- m_ft_list.remove_by_ft(ft);
- }
- }
- }
- mir_free(sn);
- }
- mir_free(icbm_cookie);
- }
-}
-void CAimProto::snac_received_info(SNAC &snac)//family 0x0002
-{
- if (snac.subcmp(0x0006)) {
- unsigned short offset = 0;
- int i = 0;
- bool away_message_received = false;
- bool away_message_unicode = false;
- bool away_message_utf = false;
- bool profile_received = false;
- bool profile_unicode = false;
- bool profile_utf = false;
- unsigned char sn_length = snac.ubyte();
- char* sn = snac.part(1, sn_length);
- unsigned short tlv_count = snac.ushort(3 + sn_length);
- offset = 5 + sn_length;
- MCONTACT hContact = contact_from_sn(sn, true, true);
-
- while (offset < snac.len()) {
- TLV tlv(snac.val(offset));
-
- if (++i > tlv_count) {
- if (tlv.cmp(0x0001)) { //profile encoding
- char *enc = tlv.dup();
- profile_unicode = strstr(enc, "unicode-2-0") != nullptr;
- profile_utf = strstr(enc, "utf-8") != nullptr;
- mir_free(enc);
- }
- else if (tlv.cmp(0x0002)) { //profile message string
- char *msg = profile_unicode ? tlv.dupw() : tlv.dup();
-
- profile_received = true;
- write_profile(sn, msg, profile_unicode | profile_utf);
- mir_free(msg);
- }
- else if (tlv.cmp(0x0003)) { //away message encoding
- char *enc = tlv.dup();
- away_message_unicode = strstr(enc, "unicode-2-0") != nullptr;
- away_message_utf = strstr(enc, "utf-8") != nullptr;
- mir_free(enc);
- }
- else if (tlv.cmp(0x0004)) { // away message string
- char *msg = away_message_unicode ? tlv.dupw() : tlv.dup();
-
- away_message_received = true;
- write_away_message(sn, msg, away_message_unicode | away_message_utf);
- mir_free(msg);
- }
- }
- offset += TLV_HEADER_SIZE + tlv.len();
- }
- if (hContact) {
- if (getWord(hContact, AIM_KEY_ST, ID_STATUS_OFFLINE) == ID_STATUS_AWAY) {
- if (!away_message_received && m_request_away_message)
- write_away_message(sn, Translate("No information has been provided by the server."), false);
- m_request_away_message = 0;
- }
- if (!profile_received && m_request_HTML_profile)
- write_profile(sn, "No Profile", false);
- m_request_HTML_profile = 0;
- }
- mir_free(sn);
- }
-}
-void CAimProto::snac_typing_notification(SNAC &snac)//family 0x004
-{
- if (snac.subcmp(0x0014)) {
- unsigned char sn_length = snac.ubyte(10);
- char *sn = snac.part(11, sn_length);
- MCONTACT hContact = contact_from_sn(sn);
- if (hContact) {
- unsigned short type = snac.ushort(11 + sn_length);
- if (type == 0x0000)//typing finished
- CallService(MS_PROTO_CONTACTISTYPING, hContact, (WPARAM)PROTOTYPE_CONTACTTYPING_OFF);
- else if (type == 0x0001)//typed
- CallService(MS_PROTO_CONTACTISTYPING, hContact, PROTOTYPE_CONTACTTYPING_INFINITE);
- else if (type == 0x0002)//typing
- CallService(MS_PROTO_CONTACTISTYPING, hContact, (LPARAM)60);
- }
- mir_free(sn);
- }
-}
-void CAimProto::snac_list_modification_ack(SNAC &snac)//family 0x0013
-{
- if (snac.subcmp(0x000e)) {
- unsigned short id = snac.id();
- TLV tlv(snac.val(2));
- unsigned short code = snac.ushort(6 + tlv.len());
-
- switch (id) {
- case 0x000a:
- switch (code) {
- case 0x0000:
- // ShowPopup(LPGEN("Successfully removed buddy from list."), ERROR_POPUP);
- break;
-
- case 0x0002:
- ShowPopup(LPGEN("Item you want to delete not found in list."), ERROR_POPUP);
- break;
-
- default:
- char msg[64];
- mir_snprintf(msg, "Error removing buddy from list. Error code %#x", code);
- ShowPopup(msg, ERROR_POPUP);
- break;
- }
- break;
-
- case 0x0008:
- switch (code) {
- case 0x0000:
- // ShowPopup("Successfully added buddy to list.", ERROR_POPUP);
- break;
-
- case 0x0003:
- ShowPopup(LPGEN("Failed to add buddy to list: Item already exist."), ERROR_POPUP);
- break;
-
- case 0x000a:
- ShowPopup(LPGEN("Error adding buddy (invalid ID or already in list?)"), ERROR_POPUP);
- break;
-
- case 0x000c:
- ShowPopup(LPGEN("Cannot add buddy. Limit for this type of item exceeded."), ERROR_POPUP);
- break;
-
- case 0x000d:
- ShowPopup(LPGEN("Error? Attempting to add ICQ contact to an AIM list."), ERROR_POPUP);
- break;
-
- case 0x000e:
- ShowPopup(LPGEN("Cannot add this buddy because it requires authorization."), ERROR_POPUP);
- break;
-
- default:
- char msg[64];
- mir_snprintf(msg, Translate("Unknown error when adding buddy to list. Error code %#x"), code);
- ShowPopup(msg, ERROR_POPUP);
- break;
- }
- break;
-
- case 0x0009:
- switch (code) {
- case 0x0000:
- case 0x000e:
- break;
-
- case 0x0002:
- ShowPopup(LPGEN("Item you want to modify not found in list."), ERROR_POPUP);
- break;
-
- default:
- char msg[64];
- mir_snprintf(msg, Translate("Unknown error when attempting to modify a group. Error code %#x"), code);
- ShowPopup(msg, ERROR_POPUP);
- break;
- }
- break;
- }
- }
-}
-
-void CAimProto::snac_service_redirect(SNAC &snac)//family 0x0001
-{
- if (snac.subcmp(0x0005)) {
- char* server = nullptr;
- char* local_cookie = nullptr;
- char* host = nullptr;
- int local_cookie_length = 0;
- unsigned short family = 0;
- unsigned char use_ssl = 0;
-
- int offset = 2; // skip number of bytes in family version tlv
- while (offset < snac.len()) {
- TLV tlv(snac.val(offset));
- if (tlv.cmp(0x000d)) {
- family = tlv.ushort();
- }
- else if (tlv.cmp(0x0005)) {
- server = tlv.dup();
- }
- else if (tlv.cmp(0x0006)) {
- local_cookie = tlv.dup();
- local_cookie_length = tlv.len();
- }
- else if (tlv.cmp(0x008d)) {
- host = tlv.dup();
- }
- else if (tlv.cmp(0x008e)) {
- use_ssl = tlv.ubyte();
- }
- offset += TLV_HEADER_SIZE + tlv.len();
- }
- if (family == 0x0018) {
- m_hMailConn = aim_connect(server, get_default_port(), false/*use_ssl != 0*/, host);
- if (m_hMailConn) {
- debugLogA("Successfully Connected to the Mail Server.");
- MAIL_COOKIE = local_cookie;
- MAIL_COOKIE_LENGTH = local_cookie_length;
- ForkThread(&CAimProto::aim_mail_negotiation, nullptr);
- }
- else debugLogA("Failed to connect to the Mail Server.");
- }
- else if (family == 0x0010) {
- m_hAvatarConn = aim_connect(server, get_default_port(), false/*use_ssl != 0*/);
- if (m_hAvatarConn) {
- debugLogA("Successfully Connected to the Avatar Server.");
- AVATAR_COOKIE = local_cookie;
- AVATAR_COOKIE_LENGTH = local_cookie_length;
- ForkThread(&CAimProto::aim_avatar_negotiation, nullptr);
- }
- else debugLogA("Failed to connect to the Avatar Server.");
- }
- else if (family == 0x000D) {
- m_hChatNavConn = aim_connect(server, get_default_port(), use_ssl != 0, host);
- if (m_hChatNavConn) {
- debugLogA("Successfully Connected to the Chat Navigation Server.");
- CHATNAV_COOKIE = local_cookie;
- CHATNAV_COOKIE_LENGTH = local_cookie_length;
- ForkThread(&CAimProto::aim_chatnav_negotiation, nullptr);
- }
- else debugLogA("Failed to connect to the Chat Navigation Server.");
- }
- else if (family == 0x000E) {
- chat_list_item* item = find_chat_by_cid(snac.idh());
- if (item) {
- item->hconn = aim_connect(server, get_default_port(), use_ssl != 0, host);
- if (item->hconn) {
- debugLogA("Successfully Connected to the Chat Server.");
- chat_start(item->id, item->exchange);
- item->CHAT_COOKIE = local_cookie;
- item->CHAT_COOKIE_LENGTH = local_cookie_length;
- ForkThread(&CAimProto::aim_chat_negotiation, item);
- }
- else debugLogA("Failed to connect to the Chat Server.");
- }
- }
- else if (family == 0x0007) {
- m_hAdminConn = aim_connect(server, get_default_port(), false /*use_ssl != 0*/);
- if (m_hAdminConn) {
- debugLogA("Successfully Connected to the Admin Server.");
- ADMIN_COOKIE = local_cookie;
- ADMIN_COOKIE_LENGTH = local_cookie_length;
- ForkThread(&CAimProto::aim_admin_negotiation, nullptr);
- }
- else debugLogA("Failed to connect to the Admin Server.");
- }
- mir_free(server);
- mir_free(host);
- }
-}
-
-void CAimProto::snac_mail_response(SNAC &snac)//family 0x0018
-{
- if (snac.subcmp(0x0007)) {
- char* sn = nullptr;
- time_t time = 0;
- unsigned short num_msgs = 0;
- unsigned short flags = 0;
- char new_mail = 0;
- char* url = nullptr;
- char* address = nullptr;
-
- int position = 26;
- int num_tlvs = snac.ushort(24);
- for (int i = 0; i < num_tlvs; i++) {
- TLV tlv(snac.val(position));
- if (tlv.cmp(0x0009)) {
- sn = tlv.dup();
- }
- else if (tlv.cmp(0x001d)) {
- time = tlv.ulong();
- }
- else if (tlv.cmp(0x0080)) {
- num_msgs = tlv.ushort();
- }
- else if (tlv.cmp(0x0081)) {
- new_mail = tlv.ubyte();
- }
- else if (tlv.cmp(0x0084)) {
- flags = tlv.ushort();
- }
- else if (tlv.cmp(0x0007)) {
- url = tlv.dup();
- }
- else if (tlv.cmp(0x0082)) {
- address = tlv.dup();
- }
- position += TLV_HEADER_SIZE + tlv.len();
- }
- if (new_mail && num_msgs) {
- wchar_t msg[1024];
-
- int len = mir_snwprintf(msg, L"%S@%S (%d)\r\n%s ", sn, address, num_msgs,
- TranslateT("You've got mail! Checked at"));
-
- SYSTEMTIME stLocal;
- GetLocalTime(&stLocal);
- GetTimeFormat(LOCALE_USER_DEFAULT, 0, &stLocal, nullptr, msg + len, _countof(msg) - len);
-
- ShowPopup((char*)msg, MAIL_POPUP | TCHAR_POPUP, url);
- }
- mir_free(sn);
- mir_free(address);
- mir_free(url);
- }
-}
-
-void CAimProto::snac_retrieve_avatar(SNAC &snac)//family 0x0010
-{
- if (snac.subcmp(0x0007)) {
- int sn_len = snac.ubyte(0);
- char* sn = snac.part(1, sn_len);
-
- int parse_off = sn_len + 4;
- parse_off += snac.ubyte(parse_off);
-
- int hash_size = snac.ubyte(5 + parse_off);
- char* hash_string = bytes_to_string(snac.val(6 + parse_off), hash_size);
- parse_off += hash_size + 6;
-
- int icon_length = snac.ushort(parse_off);
- char* icon_data = snac.val(parse_off + 2);
-
- avatar_retrieval_handler(sn, hash_string, icon_data, icon_length);
-
- mir_free(hash_string);
- mir_free(sn);
- }
-}
-void CAimProto::snac_upload_reply_avatar(SNAC &snac)//family 0x0010
-{
- if (snac.subcmp(0x0003)) {
- int code = snac.ubyte(0);
- switch (code) {
- case 0:
- break;
- case 3:
- ShowPopup(LPGEN("Error uploading avatar. (Too small)"), ERROR_POPUP);
- break;
- case 4:
- ShowPopup(LPGEN("Error uploading avatar. (Too big)"), ERROR_POPUP);
- break;
- case 5:
- ShowPopup(LPGEN("Error uploading avatar. (Wrong type)"), ERROR_POPUP);
- break;
- case 6:
- ShowPopup(LPGEN("Error uploading avatar. (Is banned)"), ERROR_POPUP);
- break;
- default:
- ShowPopup(LPGEN("Error uploading avatar. (Unknown error)"), ERROR_POPUP);
- break;
- }
- }
-}
-void CAimProto::snac_email_search_results(SNAC &snac)//family 0x000A
-{
- if (snac.subcmp(0x0003)) { // Found some buddies
- PROTOSEARCHRESULT psr = { 0 };
- psr.cbSize = sizeof(psr);
-
- unsigned short offset = 0;
- while (offset < snac.len()) { // Loop through all the TLVs and pull out the buddy name
- TLV tlv(snac.val(offset));
- offset += TLV_HEADER_SIZE;
- psr.id.w = (wchar_t*)tlv.dup();
- offset += tlv.len();
- ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)1, (LPARAM)& psr);
- mir_free(psr.nick.w);
- }
- ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)1, 0);
- }
- else // If no match, stop the search.
- CAimProto::ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)1, 0);
-}
-
-void CAimProto::snac_chatnav_info_response(SNAC &snac, HNETLIBCONN hServerConn, unsigned short &seqno)//family 0x000D
-{
- if (snac.subcmp(0x0009)) {
- debugLogA("Chat Info Received");
-
- unsigned short offset_info = 0;
- while (offset_info < snac.len()) { // Loop through all the TLVs and pull out the buddy name
- TLV info_tlv(snac.val(offset_info));
- if (info_tlv.cmp(0x0001)) // Redirect
- {
- }
- else if (info_tlv.cmp(0x0002)) { // Max Concurrent Rooms (usually 10)
- // This typecasting pointer to number and as such bogus
- MAX_ROOMS = info_tlv.ubyte();
-
- aim_chatnav_ready(hServerConn, seqno);
- SetEvent(m_hChatNavEvent);
- }
- else if (info_tlv.cmp(0x0003)) // Exchanges
- {
- }
- else if (info_tlv.cmp(0x0004)) { // Room Info
- // Main TLV info
- unsigned short exchange = 0;
- unsigned short cookie_len = 0;
- char* cookie = nullptr;
- unsigned short instance = 0;
- unsigned short num_tlv = 0;
- unsigned short tlv_offset = 0;
-
- exchange = info_tlv.ushort(0); // Exchange
- cookie_len = info_tlv.ubyte(2); // Cookie Length
- cookie = info_tlv.part(3, cookie_len); // Cookie String
- instance = info_tlv.ushort(3 + cookie_len); // Instance
- num_tlv = info_tlv.ushort(6 + cookie_len); // Number of TLVs
- tlv_offset = 8 + cookie_len; // We're looking at any remaining TLVs
-
- char* name = nullptr;
- for (int i = 0; i < num_tlv; i++) // Loop through all the TLVs
- {
- TLV tlv(info_tlv.val() + tlv_offset);
-
- // TLV List
- if (tlv.cmp(0x00d3))
- name = tlv.dup();
- tlv_offset += TLV_HEADER_SIZE + tlv.len();
- }
-
- chat_list_item *item = find_chat_by_id(name);
- if (item == nullptr) {
- item = new chat_list_item(name, cookie, exchange, instance);
- m_chat_rooms.insert(item);
-
- //Join the actual room
- aim_chat_join_room(m_hServerConn, m_seqno, cookie, exchange, instance, item->cid);
- }
-
- mir_free(name);
- mir_free(cookie);
- }
- offset_info += TLV_HEADER_SIZE + info_tlv.len();
- }
- }
-}
-void CAimProto::snac_chat_joined_left_users(SNAC &snac, chat_list_item* item)//family 0x000E
-{
- // Handles both joining and leaving users.
- if (snac.subcmp(0x0003) || snac.subcmp(0x0004)) {
- int offset = 0;
- while (offset < snac.len()) {
- int sn_len = snac.ubyte(offset);
- char* sn = snac.part(offset + 1, sn_len); // Most important part (screenname)
-
- chat_event(item->id, sn, snac.subcmp(0x0003) ? GC_EVENT_JOIN : GC_EVENT_PART);
-
- mir_free(sn);
-
- int num_tlv = snac.ushort(offset + 3 + sn_len);
- offset += 5 + sn_len; // We're looking at any remaining TLVs
-
- for (int i = 0; i < num_tlv; i++) { // Loop through all the TLVs
- TLV tlv(snac.val(offset));
- offset += TLV_HEADER_SIZE + tlv.len();
- }
- }
- }
-}
-void CAimProto::snac_chat_received_message(SNAC &snac, chat_list_item* item)//family 0x000E
-{
- if (snac.subcmp(0x0006)) {
- wchar_t* message = nullptr;
- char* sn = nullptr;
-
- // unsigned long cookie = snac.ulong(0);
- // unsigned short channel = snac.ushort(8);
-
- int tlv_offset = 10;
- while (tlv_offset < snac.len()) {
- TLV tlv(snac.val(tlv_offset));
-
- if (tlv.cmp(0x0003)) { // Sender information
- int sn_len = tlv.ubyte(0);
- sn = tlv.part(1, sn_len);
- }
- else if (tlv.cmp(0x0001)) // Public/Whisper flag
- {
- }
- else if (tlv.cmp(0x0005)) { // Message information
- bool uni = false;
- bool utf = false;
-
- int offset = 0;
- while (offset < tlv.len()) {
- TLV msg_tlv(tlv.val() + offset);
-
- // TLV List
- if (msg_tlv.cmp(0x0001)) {
- if (uni) {
- char* msg = msg_tlv.dupw();
- html_decode(msg);
- message = mir_utf8decodeW(msg);
- mir_free(msg);
- }
- else if (utf) {
- char* msg = msg_tlv.dup();
- html_decode(msg);
- message = mir_utf8decodeW(msg);
- mir_free(msg);
- }
- else {
- char* msg = msg_tlv.dup();
- html_decode(msg);
- message = mir_a2u(msg);
- mir_free(msg);
- }
- }
- else if (msg_tlv.cmp(0x0002)) {
- char* enc = msg_tlv.dup();
- uni = strstr(enc, "unicode-2-0") != nullptr;
- utf = strstr(enc, "utf-8") != nullptr;
- mir_free(enc);
- }
-
- offset += TLV_HEADER_SIZE + msg_tlv.len();
- }
- }
-
- tlv_offset += TLV_HEADER_SIZE + tlv.len();
- }
-
- chat_event(item->id, sn, GC_EVENT_MESSAGE, message);
-
- mir_free(message);
- mir_free(sn);
- }
-}
-
-void CAimProto::snac_admin_rate_limitations(SNAC &snac, HNETLIBCONN hServerConn, unsigned short &seqno)// family 0x0001
-{
- if (snac.subcmp(0x0007)) {
- aim_accept_rates(hServerConn, seqno);
- aim_admin_ready(hServerConn, seqno);
- SetEvent(m_hAdminEvent);
- }
-}
-
-void CAimProto::snac_admin_account_infomod(SNAC &snac) //family 0x0007
-{
- if (snac.subcmp(0x0003) || snac.subcmp(0x0005)) { // Handles info response and modification response
- bool err = false;
- bool req_email = false;
-
- WORD num_tlv = snac.ushort(2); // Number of TLVs
-
- char *sn = nullptr; // Screen Name
- char *email = nullptr; // Email address
-
- unsigned short offset = 0;
- for (int i = 0; i < num_tlv; i++) // Loop through all the TLVs
- {
- TLV tlv(snac.val(4 + offset));
-
- // TLV List
- if (tlv.cmp(0x0001))
- sn = tlv.dup();
-
- if (tlv.cmp(0x0011)) {
- req_email = true;
- email = tlv.dup();
- }
-
- if (tlv.cmp(0x0008)) { // Handles any problems when requesting/changing information
- err = true;
- admin_error(tlv.ushort());
- }
-
- offset += TLV_HEADER_SIZE + tlv.len();
- }
-
- if (snac.subcmp(0x0003) && !err) { // Requested info
- // Display messages
- if (email)
- setString(AIM_KEY_EM, email); // Save our email for future reference.
- if (sn)
- setString(AIM_KEY_SN, sn); // Update the database to reflect the formatted name.
- ProtoBroadcastAck(NULL, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE)1, 0);
-
- }
- else if (snac.subcmp(0x0005) && !err) { // Changed info
- // Display messages
- if (email && req_email) // We requested to change the email
- ShowPopup(LPGEN("A confirmation message has been sent to the new email address. Please follow its instructions."), 0);
- else if (sn) {
- setString(AIM_KEY_SN, sn); // Update the database to reflect the formatted name.
- //ShowPopup("Your Screen Name has been successfully formatted.", 0);
- }
- }
- mir_free(sn);
- mir_free(email);
- }
-}
-
-void CAimProto::snac_admin_account_confirm(SNAC &snac)//family 0x0007
-{
- if (snac.subcmp(0x0007)) {
- unsigned short status = 0;
-
- status = snac.ushort();
-
- switch (status) {
- case 0:
- ShowPopup(LPGEN("A confirmation message has been sent to your email address. Please follow its instructions."), 0);
- break;
-
- case 0x13:
- ShowPopup(LPGEN("Unable to confirm at this time. Please try again later."), 0);
- break;
-
- case 0x1e:
- ShowPopup(LPGEN("Your account has already been confirmed."), 0);
- break;
-
- case 0x23:
- ShowPopup(LPGEN("Can't start the confirmation procedure."), 0);
- break;
- }
- }
-}
diff --git a/protocols/AimOscar/src/services.cpp b/protocols/AimOscar/src/services.cpp
deleted file mode 100644
index 1012a1c611..0000000000
--- a/protocols/AimOscar/src/services.cpp
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2012 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#include "stdafx.h"
-
-INT_PTR CAimProto::GetMyAwayMsg(WPARAM wParam, LPARAM lParam)
-{
- char** msgptr = get_status_msg_loc(wParam ? wParam : m_iStatus);
- if (msgptr == nullptr) return 0;
-
- return (lParam & SGMA_UNICODE) ? (INT_PTR)mir_utf8decodeW(*msgptr) : (INT_PTR)mir_utf8decodeA(*msgptr);
-}
-
-int CAimProto::OnIdleChanged(WPARAM, LPARAM lParam)
-{
- if (m_state != 1) {
- m_idle = 0;
- return 0;
- }
-
- if (m_instantidle) //ignore- we are instant idling at the moment
- return 0;
-
- bool bIdle = (lParam & IDF_ISIDLE) != 0;
- bool bPrivacy = (lParam & IDF_PRIVACY) != 0;
-
- if (bPrivacy && m_idle) {
- aim_set_idle(m_hServerConn, m_seqno, 0);
- return 0;
- }
-
- if (bPrivacy)
- return 0;
-
- if (bIdle) //don't want to change idle time if we are already idle
- {
- MIRANDA_IDLE_INFO mii = { sizeof(mii) };
- CallService(MS_IDLE_GETIDLEINFO, 0, (LPARAM)&mii);
-
- m_idle = 1;
- aim_set_idle(m_hServerConn, m_seqno, mii.idleTime * 60);
- }
- else aim_set_idle(m_hServerConn, m_seqno, 0);
-
- return 0;
-}
-
-int CAimProto::OnWindowEvent(WPARAM, LPARAM lParam)
-{
- MessageWindowEventData* msgEvData = (MessageWindowEventData*)lParam;
-
- if (msgEvData->uType == MSG_WINDOW_EVT_CLOSE) {
- if (m_state != 1 || !is_my_contact(msgEvData->hContact))
- return 0;
-
- if (getWord(msgEvData->hContact, AIM_KEY_ST, ID_STATUS_OFFLINE) == ID_STATUS_ONTHEPHONE)
- return 0;
-
- DBVARIANT dbv;
- if (!getBool(msgEvData->hContact, AIM_KEY_BLS, false) && !getString(msgEvData->hContact, AIM_KEY_SN, &dbv)) {
- if (_stricmp(dbv.pszVal, SYSTEM_BUDDY))
- aim_typing_notification(m_hServerConn, m_seqno, dbv.pszVal, 0x000f);
- db_free(&dbv);
- }
- }
- return 0;
-}
-
-INT_PTR CAimProto::GetProfile(WPARAM wParam, LPARAM)
-{
- if (m_state != 1)
- return 0;
-
- DBVARIANT dbv;
- if (!getString(wParam, AIM_KEY_SN, &dbv)) {
- m_request_HTML_profile = 1;
- aim_query_profile(m_hServerConn, m_seqno, dbv.pszVal);
- db_free(&dbv);
- }
- return 0;
-}
-
-INT_PTR CAimProto::GetHTMLAwayMsg(WPARAM wParam, LPARAM)
-{
- if (m_state != 1)
- return 0;
-
- DBVARIANT dbv;
- if (!getString(wParam, AIM_KEY_SN, &dbv)) {
- m_request_away_message = 1;
- aim_query_away_message(m_hServerConn, m_seqno, dbv.pszVal);
- }
- return 0;
-}
-
-int CAimProto::OnDbSettingChanged(WPARAM hContact, LPARAM lParam)
-{
- DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam;
-
- if (strcmp(cws->szModule, MOD_KEY_CL) == 0 && m_state == 1 && hContact) {
- if (strcmp(cws->szSetting, AIM_KEY_NL) == 0) {
- if (cws->value.type == DBVT_DELETED) {
- DBVARIANT dbv;
- if (!db_get_utf(hContact, MOD_KEY_CL, OTH_KEY_GP, &dbv) && dbv.pszVal[0]) {
- add_contact_to_group(hContact, dbv.pszVal);
- db_free(&dbv);
- }
- else
- add_contact_to_group(hContact, AIM_DEFAULT_GROUP);
- }
- }
- else if (strcmp(cws->szSetting, "MyHandle") == 0) {
- char *name;
- switch (cws->value.type) {
- case DBVT_DELETED:
- set_local_nick(hContact, nullptr, nullptr);
- break;
-
- case DBVT_ASCIIZ:
- name = mir_utf8encode(cws->value.pszVal);
- set_local_nick(hContact, name, nullptr);
- mir_free(name);
- break;
-
- case DBVT_UTF8:
- set_local_nick(hContact, cws->value.pszVal, nullptr);
- break;
-
- case DBVT_WCHAR:
- name = mir_utf8encodeW(cws->value.pwszVal);
- set_local_nick(hContact, name, nullptr);
- mir_free(name);
- break;
- }
- }
- }
-
- return 0;
-}
-
-int CAimProto::OnContactDeleted(WPARAM hContact, LPARAM)
-{
- if (m_state != 1)
- return 0;
-
- if (db_get_b(hContact, MOD_KEY_CL, AIM_KEY_NL, 0))
- return 0;
-
- DBVARIANT dbv;
- if (!getString(hContact, AIM_KEY_SN, &dbv)) {
- for (int i = 1;; ++i) {
- unsigned short item_id = getBuddyId(hContact, i);
- if (item_id == 0) break;
-
- unsigned short group_id = getGroupId(hContact, i);
- if (group_id) {
- bool is_not_in_list = getBool(hContact, AIM_KEY_NIL, false);
- aim_ssi_update(m_hServerConn, m_seqno, true);
- aim_delete_contact(m_hServerConn, m_seqno, dbv.pszVal, item_id, group_id, 0, is_not_in_list);
- char *group = m_group_list.find_name(group_id);
- update_server_group(group, group_id);
- aim_ssi_update(m_hServerConn, m_seqno, false);
- }
- }
- db_free(&dbv);
- }
- return 0;
-}
-
-
-int CAimProto::OnGroupChange(WPARAM hContact, LPARAM lParam)
-{
- if (m_state != 1 || !getByte(AIM_KEY_MG, 1))
- return 0;
-
- CLISTGROUPCHANGE *grpchg = (CLISTGROUPCHANGE*)lParam;
-
- if (hContact == NULL) {
- if (grpchg->pszNewName == nullptr && grpchg->pszOldName != nullptr) {
- T2Utf szOldName(grpchg->pszOldName);
- unsigned short group_id = m_group_list.find_id(szOldName);
- if (group_id) {
- aim_delete_contact(m_hServerConn, m_seqno, szOldName, 0, group_id, 1, false);
- m_group_list.remove_by_id(group_id);
- update_server_group("", 0);
- }
- }
- else if (grpchg->pszNewName != nullptr && grpchg->pszOldName != nullptr) {
- unsigned short group_id = m_group_list.find_id(T2Utf(grpchg->pszOldName));
- if (group_id)
- update_server_group(T2Utf(grpchg->pszNewName), group_id);
- }
- }
- else {
- if (is_my_contact(hContact) && getBuddyId(hContact, 1) && !db_get_b(hContact, MOD_KEY_CL, AIM_KEY_NL, 0)) {
- if (grpchg->pszNewName)
- add_contact_to_group(hContact, T2Utf(grpchg->pszNewName));
- else
- add_contact_to_group(hContact, AIM_DEFAULT_GROUP);
- }
- }
- return 0;
-}
-
-INT_PTR CAimProto::AddToServerList(WPARAM hContact, LPARAM)
-{
- if (m_state != 1)
- return 0;
-
- DBVARIANT dbv;
- if (!db_get_utf(hContact, MOD_KEY_CL, OTH_KEY_GP, &dbv) && dbv.pszVal[0]) {
- add_contact_to_group(hContact, dbv.pszVal);
- db_free(&dbv);
- }
- else add_contact_to_group(hContact, AIM_DEFAULT_GROUP);
- return 0;
-}
-
-INT_PTR CAimProto::BlockBuddy(WPARAM hContact, LPARAM)
-{
- if (m_state != 1)
- return 0;
-
- unsigned short item_id;
- DBVARIANT dbv;
- if (getString(hContact, AIM_KEY_SN, &dbv))
- return 0;
-
- switch (m_pd_mode) {
- case 1:
- m_pd_mode = 4;
- aim_set_pd_info(m_hServerConn, m_seqno);
-
- case 4:
- item_id = m_block_list.find_id(dbv.pszVal);
- if (item_id != 0) {
- m_block_list.remove_by_id(item_id);
- aim_delete_contact(m_hServerConn, m_seqno, dbv.pszVal, item_id, 0, 3, false);
- }
- else {
- item_id = m_block_list.add(dbv.pszVal);
- aim_add_contact(m_hServerConn, m_seqno, dbv.pszVal, item_id, 0, 3, nullptr);
- }
- break;
-
- case 2:
- m_pd_mode = 3;
- aim_set_pd_info(m_hServerConn, m_seqno);
-
- case 3:
- item_id = m_allow_list.find_id(dbv.pszVal);
- if (item_id != 0) {
- m_allow_list.remove_by_id(item_id);
- aim_delete_contact(m_hServerConn, m_seqno, dbv.pszVal, item_id, 0, 2, false);
- }
- else {
- item_id = m_allow_list.add(dbv.pszVal);
- aim_add_contact(m_hServerConn, m_seqno, dbv.pszVal, item_id, 0, 2);
- }
- break;
- }
- db_free(&dbv);
-
- return 0;
-}
-
-INT_PTR CAimProto::JoinChatUI(WPARAM, LPARAM)
-{
- DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_CHAT), nullptr, join_chat_dialog, LPARAM(this));
- return 0;
-}
-
-INT_PTR CAimProto::OnJoinChat(WPARAM hContact, LPARAM)
-{
- if (m_state != 1)
- return 0;
-
- DBVARIANT dbv;
- if (!getString(hContact, "ChatRoomID", &dbv)) {
- chatnav_param* par = new chatnav_param(dbv.pszVal, getWord(hContact, "Exchange", 4));
- ForkThread(&CAimProto::chatnav_request_thread, par);
- db_free(&dbv);
- }
- return 0;
-}
-
-INT_PTR CAimProto::OnLeaveChat(WPARAM wParam, LPARAM)
-{
- if (m_state != 1)
- return 0;
-
- MCONTACT hContact = wParam;
-
- DBVARIANT dbv;
- if (!getString(hContact, "ChatRoomID", &dbv)) {
- chat_leave(dbv.pszVal);
- db_free(&dbv);
- }
- return 0;
-}
-
-INT_PTR CAimProto::InstantIdle(WPARAM, LPARAM)
-{
- DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_IDLE), nullptr, instant_idle_dialog, LPARAM(this));
- return 0;
-}
-
-INT_PTR CAimProto::ManageAccount(WPARAM, LPARAM)
-{
- ShellExecuteA(nullptr, "open", "https://my.screenname.aol.com", nullptr, nullptr, SW_SHOW);
- return 0;
-}
-
-INT_PTR CAimProto::GetAvatarInfo(WPARAM wParam, LPARAM lParam)
-{
- PROTO_AVATAR_INFORMATION *pai = (PROTO_AVATAR_INFORMATION*)lParam;
-
- pai->filename[0] = 0;
- pai->format = PA_FORMAT_UNKNOWN;
-
- if (getByte(AIM_KEY_DA, 0))
- return GAIR_NOAVATAR;
-
- switch (get_avatar_filename(pai->hContact, pai->filename, _countof(pai->filename), nullptr)) {
- case GAIR_SUCCESS:
- if (!(wParam & GAIF_FORCE) || m_state != 1)
- return GAIR_SUCCESS;
-
- case GAIR_WAITFOR:
- pai->format = ProtoGetAvatarFormat(pai->filename);
- break;
-
- default:
- return GAIR_NOAVATAR;
- }
-
- if (m_state == 1) {
- ForkThread(&CAimProto::avatar_request_thread, (void*)pai->hContact);
- return GAIR_WAITFOR;
- }
-
- return GAIR_NOAVATAR;
-}
-
-INT_PTR CAimProto::GetAvatarCaps(WPARAM wParam, LPARAM lParam)
-{
- int res = 0;
-
- switch (wParam) {
- case AF_MAXSIZE:
- ((POINT*)lParam)->x = 100;
- ((POINT*)lParam)->y = 100;
- break;
-
- case AF_MAXFILESIZE:
- res = 11264;
- break;
-
- case AF_PROPORTION:
- res = PIP_SQUARE;
- break;
-
- case AF_FORMATSUPPORTED:
- res = (lParam == PA_FORMAT_JPEG || lParam == PA_FORMAT_GIF || lParam == PA_FORMAT_BMP);
- break;
-
- case AF_ENABLED:
- case AF_DONTNEEDDELAYS:
- case AF_FETCHIFPROTONOTVISIBLE:
- case AF_FETCHIFCONTACTOFFLINE:
- res = 1;
- break;
- }
-
- return res;
-}
-
-INT_PTR CAimProto::GetAvatar(WPARAM wParam, LPARAM lParam)
-{
- wchar_t* buf = (wchar_t*)wParam;
- size_t size = (size_t)lParam;
- if (buf == nullptr || size <= 0)
- return -1;
-
- PROTO_AVATAR_INFORMATION ai = { 0 };
- if (GetAvatarInfo(0, (LPARAM)&ai) == GAIR_SUCCESS) {
- wcsncpy_s(buf, size, ai.filename, _TRUNCATE);
- return 0;
- }
-
- return -1;
-}
-
-INT_PTR CAimProto::SetAvatar(WPARAM, LPARAM lParam)
-{
- wchar_t *szFileName = (wchar_t*)lParam;
-
- if (m_state != 1)
- return 1;
-
- if (szFileName == nullptr) {
- aim_ssi_update(m_hServerConn, m_seqno, true);
- aim_delete_avatar_hash(m_hServerConn, m_seqno, 1, 1, m_avatar_id_sm);
- aim_delete_avatar_hash(m_hServerConn, m_seqno, 1, 12, m_avatar_id_lg);
- aim_ssi_update(m_hServerConn, m_seqno, false);
-
- avatar_request_handler(NULL, nullptr, 0);
- }
- else {
- char hash[16], hash1[16], *data, *data1 = nullptr;
- unsigned short size, size1 = 0;
-
- if (!get_avatar_hash(szFileName, hash, &data, size)) {
- mir_free(hash);
- return 1;
- }
-
- rescale_image(data, size, data1, size1);
-
- if (size1) {
- mir_md5_state_t state;
- mir_md5_init(&state);
- mir_md5_append(&state, (unsigned char*)data1, size1);
- mir_md5_finish(&state, (unsigned char*)hash1);
-
- mir_free(m_hash_lg); m_hash_lg = bytes_to_string(hash, sizeof(hash));
- mir_free(m_hash_sm); m_hash_sm = bytes_to_string(hash1, sizeof(hash1));
-
- aim_ssi_update(m_hServerConn, m_seqno, true);
- aim_set_avatar_hash(m_hServerConn, m_seqno, 1, 1, m_avatar_id_sm, 16, hash1);
- aim_set_avatar_hash(m_hServerConn, m_seqno, 1, 12, m_avatar_id_lg, 16, hash);
- aim_ssi_update(m_hServerConn, m_seqno, false);
- }
- else {
- mir_free(m_hash_lg); m_hash_lg = nullptr;
- mir_free(m_hash_sm); m_hash_sm = bytes_to_string(hash, sizeof(hash1));
-
- aim_ssi_update(m_hServerConn, m_seqno, true);
- aim_set_avatar_hash(m_hServerConn, m_seqno, 1, 1, m_avatar_id_sm, 16, hash);
- aim_delete_avatar_hash(m_hServerConn, m_seqno, 1, 12, m_avatar_id_lg);
- aim_ssi_update(m_hServerConn, m_seqno, false);
- }
-
- avatar_request_handler(NULL, nullptr, 0);
-
- avatar_up_req *req = new avatar_up_req(data, size, data1, size1);
- ForkThread(&CAimProto::avatar_upload_thread, req);
-
- wchar_t tFileName[MAX_PATH];
- wchar_t *ext = wcsrchr(szFileName, '.');
- get_avatar_filename(NULL, tFileName, _countof(tFileName), ext);
- int fileId = _wopen(tFileName, _O_CREAT | _O_TRUNC | _O_WRONLY | O_BINARY, _S_IREAD | _S_IWRITE);
- if (fileId < 0) {
- char errmsg[512];
- mir_snprintf(errmsg, "Cannot store avatar. File '%s' could not be created/overwritten", tFileName);
- ShowPopup(errmsg, ERROR_POPUP);
- return 1;
- }
- _write(fileId, data, size);
- _close(fileId);
- }
- return 0;
-}
diff --git a/protocols/AimOscar/src/snac.cpp b/protocols/AimOscar/src/snac.cpp
deleted file mode 100644
index 0dd1c12d3f..0000000000
--- a/protocols/AimOscar/src/snac.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#include "stdafx.h"
-
-SNAC::SNAC(char* buf,unsigned short length)
-{
- service_=_htons((*(unsigned short*)&buf[0]));
- subgroup_=_htons((*(unsigned short*)&buf[2]));
- flags_=_htons((*(unsigned short*)&buf[4]));
- idh_=_htons((*(unsigned short*)&buf[6]));
- id_=_htons((*(unsigned short*)&buf[8]));
- value_=&buf[SNAC_SIZE];
- length_=length;
-}
-int SNAC::cmp(unsigned short service)
-{
- if (service_==service)
- return 1;
- else
- return 0;
-}
-int SNAC::subcmp(unsigned short subgroup)
-{
- if (subgroup_==subgroup)
- return 1;
- else
- return 0;
-}
-unsigned short SNAC::ushort(int pos)
-{
- return _htons(*(unsigned short*)&value_[pos]);
-}
-unsigned long SNAC::ulong(int pos)
-{
- return _htonl(*(unsigned long*)&value_[pos]);
-}
-unsigned char SNAC::ubyte(int pos)
-{
- return value_[pos];
-}
-char* SNAC::part(int pos, int length)
-{
- char* value = (char*)mir_alloc(length+1);
- memcpy(value, &value_[pos], length);
- value[length] = '\0';
- return value;
-}
diff --git a/protocols/AimOscar/src/snac.h b/protocols/AimOscar/src/snac.h
deleted file mode 100644
index 5c97462f22..0000000000
--- a/protocols/AimOscar/src/snac.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef SNAC_H
-#define SNAC_H
-
-#define SNAC_SIZE 10
-
-class SNAC
-{
- unsigned short service_;
- unsigned short subgroup_;
- unsigned short length_;
- unsigned short flags_;
- unsigned short idh_;
- unsigned short id_;
- char *value_;
-
-public:
- SNAC(char *buf, unsigned short length);
- int cmp(unsigned short service);
- int subcmp(unsigned short subgroup);
- unsigned short ushort(int pos = 0);
- unsigned long ulong(int pos = 0);
- unsigned char ubyte(int pos = 0);
- char* part(int pos, int length);
- char* val(int pos = 0) { return &value_[pos]; }
- unsigned short len(void) { return length_; }
- unsigned short flags(void) { return flags_; }
- unsigned short id(void) { return id_; }
- unsigned short idh(void) { return idh_; }
-};
-
-#endif
diff --git a/protocols/AimOscar/src/stdafx.cxx b/protocols/AimOscar/src/stdafx.cxx
deleted file mode 100644
index b05ed73bc5..0000000000
--- a/protocols/AimOscar/src/stdafx.cxx
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
-Copyright (C) 2012-17 Miranda NG project (https://miranda-ng.org)
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation version 2
-of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h" \ No newline at end of file
diff --git a/protocols/AimOscar/src/stdafx.h b/protocols/AimOscar/src/stdafx.h
deleted file mode 100755
index 42beead6a0..0000000000
--- a/protocols/AimOscar/src/stdafx.h
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2012 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef AIM_H
-#define AIM_H
-
-//System includes
-#include <windows.h>
-#include <fcntl.h>
-#include <io.h>
-#include <richedit.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <malloc.h>
-#include <Uxtheme.h>
-
-//Miranda NG includes
-#include <msapi/vssym32.h>
-#include <newpluginapi.h>
-#include <m_avatars.h>
-#include <m_button.h>
-#include <m_chat.h>
-#include <m_clist.h>
-#include <m_database.h>
-#include <m_history.h>
-#include <m_idle.h>
-#include <m_langpack.h>
-#include <m_message.h>
-#include <m_netlib.h>
-#include <m_options.h>
-#include <m_popup.h>
-#include <m_userinfo.h>
-#include <m_icolib.h>
-#include <m_imgsrvc.h>
-#include <win2k.h>
-#include <m_extraicons.h>
-#include <m_protoint.h>
-#include <m_xml.h>
-
-#include <m_folders.h>
-#include <m_assocmgr.h>
-
-//rest of includes
-#include "avatars.h"
-#include "utility.h"
-#include "chat.h"
-#include "direct_connect.h"
-#include "conv.h"
-#include "file.h"
-#include "flap.h"
-#include "links.h"
-#include "snac.h"
-#include "tlv.h"
-#include "packets.h"
-#include "proxy.h"
-#include "resource.h"
-#include "proto.h"
-#include "theme.h"
-#include "ui.h"
-#include "version.h"
-
-// Protocol limits
-#define MAX_SCREEN_NAME_LENGTH 97
-#define MAX_GROUP_NAME_LENGTH 48
-#define MAX_NICKNAME_LENGTH 64
-#define MAX_MESSAGE_LENGTH 3978
-#define MAX_STATUS_MESSAGE_LENGTH 251
-#define MAX_AWAY_MESSAGE_LENGTH 4096
-#define MAX_ICON_SIZE 7168
-
-// ICBM parameter flags
-#define ICBM_CHANNEL_MSGS_ALLOWED 0x00000001
-#define ICBM_MISSED_CALLS_ENABLED 0x00000002
-#define ICBM_EVENTS_ALLOWED 0x00000008
-#define ICBM_SMS_SUPPORTED 0x00000010
-#define ICBM_OFFLINE_MSGS_ALLOWED 0x00000100
-
-// SSI preferences
-#define SHOW_IDLE 0x00000400
-#define SHOW_RECENT_BUDDIES 0x00020000
-#define SHOW_TYPING 0x00400000
-
-//Extended Status Icon Numbers
-#define ACCOUNT_TYPE_UNCONFIRMED 1
-#define ACCOUNT_TYPE_CONFIRMED 2
-#define ACCOUNT_TYPE_ICQ 3
-#define ACCOUNT_TYPE_AOL 4
-#define ACCOUNT_TYPE_ADMIN 5
-#define EXTENDED_STATUS_BOT 1
-#define EXTENDED_STATUS_HIPTOP 2
-
-//Popup flags
-#define MAIL_POPUP 0x04
-#define ERROR_POPUP 0x08
-#define TCHAR_POPUP 0x10
-
-//Main Option Window Keys
-#define AIM_KEY_SN "SN"
-#define AIM_KEY_NK "Nick"
-#define AIM_KEY_PW "Password"
-#define AIM_KEY_HN "loginhost"
-#define AIM_KEY_PN "loginport"
-#define AIM_KEY_DC "DelConf"//delivery confirmation
-#define AIM_KEY_FP "ForceProxyTransfer"
-#define AIM_KEY_HF "HiptopFake"
-#define AIM_KEY_AT "DisableATIcons"
-#define AIM_KEY_ES "DisableESIcons"
-#define AIM_KEY_DM "DisableModeMsg"
-#define AIM_KEY_FI "FormatIncoming"//html->bbcodes
-#define AIM_KEY_FO "FormatOutgoing"//bbcodes->html
-#define AIM_KEY_II "InstantIdle"
-#define AIM_KEY_IIT "InstantIdleTS"
-#define AIM_KEY_CM "CheckMail"
-#define AIM_KEY_MG "ManageGroups"
-#define AIM_KEY_DA "DisableAvatars"
-#define AIM_KEY_DSSL "DisableSSL"
-#define AIM_KEY_CLIENTLOGIN "UseClientLogin"
-#define AIM_KEY_FSC "ForceSingleClient"
-
-#define OTH_KEY_SM "StatusMsg"
-#define OTH_KEY_GP "Group"
-//Module Name Key
-#define MOD_KEY_CL "CList"
-//Settings Keys
-#define AIM_KEY_PR "Profile"
-#define AIM_KEY_LA "LastAwayChange"
-//Contact Keys
-#define AIM_KEY_BI "BuddyId"
-#define AIM_KEY_GI "GroupId"
-#define AIM_KEY_ST "Status"
-#define AIM_KEY_IT "IdleTS"
-#define AIM_KEY_OT "LogonTS"
-#define AIM_KEY_MS "MemberTS"
-#define AIM_KEY_AC "AccType"//account type
-#define AIM_KEY_ET "ESType"//Extended Status type
-#define AIM_KEY_MV "MirVer"
-#define AIM_KEY_US "Utf8Support"
-#define AIM_KEY_NL "NotOnList"
-#define AIM_KEY_LM "LastMessage"
-#define AIM_KEY_AH "AvatarHash"
-#define AIM_KEY_AHT "AvatarType"
-#define AIM_KEY_EM "e-mail"
-#define AIM_KEY_LV "LastVer"
-#define AIM_KEY_TIS "TotalIMsSent"
-#define AIM_KEY_TIR "TotalIMsReceived"
-#define AIM_KEY_TAM "TotalAwayMessages"
-#define AIM_KEY_TTO "TotalTimeOnline"
-#define AIM_KEY_BLS "IsBlast"
-#define AIM_KEY_NIL "IsNotInList"
-
-#define AIM_LOGIN_URL "https://api.screenname.aol.com/auth/clientLogin"
-#define AIM_SESSION_URL "https://api.oscar.aol.com/aim/startOSCARSession"
-#define AIM_DEFAULT_CLIENT_KEY "ma15d7JTxbmVG-RP" //this one from libpurple, i am not able to create one, sorry guys
-#define AIM_DEFAULT_DISTID "1553" //this one from libpurple, i am not able to create one, sorry guys
-
-
-
-#define AIM_DEFAULT_SERVER "login.oscar.aol.com"
-#define AIM_PROXY_SERVER "ars.oscar.aol.com"
-#define AIM_DEFAULT_PORT 5190
-
-//Some Defaults for various things
-#define DEFAULT_KEEPALIVE_TIMER 39 // secs
-#define DEFAULT_GRACE_PERIOD 60
-#define AIM_DEFAULT_GROUP "miranda merged"
-#define SYSTEM_BUDDY "aolsystemmsg"
-#define DEFAULT_AWAY_MSG "I am away from my computer right now."
-//Md5 Roasting stuff
-#define AIM_MD5_STRING "AOL Instant Messenger (SM)"
-#define MD5_HASH_LENGTH 16
-
-//Aim Version Stuff
-#define AIM_CLIENT_MAJOR_VERSION 0x0005
-#define AIM_CLIENT_MINOR_VERSION 0x0001
-#define AIM_CLIENT_LESSER_VERSION 0x0000
-#define AIM_CLIENT_BUILD_NUMBER 0x0bdc
-#define AIM_CLIENT_ID_NUMBER 0x0109
-#define AIM_CLIENT_DISTRIBUTION_NUMBER 0x0611
-
-#define AIM_LANGUAGE "en"
-#define AIM_COUNTRY "us"
-#define AIM_MSG_TYPE "text/x-aolrtf; charset=\"us-ascii\""
-#define AIM_MSG_TYPE_UNICODE "text/x-aolrtf; charset=\"unicode-2-0\""
-#define AIM_TOOL_VERSION "\x01\x10\x18\xf1"
-
-//Supported Clients
-#define CLIENT_UNKNOWN "?"
-#define CLIENT_AIM5 "AIM 5.x"
-#define CLIENT_AIM4 "AIM 4.x"
-#define CLIENT_AIMEXPRESS5 "AIM Express 5"
-#define CLIENT_AIMEXPRESS6 "AIM Express 6"
-#define CLIENT_AIMEXPRESS7 "AIM Express 7"
-#define CLIENT_ICQ "ICQ"
-#define CLIENT_AIM_TRITON "AIM Triton"
-#define CLIENT_AIM6_1 "AIM 6.1"
-#define CLIENT_AIM6_5 "AIM 6.5"
-#define CLIENT_AIM6_8 "AIM 6.8"
-#define CLIENT_AIM6_9 "AIM 6.9"
-#define CLIENT_AIM7_0 "AIM 7.0"
-#define CLIENT_AIMTOC "AIM TOC"
-#define CLIENT_BOT "AIM Bot"
-#define CLIENT_GAIM "Gaim"
-#define CLIENT_PURPLE "Purple"
-#define CLIENT_ADIUM "Adium X"
-#define CLIENT_GPRS "GPRS"
-#define CLIENT_ICHAT "iChat"
-#define CLIENT_IM2 "IM2"
-#define CLIENT_KOPETE "Kopete"
-#define CLIENT_MEEBO "Meebo"
-#define CLIENT_DIGSBY "Digsby"
-#define CLIENT_BEEJIVE "beejive"
-#define CLIENT_MICQ "mICQ"
-#define CLIENT_AIMOSCAR "Miranda IM %d.%d.%d.%d (AIM v%d.%d.%d.%d)"
-#define CLIENT_OSCARJ "Miranda IM %d.%d.%d.%d%s (ICQ v%d.%d.%d.%d%s)"
-#define CLIENT_OSCARSN "Miranda IM %d.%d.%d.%d%s (ICQ S!N v%d.%d.%d.%d%s)%s"
-#define CLIENT_OSCARPL "Miranda IM %d.%d.%d.%d%s (ICQ Plus v%d.%d.%d.%d%s)%s"
-#define CLIENT_NAIM "naim"
-#define CLIENT_QIP "qip"
-#define CLIENT_SIM "SIM"
-#define CLIENT_SMS "SMS"
-#define CLIENT_TERRAIM "TerraIM"
-#define CLIENT_TRILLIAN_PRO "Trillian Pro"
-#define CLIENT_TRILLIAN "Trillian"
-#define CLIENT_TRILLIAN_ASTRA "Trillian Astra"
-#define CLIENT_BLAST "Blast Group"
-
-//Aim Caps
-#define AIM_CAPS_LENGTH 16
-
-// Official
-#define AIM_CAP_SHORT_CAPS "\x09\x46\x00\x00\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_SECURE_IM "\x09\x46\x00\x01\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_XHTML_IM "\x09\x46\x00\x02\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_RTCVIDEO "\x09\x46\x01\x01\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_HAS_MICROPHONE "\x09\x46\x01\x02\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_HAS_CAMERA "\x09\x46\x01\x03\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_RTCAUDIO "\x09\x46\x01\x04\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_HOST_STATUS_TEXT_AWARE "\x09\x46\x01\x0a\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_RT_IM "\x09\x46\x01\x0b\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_SMART_CAPS "\x09\x46\x01\xff\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_FILE_TRANSFER "\x09\x46\x13\x43\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_DIRECT_IM "\x09\x46\x13\x45\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_FILE_SHARING "\x09\x46\x13\x48\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_SUPPORT_ICQ "\x09\x46\x13\x4D\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-
-#define AIM_CAP_AVAILABLE_FOR_CALL "\x09\x46\x01\x05\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_ACA "\x09\x46\x01\x06\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_MULTI_AUDIO "\x09\x46\x01\x07\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_MULTI_VIDEO "\x09\x46\x01\x08\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_VICEROY "\x09\x46\xf0\x04\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_BUDDY_ICON "\x09\x46\x13\x46\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_VOICE_CHAT "\x09\x46\x13\x41\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_DIRECT_PLAY "\x09\x46\x13\x42\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_ICQ_DIRECT_CONNECT "\x09\x46\x13\x44\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_GAMES "\x09\x46\x13\x47\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_ICQ_SERVER_RELAY "\x09\x46\x13\x49\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"//icq? channel 2 extended, TLV(0x2711) based messages
-#define AIM_CAP_CHAT_ROBOTS "\x09\x46\x13\x4A\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_SHARE_BUDDIES "\x09\x46\x13\x4B\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_CHAT "\x74\x8F\x24\x20\x62\x87\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_AMO "\x09\x46\x01\x0c\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-
-// Extensions
-#define AIM_CAP_HIPTOP "\x09\x46\x13\x23\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_UTF8 "\x09\x46\x13\x4E\x4C\x7F\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_UNKNOWN4 "\x09\x46\xf0\x03\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_UNKNOWNC "\x09\x46\xf0\x05\x4c\x7f\x11\xD1\x82\x22\x44\x45\x53\x54\0\0"
-#define AIM_CAP_IM2 "\x74\xed\xc3\x36\x44\xdf\x48\x5b\x8b\x1c\x67\x1a\x1f\x86\x09\x9f"
-#define AIM_CAP_TRILLIAN "\xF2\xE7\xC7\xF4\xFE\xAD\x4D\xFB\xB2\x35\x36\x79\x8B\xDF\0\0"
-extern char AIM_CAP_MIRANDA[]; //Miranda cap EXTERN
-
-//Aim Services
-#define AIM_SERVICE_GENERIC "\0\x01\0\x04"//version 4
-#define AIM_SERVICE_SSI "\0\x13\0\x03"//version 3
-#define AIM_SERVICE_LOCATION "\0\x02\0\x01"//version 1
-#define AIM_SERVICE_BUDDYLIST "\0\x03\0\x01"//version 1
-#define AIM_SERVICE_MESSAGING "\0\x04\0\x01"//version 1
-#define AIM_SERVICE_INVITATION "\0\x06\0\x01"//version 1
-#define AIM_SERVICE_ADMIN "\0\x07\0\x01"//version 1
-#define AIM_SERVICE_POPUP "\0\x08\0\x01"//version 1
-#define AIM_SERVICE_BOS "\0\x09\0\x01"//version 1
-#define AIM_SERVICE_AVATAR "\0\x10\0\x01"//version 1
-#define AIM_SERVICE_USERLOOKUP "\0\x0A\0\x01"//version 1
-#define AIM_SERVICE_STATS "\0\x0B\0\x01"//version 1
-#define AIM_SERVICE_CHATNAV "\0\x0D\0\x01"//version 1
-#define AIM_SERVICE_DIRSEARCH "\0\x0F\0\x01"//version 1
-#define AIM_SERVICE_CHAT "\0\x0E\0\x01"//version 1
-#define AIM_SERVICE_ICQ "\0\x15\0\x01"//version 1
-#define AIM_SERVICE_MAIL "\0\x18\0\x01"//version 1
-#define AIM_SERVICE_UNKNOWN "\0\x22\0\x01"//version 1
-#define AIM_SERVICE_RATES "\0\x01\0\x02\0\x03\0\x04\0\x05"
-
-//Aim Statuses
-#define AIM_STATUS_WEBAWARE "\0\x01"
-#define AIM_STATUS_SHOWIP "\0\x02"
-#define AIM_STATUS_BIRTHDAY "\0\x08"
-#define AIM_STATUS_WEBFRONT "\0\x20"
-#define AIM_STATUS_DCAUTH "\x10\0"
-#define AIM_STATUS_DCCONT "\x20\0"
-#define AIM_STATUS_NULL "\0\0"
-
-#define AIM_STATUS_ONLINE 0x00000000
-#define AIM_STATUS_AWAY 0x00000001
-#define AIM_STATUS_DND 0x00000002
-#define AIM_STATUS_OUT 0x00000004
-#define AIM_STATUS_BUSY 0x00000010
-#define AIM_STATUS_CHAT 0x00000020 // Broken. If set, you cannot unset.
-#define AIM_STATUS_INVISIBLE 0x00000100
-
-extern HINSTANCE hInstance; //plugin dll instance
-
-#endif
diff --git a/protocols/AimOscar/src/theme.cpp b/protocols/AimOscar/src/theme.cpp
deleted file mode 100644
index 762c841a39..0000000000
--- a/protocols/AimOscar/src/theme.cpp
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#include "stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Icons init
-
-static IconItem iconList[] =
-{
- { LPGEN("ICQ"), "icq", IDI_ICQ },
- { LPGEN("Add"), "add", IDI_ADD },
- { LPGEN("Block"), "block", IDI_BLOCK },
- { LPGEN("Profile"), "profile", IDI_PROFILE },
- { LPGEN("AOL mail"), "mail", IDI_MAIL },
- { LPGEN("AIM icon"), "aim", IDI_AIM },
- { LPGEN("Hiptop"), "hiptop", IDI_HIPTOP },
- { LPGEN("AOL bot"), "bot", IDI_BOT },
- { LPGEN("Admin"), "admin", IDI_ADMIN },
- { LPGEN("Confirmed"), "confirm", IDI_CONFIRMED },
- { LPGEN("Not confirmed"), "uconfirm", IDI_UNCONFIRMED },
- { LPGEN("Blocked list"), "away", IDI_AWAY },
- { LPGEN("Idle"), "idle", IDI_IDLE },
- { LPGEN("AOL"), "aol", IDI_AOL },
-
- { LPGEN("Foreground color"), "foreclr", IDI_FOREGROUNDCOLOR },
- { LPGEN("Background color"), "backclr", IDI_BACKGROUNDCOLOR },
- { LPGEN("Bold"), "bold", IDI_BOLD },
- { LPGEN("Not bold"), "nbold", IDI_NBOLD },
- { LPGEN("Italic"), "italic", IDI_ITALIC },
- { LPGEN("Not italic"), "nitalic", IDI_NITALIC },
- { LPGEN("Underline"), "undrln", IDI_UNDERLINE },
- { LPGEN("Not underline"), "nundrln", IDI_NUNDERLINE },
- { LPGEN("Subscript"), "sub_scrpt", IDI_SUBSCRIPT },
- { LPGEN("Not subscript"), "nsub_scrpt", IDI_NSUBSCRIPT },
- { LPGEN("Superscript"), "sup_scrpt", IDI_SUPERSCRIPT },
- { LPGEN("Not superscript"), "nsup_scrpt", IDI_NSUPERSCRIPT },
- { LPGEN("Normal script"), "norm_scrpt", IDI_NORMALSCRIPT },
- { LPGEN("Not normal script"), "nnorm_scrpt", IDI_NNORMALSCRIPT }
-};
-
-void InitIcons(void)
-{
- Icon_Register(hInstance, "Protocols/AIM", iconList, 14, "AIM");
- Icon_Register(hInstance, "Protocols/AIM/" LPGEN("Profile editor"), iconList + 14, 14, "AIM");
-}
-
-HICON LoadIconEx(const char *name, bool big)
-{
- char szSettingName[100];
- mir_snprintf(szSettingName, "AIM_%s", name);
- return IcoLib_GetIcon(szSettingName, big);
-}
-
-HANDLE GetIconHandle(const char *name)
-{
- for (int i = 0; i < _countof(iconList); i++)
- if (!mir_strcmp(iconList[i].szName, name))
- return iconList[i].hIcolib;
-
- return nullptr;
-}
-
-void ReleaseIconEx(const char *name, bool big)
-{
- char szSettingName[100];
- mir_snprintf(szSettingName, "%s_%s", "AIM", name);
- IcoLib_Release(szSettingName, big);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Extra Icons
-
-extern OBJLIST<CAimProto> g_Instances;
-
-static HANDLE bot_icon, icq_icon, aol_icon, hiptop_icon;
-static HANDLE admin_icon, confirmed_icon, unconfirmed_icon;
-
-static HANDLE hExtraAT, hExtraES;
-
-static const char* extra_AT_icon_name[5] =
-{
- "uconfirm",
- "confirm",
- "icq",
- "aol",
- "admin",
-};
-
-static const char* extra_ES_icon_name[2] =
-{
- "bot",
- "hiptop",
-};
-
-static void set_AT_icon(CAimProto* ppro, MCONTACT hContact)
-{
- if (ppro->isChatRoom(hContact)) return;
-
- unsigned i = ppro->getByte(hContact, AIM_KEY_AC, 0) - 1;
- ExtraIcon_SetIcon(hExtraAT, hContact, (i < 5) ? GetIconHandle(extra_AT_icon_name[i]) : nullptr);
-}
-
-static void set_ES_icon(CAimProto* ppro, MCONTACT hContact)
-{
- if (ppro->isChatRoom(hContact)) return;
-
- unsigned i = ppro->getByte(hContact, AIM_KEY_ET, 0) - 1;
- ExtraIcon_SetIcon(hExtraAT, hContact, (i < 2) ? GetIconHandle(extra_ES_icon_name[i]) : nullptr);
-}
-
-void set_contact_icon(CAimProto* ppro, MCONTACT hContact)
-{
- if (!ppro->getByte(AIM_KEY_AT, 0)) set_AT_icon(ppro, hContact);
- if (!ppro->getByte(AIM_KEY_ES, 0)) set_ES_icon(ppro, hContact);
-}
-
-void remove_AT_icons(CAimProto* ppro)
-{
- for (MCONTACT hContact = db_find_first(ppro->m_szModuleName); hContact; hContact = db_find_next(hContact, ppro->m_szModuleName))
- if (!ppro->isChatRoom(hContact))
- ExtraIcon_Clear(hExtraAT, hContact);
-}
-
-void remove_ES_icons(CAimProto* ppro)
-{
- for (MCONTACT hContact = db_find_first(ppro->m_szModuleName); hContact; hContact = db_find_next(hContact, ppro->m_szModuleName))
- if (!ppro->isChatRoom(hContact))
- ExtraIcon_Clear(hExtraES, hContact);
-}
-
-void add_AT_icons(CAimProto* ppro)
-{
- for (MCONTACT hContact = db_find_first(ppro->m_szModuleName); hContact; hContact = db_find_next(hContact, ppro->m_szModuleName))
- set_AT_icon(ppro, hContact);
-}
-
-void add_ES_icons(CAimProto* ppro)
-{
- for (MCONTACT hContact = db_find_first(ppro->m_szModuleName); hContact; hContact = db_find_next(hContact, ppro->m_szModuleName))
- set_ES_icon(ppro, hContact);
-}
-
-void InitExtraIcons(void)
-{
- hExtraAT = ExtraIcon_RegisterIcolib("aimaccounttype", LPGEN("AIM account type"), "AIM_aol");
- hExtraES = ExtraIcon_RegisterIcolib("aimextstatus", LPGEN("AIM extended status"), "AIM_hiptop");
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// OnPreBuildContactMenu
-
-int CAimProto::OnPreBuildContactMenu(WPARAM hContact, LPARAM)
-{
- bool bIsChatRoom = isChatRoom(hContact);
-
- //see if we should add the html away message context menu items
- Menu_ShowItem(m_hHTMLAwayContextMenuItem, getWord(hContact, AIM_KEY_ST, ID_STATUS_OFFLINE) == ID_STATUS_AWAY && !bIsChatRoom);
- Menu_ShowItem(m_hAddToServerListContextMenuItem, !getBuddyId(hContact, 1) && m_state != 0 && !bIsChatRoom);
-
- ptrA id(getStringA(hContact, AIM_KEY_SN));
- if (id == NULL)
- return 0;
-
- switch (m_pd_mode) {
- case 1:
- Menu_ModifyItem(m_hBlockContextMenuItem, LPGENW("&Block"));
- break;
-
- case 2:
- Menu_ModifyItem(m_hBlockContextMenuItem, LPGENW("&Unblock"));
- break;
-
- case 3:
- Menu_ModifyItem(m_hBlockContextMenuItem, m_allow_list.find_id(id) ? LPGENW("&Block") : LPGENW("&Unblock"));
- break;
-
- case 4:
- Menu_ModifyItem(m_hBlockContextMenuItem, m_block_list.find_id(id) ? LPGENW("&Unblock") : LPGENW("&Block"));
- break;
-
- default:
- Menu_ShowItem(m_hBlockContextMenuItem, false);
- break;
- }
- return 0;
-}
-
-void CAimProto::InitMainMenus(void)
-{
- CMenuItem mi;
- mi.root = Menu_GetProtocolRoot(this);
-
- mi.pszService = "/ManageAccount";
- CreateProtoService(mi.pszService, &CAimProto::ManageAccount);
- mi.position = 201001;
- mi.hIcolibItem = GetIconHandle("aim");
- mi.name.a = LPGEN("Manage account");
- m_hMainMenu[0] = Menu_AddProtoMenuItem(&mi, m_szModuleName);
-
- mi.pszService = "/InstantIdle";
- CreateProtoService(mi.pszService, &CAimProto::InstantIdle);
- mi.position = 201002;
- mi.hIcolibItem = GetIconHandle("idle");
- mi.name.a = LPGEN("Instant idle");
- m_hMainMenu[1] = Menu_AddProtoMenuItem(&mi, m_szModuleName);
-
- mi.pszService = "/JoinChatRoom";
- CreateProtoService(mi.pszService, &CAimProto::JoinChatUI);
- mi.position = 201003;
- mi.hIcolibItem = GetIconHandle("aol");
- mi.name.a = LPGEN("Join chat room");
- m_hMainMenu[2] = Menu_AddProtoMenuItem(&mi, m_szModuleName);
-}
-
-void CAimProto::InitContactMenus(void)
-{
- CMenuItem mi;
-
- SET_UID(mi, 0xb961e2af, 0x87a, 0x4fbf, 0xb5, 0x32, 0x6, 0xe2, 0x18, 0xad, 0x29, 0xac);
- CreateProtoService("/GetHTMLAwayMsg", &CAimProto::GetHTMLAwayMsg);
- mi.pszService = "/GetHTMLAwayMsg";
- mi.position = -2000006000;
- mi.hIcolibItem = GetIconHandle("away");
- mi.name.a = LPGEN("Read &HTML away message");
- mi.flags = CMIF_NOTOFFLINE | CMIF_HIDDEN;
- m_hHTMLAwayContextMenuItem = Menu_AddContactMenuItem(&mi, m_szModuleName);
-
- SET_UID(mi, 0x7f7e4c24, 0x821c, 0x450f, 0x93, 0x76, 0xbe, 0x65, 0xe9, 0x2f, 0xb6, 0xc2);
- CreateProtoService("/GetProfile", &CAimProto::GetProfile);
- mi.pszService = "/GetProfile";
- mi.position = -2000005090;
- mi.hIcolibItem = GetIconHandle("profile");
- mi.name.a = LPGEN("Read profile");
- mi.flags = CMIF_NOTOFFLINE;
- Menu_AddContactMenuItem(&mi, m_szModuleName);
-
- SET_UID(mi, 0x3928ba10, 0x69bc, 0x4ec9, 0x96, 0x48, 0xa4, 0x1b, 0xbe, 0x58, 0x4a, 0x7e);
- CreateProtoService("/AddToServerList", &CAimProto::AddToServerList);
- mi.pszService = "/AddToServerList";
- mi.position = -2000005080;
- mi.hIcolibItem = GetIconHandle("add");
- mi.name.a = LPGEN("Add to server list");
- mi.flags = CMIF_NOTONLINE | CMIF_HIDDEN;
- m_hAddToServerListContextMenuItem = Menu_AddContactMenuItem(&mi, m_szModuleName);
-
- SET_UID(mi, 0xc6169b8f, 0x53ab, 0x4242, 0xbe, 0x90, 0xe2, 0x4a, 0xa5, 0x73, 0x88, 0x32);
- CreateProtoService("/BlockCommand", &CAimProto::BlockBuddy);
- mi.pszService = "/BlockCommand";
- mi.position = -2000005060;
- mi.hIcolibItem = GetIconHandle("block");
- mi.name.a = LPGEN("&Block");
- mi.flags = CMIF_HIDDEN;
- m_hBlockContextMenuItem = Menu_AddContactMenuItem(&mi, m_szModuleName);
-}
diff --git a/protocols/AimOscar/src/theme.h b/protocols/AimOscar/src/theme.h
deleted file mode 100644
index 73fde85851..0000000000
--- a/protocols/AimOscar/src/theme.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef THEME_H
-#define THEME_H
-
-void InitIcons(void);
-void InitExtraIcons(void);
-
-HICON LoadIconEx(const char *name, bool big = false);
-HANDLE GetIconHandle(const char *name);
-void ReleaseIconEx(const char *name, bool big = false);
-
-void add_AT_icons(CAimProto* ppro);
-void remove_AT_icons(CAimProto* ppro);
-void add_ES_icons(CAimProto* ppro);
-void remove_ES_icons(CAimProto* ppro);
-
-void set_contact_icon(CAimProto* ppro, MCONTACT hContact);
-
-#endif
diff --git a/protocols/AimOscar/src/thread.cpp b/protocols/AimOscar/src/thread.cpp
deleted file mode 100644
index 3affac892b..0000000000
--- a/protocols/AimOscar/src/thread.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2012 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-void __cdecl CAimProto::accept_file_thread(void* param)//buddy sending file
-{
- file_transfer *ft = (file_transfer*)param;
-
- HNETLIBCONN hConn = nullptr;
- if (ft->peer_force_proxy) //peer is forcing proxy
- {
- hConn = aim_peer_connect(ft->proxy_ip, get_default_port());
- if (hConn) {
- debugLogA("Connected to proxy ip that buddy specified.");
- ft->hConn = hConn;
- ForkThread(&CAimProto::aim_proxy_helper, ft);
- ft->stop_listen();
- }
- }
- else if (ft->me_force_proxy) //we are forcing proxy
- {
- hConn = aim_peer_connect(AIM_PROXY_SERVER, get_default_port());
- if (hConn) {
- debugLogA("Connected to proxy ip because we want to use a proxy for the file transfer.");
- ft->requester = true;
- ft->hConn = hConn;
- ForkThread(&CAimProto::aim_proxy_helper, ft);
- ft->stop_listen();
- }
- }
- else {
- bool verif = ft->verified_ip != m_detected_ip;
- hConn = aim_peer_connect(verif ? ft->verified_ip : ft->local_ip, ft->port);
- if (hConn) {
- debugLogA("Connected to buddy over P2P port via %s ip.", verif ? "verified" : "local");
- ft->accepted = true;
- ft->hConn = hConn;
- aim_file_ad(m_hServerConn, m_seqno, ft->sn, ft->icbm_cookie, false, ft->max_ver);
- ForkThread(&CAimProto::aim_dc_helper, ft);
- ft->stop_listen();
- }
- else if (ft->sending) {
- hConn = aim_peer_connect(AIM_PROXY_SERVER, get_default_port());
- if (hConn) {
- ft->hConn = hConn;
- ft->requester = true;
- ForkThread(&CAimProto::aim_proxy_helper, ft);
- ft->stop_listen();
- }
- }
- else {
- debugLogA("Failed to connect to buddy- asking buddy to connect to us.");
- ft->listen(this);
- ft->requester = true;
- aim_send_file(m_hServerConn, m_seqno, m_detected_ip, ft->local_port, false, ft);
- return;
- }
- }
-
- if (hConn == nullptr) {
- if (ft->req_num)
- aim_file_ad(m_hServerConn, m_seqno, ft->sn, ft->icbm_cookie, true, 0);
-
- ProtoBroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
- m_ft_list.remove_by_ft(ft);
- }
-}
diff --git a/protocols/AimOscar/src/tlv.cpp b/protocols/AimOscar/src/tlv.cpp
deleted file mode 100644
index 089a0fc17d..0000000000
--- a/protocols/AimOscar/src/tlv.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#include "stdafx.h"
-
-TLV::TLV(char* buf)
-{
- type_=_htons((*(unsigned short*)&buf[0]));
- length_=_htons((*(unsigned short*)&buf[2]));
- if (length_ > 0)
- {
- value_=(char*)mir_alloc(length_+1);
- memcpy(value_,&buf[4],length_);
- }
- else
- value_= nullptr;
-}
-
-TLV::TLV(unsigned short type, unsigned short length, const char* value)
-{
- type_ = type;
- length_ = length;
- if (length_ > 0)
- {
- value_ = (char*)mir_alloc(length_+1);
- memcpy(value_, value, length_);
- }
- else
- value_= nullptr;
-}
-
-TLV::~TLV()
-{
- mir_free(value_);
-}
-
-unsigned short TLV::ushort(int pos)
-{
- return _htons(*(unsigned short*)&value_[pos]);
-}
-
-unsigned long TLV::ulong(int pos)
-{
- return _htonl(*(unsigned long*)&value_[pos]);
-}
-
-unsigned __int64 TLV::u64(int pos)
-{
- return _htonl64(*(unsigned __int64*)&value_[pos]);
-}
-
-unsigned char TLV::ubyte(int pos)
-{
- return value_[pos];
-}
-
-char* TLV::part(int pos, int length)//returns part of the tlv value
-{
- if ((pos + length) > length_) return nullptr;
-
- char* value = (char*)mir_alloc(length + 2);
- memcpy(value, &value_[pos], length);
- value[length] = '\0';
- value[length+1] = '\0';
-
- return value;
-}
-
-char* TLV::dupw(void)
-{
- wchar_t *str = (wchar_t*)part(0, length_);
- wcs_htons(str);
-
- char* stru = mir_utf8encodeW(str);
- mir_free(str);
-
- return stru;
-}
-
-
-unsigned short TLV::whole(char* buf)//returns the whole tlv
-{
- *(unsigned short*)buf = _htons(type_);
- *(unsigned short*)&buf[2] = _htons(length_);
- memcpy(&buf[4], value_, length_);
- return length_ + TLV_HEADER_SIZE;
-}
diff --git a/protocols/AimOscar/src/tlv.h b/protocols/AimOscar/src/tlv.h
deleted file mode 100644
index 1522650b65..0000000000
--- a/protocols/AimOscar/src/tlv.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef TLV_H
-#define TLV_H
-
-#define TLV_HEADER_SIZE 4
-
-class TLV
-{
-private:
- unsigned short type_;
- unsigned short length_;
- char* value_;
-public:
- TLV(char* buf);
- TLV(unsigned short type, unsigned short length, const char* value);
- ~TLV();
-
- int cmp(unsigned short type) { return type_ == type; }
- unsigned short len(void) { return length_; }
- char* val(void) { return value_; }
-
- char* part(int pos, int length);
- char* dup(void) { return part(0, length_); };
- char* dupw(void);
-
- unsigned short whole(char* buf);
- unsigned short ushort(int pos=0);
- unsigned long ulong(int pos=0);
- unsigned __int64 u64(int pos=0);
- unsigned char ubyte(int pos=0);
-};
-
-#endif
diff --git a/protocols/AimOscar/src/ui.cpp b/protocols/AimOscar/src/ui.cpp
deleted file mode 100755
index 7bf8eed909..0000000000
--- a/protocols/AimOscar/src/ui.cpp
+++ /dev/null
@@ -1,1457 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2012 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-HANDLE hThemeButton = nullptr;
-COLORREF foreground=0;
-COLORREF background=0xffffff;
-COLORREF custColours[16]={0};
-
-static int CALLBACK EnumFontsProc(ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX* /*lpntme*/, int /*FontType*/, LPARAM lParam)
-{
- if (!IsWindow((HWND)lParam))
- return FALSE;
- if (SendMessage((HWND)lParam, CB_FINDSTRINGEXACT, 1, (LPARAM)lpelfe->elfLogFont.lfFaceName) == CB_ERR)
- SendMessage((HWND)lParam, CB_ADDSTRING, 0, (LPARAM)lpelfe->elfLogFont.lfFaceName);
- return TRUE;
-}
-
-void DrawMyControl(HDC hDC, HWND /*hwndButton*/, HANDLE hTheme, UINT iState, RECT rect)
-{
- BOOL bIsPressed = (iState & ODS_SELECTED);
- BOOL bIsFocused = (iState & ODS_FOCUS);
- if (hTheme) {
- DWORD state = (bIsPressed) ? PBS_PRESSED : PBS_NORMAL;
- if (state == PBS_NORMAL) {
- if (bIsFocused)
- state = PBS_DEFAULTED;
- }
- rect.top -= 1;
- rect.left -= 1;
- DrawThemeBackground(hTheme, hDC, BP_PUSHBUTTON, state, &rect, nullptr);
- }
- else {
- if (bIsFocused) {
- HBRUSH br = CreateSolidBrush(RGB(0, 0, 0));
- FrameRect(hDC, &rect, br);
- InflateRect(&rect, -1, -1);
- DeleteObject(br);
- } // if
- COLORREF crColor = GetSysColor(COLOR_BTNFACE);
- HBRUSH brBackground = CreateSolidBrush(crColor);
- FillRect(hDC, &rect, brBackground);
- DeleteObject(brBackground);
- // Draw pressed button
- if (bIsPressed) {
- HBRUSH brBtnShadow = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
- FrameRect(hDC, &rect, brBtnShadow);
- DeleteObject(brBtnShadow);
- }
- else // ...else draw non pressed button
- {
- UINT uState = DFCS_BUTTONPUSH;
- DrawFrameControl(hDC, &rect, DFC_BUTTON, uState);
- }
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// User info dialog
-
-static INT_PTR CALLBACK userinfo_dialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- CAimProto* ppro = (CAimProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-
- switch (msg) {
- case WM_INITDIALOG:
- {
- SendDlgItemMessage(hwndDlg, IDC_BOLD, BUTTONSETASPUSHBTN, TRUE, 0);
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_SETEVENTMASK, 0, ENM_CHANGE | ENM_SELCHANGE | ENM_REQUESTRESIZE);
- SendDlgItemMessage(hwndDlg, IDC_BACKGROUNDCOLORPICKER, CPM_SETCOLOUR, 0, 0x00ffffff);
- LOGFONT lf = { 0 };
- HDC hdc = GetDC(hwndDlg);
- lf.lfCharSet = DEFAULT_CHARSET;
- lf.lfFaceName[0] = 0;
- lf.lfPitchAndFamily = 0;
- EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)EnumFontsProc, (LPARAM)GetDlgItem(hwndDlg, IDC_TYPEFACE), 0);
- ReleaseDC(hwndDlg, hdc);
- SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_ADDSTRING, 0, (LPARAM)TEXT("8"));
- SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_ADDSTRING, 0, (LPARAM)TEXT("10"));
- SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_ADDSTRING, 0, (LPARAM)TEXT("12"));
- SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_ADDSTRING, 0, (LPARAM)TEXT("14"));
- SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_ADDSTRING, 0, (LPARAM)TEXT("18"));
- SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_ADDSTRING, 0, (LPARAM)TEXT("24"));
- SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_ADDSTRING, 0, (LPARAM)TEXT("36"));
- SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_SETCURSEL, 2, 0);
- if (SendDlgItemMessage(hwndDlg, IDC_TYPEFACE, CB_SELECTSTRING, 1, (LPARAM)TEXT("Arial")) != CB_ERR) {
- CHARFORMAT2 cf;
- cf.cbSize = sizeof(cf);
- cf.yHeight = 12 * 20;
- cf.dwMask = CFM_SIZE | CFM_FACE;
- mir_wstrcpy(cf.szFaceName, TEXT("Arial"));
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
- }
- else {
- CHARFORMAT2 cf;
- cf.cbSize = sizeof(cf);
- cf.yHeight = 12 * 20;
- cf.dwMask = CFM_SIZE;
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
- }
- break;
- }
- case WM_CLOSE:
- EndDialog(hwndDlg, 0);
- break;
-
- case WM_SIZING:
- {
- RECT* rect = (RECT*)lParam;
-#define MIN_HEIGHT 200
-#define MIN_WIDTH 400
- if (WMSZ_RIGHT == wParam || WMSZ_TOPRIGHT == wParam || WMSZ_BOTTOMRIGHT == wParam) {
- if (rect->right - rect->left < MIN_WIDTH)
- rect->right = rect->left + MIN_WIDTH;
- }
- if (WMSZ_LEFT == wParam || WMSZ_TOPLEFT == wParam || WMSZ_BOTTOMLEFT == wParam) {
- if (rect->right - rect->left < MIN_WIDTH)
- rect->left = rect->right - MIN_WIDTH;
- }
- if (WMSZ_TOP == wParam || WMSZ_TOPRIGHT == wParam || WMSZ_TOPLEFT == wParam) {
- if (rect->bottom - rect->top < MIN_HEIGHT)
- rect->top = rect->bottom - MIN_HEIGHT;
- }
- if (WMSZ_BOTTOM == wParam || WMSZ_BOTTOMLEFT == wParam || WMSZ_BOTTOMRIGHT == wParam) {
- if (rect->bottom - rect->top < MIN_HEIGHT)
- rect->bottom = rect->top + MIN_HEIGHT;
- }
- break;
- }
-
- case WM_SIZE:
- {
- int width = LOWORD(lParam);
- int height = HIWORD(lParam);
- SetWindowPos(GetDlgItem(hwndDlg, IDC_PROFILE), HWND_TOP, 6, 60, width - 12, height - 67, 0); // this 'case' should go away
- SetWindowPos(GetDlgItem(hwndDlg, IDC_SETPROFILE), HWND_TOP, width - 97, height - 224, 0, 0, SWP_NOSIZE); // since there's no profile window resize anymore
- break;
- }
- case WM_NOTIFY:
- switch (LOWORD(wParam)) {
- case IDC_PROFILE:
- if (((LPNMHDR)lParam)->code == EN_SELCHANGE) {
- CHARFORMAT2 cfOld;
- cfOld.cbSize = sizeof(CHARFORMAT2);
- cfOld.dwMask = CFM_FACE | CFM_SIZE;
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfOld);
- if (SendDlgItemMessage(hwndDlg, IDC_TYPEFACE, CB_SELECTSTRING, 1, (LPARAM)cfOld.szFaceName) == -1) {
- SendDlgItemMessage(hwndDlg, IDC_TYPEFACE, CB_ADDSTRING, 0, (LPARAM)cfOld.szFaceName);
- SendDlgItemMessage(hwndDlg, IDC_TYPEFACE, CB_SELECTSTRING, 1, (LPARAM)cfOld.szFaceName);
- }
- char size[10];
- _itoa(cfOld.yHeight / 20, size, sizeof(size));
- //SetDlgItemText(hwndDlg, IDC_FONTSIZE, size);
- SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_SELECTSTRING, 1, (LPARAM)size);
- InvalidateRect(GetDlgItem(hwndDlg, IDC_SUPERSCRIPT), nullptr, FALSE);
- InvalidateRect(GetDlgItem(hwndDlg, IDC_NORMALSCRIPT), nullptr, FALSE);
- InvalidateRect(GetDlgItem(hwndDlg, IDC_SUBSCRIPT), nullptr, FALSE);
- InvalidateRect(GetDlgItem(hwndDlg, IDC_BOLD), nullptr, FALSE);
- InvalidateRect(GetDlgItem(hwndDlg, IDC_ITALIC), nullptr, FALSE);
- InvalidateRect(GetDlgItem(hwndDlg, IDC_UNDERLINE), nullptr, FALSE);
- }
- else if (((LPNMHDR)lParam)->code == EN_REQUESTRESIZE) {
- // REQRESIZE* rr= (REQRESIZE*)lParam;
- //SetWindowPos(GetDlgItem(hwndDlg, IDC_PROFILE),HWND_TOP,rr->rc.left,rr->rc.top,rr->rc.right,rr->rc.bottom,0);
- }
- break;
-
- default:
- if (((LPNMHDR)lParam)->code == PSN_PARAMCHANGED) {
- ppro = (CAimProto*)((PSHNOTIFY*)lParam)->lParam;
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)ppro);
-
- DBVARIANT dbv;
- if (!db_get_utf(NULL, ppro->m_szModuleName, AIM_KEY_PR, &dbv)) {
- html_decode(dbv.pszVal);
- wchar_t *txt = mir_utf8decodeW(dbv.pszVal);
- SetDlgItemText(hwndDlg, IDC_PROFILE, txt);
- mir_free(txt);
- db_free(&dbv);
- }
- }
- }
- break;
-
- case WM_DRAWITEM:
- {
- CloseThemeData(hThemeButton);
- hThemeButton = OpenThemeData(GetDlgItem(hwndDlg, IDC_BOLD), L"Button");
- LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam;
- if (lpDIS->CtlID == IDC_SUPERSCRIPT) {
- CHARFORMAT2 cfOld;
- cfOld.cbSize = sizeof(CHARFORMAT2);
- cfOld.dwMask = CFM_SUPERSCRIPT;
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfOld);
- BOOL isSuper = (cfOld.dwEffects & CFE_SUPERSCRIPT) && (cfOld.dwMask & CFM_SUPERSCRIPT);
- if (isSuper) {
- DrawMyControl(lpDIS->hDC, GetDlgItem(hwndDlg, IDC_BOLD), hThemeButton, lpDIS->itemState | ODS_SELECTED, lpDIS->rcItem);
- DrawIconEx(lpDIS->hDC, 4, 5, LoadIconEx("sup_scrpt"), 16, 16, 0, nullptr, DI_NORMAL);
- ReleaseIconEx("sup_scrpt");
- }
- else {
- DrawMyControl(lpDIS->hDC, GetDlgItem(hwndDlg, IDC_BOLD), hThemeButton, lpDIS->itemState, lpDIS->rcItem);
- DrawIconEx(lpDIS->hDC, 4, 5, LoadIconEx("nsup_scrpt"), 16, 16, 0, nullptr, DI_NORMAL);
- ReleaseIconEx("nsup_scrpt");
- }
- }
- else if (lpDIS->CtlID == IDC_NORMALSCRIPT) {
- CHARFORMAT2 cfOld;
- cfOld.cbSize = sizeof(CHARFORMAT2);
- cfOld.dwMask = CFM_SUBSCRIPT | CFM_SUPERSCRIPT;
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfOld);
- BOOL isSub = (cfOld.dwEffects & CFE_SUBSCRIPT) && (cfOld.dwMask & CFM_SUBSCRIPT);
- BOOL isSuper = (cfOld.dwEffects & CFE_SUPERSCRIPT) && (cfOld.dwMask & CFM_SUPERSCRIPT);
- if (!isSub&&!isSuper) {
- DrawMyControl(lpDIS->hDC, GetDlgItem(hwndDlg, IDC_BOLD), hThemeButton, lpDIS->itemState | ODS_SELECTED, lpDIS->rcItem);
- DrawIconEx(lpDIS->hDC, 4, 5, LoadIconEx("norm_scrpt"), 16, 16, 0, nullptr, DI_NORMAL);
- ReleaseIconEx("norm_scrpt");
- }
- else {
- DrawMyControl(lpDIS->hDC, GetDlgItem(hwndDlg, IDC_BOLD), hThemeButton, lpDIS->itemState, lpDIS->rcItem);
- DrawIconEx(lpDIS->hDC, 4, 5, LoadIconEx("nnorm_scrpt"), 16, 16, 0, nullptr, DI_NORMAL);
- ReleaseIconEx("nnorm_scrpt");
- }
- }
- else if (lpDIS->CtlID == IDC_SUBSCRIPT) {
- CHARFORMAT2 cfOld;
- cfOld.cbSize = sizeof(CHARFORMAT2);
- cfOld.dwMask = CFM_SUBSCRIPT;
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfOld);
- BOOL isSub = (cfOld.dwEffects & CFE_SUBSCRIPT) && (cfOld.dwMask & CFM_SUBSCRIPT);
- if (isSub) {
- DrawMyControl(lpDIS->hDC, GetDlgItem(hwndDlg, IDC_BOLD), hThemeButton, lpDIS->itemState | ODS_SELECTED, lpDIS->rcItem);
- DrawIconEx(lpDIS->hDC, 4, 5, LoadIconEx("sub_scrpt"), 16, 16, 0, nullptr, DI_NORMAL);
- ReleaseIconEx("sub_scrpt");
- }
- else {
- DrawMyControl(lpDIS->hDC, GetDlgItem(hwndDlg, IDC_BOLD), hThemeButton, lpDIS->itemState, lpDIS->rcItem);
- DrawIconEx(lpDIS->hDC, 4, 5, LoadIconEx("nsub_scrpt"), 16, 16, 0, nullptr, DI_NORMAL);
- ReleaseIconEx("nsub_scrpt");
- }
- }
- else if (lpDIS->CtlID == IDC_BOLD) {
- CHARFORMAT2 cfOld;
- cfOld.cbSize = sizeof(CHARFORMAT2);
- cfOld.dwMask = CFM_BOLD;
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfOld);
- BOOL isBold = (cfOld.dwEffects & CFE_BOLD) && (cfOld.dwMask & CFM_BOLD);
- if (!isBold) {
- DrawMyControl(lpDIS->hDC, GetDlgItem(hwndDlg, IDC_BOLD), hThemeButton, lpDIS->itemState, lpDIS->rcItem);
- DrawIconEx(lpDIS->hDC, 4, 5, LoadIconEx("nbold"), 16, 16, 0, nullptr, DI_NORMAL);
- ReleaseIconEx("nbold");
- }
- else {
- DrawMyControl(lpDIS->hDC, GetDlgItem(hwndDlg, IDC_BOLD), hThemeButton, lpDIS->itemState | ODS_SELECTED, lpDIS->rcItem);
- DrawIconEx(lpDIS->hDC, 4, 5, LoadIconEx("bold"), 16, 16, 0, nullptr, DI_NORMAL);
- ReleaseIconEx("bold");
- }
- }
- else if (lpDIS->CtlID == IDC_ITALIC) {
- CHARFORMAT2 cfOld;
- cfOld.cbSize = sizeof(CHARFORMAT2);
- cfOld.dwMask = CFM_ITALIC;
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfOld);
- BOOL isItalic = (cfOld.dwEffects & CFE_ITALIC) && (cfOld.dwMask & CFM_ITALIC);
- if (!isItalic) {
- DrawMyControl(lpDIS->hDC, GetDlgItem(hwndDlg, IDC_ITALIC), hThemeButton, lpDIS->itemState, lpDIS->rcItem);
- DrawIconEx(lpDIS->hDC, 4, 5, LoadIconEx("nitalic"), 16, 16, 0, nullptr, DI_NORMAL);
- ReleaseIconEx("nitalic");
- }
- else {
- DrawMyControl(lpDIS->hDC, GetDlgItem(hwndDlg, IDC_ITALIC), hThemeButton, lpDIS->itemState | ODS_SELECTED, lpDIS->rcItem);
- DrawIconEx(lpDIS->hDC, 4, 5, LoadIconEx("italic"), 16, 16, 0, nullptr, DI_NORMAL);
- ReleaseIconEx("italic");
- }
- }
- else if (lpDIS->CtlID == IDC_UNDERLINE) {
- CHARFORMAT2 cfOld;
- cfOld.cbSize = sizeof(CHARFORMAT2);
- cfOld.dwMask = CFM_UNDERLINE;
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfOld);
- BOOL isUnderline = (cfOld.dwEffects & CFE_UNDERLINE) && (cfOld.dwMask & CFM_UNDERLINE);
- if (!isUnderline) {
- DrawMyControl(lpDIS->hDC, GetDlgItem(hwndDlg, IDC_UNDERLINE), hThemeButton, lpDIS->itemState, lpDIS->rcItem);
- DrawIconEx(lpDIS->hDC, 4, 5, LoadIconEx("nundrln"), 16, 16, 0, nullptr, DI_NORMAL);
- ReleaseIconEx("nundrln");
- }
- else {
- DrawMyControl(lpDIS->hDC, GetDlgItem(hwndDlg, IDC_UNDERLINE), hThemeButton, lpDIS->itemState | ODS_SELECTED, lpDIS->rcItem);
- DrawIconEx(lpDIS->hDC, 4, 5, LoadIconEx("undrln"), 16, 16, 0, nullptr, DI_NORMAL);
- ReleaseIconEx("undrln");
- }
- }
- else if (lpDIS->CtlID == IDC_FOREGROUNDCOLOR) {
- DrawMyControl(lpDIS->hDC, GetDlgItem(hwndDlg, IDC_FOREGROUNDCOLOR), hThemeButton, lpDIS->itemState, lpDIS->rcItem);
- DrawIconEx(lpDIS->hDC, 4, 2, LoadIconEx("foreclr"), 16, 16, 0, nullptr, DI_NORMAL);
- ReleaseIconEx("foreclr");
- HBRUSH hbr = CreateSolidBrush(foreground);
- HPEN hp = CreatePen(PS_SOLID, 1, ~foreground & 0x00ffffff);
- SelectObject(lpDIS->hDC, hp);
- RECT rect = lpDIS->rcItem;
- rect.top += 18;
- rect.bottom -= 4;
- rect.left += 5;
- rect.right -= 5;
- Rectangle(lpDIS->hDC, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1);
- FillRect(lpDIS->hDC, &rect, hbr);
- DeleteObject(hbr);
- DeleteObject(hp);
- }
- else if (lpDIS->CtlID == IDC_FOREGROUNDCOLORPICKER) {
- DrawMyControl(lpDIS->hDC, GetDlgItem(hwndDlg, IDC_FOREGROUNDCOLORPICKER), hThemeButton, lpDIS->itemState, lpDIS->rcItem);
- HBRUSH hbr = CreateSolidBrush(foreground);
- HPEN hp = CreatePen(PS_SOLID, 1, ~foreground & 0x00ffffff);
- SelectObject(lpDIS->hDC, hbr);
- SelectObject(lpDIS->hDC, hp);
- POINT tri[3];
- tri[0].x = 3;
- tri[0].y = 10;
- tri[1].x = 9;
- tri[1].y = 10;
- tri[2].x = 6;
- tri[2].y = 15;
- Polygon(lpDIS->hDC, tri, 3);
- DeleteObject(hbr);
- DeleteObject(hp);
- }
- else if (lpDIS->CtlID == IDC_BACKGROUNDCOLOR) {
- DrawMyControl(lpDIS->hDC, GetDlgItem(hwndDlg, IDC_BACKGROUNDCOLOR), hThemeButton, lpDIS->itemState, lpDIS->rcItem);
- DrawIconEx(lpDIS->hDC, 4, 2, LoadIconEx("backclr"), 16, 16, 0, nullptr, DI_NORMAL);
- ReleaseIconEx("backclr");
- HBRUSH hbr = CreateSolidBrush(background);
- HPEN hp = CreatePen(PS_SOLID, 1, ~background & 0x00ffffff);
- SelectObject(lpDIS->hDC, hp);
- RECT rect = lpDIS->rcItem;
- rect.top += 18;
- rect.bottom -= 4;
- rect.left += 5;
- rect.right -= 5;
- Rectangle(lpDIS->hDC, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1);
- FillRect(lpDIS->hDC, &rect, hbr);
- DeleteObject(hbr);
- DeleteObject(hp);
- }
- else if (lpDIS->CtlID == IDC_BACKGROUNDCOLORPICKER) {
- DrawMyControl(lpDIS->hDC, GetDlgItem(hwndDlg, IDC_BACKGROUNDCOLORPICKER), hThemeButton, lpDIS->itemState, lpDIS->rcItem);
- HBRUSH hbr = CreateSolidBrush(background);
- HPEN hp = CreatePen(PS_SOLID, 1, ~background & 0x00ffffff);
- SelectObject(lpDIS->hDC, hbr);
- SelectObject(lpDIS->hDC, hp);
- POINT tri[3];
- tri[0].x = 3;
- tri[0].y = 10;
- tri[1].x = 9;
- tri[1].y = 10;
- tri[2].x = 6;
- tri[2].y = 15;
- Polygon(lpDIS->hDC, tri, 3);
- DeleteObject(hbr);
- DeleteObject(hp);
- }
- break;
- }
-
- case WM_COMMAND:
- switch (LOWORD(wParam)) {
- case IDC_PROFILE:
- if (HIWORD(wParam) == EN_CHANGE)
- EnableWindow(GetDlgItem(hwndDlg, IDC_SETPROFILE), TRUE);
- break;
-
- case IDC_SETPROFILE:
- {
- char* buf = rtf_to_html(hwndDlg, IDC_PROFILE);
- db_set_utf(NULL, ppro->m_szModuleName, AIM_KEY_PR, buf);
- if (ppro->m_state == 1)
- ppro->aim_set_profile(ppro->m_hServerConn, ppro->m_seqno, buf);//also see set caps for profile setting
-
- mir_free(buf);
- EnableWindow(GetDlgItem(hwndDlg, IDC_SETPROFILE), FALSE);
- }
- break;
-
- case IDC_SUPERSCRIPT:
- if (HIWORD(wParam) == BN_CLICKED) {
- CHARFORMAT2 cf;
- cf.cbSize = sizeof(CHARFORMAT2);
- cf.dwMask = CFM_SUPERSCRIPT;
- cf.dwEffects = CFE_SUPERSCRIPT;
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
- SetFocus(GetDlgItem(hwndDlg, IDC_PROFILE));
- InvalidateRect(GetDlgItem(hwndDlg, IDC_NORMALSCRIPT), nullptr, FALSE);
- InvalidateRect(GetDlgItem(hwndDlg, IDC_SUBSCRIPT), nullptr, FALSE);
- }
- break;
-
- case IDC_NORMALSCRIPT:
- if (HIWORD(wParam) == BN_CLICKED) {
- CHARFORMAT2 cf;
- cf.cbSize = sizeof(CHARFORMAT2);
- cf.dwMask = CFM_SUPERSCRIPT;
- cf.dwEffects &= ~CFE_SUPERSCRIPT;
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
- SetFocus(GetDlgItem(hwndDlg, IDC_PROFILE));
- InvalidateRect(GetDlgItem(hwndDlg, IDC_SUPERSCRIPT), nullptr, FALSE);
- InvalidateRect(GetDlgItem(hwndDlg, IDC_SUBSCRIPT), nullptr, FALSE);
- }
- break;
-
- case IDC_SUBSCRIPT:
- if (HIWORD(wParam) == BN_CLICKED) {
- CHARFORMAT2 cf;
- cf.cbSize = sizeof(CHARFORMAT2);
- cf.dwMask = CFM_SUBSCRIPT;
- cf.dwEffects = CFE_SUBSCRIPT;
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
- SetFocus(GetDlgItem(hwndDlg, IDC_PROFILE));
- InvalidateRect(GetDlgItem(hwndDlg, IDC_SUPERSCRIPT), nullptr, FALSE);
- InvalidateRect(GetDlgItem(hwndDlg, IDC_NORMALSCRIPT), nullptr, FALSE);
- }
- break;
-
- case IDC_BOLD:
- if (HIWORD(wParam) == BN_CLICKED) {
- CHARFORMAT2 cfOld;
- cfOld.cbSize = sizeof(CHARFORMAT2);
- cfOld.dwMask = CFM_BOLD;
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfOld);
- BOOL isBold = (cfOld.dwEffects & CFE_BOLD) && (cfOld.dwMask & CFM_BOLD);
- CHARFORMAT2 cf;
- cf.cbSize = sizeof(CHARFORMAT2);
- cf.dwEffects = isBold ? 0 : CFE_BOLD;
- cf.dwMask = CFM_BOLD;
- CheckDlgButton(hwndDlg, IDC_BOLD, !isBold ? BST_CHECKED : BST_UNCHECKED);
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
- SetFocus(GetDlgItem(hwndDlg, IDC_PROFILE));
- }
- break;
-
- case IDC_ITALIC:
- if (HIWORD(wParam) == BN_CLICKED) {
- CHARFORMAT2 cfOld;
- cfOld.cbSize = sizeof(CHARFORMAT2);
- cfOld.dwMask = CFM_ITALIC;
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfOld);
- BOOL isItalic = (cfOld.dwEffects & CFE_ITALIC) && (cfOld.dwMask & CFM_ITALIC);
- CHARFORMAT2 cf;
- cf.cbSize = sizeof(CHARFORMAT2);
- cf.dwEffects = isItalic ? 0 : CFE_ITALIC;
- cf.dwMask = CFM_ITALIC;
- CheckDlgButton(hwndDlg, IDC_ITALIC, !isItalic ? BST_CHECKED : BST_UNCHECKED);
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
- SetFocus(GetDlgItem(hwndDlg, IDC_PROFILE));
- }
- break;
-
- case IDC_UNDERLINE:
- if (HIWORD(wParam) == BN_CLICKED) {
- CHARFORMAT2 cfOld;
- cfOld.cbSize = sizeof(CHARFORMAT2);
- cfOld.dwMask = CFM_UNDERLINE;
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfOld);
- BOOL isUnderline = (cfOld.dwEffects & CFE_UNDERLINE) && (cfOld.dwMask & CFM_UNDERLINE);
- CHARFORMAT2 cf;
- cf.cbSize = sizeof(CHARFORMAT2);
- cf.dwEffects = isUnderline ? 0 : CFE_UNDERLINE;
- cf.dwMask = CFM_UNDERLINE;
- CheckDlgButton(hwndDlg, IDC_UNDERLINE, !isUnderline ? BST_CHECKED : BST_UNCHECKED);
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
- SetFocus(GetDlgItem(hwndDlg, IDC_PROFILE));
- }
- break;
-
- case IDC_FOREGROUNDCOLOR:
- if (HIWORD(wParam) == BN_CLICKED) {
- CHARFORMAT2 cf;
- cf.cbSize = sizeof(CHARFORMAT2);
- cf.dwMask = CFM_COLOR;
- cf.dwEffects = 0;
- cf.crTextColor = foreground;
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
- SetWindowPos(GetDlgItem(hwndDlg, IDC_FOREGROUNDCOLORPICKER), GetDlgItem(hwndDlg, IDC_FOREGROUNDCOLOR), 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
- SetFocus(GetDlgItem(hwndDlg, IDC_PROFILE));
- }
- break;
-
- case IDC_FOREGROUNDCOLORPICKER:
- if (HIWORD(wParam) == BN_CLICKED) {
- CHOOSECOLOR cc = { 0 };
- custColours[0] = foreground;
- custColours[1] = background;
- cc.lStructSize = sizeof(CHOOSECOLOR);
- cc.hwndOwner = hwndDlg;
- cc.hInstance = (HWND)GetModuleHandleA("mir_app.mir");
- cc.lpCustColors = custColours;
- cc.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT;
- if (ChooseColor(&cc)) {
- foreground = cc.rgbResult;
- InvalidateRect(GetDlgItem(hwndDlg, IDC_FOREGROUNDCOLOR), nullptr, FALSE);
- }
- SetFocus(GetDlgItem(hwndDlg, IDC_PROFILE));
- }
- break;
-
- case IDC_BACKGROUNDCOLOR:
- if (HIWORD(wParam) == BN_CLICKED) {
- CHARFORMAT2 cf;
- cf.cbSize = sizeof(CHARFORMAT2);
- cf.dwMask = CFM_BACKCOLOR;
- cf.dwEffects = 0;
- cf.crBackColor = background;
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
- SetFocus(GetDlgItem(hwndDlg, IDC_PROFILE));
- }
- break;
-
- case IDC_BACKGROUNDCOLORPICKER:
- if (HIWORD(wParam) == BN_CLICKED) {
- CHOOSECOLOR cc = { 0 };
- custColours[0] = foreground;
- custColours[1] = background;
- cc.lStructSize = sizeof(CHOOSECOLOR);
- cc.hwndOwner = hwndDlg;
- cc.hInstance = (HWND)GetModuleHandle(nullptr);
- cc.lpCustColors = custColours;
- cc.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT;
- if (ChooseColor(&cc)) {
- background = cc.rgbResult;
- InvalidateRect(GetDlgItem(hwndDlg, IDC_BACKGROUNDCOLOR), nullptr, FALSE);
- }
- SetFocus(GetDlgItem(hwndDlg, IDC_PROFILE));
- }
- break;
-
- case IDC_TYPEFACE:
- if (HIWORD(wParam) == CBN_SELENDOK) {
- CHARFORMAT2A cf;
- cf.cbSize = sizeof(cf);
- cf.dwMask = CFM_FACE;
- cf.dwEffects = 0;
- SendDlgItemMessage(hwndDlg, IDC_TYPEFACE, CB_GETLBTEXT, SendDlgItemMessage(hwndDlg, IDC_TYPEFACE, CB_GETCURSEL, 0, 0), (LPARAM)cf.szFaceName);
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
- SetFocus(GetDlgItem(hwndDlg, IDC_PROFILE));
- break;
- }
- break;
-
- case IDC_FONTSIZE:
- if (HIWORD(wParam) == CBN_SELENDOK) {
- CHARFORMAT2 cf;
- cf.cbSize = sizeof(CHARFORMAT2);
- cf.dwMask = CFM_SIZE;
- cf.dwEffects = 0;
- char chsize[5] = "";
- SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_GETLBTEXT, SendDlgItemMessage(hwndDlg, IDC_FONTSIZE, CB_GETCURSEL, 0, 0), (LPARAM)chsize);
- //strlcpy(cf.szFaceName,size,mir_strlen(size)+1);
- cf.yHeight = atoi(chsize) * 20;
- SendDlgItemMessage(hwndDlg, IDC_PROFILE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
- SetFocus(GetDlgItem(hwndDlg, IDC_PROFILE));
- break;
- }
- break;
- }
- break;
- }
- return FALSE;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// View admin dialog
-
-INT_PTR CALLBACK admin_dialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- CAimProto* ppro = (CAimProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- DBVARIANT dbv;
-
- switch (msg) {
- case WM_INITDIALOG:
- TranslateDialogDefault(hwndDlg);
- SendDlgItemMessage(hwndDlg, IDC_FNAME, EM_LIMITTEXT, 63, 0);
- SendDlgItemMessage(hwndDlg, IDC_CEMAIL, EM_LIMITTEXT, 253, 0);
- SendDlgItemMessage(hwndDlg, IDC_CPW, EM_LIMITTEXT, 253, 0);
- SendDlgItemMessage(hwndDlg, IDC_NPW1, EM_LIMITTEXT, 253, 0);
- SendDlgItemMessage(hwndDlg, IDC_NPW2, EM_LIMITTEXT, 253, 0);
- break;
-
- case WM_NOTIFY:
- switch (((LPNMHDR)lParam)->code) {
- case PSN_PARAMCHANGED:
- ppro = (CAimProto*)((LPPSHNOTIFY)lParam)->lParam;
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)ppro);
-
- if (ppro->wait_conn(ppro->m_hAdminConn, ppro->m_hAdminEvent, 0x07)) { // Make a connection
- ppro->aim_admin_request_info(ppro->m_hAdminConn, ppro->m_admin_seqno, 0x01); // Get our screenname
- ppro->aim_admin_request_info(ppro->m_hAdminConn, ppro->m_admin_seqno, 0x11); // Get our email
- }
-
- case PSN_INFOCHANGED:
- if (!ppro->getString(AIM_KEY_SN, &dbv)) {
- SetDlgItemTextA(hwndDlg, IDC_FNAME, dbv.pszVal);
- db_free(&dbv);
- }
- if (!ppro->getString(AIM_KEY_EM, &dbv)) {
- SetDlgItemTextA(hwndDlg, IDC_CEMAIL, dbv.pszVal);
- db_free(&dbv);
- }
- break;
- }
- break;
-
- case WM_COMMAND:
- if (LOWORD(wParam) == IDC_SAVECHANGES) {
- if (!ppro->wait_conn(ppro->m_hAdminConn, ppro->m_hAdminEvent, 0x07)) // Make a connection
- break;
-
- char name[64];
- GetDlgItemTextA(hwndDlg, IDC_FNAME, name, _countof(name));
- if (mir_strlen(trim_str(name)) > 0 && !ppro->getString(AIM_KEY_SN, &dbv)) {
- if (mir_strcmp(name, dbv.pszVal))
- ppro->aim_admin_format_name(ppro->m_hAdminConn, ppro->m_admin_seqno, name);
- db_free(&dbv);
- }
-
- char email[254];
- GetDlgItemTextA(hwndDlg, IDC_CEMAIL, email, _countof(email));
- if (mir_strlen(trim_str(email)) > 1 && !ppro->getString(AIM_KEY_EM, &dbv)) // Must be greater than 1 or a SNAC error is thrown.
- {
- if (mir_strcmp(email, dbv.pszVal))
- ppro->aim_admin_change_email(ppro->m_hAdminConn, ppro->m_admin_seqno, email);
- db_free(&dbv);
- }
-
- ShowWindow(GetDlgItem(hwndDlg, IDC_PINFO), SW_HIDE);
-
- char cpw[256], npw1[256], npw2[256];
- GetDlgItemTextA(hwndDlg, IDC_CPW, cpw, _countof(cpw));
- GetDlgItemTextA(hwndDlg, IDC_NPW1, npw1, _countof(npw1));
- GetDlgItemTextA(hwndDlg, IDC_NPW2, npw2, _countof(npw2));
- if (cpw[0] != 0 && npw1[0] != 0 && npw2[0] != 0) {
- // AOL only requires that you send the current password and a (single) new password.
- // Let's allow the client to type (two) new passwords incase they make a mistake so we
- // can handle any input error locally.
- if (mir_strcmp(npw1, npw2) == 0) {
- ppro->aim_admin_change_password(ppro->m_hAdminConn, ppro->m_admin_seqno, cpw, npw1);
- }
- else {
- SetDlgItemTextA(hwndDlg, IDC_CPW, "");
- SetDlgItemTextA(hwndDlg, IDC_NPW1, "");
- SetDlgItemTextA(hwndDlg, IDC_NPW2, "");
- ShowWindow(GetDlgItem(hwndDlg, IDC_PINFO), SW_SHOW);
- }
- }
- }
- else if (LOWORD(wParam) == IDC_CONFIRM) // Confirmation
- {
- if (ppro->wait_conn(ppro->m_hAdminConn, ppro->m_hAdminEvent, 0x07)) // Make a connection
- ppro->aim_admin_account_confirm(ppro->m_hAdminConn, ppro->m_admin_seqno);
- }
- break;
- }
- return FALSE;
-}
-
-int CAimProto::OnUserInfoInit(WPARAM wParam, LPARAM lParam)
-{
- if (!lParam)//hContact
- {
- OPTIONSDIALOGPAGE odp = { 0 };
- odp.position = -1900000000;
- odp.flags = ODPF_USERINFOTAB | ODPF_UNICODE;
- odp.hInstance = hInstance;
- odp.szTitle.w = m_tszUserName;
- odp.dwInitParam = LPARAM(this);
-
- odp.szTab.w = LPGENW("Profile");
- odp.pszTemplate = MAKEINTRESOURCEA(IDD_INFO);
- odp.pfnDlgProc = userinfo_dialog;
- UserInfo_AddPage(wParam, &odp);
-
- odp.szTab.w = LPGENW("Admin");
- odp.pszTemplate = MAKEINTRESOURCEA(IDD_ADMIN);
- odp.pfnDlgProc = admin_dialog;
- UserInfo_AddPage(wParam, &odp);
- }
- return 0;
-}
-
-INT_PTR CAimProto::EditProfile(WPARAM, LPARAM)
-{
- DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_AIM), nullptr, userinfo_dialog, LPARAM(this));
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Options dialog
-
-static INT_PTR CALLBACK options_dialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- CAimProto* ppro = (CAimProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-
- switch (msg) {
- case WM_INITDIALOG:
- TranslateDialogDefault(hwndDlg);
-
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
- ppro = (CAimProto*)lParam;
- {
- DBVARIANT dbv;
- if (!ppro->getString(AIM_KEY_SN, &dbv)) {
- SetDlgItemTextA(hwndDlg, IDC_SN, dbv.pszVal);
- db_free(&dbv);
- }
- if (!ppro->getString(AIM_KEY_NK, &dbv)) {
- SetDlgItemTextA(hwndDlg, IDC_NK, dbv.pszVal);
- db_free(&dbv);
- }
- else if (!ppro->getString(AIM_KEY_SN, &dbv)) {
- SetDlgItemTextA(hwndDlg, IDC_NK, dbv.pszVal);
- db_free(&dbv);
- }
- if (!ppro->getString(AIM_KEY_PW, &dbv)) {
- SetDlgItemTextA(hwndDlg, IDC_PW, dbv.pszVal);
- db_free(&dbv);
- }
- if (!ppro->getString(AIM_KEY_HN, &dbv)) {
- SetDlgItemTextA(hwndDlg, IDC_HN, dbv.pszVal);
- db_free(&dbv);
- }
- else SetDlgItemTextA(hwndDlg, IDC_HN, AIM_DEFAULT_SERVER);
-
- SetDlgItemInt(hwndDlg, IDC_PN, ppro->get_default_port(), FALSE);
-
- CheckDlgButton(hwndDlg, IDC_DC, ppro->getByte(AIM_KEY_DC, 0) ? BST_CHECKED : BST_UNCHECKED);//Message Delivery Confirmation
- CheckDlgButton(hwndDlg, IDC_FP, ppro->getByte(AIM_KEY_FP, 0) ? BST_CHECKED : BST_UNCHECKED);//force proxy
- CheckDlgButton(hwndDlg, IDC_AT, ppro->getByte(AIM_KEY_AT, 0) ? BST_CHECKED : BST_UNCHECKED);//Account Type Icons
- CheckDlgButton(hwndDlg, IDC_ES, ppro->getByte(AIM_KEY_ES, 0) ? BST_CHECKED : BST_UNCHECKED);//Extended Status Type Icons
- CheckDlgButton(hwndDlg, IDC_HF, ppro->getByte(AIM_KEY_HF, 0) ? BST_CHECKED : BST_UNCHECKED);//Fake hiptopness
- CheckDlgButton(hwndDlg, IDC_DM, ppro->getByte(AIM_KEY_DM, 0) ? BST_CHECKED : BST_UNCHECKED);//Disable Sending Mode Message
- CheckDlgButton(hwndDlg, IDC_FI, ppro->getByte(AIM_KEY_FI, 1) ? BST_CHECKED : BST_UNCHECKED);//Format incoming messages
- CheckDlgButton(hwndDlg, IDC_FO, ppro->getByte(AIM_KEY_FO, 1) ? BST_CHECKED : BST_UNCHECKED);//Format outgoing messages
- CheckDlgButton(hwndDlg, IDC_II, ppro->getByte(AIM_KEY_II, 0) ? BST_CHECKED : BST_UNCHECKED);//Instant Idle
- CheckDlgButton(hwndDlg, IDC_CM, ppro->getByte(AIM_KEY_CM, 0) ? BST_CHECKED : BST_UNCHECKED);//Check Mail
- CheckDlgButton(hwndDlg, IDC_MG, ppro->getByte(AIM_KEY_MG, 1) ? BST_CHECKED : BST_UNCHECKED);//Manage Groups
- CheckDlgButton(hwndDlg, IDC_DA, ppro->getByte(AIM_KEY_DA, 0) ? BST_CHECKED : BST_UNCHECKED);//Disable Avatars
- CheckDlgButton(hwndDlg, IDC_DSSL, ppro->getByte(AIM_KEY_DSSL, 0) ? BST_CHECKED : BST_UNCHECKED);//Disable SSL
- CheckDlgButton(hwndDlg, IDC_CLIENTLOGIN, ppro->getByte(AIM_KEY_CLIENTLOGIN, 1) ? BST_CHECKED : BST_UNCHECKED);//use clientlogin
- {
- HWND dssl = GetDlgItem(hwndDlg, IDC_DSSL);
- bool clientlogin = ppro->getByte(AIM_KEY_CLIENTLOGIN, 1) != 0;
- EnableWindow(dssl, clientlogin);
- if(!clientlogin)
- CheckDlgButton(hwndDlg, IDC_DSSL, BST_CHECKED);
- }
- CheckDlgButton(hwndDlg, IDC_FSC, ppro->getByte(AIM_KEY_FSC, 0) ? BST_CHECKED : BST_UNCHECKED);//Force Single Client
- }
- break;
-
- case WM_COMMAND:
- switch (LOWORD(wParam)) {
-
-
- case IDC_SVRRESET:
- SetDlgItemTextA(hwndDlg, IDC_HN, AIM_DEFAULT_SERVER);
- SetDlgItemInt(hwndDlg, IDC_PN, ppro->get_default_port(), FALSE);
- break;
-
- case IDC_SN:
- case IDC_PN:
- case IDC_NK:
- case IDC_PW:
- case IDC_HN:
- if (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())
- return 0;
- break;
- }
- if (IsDlgButtonChecked(hwndDlg, IDC_CLIENTLOGIN))
- {
- HWND dssl = GetDlgItem(hwndDlg, IDC_DSSL);
- EnableWindow(dssl, true);
- }
- else
- {
- HWND dssl = GetDlgItem(hwndDlg, IDC_DSSL);
- EnableWindow(dssl, false);
- CheckDlgButton(hwndDlg, IDC_DSSL, BST_CHECKED);
- }
- SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
- break;
-
- case WM_NOTIFY:
- switch (((LPNMHDR)lParam)->code) {
- case PSN_APPLY:
- {
- char str[128];
- //SN
- GetDlgItemTextA(hwndDlg, IDC_SN, str, _countof(str));
- if (str[0] != 0)
- ppro->setString(AIM_KEY_SN, str);
- else
- ppro->delSetting(AIM_KEY_SN);
- //END SN
-
- //NK
- if (GetDlgItemTextA(hwndDlg, IDC_NK, str, _countof(str)))
- ppro->setString(AIM_KEY_NK, str);
- else {
- GetDlgItemTextA(hwndDlg, IDC_SN, str, _countof(str));
- ppro->setString(AIM_KEY_NK, str);
- }
- //END NK
-
- //PW
- GetDlgItemTextA(hwndDlg, IDC_PW, str, _countof(str));
- if (str[0] != 0)
- ppro->setString(AIM_KEY_PW, str);
- else
- ppro->delSetting(AIM_KEY_PW);
- //END PW
-
- //HN
- GetDlgItemTextA(hwndDlg, IDC_HN, str, _countof(str));
- if (str[0] != 0 && mir_strcmp(str, AIM_DEFAULT_SERVER))
- ppro->setString(AIM_KEY_HN, str);
- else
- ppro->delSetting(AIM_KEY_HN);
- //END HN
-
- //Delivery Confirmation
- ppro->setByte(AIM_KEY_DC, IsDlgButtonChecked(hwndDlg, IDC_DC) != 0);
- //End Delivery Confirmation
-
- //Disable Avatar
- ppro->setByte(AIM_KEY_DA, IsDlgButtonChecked(hwndDlg, IDC_DA) != 0);
- //Disable Avatar
-
- //Disable SSL
- ppro->setByte(AIM_KEY_DSSL, IsDlgButtonChecked(hwndDlg, IDC_DSSL) != 0);
- //Disable SSL
-
- //use "clientlogin"
- ppro->setByte(AIM_KEY_CLIENTLOGIN, IsDlgButtonChecked(hwndDlg, IDC_CLIENTLOGIN) != 0);
- //use "clientlogin"
-
- //Force Single Login
- ppro->setByte(AIM_KEY_FSC, IsDlgButtonChecked(hwndDlg, IDC_FSC) != 0);
- //Force Single Login
-
- //Force Proxy Transfer
- ppro->setByte(AIM_KEY_FP, IsDlgButtonChecked(hwndDlg, IDC_FP) != 0);
- //End Force Proxy Transfer
-
- //PN
- int port = GetDlgItemInt(hwndDlg, IDC_PN, nullptr, FALSE);
- if (port > 0 && port != AIM_DEFAULT_PORT)
- ppro->setWord(AIM_KEY_PN, (WORD)port);
- else
- ppro->delSetting(AIM_KEY_PN);
- //END PN
-
- //Disable Account Type Icons
- if (IsDlgButtonChecked(hwndDlg, IDC_AT)) {
- int acc_disabled = ppro->getByte(AIM_KEY_AT, 0);
- if (!acc_disabled)
- remove_AT_icons(ppro);
- ppro->setByte(AIM_KEY_AT, 1);
- }
- else {
- int acc_disabled = ppro->getByte(AIM_KEY_AT, 0);
- if (acc_disabled)
- add_AT_icons(ppro);
- ppro->setByte(AIM_KEY_AT, 0);
- }
- //END
- //Disable Extra Status Icons
- if (IsDlgButtonChecked(hwndDlg, IDC_ES)) {
- int es_disabled = ppro->getByte(AIM_KEY_ES, 0);
- ppro->setByte(AIM_KEY_ES, 1);
- if (!es_disabled)
- remove_ES_icons(ppro);
- }
- else {
- int es_disabled = ppro->getByte(AIM_KEY_ES, 0);
- ppro->setByte(AIM_KEY_ES, 0);
- if (es_disabled)
- add_ES_icons(ppro);
- }
- //End
-
- //Fake Hiptop
- if (IsDlgButtonChecked(hwndDlg, IDC_HF)) {
- int hf = ppro->getByte(AIM_KEY_HF, 0);
- if (!hf)
- ShowWindow(GetDlgItem(hwndDlg, IDC_MASQ), SW_SHOW);
- ppro->setByte(AIM_KEY_HF, 1);
- }
- else {
- int hf = ppro->getByte(AIM_KEY_HF, 0);
- if (hf)
- ShowWindow(GetDlgItem(hwndDlg, IDC_MASQ), SW_SHOW);
- ppro->setByte(AIM_KEY_HF, 0);
- }
- //End
-
- //Disable Mode Message Sending
- ppro->setByte(AIM_KEY_DM, IsDlgButtonChecked(hwndDlg, IDC_DM) != 0);
- //End Disable Mode Message Sending
-
- //Format Incoming Messages
- ppro->setByte(AIM_KEY_FI, IsDlgButtonChecked(hwndDlg, IDC_FI) != 0);
- //End Format Incoming Messages
-
- //Format Outgoing Messages
- ppro->setByte(AIM_KEY_FO, IsDlgButtonChecked(hwndDlg, IDC_FO) != 0);
- //End Format Outgoing Messages
-
- //Instant Idle on Login
- ppro->setByte(AIM_KEY_II, IsDlgButtonChecked(hwndDlg, IDC_II) != 0);
- //End
- //Check Mail on Login
- ppro->setByte(AIM_KEY_CM, IsDlgButtonChecked(hwndDlg, IDC_CM) != 0);
- //End
-
- //Manage Groups
- ppro->setByte(AIM_KEY_MG, IsDlgButtonChecked(hwndDlg, IDC_MG) != 0);
- //End
- }
- }
- break;
- }
- return FALSE;
-}
-
-
-static INT_PTR CALLBACK privacy_dialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- static const int btns[] = { IDC_ALLOWALL, IDC_BLOCKALL, IDC_ALLOWBELOW, IDC_BLOCKBELOW, IDC_ALLOWCONT };
- CAimProto* ppro = (CAimProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- int i;
-
- switch (msg) {
- case WM_INITDIALOG:
- TranslateDialogDefault(hwndDlg);
-
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
- ppro = (CAimProto*)lParam;
-
- CheckRadioButton(hwndDlg, IDC_ALLOWALL, IDC_BLOCKBELOW, btns[ppro->m_pd_mode - 1]);
-
- for (i = 0; i < ppro->m_allow_list.getCount(); ++i)
- SendDlgItemMessageA(hwndDlg, IDC_ALLOWLIST, LB_ADDSTRING, 0, (LPARAM)ppro->m_allow_list[i].name);
-
- for (i = 0; i < ppro->m_block_list.getCount(); ++i)
- SendDlgItemMessageA(hwndDlg, IDC_BLOCKLIST, LB_ADDSTRING, 0, (LPARAM)ppro->m_block_list[i].name);
-
- CheckDlgButton(hwndDlg, IDC_SIS, (ppro->m_pref1_flags & 0x400) ? BST_CHECKED : BST_CHECKED);
- break;
-
- case WM_COMMAND:
- if (LOWORD(wParam) == IDC_ALLOWADD) {
- char nick[80];
- GetDlgItemTextA(hwndDlg, IDC_ALLOWEDIT, nick, _countof(nick));
- SendDlgItemMessageA(hwndDlg, IDC_ALLOWLIST, LB_ADDSTRING, 0, (LPARAM)trim_str(nick));
- }
- else if (LOWORD(wParam) == IDC_BLOCKADD) {
- char nick[80];
- GetDlgItemTextA(hwndDlg, IDC_BLOCKEDIT, nick, _countof(nick));
- SendDlgItemMessageA(hwndDlg, IDC_BLOCKLIST, LB_ADDSTRING, 0, (LPARAM)trim_str(nick));
- }
- else if (LOWORD(wParam) == IDC_ALLOWREMOVE) {
- i = SendDlgItemMessage(hwndDlg, IDC_ALLOWLIST, LB_GETCURSEL, 0, 0);
- SendDlgItemMessage(hwndDlg, IDC_ALLOWLIST, LB_DELETESTRING, i, 0);
- }
- else if (LOWORD(wParam) == IDC_BLOCKREMOVE) {
- i = SendDlgItemMessage(hwndDlg, IDC_BLOCKLIST, LB_GETCURSEL, 0, 0);
- SendDlgItemMessage(hwndDlg, IDC_BLOCKLIST, LB_DELETESTRING, i, 0);
- }
-
- SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
- break;
-
- case WM_NOTIFY:
- if (((LPNMHDR)lParam)->code == PSN_APPLY) {
- ppro->aim_ssi_update(ppro->m_hServerConn, ppro->m_seqno, true);
- for (i = 0; i < 5; ++i) {
- if (IsDlgButtonChecked(hwndDlg, btns[i]) && ppro->m_pd_mode != i + 1) {
- ppro->m_pd_mode = (char)(i + 1);
- ppro->m_pd_flags = 1;
- ppro->aim_set_pd_info(ppro->m_hServerConn, ppro->m_seqno);
- break;
- }
- }
- for (i = 0; i < ppro->m_block_list.getCount(); ++i) {
- BdListItem& pd = ppro->m_block_list[i];
- if (SendDlgItemMessageA(hwndDlg, IDC_BLOCKLIST, LB_FINDSTRING, (WPARAM)-1, (LPARAM)pd.name) == LB_ERR) {
- ppro->aim_delete_contact(ppro->m_hServerConn, ppro->m_seqno, pd.name, pd.item_id, 0, 3, false);
- ppro->m_block_list.remove(i--);
- }
- }
- i = SendDlgItemMessage(hwndDlg, IDC_BLOCKLIST, LB_GETCOUNT, 0, 0);
- for (; i--;) {
- char nick[80];
- SendDlgItemMessageA(hwndDlg, IDC_BLOCKLIST, LB_GETTEXT, i, (LPARAM)nick);
- if (ppro->m_block_list.find_id(nick) == 0) {
- unsigned short id = ppro->m_block_list.add(nick);
- ppro->aim_add_contact(ppro->m_hServerConn, ppro->m_seqno, nick, id, 0, 3);
- }
- }
-
- for (i = 0; i < ppro->m_allow_list.getCount(); ++i) {
- BdListItem& pd = ppro->m_allow_list[i];
- if (SendDlgItemMessageA(hwndDlg, IDC_ALLOWLIST, LB_FINDSTRING, (WPARAM)-1, (LPARAM)pd.name) == LB_ERR) {
- ppro->aim_delete_contact(ppro->m_hServerConn, ppro->m_seqno, pd.name, pd.item_id, 0, 2, false);
- ppro->m_allow_list.remove(i--);
- }
- }
- i = SendDlgItemMessage(hwndDlg, IDC_ALLOWLIST, LB_GETCOUNT, 0, 0);
- for (; i--;) {
- char nick[80];
- SendDlgItemMessageA(hwndDlg, IDC_ALLOWLIST, LB_GETTEXT, i, (LPARAM)nick);
- if (ppro->m_allow_list.find_id(nick) == 0) {
- unsigned short id = ppro->m_allow_list.add(nick);
- ppro->aim_add_contact(ppro->m_hServerConn, ppro->m_seqno, nick, id, 0, 2);
- }
- }
-
- unsigned mask = (IsDlgButtonChecked(hwndDlg, IDC_SIS) == BST_CHECKED) << 10;
- if ((ppro->m_pref1_flags & 0x400) ^ mask) {
- ppro->m_pref1_flags = (ppro->m_pref1_flags & ~0x400) | mask;
- ppro->aim_ssi_update_preferences(ppro->m_hServerConn, ppro->m_seqno);
- }
-
- ppro->aim_ssi_update(ppro->m_hServerConn, ppro->m_seqno, false);
- }
- break;
- }
- return FALSE;
-}
-
-
-int CAimProto::OnOptionsInit(WPARAM wParam, LPARAM)
-{
- OPTIONSDIALOGPAGE odp = { 0 };
- odp.position = 1003000;
- odp.hInstance = hInstance;
- odp.szGroup.w = LPGENW("Network");
- odp.szTitle.w = m_tszUserName;
- odp.dwInitParam = LPARAM(this);
- odp.flags = ODPF_BOLDGROUPS | ODPF_UNICODE | ODPF_DONTTRANSLATE;
-
- odp.szTab.w = LPGENW("Basic");
- odp.pszTemplate = MAKEINTRESOURCEA(IDD_AIM);
- odp.pfnDlgProc = options_dialog;
- Options_AddPage(wParam, &odp);
-
- odp.szTab.w = LPGENW("Privacy");
- odp.pszTemplate = MAKEINTRESOURCEA(IDD_PRIVACY);
- odp.pfnDlgProc = privacy_dialog;
- Options_AddPage(wParam, &odp);
- return 0;
-}
-
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Brief account info dialog
-
-INT_PTR CALLBACK first_run_dialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- CAimProto* ppro = (CAimProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-
- switch (msg) {
- case WM_INITDIALOG:
- TranslateDialogDefault(hwndDlg);
-
- ppro = (CAimProto*)lParam;
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
- {
- DBVARIANT dbv;
- if (!ppro->getString(AIM_KEY_SN, &dbv)) {
- SetDlgItemTextA(hwndDlg, IDC_SN, dbv.pszVal);
- db_free(&dbv);
- }
-
- if (!ppro->getString(AIM_KEY_PW, &dbv)) {
- SetDlgItemTextA(hwndDlg, IDC_PW, dbv.pszVal);
- db_free(&dbv);
- }
- }
- return TRUE;
-
- case WM_COMMAND:
- if (LOWORD(wParam) == IDC_NEWAIMACCOUNTLINK) {
- Utils_OpenUrl("http://www.aim.com/redirects/inclient/register.adp");
- return TRUE;
- }
-
- if (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == GetFocus()) {
- switch (LOWORD(wParam)) {
- case IDC_SN:
- case IDC_PW:
- SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
- }
- }
- break;
-
- case WM_NOTIFY:
- if (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY) {
- char str[128];
- GetDlgItemTextA(hwndDlg, IDC_SN, str, _countof(str));
- ppro->setString(AIM_KEY_SN, str);
-
- GetDlgItemTextA(hwndDlg, IDC_PW, str, _countof(str));
- ppro->setString(AIM_KEY_PW, str);
- return TRUE;
- }
- break;
- }
-
- return FALSE;
-}
-
-INT_PTR CAimProto::SvcCreateAccMgrUI(WPARAM, LPARAM lParam)
-{
- return (INT_PTR)CreateDialogParam(hInstance, MAKEINTRESOURCE(IDD_AIMACCOUNT),
- (HWND)lParam, first_run_dialog, (LPARAM)this);
-}
-
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Instant idle dialog
-
-INT_PTR CALLBACK instant_idle_dialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- CAimProto *ppro = (CAimProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-
- switch (msg) {
- case WM_INITDIALOG:
- TranslateDialogDefault(hwndDlg);
-
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
- ppro = (CAimProto*)lParam;
- {
- Window_SetIcon_IcoLib(hwndDlg, GetIconHandle("idle"));
-
- unsigned long it = ppro->getDword(AIM_KEY_IIT, 0);
- unsigned long hours = it / 60;
- unsigned long minutes = it % 60;
- SetDlgItemInt(hwndDlg, IDC_IIH, hours, 0);
- SetDlgItemInt(hwndDlg, IDC_IIM, minutes, 0);
- }
- break;
-
- case WM_CLOSE:
- EndDialog(hwndDlg, 0);
- break;
-
- case WM_DESTROY:
- Window_FreeIcon_IcoLib(hwndDlg);
- break;
-
- case WM_COMMAND:
- {
- unsigned long hours = GetDlgItemInt(hwndDlg, IDC_IIH, nullptr, 0);
- unsigned short minutes = (unsigned short)GetDlgItemInt(hwndDlg, IDC_IIM, nullptr, 0);
- if (minutes > 59)
- minutes = 59;
-
- ppro->setDword(AIM_KEY_IIT, hours * 60 + minutes);
- switch (LOWORD(wParam)) {
- case IDOK:
- //Instant Idle
- if (ppro->m_state == 1) {
- ppro->aim_set_idle(ppro->m_hServerConn, ppro->m_seqno, hours * 60 * 60 + minutes * 60);
- ppro->m_instantidle = 1;
- }
- EndDialog(hwndDlg, IDOK);
- break;
-
- case IDCANCEL:
- ppro->aim_set_idle(ppro->m_hServerConn, ppro->m_seqno, 0);
- ppro->m_instantidle = 0;
- EndDialog(hwndDlg, IDCANCEL);
- break;
- }
- }
- break;
- }
- return FALSE;
-}
-
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Join chat dialog
-
-INT_PTR CALLBACK join_chat_dialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- CAimProto* ppro = (CAimProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-
- switch (msg) {
- case WM_INITDIALOG:
- TranslateDialogDefault(hwndDlg);
-
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
- ppro = (CAimProto*)lParam;
- Window_SetIcon_IcoLib(hwndDlg, GetIconHandle("aol"));
- break;
-
- case WM_CLOSE:
- EndDialog(hwndDlg, 0);
- break;
-
- case WM_DESTROY:
- Window_FreeIcon_IcoLib(hwndDlg);
- break;
-
- case WM_COMMAND:
- switch (LOWORD(wParam)) {
- case IDOK:
- char room[128];
- GetDlgItemTextA(hwndDlg, IDC_ROOM, room, _countof(room));
- if (ppro->m_state == 1 && room[0] != 0) {
- chatnav_param* par = new chatnav_param(room, 4);
- ppro->ForkThread(&CAimProto::chatnav_request_thread, par);
- }
- EndDialog(hwndDlg, IDOK);
- break;
-
- case IDCANCEL:
- EndDialog(hwndDlg, IDCANCEL);
- break;
- }
- break;
- }
-
- return FALSE;
-}
-/////////////////////////////////////////////////////////////////////////////////////////
-// Invite to chat dialog
-
-static void clist_chat_invite_send(MCONTACT hItem, HWND hwndList, chat_list_item* item, CAimProto* ppro, char *msg)
-{
- if (hItem == NULL)
- hItem = (MCONTACT)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_ROOT, 0);
-
- while (hItem) {
- if (IsHContactGroup(hItem)) {
- MCONTACT hItemT = (MCONTACT)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem);
- if (hItemT)
- clist_chat_invite_send(hItemT, hwndList, item, ppro, msg);
- }
- else {
- int chk = SendMessage(hwndList, CLM_GETCHECKMARK, (WPARAM)hItem, 0);
- if (chk) {
- if (IsHContactInfo(hItem)) {
- wchar_t buf[128] = L"";
- SendMessage(hwndList, CLM_GETITEMTEXT, (WPARAM)hItem, (LPARAM)buf);
-
- char *sn = mir_u2a(buf);
- ppro->aim_chat_invite(ppro->m_hServerConn, ppro->m_seqno,
- item->cookie, item->exchange, item->instance, sn, msg);
- mir_free(sn);
- }
- else {
- DBVARIANT dbv;
- if (!ppro->getString(hItem, AIM_KEY_SN, &dbv)) {
- ppro->aim_chat_invite(ppro->m_hServerConn, ppro->m_seqno,
- item->cookie, item->exchange, item->instance, dbv.pszVal, msg);
- db_free(&dbv);
- }
- }
- }
- }
- hItem = (MCONTACT)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXT, (LPARAM)hItem);
- }
-}
-
-static void clist_validate_contact(MCONTACT hItem, HWND hwndList, CAimProto* ppro)
-{
- if (!ppro->is_my_contact(hItem) || ppro->isChatRoom(hItem) ||
- ppro->getWord(hItem, AIM_KEY_ST, ID_STATUS_OFFLINE) == ID_STATUS_ONTHEPHONE)
- SendMessage(hwndList, CLM_DELETEITEM, (WPARAM)hItem, 0);
-}
-
-static void clist_chat_prepare(MCONTACT hItem, HWND hwndList, CAimProto* ppro)
-{
- if (hItem == NULL)
- hItem = (MCONTACT)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_ROOT, 0);
-
- while (hItem) {
- MCONTACT hItemN = (MCONTACT)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXT, (LPARAM)hItem);
- if (IsHContactGroup(hItem)) {
- MCONTACT hItemT = (MCONTACT)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem);
- if (hItemT)
- clist_chat_prepare(hItemT, hwndList, ppro);
- }
- else if (IsHContactContact(hItem))
- clist_validate_contact(hItem, hwndList, ppro);
-
- hItem = hItemN;
- }
-}
-
-INT_PTR CALLBACK invite_to_chat_dialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- invite_chat_param* param = (invite_chat_param*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-
- switch (msg) {
- case WM_INITDIALOG:
- TranslateDialogDefault(hwndDlg);
-
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
- param = (invite_chat_param*)lParam;
-
- Window_SetIcon_IcoLib(hwndDlg, GetIconHandle("aol"));
- SetDlgItemTextA(hwndDlg, IDC_ROOMNAME, param->id);
- SetDlgItemTextA(hwndDlg, IDC_MSG, Translate("Join me in this buddy chat!"));
- break;
-
- case WM_CLOSE:
- EndDialog(hwndDlg, 0);
- break;
-
- case WM_NCDESTROY:
- Window_FreeIcon_IcoLib(hwndDlg);
- delete param;
- break;
-
- case WM_NOTIFY:
- {
- NMCLISTCONTROL *nmc = (NMCLISTCONTROL*)lParam;
- if (nmc->hdr.idFrom == IDC_CCLIST) {
- switch (nmc->hdr.code) {
- case CLN_NEWCONTACT:
- if (param && (nmc->flags & (CLNF_ISGROUP | CLNF_ISINFO)) == 0)
- clist_validate_contact((UINT_PTR)nmc->hItem, nmc->hdr.hwndFrom, param->ppro);
- break;
-
- case CLN_LISTREBUILT:
- if (param)
- clist_chat_prepare(NULL, nmc->hdr.hwndFrom, param->ppro);
- break;
- }
- }
- }
- break;
-
- case WM_COMMAND:
- {
- switch (LOWORD(wParam)) {
- case IDC_ADDSCR:
- if (param->ppro->m_state == 1) {
- wchar_t sn[64];
- GetDlgItemText(hwndDlg, IDC_EDITSCR, sn, _countof(sn));
-
- CLCINFOITEM cii = { 0 };
- cii.cbSize = sizeof(cii);
- cii.flags = CLCIIF_CHECKBOX | CLCIIF_BELOWCONTACTS;
- cii.pszText = sn;
-
- HANDLE hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_CCLIST, CLM_ADDINFOITEM, 0, (LPARAM)&cii);
- SendDlgItemMessage(hwndDlg, IDC_CCLIST, CLM_SETCHECKMARK, (LPARAM)hItem, 1);
- }
- break;
-
- case IDOK:
- {
- chat_list_item* item = param->ppro->find_chat_by_id(param->id);
- if (item) {
- char buf[1024];
- GetDlgItemTextA(hwndDlg, IDC_MSG, buf, _countof(buf));
-
- HWND hwndList = GetDlgItem(hwndDlg, IDC_CCLIST);
- clist_chat_invite_send(NULL, hwndList, item, param->ppro, buf);
- }
- EndDialog(hwndDlg, IDOK);
- }
- break;
-
- case IDCANCEL:
- EndDialog(hwndDlg, IDCANCEL);
- break;
- }
- }
- break;
- }
- return FALSE;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Chat request dialog
-
-INT_PTR CALLBACK chat_request_dialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- invite_chat_req_param* param = (invite_chat_req_param*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-
- switch (msg) {
- case WM_INITDIALOG:
- TranslateDialogDefault(hwndDlg);
-
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
- param = (invite_chat_req_param*)lParam;
-
- Window_SetIcon_IcoLib(hwndDlg, GetIconHandle("aol"));
-
- SetDlgItemTextA(hwndDlg, IDC_ROOMNAME, strrchr(param->cnp->id, '-') + 1);
- SetDlgItemTextA(hwndDlg, IDC_SCREENNAME, param->name);
- SetDlgItemTextA(hwndDlg, IDC_MSG, param->message);
- break;
-
- case WM_CLOSE:
- EndDialog(hwndDlg, 0);
- break;
-
- case WM_DESTROY:
- Window_FreeIcon_IcoLib(hwndDlg);
- delete param;
- break;
-
- case WM_COMMAND:
- switch (LOWORD(wParam)) {
- case IDOK:
- param->ppro->ForkThread(&CAimProto::chatnav_request_thread, param->cnp);
- EndDialog(hwndDlg, IDOK);
- break;
-
- case IDCANCEL:
- param->ppro->aim_chat_deny(param->ppro->m_hServerConn, param->ppro->m_seqno, param->name, param->icbm_cookie);
- delete param->cnp;
- EndDialog(hwndDlg, IDCANCEL);
- break;
- }
- break;
- }
- return FALSE;
-}
-
-
-void CALLBACK chat_request_cb(PVOID dwParam)
-{
- CreateDialogParam(hInstance, MAKEINTRESOURCE(IDD_CHATROOM_INVITE_REQ),
- nullptr, chat_request_dialog, (LPARAM)dwParam);
-}
diff --git a/protocols/AimOscar/src/ui.h b/protocols/AimOscar/src/ui.h
deleted file mode 100644
index e6a1b984c0..0000000000
--- a/protocols/AimOscar/src/ui.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef WINDOWS_H
-#define WINDOWS_H
-
-#ifndef CFM_BACKCOLOR
-#define CFM_BACKCOLOR 0x04000000
-#endif
-#ifndef CFE_AUTOBACKCOLOR
-#define CFE_AUTOBACKCOLOR CFM_BACKCOLOR
-#endif
-
-struct invite_chat_param
-{
- char* id;
- CAimProto* ppro;
-
- invite_chat_param(const char* idt, CAimProto* prt)
- { id = mir_strdup(idt); ppro = prt; }
-};
-
-struct invite_chat_req_param
-{
- chatnav_param* cnp;
- CAimProto* ppro;
- char* message;
- char* name;
- char* icbm_cookie;
-
- invite_chat_req_param(chatnav_param* cnpt, CAimProto* prt, char* msg, char* nm, char* icki)
- { cnp = cnpt; ppro = prt; message = mir_strdup(msg); name = mir_strdup(nm);
- icbm_cookie = (char*)mir_alloc(8); memcpy(icbm_cookie, icki, 8); }
-
- ~invite_chat_req_param()
- { mir_free(message); mir_free(name); mir_free(icbm_cookie); }
-};
-
-INT_PTR CALLBACK instant_idle_dialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
-INT_PTR CALLBACK join_chat_dialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
-INT_PTR CALLBACK invite_to_chat_dialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
-INT_PTR CALLBACK chat_request_dialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
-
-void CALLBACK chat_request_cb(PVOID dwParam);
-
-#endif
diff --git a/protocols/AimOscar/src/utility.cpp b/protocols/AimOscar/src/utility.cpp
deleted file mode 100755
index eeb52b6f26..0000000000
--- a/protocols/AimOscar/src/utility.cpp
+++ /dev/null
@@ -1,663 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2012 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-void CAimProto::broadcast_status(int status)
-{
- debugLogA("Broadcast Status: %d", status);
- int old_status = m_iStatus;
- m_iStatus = status;
- if (m_iStatus == ID_STATUS_OFFLINE) {
- shutdown_file_transfers();
- shutdown_chat_conn();
-
- if (m_hServerConn) {
- aim_sendflap(m_hServerConn, 0x04, 0, nullptr, m_seqno);
- Netlib_Shutdown(m_hServerConn);
- }
-
- if (m_hMailConn && m_hMailConn != (HANDLE)1) {
- aim_sendflap(m_hMailConn, 0x04, 0, nullptr, m_mail_seqno);
- Netlib_Shutdown(m_hMailConn);
- }
- else if (m_hMailConn == (HANDLE)1)
- m_hMailConn = nullptr;
-
- if (m_hAvatarConn && m_hAvatarConn != (HANDLE)1) {
- aim_sendflap(m_hAvatarConn, 0x04, 0, nullptr, m_avatar_seqno);
- Netlib_Shutdown(m_hAvatarConn);
- }
- else if (m_hAvatarConn == (HANDLE)1)
- m_hAvatarConn = nullptr;
-
- if (m_hChatNavConn && m_hChatNavConn != (HANDLE)1) {
- aim_sendflap(m_hChatNavConn, 0x04, 0, nullptr, m_chatnav_seqno);
- Netlib_Shutdown(m_hChatNavConn);
- }
- else if (m_hChatNavConn == (HANDLE)1)
- m_hChatNavConn = nullptr;
-
- m_idle = false;
- m_instantidle = false;
- m_list_received = false;
- m_state = 0;
- m_iDesiredStatus = ID_STATUS_OFFLINE;
- replaceStr(m_last_status_msg, nullptr);
-
- m_avatar_id_lg = 0;
- m_avatar_id_sm = 0;
- replaceStr(m_hash_lg, nullptr);
- replaceStr(m_hash_sm, nullptr);
-
- m_pd_flags = 0;
- m_pd_info_id = 0;
- m_pd_mode = 0;
-
- m_seqno = 0;
- m_mail_seqno = 0;
- m_avatar_seqno = 0;
- m_chatnav_seqno = 0;
- m_admin_seqno = 0;
- }
- ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus);
-}
-
-void CAimProto::start_connection(void*)
-{
- if (m_iStatus <= ID_STATUS_OFFLINE) {
- offline_contacts();
- DBVARIANT dbv;
- if (!getString(AIM_KEY_SN, &dbv))
- db_free(&dbv);
- else {
- ShowPopup(LPGEN("Please, enter a user name in the options dialog."), 0);
- broadcast_status(ID_STATUS_OFFLINE);
- return;
- }
- if (!getString(AIM_KEY_PW, &dbv))
- db_free(&dbv);
- else {
- ShowPopup(LPGEN("Please, enter a password in the options dialog."), 0);
- broadcast_status(ID_STATUS_OFFLINE);
- return;
- }
-
-
- bool use_clientlogin = getByte(AIM_KEY_CLIENTLOGIN, 1) != 0; //clientlogin should be enabled by default
- if (!use_clientlogin)
- {
- char* login_url = getStringA(AIM_KEY_HN);
- //if (login_url == NULL) login_url = mir_strdup(use_ssl ? AIM_DEFAULT_SERVER : AIM_DEFAULT_SERVER_NS);
-
-
- if (login_url == nullptr) login_url = mir_strdup(AIM_DEFAULT_SERVER);
-
- m_hServerConn = aim_connect(login_url, get_default_port(), false, login_url); //ssl does not work anymore with old authorization algo
-
- mir_free(login_url);
-
- m_pref1_flags = 0x77ffff;
- m_pref1_set_flags = 0x77ffff;
- mir_free(m_pref2_flags); m_pref2_flags = nullptr; m_pref2_len = 0;
- mir_free(m_pref2_set_flags); m_pref2_set_flags = nullptr; m_pref2_set_len = 0;
-
- if (m_hServerConn)
- aim_connection_authorization();
- else
- broadcast_status(ID_STATUS_OFFLINE);
- }
- else
- {
- aim_connection_clientlogin();
-
- }
- }
-}
-
-bool CAimProto::wait_conn(HNETLIBCONN &hConn, HANDLE &hEvent, unsigned short service)
-{
- if (m_iStatus == ID_STATUS_OFFLINE)
- return false;
- {
- mir_cslock lck(connMutex);
- if (hConn == nullptr && m_hServerConn) {
- debugLogA("Starting Connection.");
- hConn = (HNETLIBCONN)1; //set so no additional service request attempts are made while aim is still processing the request
- aim_new_service_request(m_hServerConn, m_seqno, service);//general service connection!
- }
- }
-
- if (WaitForSingleObjectEx(hEvent, 10000, TRUE) != WAIT_OBJECT_0)
- return false;
-
- if (Miranda_IsTerminated() || m_iStatus == ID_STATUS_OFFLINE)
- return false;
-
- return true;
-}
-
-
-unsigned short CAimProto::get_default_port(void)
-{
- //return getWord(AIM_KEY_PN, getByte(AIM_KEY_DSSL, 0) ? AIM_DEFAULT_PORT : AIM_DEFAULT_SSL_PORT);
- return AIM_DEFAULT_PORT;
-}
-
-bool CAimProto::is_my_contact(MCONTACT hContact)
-{
- const char* szProto = GetContactProto(hContact);
- return szProto != nullptr && mir_strcmp(m_szModuleName, szProto) == 0;
-}
-
-MCONTACT CAimProto::find_chat_contact(const char* room)
-{
- for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
- DBVARIANT dbv;
- if (!getString(hContact, "ChatRoomID", &dbv)) {
- bool found = !mir_strcmp(room, dbv.pszVal);
- db_free(&dbv);
- if (found)
- return hContact;
- }
- }
- return NULL;
-}
-
-MCONTACT CAimProto::contact_from_sn(const char* sn, bool addIfNeeded, bool temporary)
-{
- ptrA norm_sn(normalize_name(sn));
-
- for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
- DBVARIANT dbv;
- if (!getString(hContact, AIM_KEY_SN, &dbv)) {
- bool found = !mir_strcmp(norm_sn, dbv.pszVal);
- db_free(&dbv);
- if (found)
- return hContact;
- }
- }
-
- if (addIfNeeded) {
- MCONTACT hContact = db_add_contact();
- if (hContact) {
- if (Proto_AddToContact(hContact, m_szModuleName) == 0) {
- setString(hContact, AIM_KEY_SN, norm_sn);
- setString(hContact, AIM_KEY_NK, sn);
- debugLogA("Adding contact %s to client side list.", norm_sn);
- if (temporary)
- db_set_b(hContact, "CList", "NotOnList", 1);
- return hContact;
- }
- db_delete_contact(hContact);
- }
- }
-
- return NULL;
-}
-
-void CAimProto::update_server_group(const char* group, unsigned short group_id)
-{
- unsigned short user_id_array_size;
- unsigned short* user_id_array;
-
- if (group_id)
- user_id_array = get_members_of_group(group_id, user_id_array_size);
- else {
- user_id_array_size = (unsigned short)m_group_list.getCount();
- user_id_array = (unsigned short*)mir_alloc(user_id_array_size * sizeof(unsigned short));
- for (unsigned short i = 0; i < user_id_array_size; ++i)
- user_id_array[i] = _htons(m_group_list[i].item_id);
- }
-
- debugLogA("Modifying group %s:%u on the serverside list", group, group_id);
- aim_mod_group(m_hServerConn, m_seqno, group, group_id, (char*)user_id_array,
- user_id_array_size * sizeof(unsigned short));
-
- mir_free(user_id_array);
-}
-
-void CAimProto::add_contact_to_group(MCONTACT hContact, const char* new_group)
-{
- if (new_group == nullptr)
- return;
-
- unsigned short old_group_id = getGroupId(hContact, 1);
- char *old_group = m_group_list.find_name(old_group_id);
- if (old_group && mir_strcmp(new_group, old_group) == 0)
- return;
-
- DBVARIANT dbv;
- char *nick = nullptr;
- if (!db_get_utf(hContact, MOD_KEY_CL, "MyHandle", &dbv)) {
- nick = NEWSTR_ALLOCA(dbv.pszVal);
- db_free(&dbv);
- }
-
- if (getString(hContact, AIM_KEY_SN, &dbv)) return;
-
- unsigned short item_id = getBuddyId(hContact, 1);
- unsigned short new_item_id = search_for_free_item_id(hContact);
- unsigned short new_group_id = m_group_list.find_id(new_group);
-
- if (!item_id)
- debugLogA("Contact %u not on list.", hContact);
-
- setGroupId(hContact, 1, new_group_id);
- if (new_group && mir_strcmp(new_group, AIM_DEFAULT_GROUP))
- db_set_utf(hContact, MOD_KEY_CL, OTH_KEY_GP, new_group);
- else
- db_unset(hContact, MOD_KEY_CL, OTH_KEY_GP);
-
- aim_ssi_update(m_hServerConn, m_seqno, true);
-
- if (new_group_id == 0) {
- create_group(new_group);
- debugLogA("Group %s not on list.", new_group);
- new_group_id = m_group_list.add(new_group);
- debugLogA("Adding group %s:%u to the serverside list", new_group, new_group_id);
- aim_add_contact(m_hServerConn, m_seqno, new_group, 0, new_group_id, 1);//add the group server-side even if it exist
- }
-
- debugLogA("Adding buddy %s:%u %s:%u to the serverside list", dbv.pszVal, new_item_id, new_group, new_group_id);
- aim_add_contact(m_hServerConn, m_seqno, dbv.pszVal, new_item_id, new_group_id, 0, nick);
-
- update_server_group(new_group, new_group_id);
-
- if (old_group_id && item_id) {
- bool is_not_in_list = getBool(hContact, AIM_KEY_NIL, false);
- debugLogA("Removing buddy %s:%u %s:%u from the serverside list", dbv.pszVal, item_id, old_group, old_group_id);
- aim_delete_contact(m_hServerConn, m_seqno, dbv.pszVal, item_id, old_group_id, 0, is_not_in_list);
- update_server_group(old_group, old_group_id);
- delSetting(hContact, AIM_KEY_NIL);
- }
-
- aim_ssi_update(m_hServerConn, m_seqno, false);
-
- db_free(&dbv);
-}
-
-void CAimProto::offline_contact(MCONTACT hContact, bool remove_settings)
-{
- if (remove_settings) {
- //We need some of this stuff if we are still online.
- for (int i = 1;; ++i) {
- if (deleteBuddyId(hContact, i)) break;
- deleteGroupId(hContact, i);
- }
-
- db_unset(hContact, MOD_KEY_CL, OTH_KEY_SM);
- }
- setWord(hContact, AIM_KEY_ST, ID_STATUS_OFFLINE);
-}
-
-void CAimProto::offline_contacts(void)
-{
- for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName))
- offline_contact(hContact, true);
-
- m_allow_list.destroy();
- m_block_list.destroy();
- m_group_list.destroy();
-}
-
-char *normalize_name(const char *s)
-{
- if (s == nullptr) return nullptr;
-
- char* buf = mir_strdup(s);
- _strlwr(buf);
- /*
- char *p = strchr(buf, ' ');
- if (p)
- {
- char *q = p;
- while (*p)
- {
- if (*p != ' ') *(q++) = *p;
- ++p;
- }
- *q = '\0';
- }
- */
- return buf;
-}
-
-char* trim_str(char* s)
-{
- if (s == nullptr) return nullptr;
- size_t len = mir_strlen(s);
-
- while (len) {
- if (isspace(s[len - 1])) --len;
- else break;
- }
- s[len] = 0;
-
- char* sc = s;
- while (isspace(*sc)) ++sc;
- memcpy(s, sc, mir_strlen(sc) + 1);
-
- return s;
-}
-
-void create_group(const char *group)
-{
- if (mir_strcmp(group, AIM_DEFAULT_GROUP) == 0) return;
-
- wchar_t* szGroupName = mir_utf8decodeW(group);
- Clist_GroupCreate(0, szGroupName);
- mir_free(szGroupName);
-}
-
-unsigned short CAimProto::search_for_free_item_id(MCONTACT hbuddy)//returns a free item id and links the id to the buddy
-{
- unsigned short id;
-
-retry:
- id = get_random();
-
- for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
- for (int i = 1; ; ++i) {
- unsigned short item_id = getBuddyId(hContact, i);
- if (item_id == 0) break;
-
- if (item_id == id) goto retry; //found one no need to look through anymore
- }
- }
-
- setBuddyId(hbuddy, 1, id);
- return id;
-}
-
-//returns the size of the list array aquired with data
-unsigned short* CAimProto::get_members_of_group(unsigned short group_id, unsigned short &size)
-{
- unsigned short* list = nullptr;
- size = 0;
-
- for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
- for (int i = 1; ; ++i) {
- unsigned short user_group_id = getGroupId(hContact, i);
- if (user_group_id == 0)
- break;
-
- if (group_id == user_group_id) {
- unsigned short buddy_id = getBuddyId(hContact, i);
- if (buddy_id) {
- list = (unsigned short*)mir_realloc(list, ++size*sizeof(list[0]));
- list[size - 1] = _htons(buddy_id);
- }
- }
- }
- }
- return list;
-}
-
-void CAimProto::upload_nicks(void)
-{
- for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
- DBVARIANT dbv;
- if (!db_get_utf(hContact, MOD_KEY_CL, "MyHandle", &dbv)) {
- set_local_nick(hContact, dbv.pszVal, nullptr);
- db_free(&dbv);
- }
- }
-}
-
-void CAimProto::set_local_nick(MCONTACT hContact, char* nick, char* note)
-{
- DBVARIANT dbv;
- if (getString(hContact, AIM_KEY_SN, &dbv)) return;
-
- for (int i = 1; ; ++i) {
- unsigned short group_id = getGroupId(hContact, i);
- if (group_id == 0) break;
-
- unsigned short buddy_id = getBuddyId(hContact, i);
- if (buddy_id == 0) break;
-
- aim_mod_buddy(m_hServerConn, m_seqno, dbv.pszVal, buddy_id, group_id, nick, note);
- }
- db_free(&dbv);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-unsigned short BdList::get_free_id(void)
-{
- unsigned short id;
-
-retry:
- id = get_random();
-
- for (int i = 0; i < count; ++i)
- if (items[i]->item_id == id) goto retry;
-
- return id;
-}
-
-unsigned short BdList::find_id(const char* name)
-{
- for (int i = 0; i < count; ++i) {
- if (_stricmp(items[i]->name, name) == 0)
- return items[i]->item_id;
- }
- return 0;
-}
-
-char* BdList::find_name(unsigned short id)
-{
- for (int i = 0; i < count; ++i) {
- if (items[i]->item_id == id)
- return items[i]->name;
- }
- return nullptr;
-}
-
-void BdList::remove_by_id(unsigned short id)
-{
- for (int i = 0; i < count; ++i) {
- if (items[i]->item_id == id) {
- remove(i);
- break;
- }
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-unsigned short CAimProto::getBuddyId(MCONTACT hContact, int i)
-{
- char item[sizeof(AIM_KEY_BI) + 10];
- mir_snprintf(item, AIM_KEY_BI"%d", i);
- return getWord(hContact, item, 0);
-}
-
-void CAimProto::setBuddyId(MCONTACT hContact, int i, unsigned short id)
-{
- char item[sizeof(AIM_KEY_BI) + 10];
- mir_snprintf(item, AIM_KEY_BI"%d", i);
- setWord(hContact, item, id);
-}
-
-int CAimProto::deleteBuddyId(MCONTACT hContact, int i)
-{
- char item[sizeof(AIM_KEY_BI) + 10];
- mir_snprintf(item, AIM_KEY_BI"%d", i);
- return delSetting(hContact, item);
-}
-
-unsigned short CAimProto::getGroupId(MCONTACT hContact, int i)
-{
- char item[sizeof(AIM_KEY_GI) + 10];
- mir_snprintf(item, AIM_KEY_GI"%d", i);
- return getWord(hContact, item, 0);
-}
-
-void CAimProto::setGroupId(MCONTACT hContact, int i, unsigned short id)
-{
- char item[sizeof(AIM_KEY_GI) + 10];
- mir_snprintf(item, AIM_KEY_GI"%d", i);
- setWord(hContact, item, id);
-}
-
-int CAimProto::deleteGroupId(MCONTACT hContact, int i)
-{
- char item[sizeof(AIM_KEY_GI) + 10];
- mir_snprintf(item, AIM_KEY_GI"%d", i);
- return delSetting(hContact, item);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-int CAimProto::open_contact_file(const char*, const wchar_t* file, const char*, wchar_t* &path, bool contact_dir)
-{
- path = (wchar_t*)mir_alloc(MAX_PATH * sizeof(wchar_t));
-
- int pos = mir_snwprintf(path, MAX_PATH, L"%s\\%S", VARSW(L"%miranda_userdata%"), m_szModuleName);
- if (contact_dir)
- pos += mir_snwprintf(path + pos, MAX_PATH - pos, L"\\%S", m_szModuleName);
-
- if (_waccess(path, 0))
- CreateDirectoryTreeW(path);
-
- mir_snwprintf(path + pos, MAX_PATH - pos, L"\\%s", file);
- int fid = _wopen(path, _O_CREAT | _O_RDWR | _O_BINARY, _S_IREAD);
- if (fid < 0) {
- wchar_t errmsg[512];
- mir_snwprintf(errmsg, TranslateT("Failed to open file: %s %s"), path, __tcserror(nullptr));
- ShowPopup((char*)errmsg, ERROR_POPUP | TCHAR_POPUP);
- }
- return fid;
-}
-
-void CAimProto::write_away_message(const char* sn, const char* msg, bool utf)
-{
- wchar_t* path;
- int fid = open_contact_file(sn, L"away.html", "wb", path, 1);
- if (fid >= 0) {
- if (utf) _write(fid, "\xEF\xBB\xBF", 3);
- char* s_msg = process_status_msg(msg, sn);
- _write(fid, "<h3>", 4);
- _write(fid, sn, (unsigned)mir_strlen(sn));
- _write(fid, "'s Away Message:</h3>", 21);
- _write(fid, s_msg, (unsigned)mir_strlen(s_msg));
- _close(fid);
- ShellExecute(nullptr, L"open", path, nullptr, nullptr, SW_SHOW);
- mir_free(path);
- mir_free(s_msg);
- }
-}
-
-void CAimProto::write_profile(const char* sn, const char* msg, bool utf)
-{
- wchar_t* path;
- int fid = open_contact_file(sn, L"profile.html", "wb", path, 1);
- if (fid >= 0) {
- if (utf) _write(fid, "\xEF\xBB\xBF", 3);
- char* s_msg = process_status_msg(msg, sn);
- _write(fid, "<h3>", 4);
- _write(fid, sn, (unsigned)mir_strlen(sn));
- _write(fid, "'s Profile:</h3>", 16);
- _write(fid, s_msg, (unsigned)mir_strlen(s_msg));
- _close(fid);
- ShellExecute(nullptr, L"open", path, nullptr, nullptr, SW_SHOW);
- mir_free(path);
- mir_free(s_msg);
- }
-}
-
-unsigned long aim_oft_checksum_chunk(unsigned long dwChecksum, const unsigned char *buffer, int len)
-{
- unsigned long checksum = (dwChecksum >> 16) & 0xffff;
-
- for (int i = 0; i < len; i++) {
- unsigned val = buffer[i];
-
- if ((i & 1) == 0)
- val <<= 8;
-
- if (checksum < val) ++val;
- checksum -= val;
- }
- checksum = ((checksum & 0x0000ffff) + (checksum >> 16));
- checksum = ((checksum & 0x0000ffff) + (checksum >> 16));
- return checksum << 16;
-}
-
-unsigned int aim_oft_checksum_file(wchar_t *filename, unsigned __int64 size)
-{
- unsigned long checksum = 0xffff0000;
- int fid = _wopen(filename, _O_RDONLY | _O_BINARY, _S_IREAD);
- if (fid >= 0) {
- unsigned __int64 sz = _filelengthi64(fid);
- if (size > sz) size = sz;
- while (size) {
- unsigned char buffer[8912];
- int bytes = (int)min(size, sizeof(buffer));
- bytes = _read(fid, buffer, bytes);
- size -= bytes;
- checksum = aim_oft_checksum_chunk(checksum, buffer, bytes);
- }
- _close(fid);
- }
- return checksum;
-}
-
-char* long_ip_to_char_ip(unsigned long host, char* ip)
-{
- host = _htonl(host);
- unsigned char* bytes = (unsigned char*)&host;
- size_t buf_loc = 0;
- for (int i = 0; i < 4; i++) {
- char store[16];
- _itoa(bytes[i], store, 10);
- size_t len = mir_strlen(store);
-
- memcpy(&ip[buf_loc], store, len);
- buf_loc += len;
- ip[buf_loc++] = '.';
- }
- ip[buf_loc - 1] = '\0';
-
- return ip;
-}
-
-unsigned long char_ip_to_long_ip(char* ip)
-{
- unsigned char chost[4] = { 0 };
- char *c = ip;
- for (int i = 0; i < 4; ++i) {
- chost[i] = (unsigned char)atoi(c);
- c = strchr(c, '.');
- if (c) ++c;
- else break;
- }
- return *(unsigned long*)&chost;
-}
-
-unsigned short get_random(void)
-{
- unsigned short id;
- Utils_GetRandom(&id, sizeof(id));
- id &= 0x7fff;
- return id;
-}
-
diff --git a/protocols/AimOscar/src/utility.h b/protocols/AimOscar/src/utility.h
deleted file mode 100755
index 17d50af9e1..0000000000
--- a/protocols/AimOscar/src/utility.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-Plugin of Miranda IM for communicating with users of the AIM protocol.
-Copyright (c) 2008-2009 Boris Krasnovskiy
-Copyright (C) 2005-2006 Aaron Myles Landwehr
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef UTILITY_H
-#define UTILITY_H
-
-char *normalize_name(const char *s);
-char* trim_str(char* s);
-void create_group(const char *group);
-unsigned int aim_oft_checksum_file(wchar_t *filename, unsigned __int64 size = -1);
-char* long_ip_to_char_ip(unsigned long host, char* ip);
-unsigned long char_ip_to_long_ip(char* ip);
-unsigned short get_random(void);
-
-inline int cap_cmp(const char* cap, const char* cap2) { return memcmp(cap, cap2, 16); }
-inline const char* alpha_cap_str(char ver) { return (ver & 0x80) ? " Alpha" : ""; }
-inline const char* secure_cap_str(char* ver) { return (*(int*)ver == 0xDEC0FE5A) ? " + SecureIM" : ""; }
-
-struct BdListItem
-{
- char* name;
- unsigned short item_id;
-
- BdListItem() { name = NULL; item_id = 0; }
- BdListItem(const char* snt, unsigned short id) { name = mir_strdup(snt); item_id = id; }
- ~BdListItem() { mir_free(name); }
-};
-
-struct BdList : public OBJLIST<BdListItem>
-{
- BdList() : OBJLIST<BdListItem>(5) {}
-
- void add(const char* snt, unsigned short id)
- { insert(new BdListItem(snt, id)); }
-
- unsigned short add(const char* snt)
- {
- unsigned short id = get_free_id();
- insert(new BdListItem(snt, id));
- return id;
- }
-
- unsigned short get_free_id(void);
- unsigned short find_id(const char* name);
- char* find_name(unsigned short id);
- void remove_by_id(unsigned short id);
-};
-
-#endif
diff --git a/protocols/AimOscar/src/version.h b/protocols/AimOscar/src/version.h
deleted file mode 100644
index d64d0715bb..0000000000
--- a/protocols/AimOscar/src/version.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#define __MAJOR_VERSION 0
-#define __MINOR_VERSION 11
-#define __RELEASE_NUM 0
-#define __BUILD_NUM 1
-
-#include <stdver.h>
-
-#define __PLUGIN_NAME "AIM protocol"
-#define __FILENAME "AIM.dll"
-#define __DESCRIPTION "AOL Instant Messenger (AIM) protocol support for Miranda NG."
-#define __AUTHOR "Boris Krasnovskiy, Aaron Myles Landwehr"
-#define __AUTHOREMAIL "borkra@miranda-im.org"
-#define __AUTHORWEB "https://miranda-ng.org/p/AIM/"
-#define __COPYRIGHT "© 2008-2011 Boris Krasnovskiy, 2005-2006 Aaron Myles Landwehr"
diff --git a/protocols/Discord/src/avatars.cpp b/protocols/Discord/src/avatars.cpp
index d2b629e442..73c5b49da4 100644
--- a/protocols/Discord/src/avatars.cpp
+++ b/protocols/Discord/src/avatars.cpp
@@ -191,7 +191,7 @@ INT_PTR CDiscordProto::SetMyAvatar(WPARAM, LPARAM lParam)
ptrA szFileContents((char*)mir_alloc(iFileLength));
fread(szFileContents, 1, iFileLength, in);
fclose(in);
- szPayload.Append(ptrA(mir_base64_encode((BYTE*)szFileContents.get(), iFileLength)));
+ szPayload.Append(ptrA(mir_base64_encode(szFileContents.get(), iFileLength)));
JSONNode root; root << CHAR_PARAM("avatar", szPayload);
Push(new AsyncHttpRequest(this, REQUEST_PATCH, "/users/@me", nullptr, &root));
diff --git a/protocols/Discord/src/gateway.cpp b/protocols/Discord/src/gateway.cpp
index 0f59b9382e..228e6bad25 100644
--- a/protocols/Discord/src/gateway.cpp
+++ b/protocols/Discord/src/gateway.cpp
@@ -220,7 +220,7 @@ void CDiscordProto::GatewayThreadWorker()
debugLogA("Got packet: buffer = %d, opcode = %d, headerSize = %d, final = %d, masked = %d", bufSize, hdr.opCode, hdr.headerSize, hdr.bIsFinal, hdr.bIsMasked);
// we have some additional data, not only opcode
- if (bufSize > hdr.headerSize) {
+ if ((size_t)bufSize > hdr.headerSize) {
size_t currPacketSize = bufSize - hdr.headerSize;
netbuf.append(buf, bufSize);
while (currPacketSize < hdr.payloadSize) {
diff --git a/protocols/Discord/src/main.cpp b/protocols/Discord/src/main.cpp
index 808354befb..24c2b8e7b5 100644
--- a/protocols/Discord/src/main.cpp
+++ b/protocols/Discord/src/main.cpp
@@ -34,7 +34,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/protocols/Discord/src/proto.h b/protocols/Discord/src/proto.h
index 56c04ef157..5970ce26d3 100644
--- a/protocols/Discord/src/proto.h
+++ b/protocols/Discord/src/proto.h
@@ -26,64 +26,11 @@ struct AsyncHttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject
void *pUserInfo;
};
-struct PARAM
-{
- LPCSTR szName;
- __forceinline PARAM(LPCSTR _name) : szName(_name)
- {}
-};
-
-struct BOOL_PARAM : public PARAM
-{
- bool bValue;
- __forceinline BOOL_PARAM(LPCSTR _name, bool _value) :
- PARAM(_name), bValue(_value)
- {}
-};
-AsyncHttpRequest* operator<<(AsyncHttpRequest*, const BOOL_PARAM&);
-
-struct INT_PARAM : public PARAM
-{
- int iValue;
- __forceinline INT_PARAM(LPCSTR _name, int _value) :
- PARAM(_name), iValue(_value)
- {}
-};
AsyncHttpRequest* operator<<(AsyncHttpRequest*, const INT_PARAM&);
-
-struct INT64_PARAM : public PARAM
-{
- SnowFlake iValue;
- __forceinline INT64_PARAM(LPCSTR _name, SnowFlake _value) :
- PARAM(_name), iValue(_value)
- {}
-};
AsyncHttpRequest* operator<<(AsyncHttpRequest*, const INT64_PARAM&);
-
-struct CHAR_PARAM : public PARAM
-{
- LPCSTR szValue;
- __forceinline CHAR_PARAM(LPCSTR _name, LPCSTR _value) :
- PARAM(_name), szValue(_value)
- {}
-};
AsyncHttpRequest* operator<<(AsyncHttpRequest*, const CHAR_PARAM&);
-
-struct WCHAR_PARAM : public PARAM
-{
- LPCWSTR wszValue;
- __forceinline WCHAR_PARAM(LPCSTR _name, LPCWSTR _value) :
- PARAM(_name), wszValue(_value)
- {}
-};
AsyncHttpRequest* operator<<(AsyncHttpRequest*, const WCHAR_PARAM&);
-JSONNode& operator<<(JSONNode &json, const INT_PARAM &param);
-JSONNode& operator<<(JSONNode &json, const INT64_PARAM &param);
-JSONNode& operator<<(JSONNode &json, const BOOL_PARAM &param);
-JSONNode& operator<<(JSONNode &json, const CHAR_PARAM &param);
-JSONNode& operator<<(JSONNode &json, const WCHAR_PARAM &param);
-
/////////////////////////////////////////////////////////////////////////////////////////
struct CDiscordRole : public MZeroedObject
diff --git a/protocols/Discord/src/utils.cpp b/protocols/Discord/src/utils.cpp
index 2c0b254930..0b37e53167 100644
--- a/protocols/Discord/src/utils.cpp
+++ b/protocols/Discord/src/utils.cpp
@@ -42,40 +42,6 @@ int StrToStatus(const CMStringW &str)
/////////////////////////////////////////////////////////////////////////////////////////
-JSONNode& operator<<(JSONNode &json, const INT_PARAM &param)
-{
- json.push_back(JSONNode(param.szName, param.iValue));
- return json;
-}
-
-JSONNode& operator<<(JSONNode &json, const INT64_PARAM &param)
-{
- char tmp[100];
- _i64toa_s(param.iValue, tmp, _countof(tmp), 10);
- json.push_back(JSONNode(param.szName, tmp));
- return json;
-}
-
-JSONNode& operator<<(JSONNode &json, const BOOL_PARAM &param)
-{
- json.push_back(JSONNode(param.szName, param.bValue));
- return json;
-}
-
-JSONNode& operator<<(JSONNode &json, const CHAR_PARAM &param)
-{
- json.push_back(JSONNode(param.szName, param.szValue));
- return json;
-}
-
-JSONNode& operator<<(JSONNode &json, const WCHAR_PARAM &param)
-{
- json.push_back(JSONNode(param.szName, ptrA(mir_utf8encodeW(param.wszValue)).get()));
- return json;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
time_t StringToDate(const CMStringW &str)
{
struct tm T = { 0 };
diff --git a/protocols/Discord/src/version.h b/protocols/Discord/src/version.h
index 2389a715d1..9114967209 100644
--- a/protocols/Discord/src/version.h
+++ b/protocols/Discord/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Discord.dll"
#define __DESCRIPTION "Discord support for Miranda NG."
#define __AUTHOR "George Hazan"
-#define __AUTHOREMAIL "ghazan@miranda.im"
#define __AUTHORWEB "https://miranda-ng.org/p/Discord/"
#define __COPYRIGHT "© 2016-17 Miranda NG team"
diff --git a/protocols/Dummy/src/main.cpp b/protocols/Dummy/src/main.cpp
index 135358b7f8..99071455f4 100644
--- a/protocols/Dummy/src/main.cpp
+++ b/protocols/Dummy/src/main.cpp
@@ -29,7 +29,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/protocols/Dummy/src/version.h b/protocols/Dummy/src/version.h
index 99bef970b2..3a20fa8059 100644
--- a/protocols/Dummy/src/version.h
+++ b/protocols/Dummy/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Dummy.dll"
#define __DESCRIPTION "Dummy protocol for Miranda NG. Could be used for holding contacts and history from deprecated protocols or for creating virtual contacts."
#define __AUTHOR "Robert Pösel"
-#define __AUTHOREMAIL "robyer@seznam.cz"
#define __AUTHORWEB "https://miranda-ng.org/p/Dummy/"
#define __COPYRIGHT "© 2014-17 Robert Pösel"
diff --git a/protocols/EmLanProto/amdproto_15.vcxproj b/protocols/EmLanProto/amdproto_15.vcxproj
deleted file mode 100644
index b8f71e960a..0000000000
--- a/protocols/EmLanProto/amdproto_15.vcxproj
+++ /dev/null
@@ -1,216 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectName>EmLanProto</ProjectName>
- <ProjectGuid>{2115FEBC-1EC4-4F95-A058-A523ED5295A4}</ProjectGuid>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v141_xp</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v141_xp</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v141_xp</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v141_xp</PlatformToolset>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup>
- <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)\$(Configuration)\Plugins\</OutDir>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)\$(Configuration)64\Plugins\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)\$(Configuration)\Obj\$(ProjectName)\</IntDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)\$(Configuration)64\Obj\$(ProjectName)\</IntDir>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)\$(Configuration)\Plugins\</OutDir>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)\$(Configuration)64\Plugins\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)\$(Configuration)\Obj\$(ProjectName)\</IntDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)\$(Configuration)64\Obj\$(ProjectName)\</IntDir>
- <IgnoreImportLibrary>true</IgnoreImportLibrary>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <AdditionalIncludeDirectories>..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <MinimalRebuild>true</MinimalRebuild>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
- <PrecompiledHeader>Use</PrecompiledHeader>
- <WarningLevel>Level3</WarningLevel>
- <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
- <ExceptionHandling>false</ExceptionHandling>
- <AdditionalOptions>/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
- </ClCompile>
- <Link>
- <AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <SubSystem>Windows</SubSystem>
- <BaseAddress>0x22000000</BaseAddress>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- <AdditionalLibraryDirectories>$(ProfileDir)..\..\libs\win$(PlatformArchitecture)</AdditionalLibraryDirectories>
- <RandomizedBaseAddress>false</RandomizedBaseAddress>
- <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
- </Link>
- <ResourceCompile>
- <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- </ResourceCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <AdditionalIncludeDirectories>..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
- <PrecompiledHeader>Use</PrecompiledHeader>
- <WarningLevel>Level3</WarningLevel>
- <ExceptionHandling>false</ExceptionHandling>
- <AdditionalOptions>/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
- </ClCompile>
- <Link>
- <AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <SubSystem>Windows</SubSystem>
- <BaseAddress>0x22000000</BaseAddress>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- <AdditionalLibraryDirectories>$(ProfileDir)..\..\libs\win$(PlatformArchitecture)</AdditionalLibraryDirectories>
- <RandomizedBaseAddress>false</RandomizedBaseAddress>
- </Link>
- <ResourceCompile>
- <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- </ResourceCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <Optimization>Full</Optimization>
- <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
- <AdditionalIncludeDirectories>..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <StringPooling>true</StringPooling>
- <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
- <PrecompiledHeader>Use</PrecompiledHeader>
- <WarningLevel>Level3</WarningLevel>
- <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
- <ExceptionHandling>false</ExceptionHandling>
- <AdditionalOptions>/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
- </ClCompile>
- <Link>
- <AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <SubSystem>Windows</SubSystem>
- <OptimizeReferences>true</OptimizeReferences>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <BaseAddress>0x22000000</BaseAddress>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- <AdditionalLibraryDirectories>$(ProfileDir)..\..\libs\win$(PlatformArchitecture)</AdditionalLibraryDirectories>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalOptions>/PDBALTPATH:%_PDB% %(AdditionalOptions)</AdditionalOptions>
- <RandomizedBaseAddress>false</RandomizedBaseAddress>
- </Link>
- <ResourceCompile>
- <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- </ResourceCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <ClCompile>
- <Optimization>Full</Optimization>
- <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
- <AdditionalIncludeDirectories>..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <StringPooling>true</StringPooling>
- <PrecompiledHeader>Use</PrecompiledHeader>
- <WarningLevel>Level3</WarningLevel>
- <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
- <ExceptionHandling>false</ExceptionHandling>
- <AdditionalOptions>/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
- </ClCompile>
- <Link>
- <AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <SubSystem>Windows</SubSystem>
- <OptimizeReferences>true</OptimizeReferences>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <BaseAddress>0x22000000</BaseAddress>
- <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
- <AdditionalLibraryDirectories>$(ProfileDir)..\..\libs\win$(PlatformArchitecture)</AdditionalLibraryDirectories>
- <AdditionalOptions>/PDBALTPATH:%_PDB% %(AdditionalOptions)</AdditionalOptions>
- <RandomizedBaseAddress>false</RandomizedBaseAddress>
- </Link>
- <ResourceCompile>
- <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- </ResourceCompile>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="src\amdproto.cpp" />
- <ClCompile Include="src\get_time.cpp" />
- <ClCompile Include="src\lan.cpp" />
- <ClCompile Include="src\mlan.cpp" />
- <ClCompile Include="src\stdafx.cpp">
- <PrecompiledHeader>Create</PrecompiledHeader>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="src\get_time.h" />
- <ClInclude Include="src\lan.h" />
- <ClInclude Include="src\mlan.h" />
- <ClInclude Include="src\resource.h" />
- <ClInclude Include="src\stdafx.h" />
- <ClInclude Include="src\Version.h" />
- </ItemGroup>
- <ItemGroup>
- <ResourceCompile Include="res\amdproto.rc" />
- <ResourceCompile Include="res\Version.rc" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project> \ No newline at end of file
diff --git a/protocols/EmLanProto/amdproto_15.vcxproj.filters b/protocols/EmLanProto/amdproto_15.vcxproj.filters
deleted file mode 100644
index 8d38c80fbe..0000000000
--- a/protocols/EmLanProto/amdproto_15.vcxproj.filters
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <Filter Include="Source Files">
- <UniqueIdentifier>{aa1fb7ce-7e83-46e8-b50b-cc87043ddfe8}</UniqueIdentifier>
- <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm</Extensions>
- </Filter>
- <Filter Include="Header Files">
- <UniqueIdentifier>{c7da55a0-28ce-4c6f-acbe-8e2cba06f96d}</UniqueIdentifier>
- <Extensions>h;hpp;hxx;hm;inl;inc</Extensions>
- </Filter>
- <Filter Include="Resource Files">
- <UniqueIdentifier>{ee329731-83da-4e3e-abb0-188efa6b23b2}</UniqueIdentifier>
- <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
- </Filter>
- </ItemGroup>
- <ItemGroup>
- <ResourceCompile Include="res\amdproto.rc">
- <Filter>Resource Files</Filter>
- </ResourceCompile>
- <ResourceCompile Include="res\Version.rc">
- <Filter>Resource Files</Filter>
- </ResourceCompile>
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="src\amdproto.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\get_time.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\lan.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\mlan.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\stdafx.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="src\get_time.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\lan.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\mlan.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\resource.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\stdafx.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\Version.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- </ItemGroup>
-</Project> \ No newline at end of file
diff --git a/protocols/AimOscar/aim.vcxproj b/protocols/EmLanProto/emlanproto.vcxproj
index e7e1191a55..27cf97a318 100644
--- a/protocols/AimOscar/aim.vcxproj
+++ b/protocols/EmLanProto/emlanproto.vcxproj
@@ -1,28 +1,33 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectName>AIM</ProjectName>
- <ProjectGuid>{736E59E5-CDCE-4C88-9C3A-E7913D45C9EC}</ProjectGuid>
- </PropertyGroup>
- <ImportGroup Label="PropertySheets">
- <Import Project="$(ProjectDir)..\..\build\vc.common\plugin.props" />
- </ImportGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{2115FEBC-1EC4-4F95-A058-A523ED5295A4}</ProjectGuid>
+ <ProjectName>EmLanProto</ProjectName>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(ProjectDir)..\..\build\vc.common\plugin.props" />
+ </ImportGroup>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
</Project> \ No newline at end of file
diff --git a/protocols/EmLanProto/emlanproto.vcxproj.filters b/protocols/EmLanProto/emlanproto.vcxproj.filters
new file mode 100644
index 0000000000..fcae13a9d8
--- /dev/null
+++ b/protocols/EmLanProto/emlanproto.vcxproj.filters
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(ProjectDir)..\..\build\vc.common\common.filters" />
+</Project> \ No newline at end of file
diff --git a/protocols/EmLanProto/src/amdproto.cpp b/protocols/EmLanProto/src/amdproto.cpp
index d25ebae2c8..1bcc43a24d 100644
--- a/protocols/EmLanProto/src/amdproto.cpp
+++ b/protocols/EmLanProto/src/amdproto.cpp
@@ -11,7 +11,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
@@ -29,7 +28,7 @@ bool g_InitOptions = false;
std::fstream emlanLog("EmLanLog.txt", std::ios::out|std::ios::app);
#endif
-extern "C" __declspec(dllexport) PLUGININFOEX* __cdecl MirandaPluginInfoEx(DWORD mirandaVersion)
+extern "C" __declspec(dllexport) PLUGININFOEX* __cdecl MirandaPluginInfoEx(DWORD)
{
return &pluginInfo;
}
@@ -96,7 +95,7 @@ static INT_PTR __cdecl EMPGetStatus(WPARAM, LPARAM)
return g_lan->GetMirandaStatus();
}
-INT_PTR __cdecl EMPSetStatus(WPARAM new_status, LPARAM lParam)
+INT_PTR __cdecl EMPSetStatus(WPARAM new_status, LPARAM)
{
g_lan->SetMirandaStatus(new_status);
return 0;
@@ -125,7 +124,8 @@ static INT_PTR __cdecl EMPAddToList(WPARAM flags, LPARAM lParam)
static INT_PTR __cdecl EMPBasicSearch(WPARAM, LPARAM lParam)
{
- return g_lan->Search((const char*)lParam);
+ const wchar_t *wszName = (const wchar_t*)lParam;
+ return g_lan->Search(_T2A(wszName));
}
static INT_PTR __cdecl EMPGetAwayMsg(WPARAM, LPARAM lParam)
@@ -148,27 +148,27 @@ static INT_PTR __cdecl EMPFileResume(WPARAM wParam, LPARAM lParam)
return g_lan->FileResume((int)wParam, (PROTOFILERESUME*)lParam);
}
-static INT_PTR __cdecl EMPSendFileAllow(WPARAM wParam, LPARAM lParam)
+static INT_PTR __cdecl EMPSendFileAllow(WPARAM, LPARAM lParam)
{
return g_lan->FileAllow((CCSDATA*)lParam);
}
-static INT_PTR __cdecl EMPSendFileDeny(WPARAM wParam, LPARAM lParam)
+static INT_PTR __cdecl EMPSendFileDeny(WPARAM, LPARAM lParam)
{
return g_lan->FileDeny((CCSDATA*)lParam);
}
-static INT_PTR __cdecl EMPSendFileCancel(WPARAM wParam, LPARAM lParam)
+static INT_PTR __cdecl EMPSendFileCancel(WPARAM, LPARAM lParam)
{
return g_lan->FileCancel((CCSDATA*)lParam);
}
-static INT_PTR __cdecl EMPSendFile(WPARAM wParam, LPARAM lParam)
+static INT_PTR __cdecl EMPSendFile(WPARAM, LPARAM lParam)
{
return g_lan->SendFile((CCSDATA*)lParam);
}
-static INT_PTR __cdecl EMPRecvFile(WPARAM wParam, LPARAM lParam)
+static INT_PTR __cdecl EMPRecvFile(WPARAM, LPARAM lParam)
{
g_lan->RecvFile((CCSDATA*)lParam);
return 0;
@@ -188,7 +188,7 @@ INT_PTR CALLBACK EMPDlgProcMainOpts(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPAR
int cind = 0;
for (int i = 0; i < count; i++) {
in_addr addr = g_lan->GetHostAddress(i);
- char* ipStr = inet_ntoa(addr);
+ wchar_t* ipStr = mir_a2u(inet_ntoa(addr));
if (addr.S_un.S_addr == caddr.S_un.S_addr)
cind = i;
SendDlgItemMessage(hwndDlg, IDC_LIST_IP, LB_ADDSTRING, 0, (LPARAM)ipStr);
@@ -276,7 +276,7 @@ int __cdecl EMPCreateOptionsDlg(WPARAM wParam, LPARAM)
OPTIONSDIALOGPAGE odp = { 0 };
odp.position = 100000000;
odp.hInstance = g_hInstance;
- odp.pszTemplate = MAKEINTRESOURCE(IDD_EMP_FORM_OPT);
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_EMP_FORM_OPT);
odp.szTitle.a = LPGEN("E-mage LAN protocol");
odp.szGroup.a = LPGEN("Network");
odp.flags = ODPF_BOLDGROUPS;
@@ -287,7 +287,7 @@ int __cdecl EMPCreateOptionsDlg(WPARAM wParam, LPARAM)
//////////////////////////////////////////////////////////////////////////
-INT_PTR CALLBACK EMPDlgProcMessage(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+INT_PTR CALLBACK EMPDlgProcMessage(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM)
{
HWND hwndOwner;
RECT rc, rcDlg, rcOwner;
diff --git a/protocols/EmLanProto/src/get_time.cpp b/protocols/EmLanProto/src/get_time.cpp
index 76ad065fdf..6ffccc5047 100644
--- a/protocols/EmLanProto/src/get_time.cpp
+++ b/protocols/EmLanProto/src/get_time.cpp
@@ -19,7 +19,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "stdafx.h"
-
static int daysInMonth[]={31,28,31,30,31,30,31,31,30,31,30,31};
static int IsLeapYear(int year)
{
@@ -42,24 +41,6 @@ static DWORD YMDHMSToTime(int year,int month,int day,int hour,int minute,int sec
return ret+3600*hour+60*minute+second;
}
-
-static DWORD TimestampLocalToGMT(DWORD from)
-{
- FILETIME ft1,ft2;
- LARGE_INTEGER liFiletime;
-
- //this huge number is the difference between 1970 and 1601 in seconds
- //liFiletime.QuadPart=(11644473600i64+(__int64)from)*10000000;
- __int64 t = 11644473600;
- liFiletime.QuadPart=(t+(__int64)from)*10000000;
- ft1.dwHighDateTime=liFiletime.HighPart;
- ft1.dwLowDateTime=liFiletime.LowPart;
- LocalFileTimeToFileTime(&ft1,&ft2);
- liFiletime.HighPart=ft2.dwHighDateTime;
- liFiletime.LowPart=ft2.dwLowDateTime;
- return (DWORD)(liFiletime.QuadPart/10000000-t);
-}
-
DWORD get_time()
{
SYSTEMTIME stime;
diff --git a/protocols/EmLanProto/src/lan.cpp b/protocols/EmLanProto/src/lan.cpp
index 336e64bb75..301e2a8284 100644
--- a/protocols/EmLanProto/src/lan.cpp
+++ b/protocols/EmLanProto/src/lan.cpp
@@ -191,7 +191,7 @@ void CLan::SendPacket(in_addr addr, const u_char* mes, int len)
addrTo.sin_addr = addr;
addrTo.sin_family = AF_INET;
addrTo.sin_port = PORT_NUMBER;
- int res = sendto(m_income, (const char*)mes, len, 0, (sockaddr*)&addrTo, sizeof(addrTo));
+ sendto(m_income, (const char*)mes, len, 0, (sockaddr*)&addrTo, sizeof(addrTo));
}
}
diff --git a/protocols/EmLanProto/src/lan.h b/protocols/EmLanProto/src/lan.h
index 1fd2bbe80a..c6dc217c64 100644
--- a/protocols/EmLanProto/src/lan.h
+++ b/protocols/EmLanProto/src/lan.h
@@ -69,11 +69,11 @@ protected:
void SendPacketBroadcast(const u_char* mes, int len);
//! Event - called when packet is received
- virtual void OnRecvPacket(u_char* mes, int len, in_addr from) { };
+ virtual void OnRecvPacket(u_char*, int, in_addr) { };
//! Event - called when new incoming tcp connection is created (new thread is created)
- virtual void OnInTCPConnection(u_long addr, SOCKET m_socket) { };
+ virtual void OnInTCPConnection(u_long, SOCKET) { };
//! Event - called when new outgoing tcp connection is created )new thread is created)
- virtual void OnOutTCPConnection(u_long addr, SOCKET m_socket, LPVOID lpParameter) {};
+ virtual void OnOutTCPConnection(u_long, SOCKET, LPVOID) {};
//! Creates new outgoing TCP connection
SOCKET CreateTCPConnection(u_long addr, LPVOID lpParameter);
diff --git a/protocols/EmLanProto/src/mlan.cpp b/protocols/EmLanProto/src/mlan.cpp
index 14005a3294..6cd8255697 100644
--- a/protocols/EmLanProto/src/mlan.cpp
+++ b/protocols/EmLanProto/src/mlan.cpp
@@ -35,8 +35,6 @@ CMLan::CMLan()
m_mirStatus = ID_STATUS_OFFLINE;
m_pRootContact = nullptr;
-
- m_pRootContact = nullptr;
m_hCheckThread = nullptr;
m_handleId = 1;
@@ -73,7 +71,7 @@ CMLan::~CMLan()
void CMLan::DeleteCache()
{
- TContact* pCont = m_pRootContact;
+ TContact *pCont = m_pRootContact;
m_pRootContact = nullptr;
while (pCont) {
delete[] pCont->m_nick;
@@ -190,8 +188,9 @@ void CMLan::RequestStatus(bool answer, u_long addr)
TPacket pak;
memset(&pak, 0, sizeof(pak));
pak.flReqStatus = answer;
- pak.strName = m_name;
+ pak.strName = mir_u2a(m_name);
SendPacketExt(pak, addr);
+ mir_free(pak.strName);
}
void CMLan::SendPacketExt(TPacket& pak, u_long addr)
@@ -283,9 +282,6 @@ void CMLan::OnRecvPacket(u_char* mes, int len, in_addr from)
u_int rip = cont->m_addr.S_un.S_addr;
int tip = (rip << 24) | ((rip & 0xff00) << 8) | ((rip & 0xff0000) >> 8) | (rip >> 24);
db_set_dw(hContact, PROTONAME, "IP", tip);
- // HOSTENT* host = gethostbyaddr((const char*)&rip, sizeof(rip), AF_INET);
- // if (host)
- // db_set_s(hContact, PROTONAME, "UID", host->h_name);
}
}
}
@@ -325,24 +321,22 @@ void CMLan::OnRecvPacket(u_char* mes, int len, in_addr from)
}
if (pak.idReqAwayMessage && cont) {
- MCONTACT hContact = FindContact(cont->m_addr, cont->m_nick, true, false, false);
// Removed - it causes that whoisreadingawaymessage plugin was not working
- // if (hContact)
- // {
- // int IcqStatus = 0;
- // switch (m_mirStatus)
- // {
- // case ID_STATUS_AWAY: IcqStatus = ICQ_MSGTYPE_GETAWAYMSG; break;
- // case ID_STATUS_NA: IcqStatus = ICQ_MSGTYPE_GETNAMSG; break;
- // case ID_STATUS_OCCUPIED: IcqStatus = ICQ_MSGTYPE_GETOCCUMSG; break;
- // case ID_STATUS_DND: IcqStatus = ICQ_MSGTYPE_GETDNDMSG; break;
- // case ID_STATUS_FREECHAT: IcqStatus = ICQ_MSGTYPE_GETFFCMSG; break;
- // }
- // // HACK: this is a real hack
- // db_set_dw(hContact, "ICQ", "UIN", 1/*0xffffffff*/);
- // NotifyEventHooks(m_hookIcqMsgReq, IcqStatus, 1/*0xffffffff*/);
- // db_unset(hContact, "ICQ", "UIN");
- // }
+ // MCONTACT hContact = FindContact(cont->m_addr, cont->m_nick, true, false, false);
+ // if (hContact) {
+ // int IcqStatus = 0;
+ // switch (m_mirStatus) {
+ // case ID_STATUS_AWAY: IcqStatus = ICQ_MSGTYPE_GETAWAYMSG; break;
+ // case ID_STATUS_NA: IcqStatus = ICQ_MSGTYPE_GETNAMSG; break;
+ // case ID_STATUS_OCCUPIED: IcqStatus = ICQ_MSGTYPE_GETOCCUMSG; break;
+ // case ID_STATUS_DND: IcqStatus = ICQ_MSGTYPE_GETDNDMSG; break;
+ // case ID_STATUS_FREECHAT: IcqStatus = ICQ_MSGTYPE_GETFFCMSG; break;
+ // }
+ // // HACK: this is a real hack
+ // db_set_dw(hContact, "ICQ", "UIN", 1/*0xffffffff*/);
+ // NotifyEventHooks(m_hookIcqMsgReq, IcqStatus, 1/*0xffffffff*/);
+ // db_unset(hContact, "ICQ", "UIN");
+ // }
mir_cslock lck(m_csAccessAwayMes);
@@ -370,7 +364,12 @@ void CMLan::OnRecvPacket(u_char* mes, int len, in_addr from)
void CMLan::RecvMessageUrl(CCSDATA* ccs)
{
PROTORECVEVENT *pre = (PROTORECVEVENT*)ccs->lParam;
- ptrA szMessage(Utf8Encode(pre->szMessage));
+ ptrA szMessage;
+ // input string might be already utf8-encoded
+ if (Utf8CheckString(pre->szMessage))
+ szMessage = mir_strdup(pre->szMessage);
+ else
+ szMessage = Utf8Encode(pre->szMessage);
DBEVENTINFO dbei = {};
if (!mir_strcmp(ccs->szProtoService, PSR_MESSAGE))
@@ -410,31 +409,31 @@ INT_PTR CMLan::AddToContactList(u_int flags, EMPSEARCHRESULT *psr)
int CMLan::SendMessageUrl(CCSDATA* ccs, bool isUrl)
{
int cid = GetRandomProcId();
- size_t len;
+ size_t len = 0;
if (isUrl) {
len = mir_strlen((char*)ccs->lParam);
((char*)ccs->lParam)[len] = 1;
}
- TDataHolder* hold = new TDataHolder(ccs, cid, isUrl ? LEXT_SENDURL : LEXT_SENDMESSAGE, this);
+ TDataHolder *hold = new TDataHolder(ccs, cid, isUrl ? LEXT_SENDURL : LEXT_SENDMESSAGE, this);
if (isUrl) {
((char*)ccs->lParam)[len] = 0;
hold->msg[len] = 0;
}
- CloseHandle(mir_forkthread(LaunchExt, (void*)hold));
+ mir_forkthread(LaunchExt, hold);
return cid;
}
int CMLan::Search(const char* name)
{
int cid = GetRandomProcId();
- CloseHandle(mir_forkthread(LaunchExt, (void*)new TDataHolder(name, cid, LEXT_SEARCH, this)));
+ mir_forkthread(LaunchExt, new TDataHolder(name, cid, LEXT_SEARCH, this));
return cid;
}
int CMLan::GetAwayMsg(CCSDATA* ccs)
{
int cid = GetRandomProcId();
- CloseHandle(mir_forkthread(LaunchExt, (void*)new TDataHolder(ccs, cid, LEXT_GETAWAYMSG, this)));
+ mir_forkthread(LaunchExt, new TDataHolder(ccs, cid, LEXT_GETAWAYMSG, this));
return cid;
}
@@ -484,10 +483,23 @@ void CMLan::SearchExt(TDataHolder* hold)
psr.ipaddr = cont->m_addr.S_un.S_addr;
psr.stat = cont->m_status;
psr.ver = cont->m_ver;
-
ProtoBroadcastAck(PROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)hold->id, (LPARAM)&psr);
}
}
+
+ // search string might contain some ip address
+ ULONG addr = inet_addr(hold->msg);
+ if (addr != INADDR_NONE) {
+ psr.nick.a = hold->msg;
+ psr.firstName.a = "";
+ psr.lastName.a = "";
+ psr.email.a = hold->msg;
+ psr.ipaddr = addr;
+ psr.stat = ID_STATUS_OFFLINE;
+ psr.ver = 0;
+ ProtoBroadcastAck(PROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)hold->id, (LPARAM)&psr);
+ }
+
ProtoBroadcastAck(PROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)hold->id, 0);
delete hold;
}
@@ -582,7 +594,7 @@ u_char* CMLan::CreatePacket(TPacket& pak, int* pBufLen)
if (pak.idStatus)
len += 1 + 1 + 2;
- size_t nameLen;
+ size_t nameLen = 0;
if (pak.strName) {
nameLen = mir_strlen(pak.strName);
len += 1 + 1 + nameLen + 1;
@@ -760,23 +772,17 @@ void CMLan::LoadSettings()
m_RequiredIp = db_get_dw(NULL, PROTONAME, "ipaddr", 0);
m_UseHostName = db_get_b(NULL, PROTONAME, "UseHostName", 1) != 0;
if (m_UseHostName) {
- gethostname(m_name, MAX_HOSTNAME_LEN);
+ m_nameLen = MAX_HOSTNAME_LEN;
+ GetComputerName(m_name, &m_nameLen);
CharLower(m_name);
}
else {
- DBVARIANT dbv;
- // Deleting old 'Name' value - using 'Nick' instead of it now
- if (db_get_s(NULL, PROTONAME, "Nick", &dbv)) {
- if (db_get_s(NULL, PROTONAME, "Name", &dbv))
- dbv.pszVal = "EmLan_User";
- else
- db_unset(NULL, PROTONAME, "Name");
- }
- if (!dbv.pszVal[0])
- dbv.pszVal = "EmLan_User";
- mir_strcpy(m_name, dbv.pszVal);
+ ptrW nick(db_get_wsa(NULL, PROTONAME, "Nick"));
+ if (!nick)
+ nick = mir_wstrdup(L"EmLan_User");
+ mir_wstrcpy(m_name, nick);
}
- m_nameLen = (int)mir_strlen(m_name);
+ m_nameLen = (int)mir_wstrlen(m_name);
if (GetStatus() != LM_LISTEN) {
int ipcount = GetHostAddrCount();
@@ -794,7 +800,7 @@ void CMLan::SaveSettings()
{
db_set_dw(NULL, PROTONAME, "ipaddr", m_RequiredIp);
db_set_b(NULL, PROTONAME, "UseHostName", m_UseHostName);
- db_set_s(NULL, PROTONAME, "Nick", m_name);
+ db_set_ws(NULL, PROTONAME, "Nick", m_name);
}
//////////////////////////////////////////////////////////////////////////
@@ -812,7 +818,7 @@ CMLan::TFileConnection::~TFileConnection()
}
delete[] m_szDescription;
if (m_szFiles) {
- char** cp = m_szFiles;
+ wchar_t** cp = m_szFiles;
while (*cp) {
delete[] * cp;
cp++;
@@ -1029,11 +1035,11 @@ void CMLan::OnInTCPConnection(u_long addr, SOCKET in_sock)
char* pf_to = pre.szMessage + 4;
char* pf_fr = (char*)conn->m_buf + 1 + 4 + 4;
- conn->m_szFiles = new char*[rcTotalFiles + 1];
+ conn->m_szFiles = new wchar_t*[rcTotalFiles + 1];
conn->m_szFiles[rcTotalFiles] = nullptr;
for (int i = 0; i < rcTotalFiles; i++) {
- conn->m_szFiles[i] = _strdup(pf_fr);
+ conn->m_szFiles[i] = mir_a2u(pf_fr);
if (i)
*pf_to++ = ' ';
while (*pf_fr)
@@ -1074,12 +1080,12 @@ void CMLan::OnInTCPConnection(u_long addr, SOCKET in_sock)
}
// Getting current directory
- char path[MAX_PATH];
- char* pathpart;
+ wchar_t path[MAX_PATH];
+ wchar_t* pathpart;
GetFullPathName(conn->m_szDir, MAX_PATH, path, &pathpart);
if (!SetCurrentDirectory(path)) {
if (rcTotalFiles == 1)
- conn->m_szRenamedFile = _strdup(pathpart);
+ conn->m_szRenamedFile = mir_wstrdup(pathpart);
*pathpart = 0;
if (!SetCurrentDirectory(path)) {
conn->Send(nullptr, 0);
@@ -1094,13 +1100,13 @@ void CMLan::OnInTCPConnection(u_long addr, SOCKET in_sock)
PROTOFILETRANSFERSTATUS fts;
fts.cbSize = sizeof(fts);
+ fts.flags = PFTS_UNICODE;
+ fts.hContact = conn->m_hContact;
fts.totalBytes = rcTotalSize;
fts.totalFiles = rcTotalFiles;
fts.totalProgress = 0;
- fts.szWorkingDir = conn->m_szDir;
- fts.flags = false;
- fts.hContact = conn->m_hContact;
- fts.pszFiles = conn->m_szFiles;
+ fts.wszWorkingDir = conn->m_szDir;
+ fts.pwszFiles = conn->m_szFiles;
bool err = false;
@@ -1150,7 +1156,7 @@ void CMLan::OnInTCPConnection(u_long addr, SOCKET in_sock)
}
EMLOG("Still processing");
- char* filename = conn->m_szRenamedFile;
+ wchar_t* filename = conn->m_szRenamedFile;
if (!filename)
filename = conn->m_szFiles[fileNo];
@@ -1238,7 +1244,7 @@ void CMLan::OnInTCPConnection(u_long addr, SOCKET in_sock)
delete conn;
}
-void CMLan::OnOutTCPConnection(u_long addr, SOCKET out_socket, LPVOID lpParameter)
+void CMLan::OnOutTCPConnection(u_long, SOCKET out_socket, LPVOID lpParameter)
{
EMLOG("Sending OUT TCP connection");
TFileConnection* conn = (TFileConnection*)lpParameter;
@@ -1258,13 +1264,13 @@ void CMLan::OnOutTCPConnection(u_long addr, SOCKET out_socket, LPVOID lpParamete
FileAddToList(conn);
u_char buf[FILE_SEND_BLOCK + 1];
- char name[MAX_PATH + 8];
+ wchar_t name[MAX_PATH + 8];
buf[0] = FCODE_SND_FILEREQ;
int len = 1 + 4 + 4;
int size = 0;
int filecount = 0;
- char** pf = conn->m_szFiles;
+ wchar_t** pf = conn->m_szFiles;
while (*pf) {
// TODO: FIX IT !
EMLOG("Opening file");
@@ -1279,33 +1285,33 @@ void CMLan::OnOutTCPConnection(u_long addr, SOCKET out_socket, LPVOID lpParamete
filecount++;
CloseHandle(hFile);
- char* filepart;
- GetFullPathName(*pf, MAX_PATH, (char*)name, &filepart);
+ wchar_t* filepart;
+ GetFullPathName(*pf, MAX_PATH, name, &filepart);
free(*pf);
- *pf = _strdup(name);
- mir_strcpy((char*)buf + len, filepart);
- len += (int)mir_strlen(filepart) + 1;
+ *pf = mir_wstrdup(name);
+ mir_strcpy((char*)buf + len, _T2A(filepart));
+ len += (int)mir_wstrlen(filepart) + 1;
pf++;
}
- mir_strcpy((char*)buf + len, conn->m_szDescription);
- len += (int)mir_strlen(conn->m_szDescription) + 1;
+ mir_strcpy((char*)buf + len, _T2A(conn->m_szDescription));
+ len += (int)mir_wstrlen(conn->m_szDescription) + 1;
*((int*)(buf + 1)) = size;
*((int*)(buf + 1 + 4)) = filecount;
GetCurrentDirectory(MAX_PATH, name);
- conn->m_szDir = _strdup(name);
+ conn->m_szDir = mir_wstrdup(name);
PROTOFILETRANSFERSTATUS fts;
fts.cbSize = sizeof(fts);
+ fts.flags = PFTS_SENDING | PFTS_UNICODE;
+ fts.hContact = conn->m_hContact;
fts.totalBytes = size;
fts.totalFiles = filecount;
fts.totalProgress = 0;
- fts.szWorkingDir = conn->m_szDir;
- fts.flags = PFTS_SENDING;
- fts.hContact = conn->m_hContact;
- fts.pszFiles = conn->m_szFiles;
+ fts.wszWorkingDir = conn->m_szDir;
+ fts.pwszFiles = conn->m_szFiles;
EMLOG("Sending file size");
if (conn->Send(buf, len)) {
@@ -1388,7 +1394,7 @@ void CMLan::OnOutTCPConnection(u_long addr, SOCKET out_socket, LPVOID lpParamete
EMLOG("Ok");
buf[0] = FCODE_SND_FILEDATA;
- if (readbytes != tosend) {
+ if ((int)readbytes != tosend) {
EMLOG("Error during reading file. File was changed");
CloseHandle(hFile);
conn->Send(nullptr, 0);
@@ -1455,14 +1461,14 @@ int CMLan::SendFile(CCSDATA* ccs)
conn->m_cid = cid;
conn->m_hContact = ccs->hContact;
- conn->m_szDescription = _strdup((char*)ccs->wParam);
+ conn->m_szDescription = mir_wstrdup((wchar_t*)ccs->wParam);
int files = 0;
- char** ppszFiles = (char**)ccs->lParam;
+ wchar_t** ppszFiles = (wchar_t**)ccs->lParam;
while (ppszFiles[files])
files++;
- conn->m_szFiles = new char*[files + 1];
+ conn->m_szFiles = new wchar_t*[files + 1];
for (int i = 0; i < files; i++)
- conn->m_szFiles[i] = _strdup(ppszFiles[i]);
+ conn->m_szFiles[i] = mir_wstrdup(ppszFiles[i]);
conn->m_szFiles[files] = nullptr;
u_long addr = db_get_dw(ccs->hContact, PROTONAME, "ipaddr", 0);
@@ -1485,7 +1491,7 @@ int CMLan::FileAllow(CCSDATA* ccs)
mir_cslock connLck(conn->m_csAccess);
conn->m_state = TFileConnection::FCS_ALLOW;
- conn->m_szDir = _strdup((char*)ccs->lParam);
+ conn->m_szDir = mir_wstrdup((wchar_t*)ccs->lParam);
return cid;
}
@@ -1546,7 +1552,7 @@ int CMLan::FileResume(int cid, PROTOFILERESUME* pfr)
case FILERESUME_RENAME:
conn->m_state = TFileConnection::FCS_RENAME;
delete[] conn->m_szRenamedFile;
- conn->m_szRenamedFile = _strdup((char*)pfr->szFilename);
+ conn->m_szRenamedFile = mir_wstrdup(pfr->szFilename);
break;
case FILERESUME_SKIP:
conn->m_state = TFileConnection::FCS_SKIP;
diff --git a/protocols/EmLanProto/src/mlan.h b/protocols/EmLanProto/src/mlan.h
index ed151e1212..a314c054cd 100644
--- a/protocols/EmLanProto/src/mlan.h
+++ b/protocols/EmLanProto/src/mlan.h
@@ -62,7 +62,7 @@ public:
void LoadSettings();
void SaveSettings();
- char* GetName() { return m_name; }
+ wchar_t* GetName() { return m_name; }
bool GetUseHostName() { return m_UseHostName; }
void SetUseHostName(bool val) { m_UseHostName = val; }
void SetRequiredIp(u_long ip) { m_RequiredIp = ip; }
@@ -92,8 +92,8 @@ private:
TContact* m_pRootContact;
HANDLE m_hCheckThread;
- char m_name[MAX_HOSTNAME_LEN];
- int m_nameLen;
+ wchar_t m_name[MAX_HOSTNAME_LEN];
+ DWORD m_nameLen;
mir_cs m_csAccessClass;
mir_cs m_csAccessAwayMes;
@@ -174,10 +174,10 @@ private:
u_long m_addr;
MCONTACT m_hContact;
- char* m_szDescription;
- char** m_szFiles;
- char* m_szDir;
- char* m_szRenamedFile;
+ wchar_t* m_szDescription;
+ wchar_t** m_szFiles;
+ wchar_t* m_szDir;
+ wchar_t* m_szRenamedFile;
u_char* m_buf;
int m_recSize;
diff --git a/protocols/EmLanProto/src/stdafx.cpp b/protocols/EmLanProto/src/stdafx.cxx
index fc3e963191..e8691edb87 100644
--- a/protocols/EmLanProto/src/stdafx.cpp
+++ b/protocols/EmLanProto/src/stdafx.cxx
@@ -1,8 +1,8 @@
-// stdafx.cpp : source file that includes just the standard includes
-// amdproto.pch will be the pre-compiled header
-// stdafx.obj will contain the pre-compiled type information
-
-#include "stdafx.h"
-
-// TODO: reference any additional headers you need in STDAFX.H
-// and not in this file
+// stdafx.cpp : source file that includes just the standard includes
+// amdproto.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/protocols/EmLanProto/src/stdafx.h b/protocols/EmLanProto/src/stdafx.h
index d826592439..8fefd8f2f8 100644
--- a/protocols/EmLanProto/src/stdafx.h
+++ b/protocols/EmLanProto/src/stdafx.h
@@ -5,7 +5,6 @@
#pragma once
-#define _CRT_SECURE_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
diff --git a/protocols/EmLanProto/src/version.h b/protocols/EmLanProto/src/version.h
index e5c437a35c..4a9cf125ce 100644
--- a/protocols/EmLanProto/src/version.h
+++ b/protocols/EmLanProto/src/version.h
@@ -1,7 +1,7 @@
#define __MAJOR_VERSION 0
#define __MINOR_VERSION 1
#define __RELEASE_NUM 0
-#define __BUILD_NUM 1
+#define __BUILD_NUM 2
#include <stdver.h>
#define __FILEVERSION_DWORD PLUGIN_MAKE_VERSION(__MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM)
@@ -10,6 +10,5 @@
#define __FILENAME "EmLanProto.dll"
#define __DESCRIPTION "E-mage LAN protocol support for Miranda NG."
#define __AUTHOR "kva"
-#define __AUTHOREMAIL "kva@fromru.com"
#define __AUTHORWEB "https://miranda-ng.org/p/EmLanProto/"
#define __COPYRIGHT "© Viktor Kuzmin"
diff --git a/protocols/FacebookRM/src/client.h b/protocols/FacebookRM/src/client.h
index 8d80ea72ef..4d7fe6ef1e 100644
--- a/protocols/FacebookRM/src/client.h
+++ b/protocols/FacebookRM/src/client.h
@@ -161,7 +161,7 @@ public:
}
__inline const char *__rev() {
- return "3496859"; // FIXME: Some version of communication protocol? This version is from 3.12.2017
+ return "2828561"; // FIXME: Some version of communication protocol? This version is from 12.2.2017
}
////////////////////////////////////////////////////////////
diff --git a/protocols/FacebookRM/src/json.cpp b/protocols/FacebookRM/src/json.cpp
index aabf0823f1..2deb45172f 100644
--- a/protocols/FacebookRM/src/json.cpp
+++ b/protocols/FacebookRM/src/json.cpp
@@ -282,11 +282,6 @@ void parseAttachments(FacebookProto *proto, std::string *message_text, const JSO
for (auto itAttachment = attachments_.begin(); itAttachment != attachments_.end(); ++itAttachment) {
const JSONNode &attach_ = legacy ? (*itAttachment) : (*itAttachment)["mercury"];
- // FIXME: FB now doesn't have single "attach_type" node that we can check, but it's separated in different nodes. So we must check existence of different nodes for different types of attachments (or iterate over all existing nodes and check if some attachment node exists)
- const JSONNode sticker_ = attach_["sticker_attachment"];
- const JSONNode blob_ = attach_["blob_attachment"];
- const JSONNode todo_ = attach_["todo"];
-
type = attach_["attach_type"].as_string(); // "sticker", "photo", "file", "share", "animated_image", "video"
if (type == "photo") {
@@ -1462,43 +1457,3 @@ int facebook_json_parser::parse_messages_count(std::string *data, int *messagesC
return EXIT_SUCCESS;
}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-JSONNode& operator<<(JSONNode &json, const NULL_PARAM &param)
-{
- json.push_back(JSONNode(param.szName, nullptr));
- return json;
-}
-
-JSONNode& operator<<(JSONNode &json, const JSON_PARAM &param)
-{
- json.push_back(JSONNode(param.szName, param.node));
- return json;
-}
-
-JSONNode& operator<<(JSONNode &json, const INT_PARAM &param)
-{
- json.push_back(JSONNode(param.szName, param.iValue));
- return json;
-}
-
-JSONNode& operator<<(JSONNode &json, const BOOL_PARAM &param)
-{
- json.push_back(JSONNode(param.szName, param.bValue));
- return json;
-}
-
-JSONNode& operator<<(JSONNode &json, const CHAR_PARAM &param)
-{
- json.push_back(JSONNode(param.szName, param.szValue));
- return json;
-}
-
-JSONNode& operator<<(JSONNode &json, const WCHAR_PARAM &param)
-{
- json.push_back(JSONNode(param.szName, ptrA(mir_utf8encodeW(param.wszValue)).get()));
- return json;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file
diff --git a/protocols/FacebookRM/src/json.h b/protocols/FacebookRM/src/json.h
index 27dbbf1710..d62666a66d 100644
--- a/protocols/FacebookRM/src/json.h
+++ b/protocols/FacebookRM/src/json.h
@@ -47,63 +47,3 @@ public:
this->proto = proto;
}
};
-
-struct PARAM
-{
- LPCSTR szName;
- __forceinline PARAM(LPCSTR _name) : szName(_name)
- {}
-};
-
-struct NULL_PARAM : public PARAM
-{
- __forceinline NULL_PARAM(LPCSTR _name) : PARAM(_name)
- {}
-};
-
-struct JSON_PARAM : public PARAM
-{
- JSONNode node;
- __forceinline JSON_PARAM(LPCSTR _name, JSONNode _node) :
- PARAM(_name), node(_node)
- {}
-};
-
-struct BOOL_PARAM : public PARAM
-{
- bool bValue;
- __forceinline BOOL_PARAM(LPCSTR _name, bool _value) :
- PARAM(_name), bValue(_value)
- {}
-};
-
-struct INT_PARAM : public PARAM
-{
- int iValue;
- __forceinline INT_PARAM(LPCSTR _name, int _value) :
- PARAM(_name), iValue(_value)
- {}
-};
-
-struct CHAR_PARAM : public PARAM
-{
- LPCSTR szValue;
- __forceinline CHAR_PARAM(LPCSTR _name, LPCSTR _value) :
- PARAM(_name), szValue(_value)
- {}
-};
-
-struct WCHAR_PARAM : public PARAM
-{
- LPCWSTR wszValue;
- __forceinline WCHAR_PARAM(LPCSTR _name, LPCWSTR _value) :
- PARAM(_name), wszValue(_value)
- {}
-};
-
-JSONNode& operator<<(JSONNode &json, const NULL_PARAM &param);
-JSONNode& operator<<(JSONNode &json, const JSON_PARAM &param);
-JSONNode& operator<<(JSONNode &json, const INT_PARAM &param);
-JSONNode& operator<<(JSONNode &json, const BOOL_PARAM &param);
-JSONNode& operator<<(JSONNode &json, const CHAR_PARAM &param);
-JSONNode& operator<<(JSONNode &json, const WCHAR_PARAM &param);
diff --git a/protocols/FacebookRM/src/main.cpp b/protocols/FacebookRM/src/main.cpp
index 24ed75eeb1..fbf0eef6df 100644
--- a/protocols/FacebookRM/src/main.cpp
+++ b/protocols/FacebookRM/src/main.cpp
@@ -37,7 +37,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/protocols/FacebookRM/src/messages.cpp b/protocols/FacebookRM/src/messages.cpp
index ea3ad14b32..941f7f0327 100644
--- a/protocols/FacebookRM/src/messages.cpp
+++ b/protocols/FacebookRM/src/messages.cpp
@@ -204,7 +204,7 @@ void FacebookProto::StickerAsSmiley(std::string sticker, const std::string &url,
if (facy.loading_history)
return;
- std::string b64 = ptrA(mir_base64_encode((PBYTE)sticker.c_str(), (unsigned)sticker.length()));
+ std::string b64 = ptrA(mir_base64_encode(sticker.c_str(), sticker.length()));
b64 = utils::url::encode(b64);
std::wstring filename = GetAvatarFolder() + L"\\stickers\\";
diff --git a/protocols/FacebookRM/src/proto.cpp b/protocols/FacebookRM/src/proto.cpp
index c4f33dd222..17698d6e29 100644
--- a/protocols/FacebookRM/src/proto.cpp
+++ b/protocols/FacebookRM/src/proto.cpp
@@ -383,8 +383,8 @@ int FacebookProto::OnIdleChanged(WPARAM, LPARAM lParam)
if (idle) {
// User started being idle
- MIRANDA_IDLE_INFO mii = { sizeof(mii) };
- CallService(MS_IDLE_GETIDLEINFO, 0, (LPARAM)&mii);
+ MIRANDA_IDLE_INFO mii;
+ Idle_GetInfo(mii);
// Compute time when user really became idle
m_idleTS = time(nullptr) - mii.idleTime * 60;
diff --git a/protocols/FacebookRM/src/requests/contacts.h b/protocols/FacebookRM/src/requests/contacts.h
index 960fb269b3..8fa60fced8 100644
--- a/protocols/FacebookRM/src/requests/contacts.h
+++ b/protocols/FacebookRM/src/requests/contacts.h
@@ -36,7 +36,7 @@ public:
// getting info about particular friend
-// revised 3.12.2017
+// revised 17.8.2016
class UserInfoRequest : public HttpRequest
{
public:
@@ -60,11 +60,7 @@ public:
<< CHAR_VALUE("__rev", fc->__rev())
<< "__a=1"
<< "__pc=PHASED:DEFAULT"
- << "__be=1"
- << "jazoest="
- << "__spin_r="
- << "__spin_b="
- << "__spin_t=";
+ << "__be=-1";
}
};
diff --git a/protocols/FacebookRM/src/requests/history.h b/protocols/FacebookRM/src/requests/history.h
index 88890a0f8e..9ac3d52168 100644
--- a/protocols/FacebookRM/src/requests/history.h
+++ b/protocols/FacebookRM/src/requests/history.h
@@ -24,20 +24,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define _FACEBOOK_REQUEST_HISTORY_H_
// getting thread info and messages
-// revised 3.12.2017
+// revised 17.8.2016
class ThreadInfoRequest : public HttpRequest
{
public:
// Request only messages history
ThreadInfoRequest(facebook_client *fc, bool isChat, const char *id, int offset, const char *timestamp, int limit) :
- HttpRequest(REQUEST_POST, FACEBOOK_SERVER_REGULAR "/api/graphqlbatch/")
+ HttpRequest(REQUEST_POST, FACEBOOK_SERVER_REGULAR "/ajax/mercury/thread_info.php")
{
- setCommonBody(fc);
+ Url
+ << "dpr=1";
- // FIXME: FB removed /ajax/mercury/thread_info requests and now all messaging stuff does through /api/graphqlbatch/ - all loading of threads, (unread) messages, list of contacts in groupchat, etc.
- // All these request must be rewritten to the new request. Preparation is below but unfinished.
+ setCommonBody(fc);
- //const char *type = isChat ? "thread_fbids" : "user_ids";
+ const char *type = isChat ? "thread_fbids" : "user_ids";
std::string id_ = id; // FIXME: Rewrite this without std::string...
if (isChat) {
// NOTE: Remove "id." prefix as here we need to give threadFbId and not threadId
@@ -46,38 +46,6 @@ public:
}
ptrA idEncoded(mir_urlEncode(id_.c_str()));
-
- JSONNode root, o0, query_params;
-
- int before = -1;
-
- query_params
- << CHAR_PARAM("id", id_) // TODO: Do I have to encode the id? And remove that first "id." at the begin as we do above?
- << INT_PARAM("message_limit", limit)
- << INT_PARAM("load_messages", 1)
- << BOOL_PARAM("load_read_receipts", false);
-
- if (before != -1) {
- query_params << INT_PARAM("before", before);
- }
- else {
- query_params << NULL_PARAM("before");
- }
-
- o0
- << CHAR_PARAM("doc_id", id)
- << JSON_PARAM("query_params", query_params);
-
- root << JSON_PARAM("o0", o0);
-
- Body
- << "batch_name=MessengerGraphQLThreadFetcherRe"
- << CHAR_VALUE("queries", root.write().c_str());
-
- // example request data we need to send: { "o0":{"doc_id":"456789456123","query_params" : {"id":"123456789","message_limit" : 20,"load_messages" : 1,"load_read_receipts" : false,"before" : null}} }
-
-
- /*
//if (loadMessages) {
// Grrr, offset doesn't work at all, we need to use timestamps to get back in history...
// And we don't know, what's timestamp of first message, so we need to get from latest to oldest
@@ -87,7 +55,7 @@ public:
<< CMStringA(::FORMAT, "%s[offset]=%i", begin.c_str(), offset).c_str()
<< CMStringA(::FORMAT, "%s[timestamp]=%s", begin.c_str(), timestamp).c_str()
<< CMStringA(::FORMAT, "%s[limit]=%i", begin.c_str(), limit).c_str();
- //}*/
+ //}
/*if (loadThreadInfo) {
data += "&threads[" + type + "][0]=" + idEncoded;
@@ -96,8 +64,11 @@ public:
// Request only thread info // TODO: Make it array of ids
ThreadInfoRequest(facebook_client *fc, bool isChat, const char *id) :
- HttpRequest(REQUEST_POST, FACEBOOK_SERVER_REGULAR "/api/graphqlbatch/")
+ HttpRequest(REQUEST_POST, FACEBOOK_SERVER_REGULAR "/ajax/mercury/thread_info.php")
{
+ Url
+ << "dpr=1";
+
setCommonBody(fc);
const char *type = isChat ? "thread_fbids" : "user_ids";
@@ -115,8 +86,11 @@ public:
// Request both thread info and messages for single contact/chat
ThreadInfoRequest(facebook_client *fc, bool isChat, const char *id, int limit) :
- HttpRequest(REQUEST_POST, FACEBOOK_SERVER_REGULAR "/api/graphqlbatch/")
+ HttpRequest(REQUEST_POST, FACEBOOK_SERVER_REGULAR "/ajax/mercury/thread_info.php")
{
+ Url
+ << "dpr=1";
+
setCommonBody(fc);
const char *type = isChat ? "thread_fbids" : "user_ids";
@@ -142,8 +116,11 @@ public:
// Request both thread info and messages for more threads
ThreadInfoRequest(facebook_client *fc, const LIST<char> &ids, int offset, int limit) :
- HttpRequest(REQUEST_POST, FACEBOOK_SERVER_REGULAR "/api/graphqlbatch/")
+ HttpRequest(REQUEST_POST, FACEBOOK_SERVER_REGULAR "/ajax/mercury/thread_info.php")
{
+ Url
+ << "dpr=1";
+
setCommonBody(fc);
for (int i = 0; i < ids.getCount(); i++) {
@@ -169,6 +146,7 @@ private:
void setCommonBody(facebook_client *fc)
{
Body
+ << "client=mercury"
<< CHAR_VALUE("__user", fc->self_.user_id.c_str())
<< CHAR_VALUE("__dyn", fc->__dyn())
<< CHAR_VALUE("__req", fc->__req())
@@ -177,11 +155,7 @@ private:
<< CHAR_VALUE("ttstamp", fc->ttstamp_.c_str())
<< "__a=1"
<< "__pc=PHASED:DEFAULT"
- << "__be=1"
- << "jazoest="
- << "__spin_r="
- << "__spin_b="
- << "__spin_t=";
+ << "__be=-1";
}
};
@@ -209,8 +183,6 @@ public:
<< "__a=1"
<< "__pc=PHASED:DEFAULT"
<< "__be=-1";
-
- //queries={"o0":{"doc_id":"2003371749678240","query_params":{"limit":99,"before":null,"tags":["PENDING","unread"],"includeDeliveryReceipts":true,"includeSeqID":false}}}
}
};
diff --git a/protocols/FacebookRM/src/version.h b/protocols/FacebookRM/src/version.h
index 1299f09155..08b34f8856 100644
--- a/protocols/FacebookRM/src/version.h
+++ b/protocols/FacebookRM/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Facebook.dll"
#define __DESCRIPTION "Facebook protocol support for Miranda NG."
#define __AUTHOR "Michal Zelinka, Robert Pösel"
-#define __AUTHOREMAIL "robyer@seznam.cz"
#define __AUTHORWEB "https://miranda-ng.org/p/Facebook/"
#define __COPYRIGHT "© 2011-17 Robert Pösel, 2009-11 Michal Zelinka"
diff --git a/protocols/Gadu-Gadu/src/avatar.cpp b/protocols/Gadu-Gadu/src/avatar.cpp
index 0bdf8f04d7..096ae7bfbe 100644
--- a/protocols/Gadu-Gadu/src/avatar.cpp
+++ b/protocols/Gadu-Gadu/src/avatar.cpp
@@ -382,7 +382,7 @@ void __cdecl GGPROTO::setavatarthread(void *param)
_read(file_fd, avatarFile, avatarFileLen);
_close(file_fd);
- ptrA avatarFileB64(mir_base64_encode((PBYTE)avatarFile, avatarFileLen));
+ ptrA avatarFileB64(mir_base64_encode(avatarFile, avatarFileLen));
mir_free(avatarFile);
ptrA avatarFileB64Enc(mir_urlEncode(avatarFileB64));
diff --git a/protocols/Gadu-Gadu/src/gg.cpp b/protocols/Gadu-Gadu/src/gg.cpp
index f16fba3adb..48b578b1ec 100644
--- a/protocols/Gadu-Gadu/src/gg.cpp
+++ b/protocols/Gadu-Gadu/src/gg.cpp
@@ -30,7 +30,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/protocols/Gadu-Gadu/src/version.h b/protocols/Gadu-Gadu/src/version.h
index bd32b638e1..87f697f4fc 100644
--- a/protocols/Gadu-Gadu/src/version.h
+++ b/protocols/Gadu-Gadu/src/version.h
@@ -28,6 +28,5 @@
#define __PLUGIN_NAME "Gadu-Gadu protocol"
#define __DESCRIPTION "Gadu-Gadu protocol support for Miranda NG."
#define __AUTHOR "Bartosz Bialek, Adam Strzelecki"
-#define __AUTHOREMAIL "dezred"/*antispam*/"@"/*antispam*/"gmail"/*antispam*/"."/*antispam*/"com"
#define __COPYRIGHT "© 2009-2012 Bartosz Bialek, 2003-2009 Adam Strzelecki"
#define __AUTHORWEB "https://miranda-ng.org/p/GG/"
diff --git a/protocols/ICQCorp/src/corp.cpp b/protocols/ICQCorp/src/corp.cpp
index 72d9de6ee7..27f4abaf00 100644
--- a/protocols/ICQCorp/src/corp.cpp
+++ b/protocols/ICQCorp/src/corp.cpp
@@ -32,7 +32,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE
diff --git a/protocols/ICQCorp/src/version.h b/protocols/ICQCorp/src/version.h
index dd28b0b456..9376de1ca7 100644
--- a/protocols/ICQCorp/src/version.h
+++ b/protocols/ICQCorp/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "ICQCorp.dll"
#define __DESCRIPTION "ICQ corporate protocol support for Miranda NG."
#define __AUTHOR "Miranda NG Team, Eugene Tarasenko"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/ICQCorp/"
#define __COPYRIGHT "© 2014-17 Miranda NG Team, 2003-2005 Eugene Tarasenko"
diff --git a/protocols/IRCG/res/IRC.rc b/protocols/IRCG/res/IRC.rc
index 3b7e3a71b9..9dc719003b 100644
--- a/protocols/IRCG/res/IRC.rc
+++ b/protocols/IRCG/res/IRC.rc
@@ -58,13 +58,13 @@ BEGIN
LTEXT "Server name",IDC_STATIC,10,22,125,8,0,WS_EX_TRANSPARENT
COMBOBOX IDC_SERVERCOMBO,10,30,125,90,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
CONTROL "Internet address",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,10,45,81,8,WS_EX_TRANSPARENT
- EDITTEXT IDC_SERVER,10,53,88,12,ES_AUTOHSCROLL | ES_READONLY | WS_GROUP | WS_TABSTOP
+ EDITTEXT IDC_SERVER,10,53,88,12,ES_AUTOHSCROLL | ES_READONLY | WS_GROUP
LTEXT "SSL",IDC_STATIC,107,45,28,8,0,WS_EX_TRANSPARENT
- EDITTEXT IDC_SSL,107,53,28,12,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER | WS_TABSTOP,WS_EX_RIGHT
- LTEXT "Port range",IDC_STATIC,10,67,125,8,0,WS_EX_TRANSPARENT
- EDITTEXT IDC_PORT,10,75,50,12,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER | WS_TABSTOP,WS_EX_RIGHT
- LTEXT "->",IDC_STATIC,71,75,8,8
- EDITTEXT IDC_PORT2,85,75,50,12,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER | WS_TABSTOP,WS_EX_RIGHT
+ EDITTEXT IDC_SSL,107,53,28,12,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER,WS_EX_RIGHT
+ LTEXT "Port range",IDC_STATIC,10,67,79,8,0,WS_EX_TRANSPARENT
+ EDITTEXT IDC_PORT,10,75,33,12,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER,WS_EX_RIGHT
+ LTEXT "->",IDC_STATIC,45,76,8,8
+ EDITTEXT IDC_PORT2,54,75,33,12,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER,WS_EX_RIGHT
LTEXT "Password",IDC_STATIC,10,90,125,8,0,WS_EX_TRANSPARENT
EDITTEXT IDC_PASS,10,100,125,12,ES_PASSWORD | ES_AUTOHSCROLL
CONTROL "&Add",IDC_ADDSERVER,"MButtonClass",WS_DISABLED | WS_TABSTOP,16,116,27,14,WS_EX_NOACTIVATE | 0x10000000L
@@ -107,6 +107,7 @@ BEGIN
RTEXT "Don't check if more than (users):",IDC_STATIC,142,212,124,8
EDITTEXT IDC_LIMIT,267,210,29,12,ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
CONTROL "Spin2",IDC_SPIN2,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,284,209,11,14
+ CONTROL "SASL",IDC_SASL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,103,77,32,10
END
IDD_INFO DIALOGEX 0, 0, 267, 214
@@ -202,8 +203,8 @@ BEGIN
EDITTEXT IDC_ADD_ADDRESS,7,68,120,12,ES_AUTOHSCROLL | WS_GROUP
EDITTEXT IDC_ADD_PORT,7,92,47,12,ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
EDITTEXT IDC_ADD_PORT2,80,92,47,12,ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
- CONTROL "Auto",IDC_AUTO,"Button",BS_AUTORADIOBUTTON,139,52,32,10
- CONTROL "On",IDC_ON,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,139,69,32,10
+ CONTROL "Auto",IDC_AUTO,"Button",BS_AUTORADIOBUTTON | WS_GROUP,139,52,32,10
+ CONTROL "On",IDC_ON,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,139,69,32,10
CONTROL "Off",IDC_OFF,"Button",BS_AUTORADIOBUTTON,139,86,32,10
DEFPUSHBUTTON "&OK",IDOK,63,115,50,14
PUSHBUTTON "&Cancel",IDCANCEL,125,115,50,14
@@ -694,6 +695,18 @@ END
//
IDR_SERVERS TEXT "..\\docs\\IRC_servers.ini"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// AFX_DIALOG_LAYOUT
+//
+
+IDD_PREFS_CONNECT AFX_DIALOG_LAYOUT
+BEGIN
+ 0
+END
+
#endif // Neutral resources
/////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/IRCG/src/commandmonitor.cpp b/protocols/IRCG/src/commandmonitor.cpp
index 6694c24698..e07a5e6283 100644
--- a/protocols/IRCG/src/commandmonitor.cpp
+++ b/protocols/IRCG/src/commandmonitor.cpp
@@ -258,7 +258,7 @@ void __cdecl CIrcProto::ResolveIPThread(void *di)
delete ipr;
}
-bool CIrcProto::OnIrc_PING(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_PING(const CIrcMessage *pmsg)
{
wchar_t szResponse[100];
if (pmsg->parameters.getCount() > 0)
@@ -269,7 +269,7 @@ bool CIrcProto::OnIrc_PING(const CIrcMessage* pmsg)
return false;
}
-bool CIrcProto::OnIrc_WELCOME(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_WELCOME(const CIrcMessage *pmsg)
{
if (pmsg->parameters[0] != m_info.sNick)
m_info.sNick = pmsg->parameters[0];
@@ -294,7 +294,7 @@ bool CIrcProto::OnIrc_WELCOME(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_WHOTOOLONG(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_WHOTOOLONG(const CIrcMessage *pmsg)
{
CMStringW command = GetNextUserhostReason(2);
if (command[0] == 'U')
@@ -303,7 +303,7 @@ bool CIrcProto::OnIrc_WHOTOOLONG(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_BACKFROMAWAY(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_BACKFROMAWAY(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming) {
int Temp = m_iStatus;
@@ -318,7 +318,7 @@ bool CIrcProto::OnIrc_BACKFROMAWAY(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_SETAWAY(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_SETAWAY(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming) {
int Temp = m_iDesiredStatus;
@@ -357,7 +357,7 @@ bool CIrcProto::OnIrc_SETAWAY(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_JOIN(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_JOIN(const CIrcMessage *pmsg)
{
if (pmsg->parameters.getCount() > 0 && pmsg->m_bIncoming && pmsg->prefix.sNick != m_info.sNick) {
CMStringW host = pmsg->prefix.sUser + L"@" + pmsg->prefix.sHost;
@@ -369,7 +369,7 @@ bool CIrcProto::OnIrc_JOIN(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_QUIT(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_QUIT(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming) {
CMStringW host = pmsg->prefix.sUser + L"@" + pmsg->prefix.sHost;
@@ -384,7 +384,7 @@ bool CIrcProto::OnIrc_QUIT(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_PART(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_PART(const CIrcMessage *pmsg)
{
if (pmsg->parameters.getCount() > 0 && pmsg->m_bIncoming) {
CMStringW host = pmsg->prefix.sUser + L"@" + pmsg->prefix.sHost;
@@ -399,7 +399,7 @@ bool CIrcProto::OnIrc_PART(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_KICK(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_KICK(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && pmsg->parameters.getCount() > 1)
DoEvent(GC_EVENT_KICK, pmsg->parameters[0], pmsg->parameters[1], pmsg->parameters.getCount() > 2 ? pmsg->parameters[2].c_str() : nullptr, pmsg->prefix.sNick, nullptr, NULL, true, false);
@@ -422,7 +422,7 @@ bool CIrcProto::OnIrc_KICK(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_MODEQUERY(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_MODEQUERY(const CIrcMessage *pmsg)
{
if (pmsg->parameters.getCount() > 2 && pmsg->m_bIncoming && IsChannel(pmsg->parameters[1])) {
CMStringW sPassword = L"";
@@ -456,7 +456,7 @@ bool CIrcProto::OnIrc_MODEQUERY(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_MODE(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_MODE(const CIrcMessage *pmsg)
{
bool flag = false;
bool bContainsValidModes = false;
@@ -567,7 +567,7 @@ bool CIrcProto::OnIrc_MODE(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_NICK(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_NICK(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && pmsg->parameters.getCount() > 0) {
bool bIsMe = pmsg->prefix.sNick == m_info.sNick ? true : false;
@@ -596,7 +596,7 @@ bool CIrcProto::OnIrc_NICK(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_NOTICE(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_NOTICE(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && pmsg->parameters.getCount() > 1) {
if (IsCTCP(pmsg))
@@ -639,7 +639,7 @@ bool CIrcProto::OnIrc_NOTICE(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_YOURHOST(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_YOURHOST(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming) {
static const wchar_t* lpszFmt = L"Your host is %99[^ \x5b,], running version %99s";
@@ -654,7 +654,7 @@ bool CIrcProto::OnIrc_YOURHOST(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_INVITE(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_INVITE(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && (m_ignore && IsIgnored(pmsg->prefix.sNick, pmsg->prefix.sUser, pmsg->prefix.sHost, 'i')))
return true;
@@ -666,7 +666,7 @@ bool CIrcProto::OnIrc_INVITE(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_PINGPONG(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_PINGPONG(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && pmsg->sCommand == L"PING") {
wchar_t szResponse[100];
@@ -677,7 +677,7 @@ bool CIrcProto::OnIrc_PINGPONG(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_PRIVMSG(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_PRIVMSG(const CIrcMessage *pmsg)
{
if (pmsg->parameters.getCount() > 1) {
if (IsCTCP(pmsg))
@@ -727,7 +727,7 @@ bool CIrcProto::OnIrc_PRIVMSG(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::IsCTCP(const CIrcMessage* pmsg)
+bool CIrcProto::IsCTCP(const CIrcMessage *pmsg)
{
// is it a ctcp command, i e is the first and last characer of a PRIVMSG or NOTICE text ASCII 1
CMStringW mess = pmsg->parameters[1];
@@ -1232,7 +1232,7 @@ bool CIrcProto::IsCTCP(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_NAMES(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_NAMES(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && pmsg->parameters.getCount() > 3)
sNamesList += pmsg->parameters[3] + L" ";
@@ -1240,7 +1240,7 @@ bool CIrcProto::OnIrc_NAMES(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_ENDNAMES(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_ENDNAMES(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && pmsg->parameters.getCount() > 1) {
CMStringW name = L"a";
@@ -1411,7 +1411,7 @@ bool CIrcProto::OnIrc_ENDNAMES(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_INITIALTOPIC(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_INITIALTOPIC(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && pmsg->parameters.getCount() > 2) {
AddWindowItemData(pmsg->parameters[1], nullptr, nullptr, nullptr, pmsg->parameters[2]);
@@ -1423,7 +1423,7 @@ bool CIrcProto::OnIrc_INITIALTOPIC(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_INITIALTOPICNAME(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_INITIALTOPICNAME(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && pmsg->parameters.getCount() > 3) {
wchar_t tTimeBuf[128], *tStopStr;
@@ -1437,7 +1437,7 @@ bool CIrcProto::OnIrc_INITIALTOPICNAME(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_TOPIC(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_TOPIC(const CIrcMessage *pmsg)
{
if (pmsg->parameters.getCount() > 1 && pmsg->m_bIncoming) {
DoEvent(GC_EVENT_TOPIC, pmsg->parameters[0], pmsg->prefix.sNick, pmsg->parameters[1], nullptr, sTopicTime.IsEmpty() ? nullptr : sTopicTime.c_str(), NULL, true, false);
@@ -1457,7 +1457,7 @@ static void __stdcall sttShowDlgList(void* param)
SetEvent(ppro->m_evWndCreate);
}
-bool CIrcProto::OnIrc_LISTSTART(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_LISTSTART(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming) {
CallFunctionAsync(sttShowDlgList, this);
@@ -1469,7 +1469,7 @@ bool CIrcProto::OnIrc_LISTSTART(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_LIST(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_LIST(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming == 1 && m_listDlg && pmsg->parameters.getCount() > 2) {
m_channelNumber++;
@@ -1526,7 +1526,7 @@ bool CIrcProto::OnIrc_LIST(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_LISTEND(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_LISTEND(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && m_listDlg) {
EnableWindow(GetDlgItem(m_listDlg->GetHwnd(), IDC_JOIN), true);
@@ -1551,7 +1551,7 @@ bool CIrcProto::OnIrc_LISTEND(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_BANLIST(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_BANLIST(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && pmsg->parameters.getCount() > 2) {
if (m_managerDlg->GetHwnd() && (
@@ -1580,7 +1580,7 @@ bool CIrcProto::OnIrc_BANLIST(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_BANLISTEND(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_BANLISTEND(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && pmsg->parameters.getCount() > 1) {
if (m_managerDlg->GetHwnd() &&
@@ -1617,7 +1617,7 @@ static void __stdcall sttShowWhoisWnd(void* param)
delete pmsg;
}
-bool CIrcProto::OnIrc_WHOIS_NAME(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_WHOIS_NAME(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && pmsg->parameters.getCount() > 5 && m_manualWhoisCount > 0) {
CallFunctionAsync(sttShowWhoisWnd, new CIrcMessage(*pmsg));
@@ -1627,7 +1627,7 @@ bool CIrcProto::OnIrc_WHOIS_NAME(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_WHOIS_CHANNELS(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_WHOIS_CHANNELS(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && m_whoisDlg && pmsg->parameters.getCount() > 2 && m_manualWhoisCount > 0)
m_whoisDlg->m_InfoChannels.SetText(pmsg->parameters[2]);
@@ -1635,7 +1635,7 @@ bool CIrcProto::OnIrc_WHOIS_CHANNELS(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_WHOIS_AWAY(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_WHOIS_AWAY(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && m_whoisDlg && pmsg->parameters.getCount() > 2 && m_manualWhoisCount > 0)
m_whoisDlg->m_InfoAway2.SetText(pmsg->parameters[2]);
@@ -1645,7 +1645,7 @@ bool CIrcProto::OnIrc_WHOIS_AWAY(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_WHOIS_OTHER(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_WHOIS_OTHER(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && m_whoisDlg && pmsg->parameters.getCount() > 2 && m_manualWhoisCount > 0) {
wchar_t temp[1024], temp2[1024];
@@ -1658,7 +1658,7 @@ bool CIrcProto::OnIrc_WHOIS_OTHER(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_WHOIS_END(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_WHOIS_END(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && pmsg->parameters.getCount() > 1 && m_manualWhoisCount < 1) {
CONTACT user = { pmsg->parameters[1], nullptr, nullptr, false, false, true };
@@ -1674,7 +1674,7 @@ bool CIrcProto::OnIrc_WHOIS_END(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_WHOIS_IDLE(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_WHOIS_IDLE(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && m_whoisDlg && pmsg->parameters.getCount() > 2 && m_manualWhoisCount > 0) {
int S = _wtoi(pmsg->parameters[2]);
@@ -1708,7 +1708,7 @@ bool CIrcProto::OnIrc_WHOIS_IDLE(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_WHOIS_SERVER(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_WHOIS_SERVER(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && m_whoisDlg && pmsg->parameters.getCount() > 2 && m_manualWhoisCount > 0)
m_whoisDlg->m_InfoServer.SetText(pmsg->parameters[2]);
@@ -1716,7 +1716,7 @@ bool CIrcProto::OnIrc_WHOIS_SERVER(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_WHOIS_AUTH(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_WHOIS_AUTH(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && m_whoisDlg && pmsg->parameters.getCount() > 2 && m_manualWhoisCount > 0) {
if (pmsg->sCommand == L"330")
@@ -1730,7 +1730,7 @@ bool CIrcProto::OnIrc_WHOIS_AUTH(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_WHOIS_NO_USER(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_WHOIS_NO_USER(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && pmsg->parameters.getCount() > 2 && !IsChannel(pmsg->parameters[1])) {
if (m_whoisDlg)
@@ -1782,7 +1782,7 @@ static void __stdcall sttShowNickWnd(void* param)
delete pmsg;
}
-bool CIrcProto::OnIrc_NICK_ERR(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_NICK_ERR(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming) {
if (nickflag && ((m_alternativeNick[0] != 0)) && (pmsg->parameters.getCount() > 2 && mir_wstrcmp(pmsg->parameters[1], m_alternativeNick))) {
@@ -1801,7 +1801,7 @@ bool CIrcProto::OnIrc_NICK_ERR(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_JOINERROR(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_JOINERROR(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming) {
DBVARIANT dbv;
@@ -1831,7 +1831,7 @@ bool CIrcProto::OnIrc_JOINERROR(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_UNKNOWN(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_UNKNOWN(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && pmsg->parameters.getCount() > 0) {
if (pmsg->parameters[0] == L"WHO" && GetNextUserhostReason(2) != L"U")
@@ -1843,7 +1843,7 @@ bool CIrcProto::OnIrc_UNKNOWN(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_ENDMOTD(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_ENDMOTD(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && !bPerformDone)
DoOnConnect(pmsg);
@@ -1851,7 +1851,7 @@ bool CIrcProto::OnIrc_ENDMOTD(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_NOOFCHANNELS(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_NOOFCHANNELS(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && pmsg->parameters.getCount() > 1)
m_noOfChannels = _wtoi(pmsg->parameters[1]);
@@ -1863,7 +1863,7 @@ bool CIrcProto::OnIrc_NOOFCHANNELS(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_ERROR(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_ERROR(const CIrcMessage *pmsg)
{
if (pmsg->m_bIncoming && !m_disableErrorPopups && m_iDesiredStatus != ID_STATUS_OFFLINE) {
CMStringW S;
@@ -1877,7 +1877,7 @@ bool CIrcProto::OnIrc_ERROR(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_WHO_END(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_WHO_END(const CIrcMessage *pmsg)
{
CMStringW command = GetNextUserhostReason(2);
if (command[0] == 'S') {
@@ -1974,7 +1974,7 @@ bool CIrcProto::OnIrc_WHO_END(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_WHO_REPLY(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_WHO_REPLY(const CIrcMessage *pmsg)
{
CMStringW command = PeekAtReasons(2);
if (pmsg->m_bIncoming && pmsg->parameters.getCount() > 6 && command[0] == 'S') {
@@ -1991,7 +1991,7 @@ bool CIrcProto::OnIrc_WHO_REPLY(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_TRYAGAIN(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_TRYAGAIN(const CIrcMessage *pmsg)
{
CMStringW command = L"";
if (pmsg->m_bIncoming && pmsg->parameters.getCount() > 1) {
@@ -2006,7 +2006,7 @@ bool CIrcProto::OnIrc_TRYAGAIN(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_USERHOST_REPLY(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_USERHOST_REPLY(const CIrcMessage *pmsg)
{
CMStringW command;
if (pmsg->m_bIncoming) {
@@ -2145,7 +2145,46 @@ bool CIrcProto::OnIrc_USERHOST_REPLY(const CIrcMessage* pmsg)
return true;
}
-bool CIrcProto::OnIrc_SUPPORT(const CIrcMessage* pmsg)
+bool CIrcProto::OnIrc_AUTH_OK(const CIrcMessage *pmsg)
+{
+ if (pmsg->m_bIncoming && !bPerformDone)
+ DoOnConnect(pmsg);
+
+ return true;
+}
+
+bool CIrcProto::OnIrc_AUTH_FAIL(const CIrcMessage*)
+{
+ int Temp = m_iDesiredStatus;
+ m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE;
+ ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, nullptr, LOGINERR_WRONGPASSWORD);
+ ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)Temp, ID_STATUS_OFFLINE);
+ return false;
+}
+
+bool CIrcProto::OnIrc_AUTHENTICATE(const CIrcMessage *pmsg)
+{
+ if (m_bUseSASL && pmsg->parameters[0] == "+") {
+ CMStringA payload(FORMAT, "%S%c%S%c%s%c", m_userID, 0, m_userID, 0, m_password, 0);
+ NLSend("AUTHENTICATE %s\r\n", ptrA(mir_base64_encode(payload, payload.GetLength())).get());
+ NLSend("CAP END\r\n");
+ }
+
+ return true;
+}
+
+bool CIrcProto::OnIrc_CAP(const CIrcMessage *pmsg)
+{
+ if (pmsg->parameters.getCount() < 3)
+ return true;
+
+ if (m_bUseSASL && pmsg->parameters[1] == "ACK" && pmsg->parameters[2].Trim() == "sasl") {
+ NLSend("AUTHENTICATE PLAIN\r\n");
+ }
+ return true;
+}
+
+bool CIrcProto::OnIrc_SUPPORT(const CIrcMessage *pmsg)
{
static const wchar_t *lpszFmt = L"Try server %99[^ ,], port %19s";
wchar_t szAltServer[100];
@@ -2224,7 +2263,7 @@ bool CIrcProto::OnIrc_SUPPORT(const CIrcMessage* pmsg)
return true;
}
-void CIrcProto::OnIrcDefault(const CIrcMessage* pmsg)
+void CIrcProto::OnIrcDefault(const CIrcMessage *pmsg)
{
ShowMessage(pmsg);
}
diff --git a/protocols/IRCG/src/irc_dlg.h b/protocols/IRCG/src/irc_dlg.h
index a9610a97f3..0a23223930 100644
--- a/protocols/IRCG/src/irc_dlg.h
+++ b/protocols/IRCG/src/irc_dlg.h
@@ -203,8 +203,9 @@ struct CConnectPrefsDlg : public CProtoDlgBase < CIrcProto >
CCtrlCheck m_forceVisible, m_rejoinOnKick, m_rejoinChannels, m_disableError,
m_address, m_useServer, m_showServer, m_keepAlive, m_autoJoin,
- m_oldStyle, m_onlineNotif, m_channelAway, m_enableServer;
- CCtrlEdit m_onlineTimer, m_limit, m_spin1, m_spin2, m_ssl;
+ m_oldStyle, m_onlineNotif, m_channelAway, m_enableServer, m_useSasl;
+ CCtrlEdit m_onlineTimer, m_limit, m_ssl;
+ CCtrlSpin m_spin1, m_spin2;
CConnectPrefsDlg(CIrcProto* _pro);
diff --git a/protocols/IRCG/src/irclib.cpp b/protocols/IRCG/src/irclib.cpp
index 94f736affa..0033ec2d6c 100644
--- a/protocols/IRCG/src/irclib.cpp
+++ b/protocols/IRCG/src/irclib.cpp
@@ -224,11 +224,12 @@ bool CIrcProto::Connect(const CIrcSessionInfo& info)
m_info = info;
+ if (m_bUseSASL)
+ NLSend("CAP REQ :sasl\r\n");
+
// start receiving messages from host
ForkThread(&CIrcProto::ThreadProc, nullptr);
Sleep(100);
- if (info.sPassword.GetLength())
- NLSend("PASS %s\r\n", info.sPassword.c_str());
NLSend(L"NICK %s\r\n", info.sNick.c_str());
CMStringW userID = GetWord(info.sUserID.c_str(), 0);
@@ -242,6 +243,9 @@ bool CIrcProto::Connect(const CIrcSessionInfo& info)
HostName = L"host";
NLSend(L"USER %s %s %s :%s\r\n", userID.c_str(), HostName.c_str(), L"server", info.sFullName.c_str());
+ if (!m_bUseSASL && info.sPassword.GetLength())
+ NLSend("PASS %s\r\n", info.sPassword.c_str());
+
return con != nullptr;
}
diff --git a/protocols/IRCG/src/ircproto.cpp b/protocols/IRCG/src/ircproto.cpp
index 869732806a..69b19da59b 100644
--- a/protocols/IRCG/src/ircproto.cpp
+++ b/protocols/IRCG/src/ircproto.cpp
@@ -82,6 +82,8 @@ CIrcProto::CIrcProto(const char* szModuleName, const wchar_t* tszUserName) :
IRC_MAP_ENTRY("NOTICE", NOTICE)
IRC_MAP_ENTRY("PING", PINGPONG)
IRC_MAP_ENTRY("PONG", PINGPONG)
+ IRC_MAP_ENTRY("CAP", CAP)
+ IRC_MAP_ENTRY("AUTHENTICATE", AUTHENTICATE)
IRC_MAP_ENTRY("INVITE", INVITE)
IRC_MAP_ENTRY("ERROR", ERROR)
IRC_MAP_ENTRY("001", WELCOME)
@@ -134,6 +136,10 @@ CIrcProto::CIrcProto(const char* szModuleName, const wchar_t* tszUserName) :
IRC_MAP_ENTRY("474", JOINERROR)
IRC_MAP_ENTRY("475", JOINERROR)
IRC_MAP_ENTRY("671", WHOIS_OTHER) //Encryption info (SSL connect)
+ IRC_MAP_ENTRY("903", AUTH_OK)
+ IRC_MAP_ENTRY("904", AUTH_FAIL)
+ IRC_MAP_ENTRY("905", AUTH_FAIL)
+ IRC_MAP_ENTRY("906", AUTH_FAIL)
}
CIrcProto::~CIrcProto()
diff --git a/protocols/IRCG/src/main.cpp b/protocols/IRCG/src/main.cpp
index 8ca2aa485d..c821c183c2 100644
--- a/protocols/IRCG/src/main.cpp
+++ b/protocols/IRCG/src/main.cpp
@@ -52,7 +52,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESC,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/protocols/IRCG/src/options.cpp b/protocols/IRCG/src/options.cpp
index 374500cb5f..0fedca772e 100644
--- a/protocols/IRCG/src/options.cpp
+++ b/protocols/IRCG/src/options.cpp
@@ -423,6 +423,7 @@ static TDbSetting ConnectSettings[] =
{ FIELD_OFFSET(CIrcProto, m_showAddresses), "ShowAddresses", DBVT_BYTE },
{ FIELD_OFFSET(CIrcProto, m_oldStyleModes), "OldStyleModes", DBVT_BYTE },
{ FIELD_OFFSET(CIrcProto, m_useServer), "UseServer", DBVT_BYTE, 0, 1 },
+ { FIELD_OFFSET(CIrcProto, m_bUseSASL), "UseSASL", DBVT_BYTE },
{ FIELD_OFFSET(CIrcProto, m_hideServerWindow), "HideServerWindow", DBVT_BYTE, 0, 1 },
{ FIELD_OFFSET(CIrcProto, m_serverComboSelection), "ServerComboSelection", DBVT_DWORD, 0 },
{ FIELD_OFFSET(CIrcProto, m_sendKeepAlive), "SendKeepAlive", DBVT_BYTE, 0, 1 },
@@ -457,6 +458,7 @@ CConnectPrefsDlg::CConnectPrefsDlg(CIrcProto* _pro)
m_keepAlive(this, IDC_KEEPALIVE),
m_autoJoin(this, IDC_AUTOJOIN),
m_oldStyle(this, IDC_OLDSTYLE),
+ m_useSasl(this, IDC_SASL),
m_onlineNotif(this, IDC_ONLINENOTIF),
m_channelAway(this, IDC_CHANNELAWAY),
m_enableServer(this, IDC_STARTUP),
@@ -509,10 +511,12 @@ void CConnectPrefsDlg::OnInitDialog()
}
}
- m_spin1.SendMsg(UDM_SETRANGE, 0, MAKELONG(999, 20));
- m_spin1.SendMsg(UDM_SETPOS, 0, MAKELONG(m_proto->m_onlineNotificationTime, 0));
- m_spin2.SendMsg(UDM_SETRANGE, 0, MAKELONG(200, 0));
- m_spin2.SendMsg(UDM_SETPOS, 0, MAKELONG(m_proto->m_onlineNotificationLimit, 0));
+ m_spin1.SetRange(999, 20);
+ m_spin1.SetPosition(m_proto->m_onlineNotificationTime);
+
+ m_spin2.SetRange(200);
+ m_spin2.SetPosition(m_proto->m_onlineNotificationLimit);
+
m_nick.SetText(m_proto->m_nick);
m_nick2.SetText(m_proto->m_alternativeNick);
m_userID.SetText(m_proto->m_userID);
@@ -522,6 +526,7 @@ void CConnectPrefsDlg::OnInitDialog()
m_identPort.SetText(m_proto->m_identPort);
m_address.SetState(m_proto->m_showAddresses);
m_oldStyle.SetState(m_proto->m_oldStyleModes);
+ m_useSasl.SetState(m_proto->m_bUseSASL);
m_channelAway.SetState(m_proto->m_channelAwayNotification);
m_onlineNotif.SetState(m_proto->m_autoOnlineNotification);
m_onlineTimer.Enable(m_proto->m_autoOnlineNotification);
@@ -708,6 +713,7 @@ void CConnectPrefsDlg::OnApply()
m_proto->m_showAddresses = m_address.GetState();
m_proto->m_oldStyleModes = m_oldStyle.GetState();
m_proto->m_useServer = m_useServer.GetState();
+ m_proto->m_bUseSASL = m_useSasl.GetState();
Menu_EnableItem(m_proto->hMenuServer, m_proto->m_useServer != 0);
diff --git a/protocols/IRCG/src/resource.h b/protocols/IRCG/src/resource.h
index b2462f00ca..6f21099b10 100644
--- a/protocols/IRCG/src/resource.h
+++ b/protocols/IRCG/src/resource.h
@@ -1,6 +1,6 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
-// Used by ..\res\IRC.rc
+// Used by w:\miranda-ng\protocols\IRCG\res\IRC.rc
//
#define ID_INFO_QUERY 3
#define IDD_PREFS_MAIN 101
@@ -184,6 +184,7 @@
#define IDC_FILTER_STRING 1235
#define IDC_BUTTON1 1236
#define IDC_FILTER_BTN 1237
+#define IDC_SASL 1238
#define ID_MENU1_OP 40013
#define ID_MENU1_DEOP 40014
#define ID_MENU1_VOICE 40015
@@ -242,9 +243,9 @@
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 203
+#define _APS_NEXT_RESOURCE_VALUE 204
#define _APS_NEXT_COMMAND_VALUE 40067
-#define _APS_NEXT_CONTROL_VALUE 1238
+#define _APS_NEXT_CONTROL_VALUE 1239
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
diff --git a/protocols/IRCG/src/services.cpp b/protocols/IRCG/src/services.cpp
index c6ed1fb46c..07097155ce 100644
--- a/protocols/IRCG/src/services.cpp
+++ b/protocols/IRCG/src/services.cpp
@@ -704,17 +704,12 @@ int __cdecl CIrcProto::GCEventHook(WPARAM, LPARAM lParam)
break;
case 30:
{
- PROTOSEARCHRESULT psr = { 0 };
+ PROTOSEARCHRESULT psr = {};
psr.cbSize = sizeof(psr);
psr.flags = PSR_UNICODE;
psr.id.w = gch->ptszUID;
psr.nick.w = gch->ptszUID;
-
- ADDCONTACTSTRUCT acs = { 0 };
- acs.handleType = HANDLE_SEARCHRESULT;
- acs.szProto = m_szModuleName;
- acs.psr = &psr;
- CallService(MS_ADDCONTACT_SHOW, 0, (LPARAM)&acs);
+ Contact_AddBySearch(m_szModuleName, &psr);
}
break;
case 31: //slap
diff --git a/protocols/IRCG/src/stdafx.h b/protocols/IRCG/src/stdafx.h
index 4a5c6eea79..14da73d80a 100644
--- a/protocols/IRCG/src/stdafx.h
+++ b/protocols/IRCG/src/stdafx.h
@@ -56,7 +56,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "m_chat_int.h"
#include "m_message.h"
#include "m_userinfo.h"
-#include "m_addcontact.h"
+#include "m_contacts.h"
#include "m_button.h"
#include "m_genmenu.h"
#include "m_file.h"
@@ -324,6 +324,7 @@ struct CIrcProto : public PROTO<CIrcProto>
BYTE m_channelAwayNotification;
BYTE m_sendNotice;
BYTE m_utfAutodetect;
+ BYTE m_bUseSASL;
int m_codepage;
COLORREF colors[16];
HICON hIcon[13];
@@ -567,6 +568,10 @@ private:
bool OnIrc_WHO_END(const CIrcMessage *pmsg);
bool OnIrc_WHO_REPLY(const CIrcMessage *pmsg);
bool OnIrc_WHOTOOLONG(const CIrcMessage *pmsg);
+ bool OnIrc_AUTHENTICATE(const CIrcMessage *pmsg);
+ bool OnIrc_AUTH_OK(const CIrcMessage *pmsg);
+ bool OnIrc_AUTH_FAIL(const CIrcMessage *pmsg);
+ bool OnIrc_CAP(const CIrcMessage *pmsg);
bool IsCTCP(const CIrcMessage *pmsg);
diff --git a/protocols/IRCG/src/version.h b/protocols/IRCG/src/version.h
index a708c116a6..4ef31cab0e 100644
--- a/protocols/IRCG/src/version.h
+++ b/protocols/IRCG/src/version.h
@@ -1,13 +1,12 @@
#define __MAJOR_VERSION 0
#define __MINOR_VERSION 95
#define __RELEASE_NUM 7
-#define __BUILD_NUM 1
+#define __BUILD_NUM 2
#include <stdver.h>
#define __DESC "Internet Relay Chat (IRC) protocol support for Miranda NG."
#define __AUTHOR "Miranda team"
-#define __AUTHOREMAIL "ghazan@miranda.im"
#define __COPYRIGHT "© 2003-17 Jurgen Persson, George Hazan"
#define __AUTHORWEB "https://miranda-ng.org/p/IRC/"
diff --git a/protocols/IcqOscarJ/src/init.cpp b/protocols/IcqOscarJ/src/init.cpp
index ca3806e78a..da3403e901 100644
--- a/protocols/IcqOscarJ/src/init.cpp
+++ b/protocols/IcqOscarJ/src/init.cpp
@@ -43,7 +43,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE, //doesn't replace anything built-in
diff --git a/protocols/IcqOscarJ/src/version.h b/protocols/IcqOscarJ/src/version.h
index ade9e14996..2f441cda7d 100644
--- a/protocols/IcqOscarJ/src/version.h
+++ b/protocols/IcqOscarJ/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "ICQ.dll"
#define __DESCRIPTION "ICQ protocol support for Miranda NG."
#define __AUTHOR "Joe Kucera, Bio, Martin Öberg, Richard Hughes, Jon Keating, etc."
-#define __AUTHOREMAIL "jokusoftware@miranda-im.org"
#define __AUTHORWEB "https://miranda-ng.org/p/ICQ/"
#define __COPYRIGHT "© 2000-17 M.Öberg, R.Hughes, J.Keating, Bio, Angeli-Ka, G.Hazan, J.Kucera"
diff --git a/protocols/JabberG/src/jabber.cpp b/protocols/JabberG/src/jabber.cpp
index 4b4b4eb268..ff2a4290af 100755
--- a/protocols/JabberG/src/jabber.cpp
+++ b/protocols/JabberG/src/jabber.cpp
@@ -53,7 +53,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/protocols/JabberG/src/jabber_caps.cpp b/protocols/JabberG/src/jabber_caps.cpp
index 94d2432ff6..89d3bf9c13 100755
--- a/protocols/JabberG/src/jabber_caps.cpp
+++ b/protocols/JabberG/src/jabber_caps.cpp
@@ -498,7 +498,7 @@ void CJabberClientCapsManager::UpdateFeatHash()
BYTE hash[MIR_SHA1_HASH_SIZE];
mir_sha1_hash((BYTE*)feat_buf.c_str(), feat_buf.GetLength(), hash);
- ptrA szHash(mir_base64_encode((BYTE*)&hash, sizeof(hash)));
+ ptrA szHash(mir_base64_encode(&hash, sizeof(hash)));
m_szFeaturesCrc = szHash;
}
diff --git a/protocols/JabberG/src/jabber_captcha.cpp b/protocols/JabberG/src/jabber_captcha.cpp
index 31112306bb..6fcc3418a5 100644
--- a/protocols/JabberG/src/jabber_captcha.cpp
+++ b/protocols/JabberG/src/jabber_captcha.cpp
@@ -141,7 +141,7 @@ bool CJabberProto::ProcessCaptcha(HXML node, HXML parentNode, ThreadData *info)
if (o == nullptr || XmlGetText(o) == nullptr)
return false;
- unsigned bufferLen;
+ size_t bufferLen;
ptrA buffer((char*)mir_base64_decode( _T2A(XmlGetText(o)), &bufferLen));
if (buffer == nullptr)
return false;
diff --git a/protocols/JabberG/src/jabber_chat.cpp b/protocols/JabberG/src/jabber_chat.cpp
index b609d1a111..f0ed8f315e 100644
--- a/protocols/JabberG/src/jabber_chat.cpp
+++ b/protocols/JabberG/src/jabber_chat.cpp
@@ -1204,12 +1204,7 @@ static void sttNickListHook(CJabberProto *ppro, JABBER_LIST_ITEM *item, GCHOOK*
if (wchar_t *tmp = wcschr(psr.id.w, '/'))
*tmp = 0;
psr.nick.w = psr.id.w;
-
- ADDCONTACTSTRUCT acs = { 0 };
- acs.handleType = HANDLE_SEARCHRESULT;
- acs.szProto = ppro->m_szModuleName;
- acs.psr = &psr;
- CallService(MS_ADDCONTACT_SHOW, (WPARAM)pcli->hwndContactList, (LPARAM)&acs);
+ Contact_AddBySearch(ppro->m_szModuleName, &psr, pcli->hwndContactList);
}
break;
}
diff --git a/protocols/JabberG/src/jabber_events.cpp b/protocols/JabberG/src/jabber_events.cpp
index 46cfe9a356..ce10d6b7aa 100644
--- a/protocols/JabberG/src/jabber_events.cpp
+++ b/protocols/JabberG/src/jabber_events.cpp
@@ -187,8 +187,8 @@ int CJabberProto::OnIdleChanged(WPARAM, LPARAM lParam)
}
if (lParam & IDF_ISIDLE) {
- MIRANDA_IDLE_INFO mii = { sizeof(mii) };
- CallService(MS_IDLE_GETIDLEINFO, 0, (LPARAM)&mii);
+ MIRANDA_IDLE_INFO mii;
+ Idle_GetInfo(mii);
m_tmJabberIdleStartTime = time(nullptr) - mii.idleTime * 60;
}
else m_tmJabberIdleStartTime = 0;
diff --git a/protocols/JabberG/src/jabber_ft.cpp b/protocols/JabberG/src/jabber_ft.cpp
index 94a7fae28b..1da840f38e 100644
--- a/protocols/JabberG/src/jabber_ft.cpp
+++ b/protocols/JabberG/src/jabber_ft.cpp
@@ -244,7 +244,7 @@ BOOL CJabberProto::FtIbbSend(int blocksize, filetransfer *ft)
// let others send data too
Sleep(2);
- char *encoded = mir_base64_encode((PBYTE)(char*)buffer, numRead);
+ char *encoded = mir_base64_encode(buffer, numRead);
msg << XCHILD(L"data", _A2T(encoded)) << XATTR(L"xmlns", JABBER_FEAT_IBB)
<< XATTR(L"sid", ft->jibb->sid) << XATTRI(L"seq", ft->jibb->wPacketId);
diff --git a/protocols/JabberG/src/jabber_ibb.cpp b/protocols/JabberG/src/jabber_ibb.cpp
index 68d2e942eb..aa6d60f45c 100644
--- a/protocols/JabberG/src/jabber_ibb.cpp
+++ b/protocols/JabberG/src/jabber_ibb.cpp
@@ -178,7 +178,7 @@ BOOL CJabberProto::OnIbbRecvdData(const wchar_t *data, const wchar_t *sid, const
item->jibb->wPacketId++;
- unsigned length;
+ size_t length;
ptrA decodedData((char*)mir_base64_decode( _T2A(data), &length));
if (decodedData == nullptr)
return FALSE;
diff --git a/protocols/JabberG/src/jabber_iq_handlers.cpp b/protocols/JabberG/src/jabber_iq_handlers.cpp
index b5ef1970c6..f48da30b6e 100644
--- a/protocols/JabberG/src/jabber_iq_handlers.cpp
+++ b/protocols/JabberG/src/jabber_iq_handlers.cpp
@@ -172,7 +172,7 @@ BOOL CJabberProto::OnIqRequestAvatar(HXML, CJabberIqInfo *pInfo)
fread(buffer, bytes, 1, in);
fclose(in);
- ptrA str(mir_base64_encode((PBYTE)(char*)buffer, bytes));
+ ptrA str(mir_base64_encode(buffer, bytes));
m_ThreadInfo->send(XmlNodeIq(L"result", pInfo) << XQUERY(JABBER_FEAT_AVATAR) << XCHILD(L"query", _A2T(str)) << XATTR(L"mimetype", szMimeType));
return TRUE;
}
diff --git a/protocols/JabberG/src/jabber_iqid.cpp b/protocols/JabberG/src/jabber_iqid.cpp
index 0b3fc98448..a021a4bf40 100755
--- a/protocols/JabberG/src/jabber_iqid.cpp
+++ b/protocols/JabberG/src/jabber_iqid.cpp
@@ -588,7 +588,7 @@ void CJabberProto::OnIqResultGetVcardPhoto(HXML n, MCONTACT hContact, bool &hasP
if (o == nullptr || ptszBinval == nullptr)
return;
- unsigned bufferLen;
+ size_t bufferLen;
ptrA buffer((char*)mir_base64_decode(_T2A(ptszBinval), &bufferLen));
if (buffer == nullptr)
return;
@@ -1406,7 +1406,7 @@ void CJabberProto::OnIqResultGetServerAvatar(HXML iqNode, CJabberIqInfo*)
void CJabberProto::OnIqResultGotAvatar(MCONTACT hContact, HXML n, const wchar_t *mimeType)
{
- unsigned resultLen;
+ size_t resultLen;
ptrA body((char*)mir_base64_decode(_T2A(XmlGetText(n)), &resultLen));
if (body == nullptr)
return;
diff --git a/protocols/JabberG/src/jabber_misc.cpp b/protocols/JabberG/src/jabber_misc.cpp
index c0c14eb400..f255edfd28 100755
--- a/protocols/JabberG/src/jabber_misc.cpp
+++ b/protocols/JabberG/src/jabber_misc.cpp
@@ -476,7 +476,7 @@ CMStringW CJabberProto::ExtractImage(HXML node)
if (h != INVALID_HANDLE_VALUE) {
DWORD n;
- unsigned int bufferLen;
+ size_t bufferLen;
ptrA buffer((char*)mir_base64_decode(_T2A(image), &bufferLen));
WriteFile(h, buffer, bufferLen, &n, nullptr);
CloseHandle(h);
diff --git a/protocols/JabberG/src/jabber_omemo.cpp b/protocols/JabberG/src/jabber_omemo.cpp
index 5d09ec7042..0ac611151a 100755
--- a/protocols/JabberG/src/jabber_omemo.cpp
+++ b/protocols/JabberG/src/jabber_omemo.cpp
@@ -570,7 +570,7 @@ namespace omemo {
signal_buffer *key_buf;
ec_public_key_serialize(&key_buf, public_key);
// SIGNAL_UNREF(public_key);
- char *key = mir_base64_encode(signal_buffer_data(key_buf), (unsigned int)signal_buffer_len(key_buf));
+ char *key = mir_base64_encode(signal_buffer_data(key_buf), signal_buffer_len(key_buf));
char *fingerprint = (char*)mir_alloc((signal_buffer_len(key_buf) * 2) + 1);
bin2hex(signal_buffer_data(key_buf), signal_buffer_len(key_buf), fingerprint);
proto->setString("OmemoFingerprintOwn", fingerprint);
@@ -581,7 +581,7 @@ namespace omemo {
ec_private_key *private_key = ratchet_identity_key_pair_get_private(new_dev->device_key);
ec_private_key_serialize(&key_buf, private_key);
// SIGNAL_UNREF(private_key);
- key = mir_base64_encode(signal_buffer_data(key_buf), (unsigned int)signal_buffer_len(key_buf));
+ key = mir_base64_encode(signal_buffer_data(key_buf), signal_buffer_len(key_buf));
proto->setString("OmemoDevicePrivateKey", key);
mir_free(key);
signal_buffer_free(key_buf);
@@ -608,11 +608,11 @@ namespace omemo {
public_key = ec_key_pair_get_public(signed_pre_key_pair);
ec_public_key_serialize(&key_buf, public_key);
// SIGNAL_UNREF(public_key);
- key = mir_base64_encode(signal_buffer_data(key_buf), (unsigned int)signal_buffer_len(key_buf));
+ key = mir_base64_encode(signal_buffer_data(key_buf), signal_buffer_len(key_buf));
proto->setString("OmemoSignedPreKeyPublic", key);
mir_free(key);
signal_buffer_free(key_buf);
- char *signature = mir_base64_encode(session_signed_pre_key_get_signature(signed_pre_key), (unsigned int)session_signed_pre_key_get_signature_len(signed_pre_key));
+ char *signature = mir_base64_encode(session_signed_pre_key_get_signature(signed_pre_key), session_signed_pre_key_get_signature_len(signed_pre_key));
proto->setString("OmemoSignedPreKeySignature", signature);
mir_free(signature);
@@ -638,7 +638,7 @@ namespace omemo {
public_key = ec_key_pair_get_public(pre_key_pair);
ec_public_key_serialize(&key_buf, public_key);
SIGNAL_UNREF(public_key);
- key = mir_base64_encode(signal_buffer_data(key_buf), (unsigned int)signal_buffer_len(key_buf));
+ key = mir_base64_encode(signal_buffer_data(key_buf), signal_buffer_len(key_buf));
mir_snprintf(setting_name, "OmemoPreKey%uPublic", pre_key_id);
proto->setString(setting_name, key);
mir_free(key);
@@ -689,7 +689,7 @@ namespace omemo {
char *id_buf_ptr = id_buf;
id_buf_ptr += address->name_len;
memcpy(id_buf_ptr, &address->device_id, sizeof(int32_t));
- char *id_str = mir_base64_encode((BYTE*)id_buf, (unsigned int)(address->name_len + sizeof(int32_t)));
+ char *id_str = mir_base64_encode(id_buf, address->name_len + sizeof(int32_t));
mir_free(id_buf);
char *setting_name = (char*)mir_alloc(strlen(id_str) + 65);
mir_snprintf(setting_name, strlen(id_str) + 64, "%s%s", "OmemoSignalSession_", id_str);
@@ -729,12 +729,12 @@ namespace omemo {
{
char *ptr = (char*)szSetting;
ptr += mir_strlen("OmemoSignalSession_");
- char *current_name = mir_base64_encode((BYTE*)data->name, (unsigned int)data->name_len);
+ char *current_name = mir_base64_encode(data->name, data->name_len);
if (strstr(ptr, current_name))
{
char *dev_encoded = ptr;
dev_encoded += strlen(current_name);
- unsigned int len;
+ size_t len;
void *dev_tmp = mir_base64_decode(dev_encoded, &len);
signal_int_list_push_back(data->sessions, *((int *)dev_tmp));
data->arr_size++;
@@ -790,7 +790,7 @@ namespace omemo {
char *id_buf_ptr = id_buf;
id_buf_ptr += address->name_len;
memcpy(id_buf_ptr, &address->device_id, sizeof(int32_t));
- char *id_str = mir_base64_encode((BYTE*)id_buf, (unsigned int)(address->name_len + sizeof(int32_t)));
+ char *id_str = mir_base64_encode(id_buf, address->name_len + sizeof(int32_t));
mir_free(id_buf);
char *setting_name = (char*)mir_alloc(strlen(id_str) + 65);
mir_snprintf(setting_name, strlen(id_str) + 64, "%s%s", "OmemoSignalSession_", id_str);
@@ -817,7 +817,7 @@ namespace omemo {
char *id_buf_ptr = id_buf;
id_buf_ptr += address->name_len;
memcpy(id_buf_ptr, &address->device_id, sizeof(int32_t));
- char *id_str = mir_base64_encode((BYTE*)id_buf, (unsigned int)(address->name_len + sizeof(int32_t)));
+ char *id_str = mir_base64_encode(id_buf, address->name_len + sizeof(int32_t));
mir_free(id_buf);
char *setting_name = (char*)mir_alloc(strlen(id_str) + 65);
mir_snprintf(setting_name, strlen(id_str) + 64, "%s%s", "OmemoSignalSession_", id_str);
@@ -852,7 +852,7 @@ namespace omemo {
char *id_buf_ptr = id_buf;
id_buf_ptr += address->name_len;
memcpy(id_buf_ptr, &address->device_id, sizeof(int32_t));
- char *id_str = mir_base64_encode((BYTE*)id_buf, (unsigned int)(address->name_len + sizeof(int32_t)));
+ char *id_str = mir_base64_encode(id_buf, address->name_len + sizeof(int32_t));
mir_free(id_buf);
char *setting_name = (char*)mir_alloc(strlen(id_str) + 65);
mir_snprintf(setting_name, strlen(id_str) + 64, "%s%s", "OmemoSignalSession_", id_str);
@@ -877,7 +877,7 @@ namespace omemo {
{
char *ptr = (char*)szSetting;
ptr += mir_strlen("OmemoSignalSession_");
- char *current_name = mir_base64_encode((BYTE*)data->name, (unsigned int)data->name_len);
+ char *current_name = mir_base64_encode(data->name, data->name_len);
if (strstr(ptr, current_name))
data->settings.push_back(mir_strdup(szSetting));
mir_free(current_name);
@@ -984,7 +984,7 @@ namespace omemo {
public_key = ec_key_pair_get_public(pre_key_pair);
ec_public_key_serialize(&key_buf, public_key);
SIGNAL_UNREF(public_key);
- key = mir_base64_encode(signal_buffer_data(key_buf), (unsigned int)signal_buffer_len(key_buf));
+ key = mir_base64_encode(signal_buffer_data(key_buf), signal_buffer_len(key_buf));
mir_snprintf(setting_name, strlen("OmemoSignalPreKey_") + 31, "OmemoPreKey%uPublic", pre_key_id);
data->proto->setString(setting_name, key);
mir_free(key);
@@ -992,7 +992,7 @@ namespace omemo {
/* private_key = ec_key_pair_get_private(pre_key_pair);
ec_private_key_serialize(&key_buf, private_key);
SIGNAL_UNREF(private_key);
- key = mir_base64_encode(signal_buffer_data(key_buf), (unsigned int)signal_buffer_len(key_buf));
+ key = mir_base64_encode(signal_buffer_data(key_buf), signal_buffer_len(key_buf));
mir_snprintf(setting_name, strlen("OmemoSignalPreKey_") + 31, "OmemoPreKey%uPrivate", pre_key_id);
data->proto->setString(setting_name, key);
mir_free(key);
@@ -1187,7 +1187,7 @@ namespace omemo {
signal_store_backend_user_data* data = (signal_store_backend_user_data*)user_data;
char *pub_key = data->proto->getStringA("OmemoDevicePublicKey");
char *priv_key = data->proto->getStringA("OmemoDevicePrivateKey");
- unsigned int pub_key_len = 0, priv_key_len = 0;
+ size_t pub_key_len = 0, priv_key_len = 0;
char *pub_key_buf = (char*)mir_base64_decode(pub_key, &pub_key_len);
mir_free(pub_key);
char *priv_key_buf = (char*)mir_base64_decode(priv_key, &priv_key_len);
@@ -1242,7 +1242,7 @@ namespace omemo {
char *id_buf_ptr = id_buf;
id_buf_ptr += address->name_len;
memcpy(id_buf_ptr, &address->device_id, sizeof(int32_t));
- char *id_str = mir_base64_encode((BYTE*)id_buf, (unsigned int)(address->name_len + sizeof(int32_t)));
+ char *id_str = mir_base64_encode(id_buf, address->name_len + sizeof(int32_t));
mir_free(id_buf);
char *setting_name = (char*)mir_alloc(strlen(id_str) + 65);
mir_snprintf(setting_name, strlen(id_str) + 64, "%s%s", "OmemoSignalIdentity_", id_str);
@@ -1284,7 +1284,7 @@ namespace omemo {
char *id_buf_ptr = id_buf;
id_buf_ptr += address->name_len;
memcpy(id_buf_ptr, &address->device_id, sizeof(int32_t));
- char *id_str = mir_base64_encode((BYTE*)id_buf, (unsigned int)(address->name_len + sizeof(int32_t)));
+ char *id_str = mir_base64_encode(id_buf, address->name_len + sizeof(int32_t));
mir_free(id_buf);
char *setting_name = (char*)mir_alloc(strlen(id_str) + 65);
mir_snprintf(setting_name, strlen(id_str) + 64, "%s%s", "OmemoSignalIdentity_", id_str);
@@ -1400,7 +1400,7 @@ namespace omemo {
unsigned int key_id_int = _wtoi(key_id);
char *pre_key_a = mir_u2a(pre_key_public);
- unsigned int key_buf_len;
+ size_t key_buf_len;
uint8_t *key_buf = (uint8_t*)mir_base64_decode(pre_key_a, &key_buf_len);
ec_public_key *prekey;
if (curve_decode_point(&prekey, key_buf, key_buf_len, global_context))
@@ -1542,7 +1542,7 @@ namespace omemo {
public_key = ec_key_pair_get_public(pre_key_pair);
ec_public_key_serialize(&key_buf, public_key);
SIGNAL_UNREF(public_key);
- key = mir_base64_encode(signal_buffer_data(key_buf), (unsigned int)signal_buffer_len(key_buf));
+ key = mir_base64_encode(signal_buffer_data(key_buf), signal_buffer_len(key_buf));
mir_snprintf(setting_name, "OmemoPreKey%uPublic", pre_key_id);
proto->setString(setting_name, key);
mir_free(key);
@@ -1670,14 +1670,14 @@ void CJabberProto::OmemoHandleMessage(HXML node, wchar_t *jid, time_t msgTime)
debugLogA("Jabber OMEMO: message does not have decryption key for our device");
return; //node does not contain key for our device
}
- unsigned int encrypted_key_len;
+ size_t encrypted_key_len;
unsigned char *encrypted_key;
{
char *key_buf = mir_u2a(encrypted_key_base64);
encrypted_key = (unsigned char*)mir_base64_decode(key_buf, &encrypted_key_len);
mir_free(key_buf);
}
- unsigned int iv_len;
+ size_t iv_len;
unsigned char *iv;
{
char *iv_buf = mir_u2a(iv_base64);
@@ -1799,7 +1799,7 @@ void CJabberProto::OmemoHandleMessage(HXML node, wchar_t *jid, time_t msgTime)
char *out = nullptr;
{
int dec_success = 0;
- unsigned int payload_len = 0;
+ size_t payload_len = 0;
int outl = 0, round_len = 0;
char *payload_base64 = mir_u2a(payload_base64w);
unsigned char *payload = (unsigned char*)mir_base64_decode(payload_base64, &payload_len);
@@ -2317,7 +2317,7 @@ unsigned int CJabberProto::OmemoEncryptMessage(XmlNode &msg, const wchar_t *msg_
mir_free(in);
HXML encrypted = msg << XCHILDNS(L"encrypted", JABBER_FEAT_OMEMO);
HXML payload = encrypted << XCHILD(L"payload");
- char *payload_base64 = mir_base64_encode((BYTE*)out, tmp_len);
+ char *payload_base64 = mir_base64_encode(out, tmp_len);
wchar_t *payload_base64w = mir_a2u(payload_base64);
mir_free(payload_base64);
xmlSetText(payload, payload_base64w);
@@ -2357,7 +2357,7 @@ unsigned int CJabberProto::OmemoEncryptMessage(XmlNode &msg, const wchar_t *msg_
key_node << XATTR(L"prekey", L"true");
}
signal_buffer *serialized_encrypted_key = ciphertext_message_get_serialized(encrypted_key);
- char *key_base64 = mir_base64_encode(signal_buffer_data(serialized_encrypted_key), (unsigned int)signal_buffer_len(serialized_encrypted_key));
+ char *key_base64 = mir_base64_encode(signal_buffer_data(serialized_encrypted_key), signal_buffer_len(serialized_encrypted_key));
wchar_t *key_base64w = mir_a2u(key_base64);
mir_free(key_base64);
xmlSetText(key_node, key_base64w);
@@ -2367,7 +2367,7 @@ unsigned int CJabberProto::OmemoEncryptMessage(XmlNode &msg, const wchar_t *msg_
}
}
HXML iv_node = header << XCHILD(L"iv");
- char *iv_base64 = mir_base64_encode((BYTE*)iv, _countof_portable(iv));
+ char *iv_base64 = mir_base64_encode(iv, _countof_portable(iv));
wchar_t *iv_base64w = mir_a2u(iv_base64);
mir_free(iv_base64);
xmlSetText(iv_node, iv_base64w);
diff --git a/protocols/JabberG/src/jabber_secur.cpp b/protocols/JabberG/src/jabber_secur.cpp
index edf0324766..25a0f2bad4 100644
--- a/protocols/JabberG/src/jabber_secur.cpp
+++ b/protocols/JabberG/src/jabber_secur.cpp
@@ -144,7 +144,7 @@ char* TMD5Auth::getChallenge(const wchar_t *challenge)
iCallCount++;
- unsigned resultLen;
+ size_t resultLen;
ptrA text((char*)mir_base64_decode( _T2A(challenge), &resultLen));
TStringPairs pairs(text);
@@ -201,7 +201,7 @@ char* TMD5Auth::getChallenge(const wchar_t *challenge)
uname, realm, nonce, cnonce, iCallCount, serv,
htonl(digest[0]), htonl(digest[1]), htonl(digest[2]), htonl(digest[3]));
- return mir_base64_encode((PBYTE)buf, cbLen);
+ return mir_base64_encode(buf, cbLen);
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -240,7 +240,7 @@ void TScramAuth::Hi(BYTE* res, char* passw, size_t passwLen, char* salt, size_t
char* TScramAuth::getChallenge(const wchar_t *challenge)
{
- unsigned chlLen, saltLen = 0;
+ size_t chlLen, saltLen = 0;
ptrA snonce, salt;
int ind = -1;
@@ -293,12 +293,12 @@ char* TScramAuth::getChallenge(const wchar_t *challenge)
BYTE srvSig[MIR_SHA1_HASH_SIZE];
mir_hmac_sha1(srvSig, serverKey, sizeof(serverKey), (BYTE*)authmsg, authmsgLen);
- serverSignature = mir_base64_encode((PBYTE)srvSig, sizeof(srvSig));
+ serverSignature = mir_base64_encode(srvSig, sizeof(srvSig));
char buf[4096];
- ptrA encproof(mir_base64_encode((PBYTE)clientProof, sizeof(clientProof)));
+ ptrA encproof(mir_base64_encode(clientProof, sizeof(clientProof)));
int cbLen = mir_snprintf(buf, "c=biws,r=%s,p=%s", snonce, encproof);
- return mir_base64_encode((PBYTE)buf, cbLen);
+ return mir_base64_encode(buf, cbLen);
}
char* TScramAuth::getInitialRequest()
@@ -307,17 +307,17 @@ char* TScramAuth::getInitialRequest()
unsigned char nonce[24];
Utils_GetRandom(nonce, sizeof(nonce));
- cnonce = mir_base64_encode((PBYTE)nonce, sizeof(nonce));
+ cnonce = mir_base64_encode(nonce, sizeof(nonce));
char buf[4096];
int cbLen = mir_snprintf(buf, "n,,n=%s,r=%s", uname, cnonce);
msg1 = mir_strdup(buf + 3);
- return mir_base64_encode((PBYTE)buf, cbLen);
+ return mir_base64_encode(buf, cbLen);
}
bool TScramAuth::validateLogin(const wchar_t *challenge)
{
- unsigned chlLen;
+ size_t chlLen;
ptrA chl((char*)mir_base64_decode(_T2A(challenge), &chlLen));
return chl && strncmp((char*)chl + 2, serverSignature, chlLen - 2) == 0;
}
@@ -347,7 +347,7 @@ char* TPlainAuth::getInitialRequest()
else
size = mir_snprintf(toEncode, size, "%c%s%c%s", 0, uname, 0, passw);
- return mir_base64_encode((PBYTE)toEncode, (int)size);
+ return mir_base64_encode(toEncode, size);
}
/////////////////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/JabberG/src/jabber_svc.cpp b/protocols/JabberG/src/jabber_svc.cpp
index b4895f1cc3..8241b8a2ee 100644
--- a/protocols/JabberG/src/jabber_svc.cpp
+++ b/protocols/JabberG/src/jabber_svc.cpp
@@ -30,7 +30,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <sys/types.h>
#include <sys/stat.h>
-#include "m_addcontact.h"
#include "jabber_disco.h"
/////////////////////////////////////////////////////////////////////////////////////////
@@ -456,12 +455,7 @@ INT_PTR __cdecl CJabberProto::JabberServiceParseXmppURI(WPARAM, LPARAM lParam)
psr.flags = PSR_UNICODE;
psr.nick.w = szJid;
psr.id.w = szJid;
-
- ADDCONTACTSTRUCT acs;
- acs.handleType = HANDLE_SEARCHRESULT;
- acs.szProto = m_szModuleName;
- acs.psr = &psr;
- CallService(MS_ADDCONTACT_SHOW, 0, (LPARAM)&acs);
+ Contact_AddBySearch(m_szModuleName, &psr);
}
return 0;
}
diff --git a/protocols/JabberG/src/jabber_vcard.cpp b/protocols/JabberG/src/jabber_vcard.cpp
index 9c3214a985..550d9f5612 100644
--- a/protocols/JabberG/src/jabber_vcard.cpp
+++ b/protocols/JabberG/src/jabber_vcard.cpp
@@ -1130,7 +1130,7 @@ void CJabberProto::SetServerVcard(BOOL bPhotoChanged, wchar_t* szPhotoFileName)
if (buffer != nullptr) {
DWORD nRead;
if (ReadFile(hFile, buffer, st.st_size, &nRead, nullptr)) {
- ptrA str(mir_base64_encode((PBYTE)(LPSTR)buffer, nRead));
+ ptrA str(mir_base64_encode(buffer, nRead));
const wchar_t *szFileType = ProtoGetAvatarMimeType(ProtoGetBufferFormat(buffer));
if (str != nullptr && szFileType != nullptr) {
n = v << XCHILD(L"PHOTO");
diff --git a/protocols/JabberG/src/stdafx.h b/protocols/JabberG/src/stdafx.h
index 6610c2288c..830bb3685f 100644
--- a/protocols/JabberG/src/stdafx.h
+++ b/protocols/JabberG/src/stdafx.h
@@ -88,7 +88,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <m_imgsrvc.h>
#include <m_clc.h>
-#include <m_addcontact.h>
#include <m_folders.h>
#include <m_fingerprint.h>
#include <m_jabber.h>
diff --git a/protocols/JabberG/src/version.h b/protocols/JabberG/src/version.h
index 088b87f37c..b64aefa1b7 100644
--- a/protocols/JabberG/src/version.h
+++ b/protocols/JabberG/src/version.h
@@ -8,6 +8,5 @@
#define __PLUGIN_NAME "Jabber protocol"
#define __DESCRIPTION "Jabber (XMPP) protocol support for Miranda NG."
#define __AUTHOR "George Hazan, Maxim Mluhov, Victor Pavlychko, Artem Shpynov, Michael Stepura"
-#define __AUTHOREMAIL "ghazan@miranda.im"
#define __COPYRIGHT "© 2005-17 George Hazan, Maxim Mluhov, Victor Pavlychko, Artem Shpynov, Michael Stepura"
#define __AUTHORWEB "https://miranda-ng.org/p/Jabber/"
diff --git a/protocols/MRA/src/Mra.cpp b/protocols/MRA/src/Mra.cpp
index d162edeb5e..2e10d02fae 100644
--- a/protocols/MRA/src/Mra.cpp
+++ b/protocols/MRA/src/Mra.cpp
@@ -11,7 +11,6 @@ PLUGININFOEX pluginInfoEx = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/protocols/MRA/src/MraOfflineMsg.cpp b/protocols/MRA/src/MraOfflineMsg.cpp
index a5e786a6ba..1495f6d2a2 100644
--- a/protocols/MRA/src/MraOfflineMsg.cpp
+++ b/protocols/MRA/src/MraOfflineMsg.cpp
@@ -138,7 +138,7 @@ static DWORD PlainText2message(const CMStringA &szContentType, const CMStringA &
// Content-Type: text/plain; charset = CP-1251
if ( strstr(szContentType, "utf-16le")) {
// charset = UTF-16LE// предполагаем что оно в base64
- unsigned dwTextSize;
+ size_t dwTextSize;
ptrA lpszText((LPSTR)mir_base64_decode(szBody, &dwTextSize));
if (lpszText) {
plpsText = CMStringA(lpszText, dwTextSize);
diff --git a/protocols/MRA/src/MraSendCommand.cpp b/protocols/MRA/src/MraSendCommand.cpp
index 32dd012880..54352926ac 100644
--- a/protocols/MRA/src/MraSendCommand.cpp
+++ b/protocols/MRA/src/MraSendCommand.cpp
@@ -89,7 +89,7 @@ DWORD CMraProto::MraMessage(BOOL bAddToQueue, MCONTACT hContact, DWORD dwAckType
buf.SetUL(2);
buf.SetLPSW(L"");//***deb possible nick here
buf.SetLPSW(lpwszMessage);
- lpszMessageConverted = mir_base64_encode(buf.Data(), (int)buf.Len());
+ lpszMessageConverted = mir_base64_encode(buf.Data(), buf.Len());
dwMessageConvertedSize = mir_strlen(lpszMessageConverted);
}
// messages with Flash
@@ -109,7 +109,7 @@ DWORD CMraProto::MraMessage(BOOL bAddToQueue, MCONTACT hContact, DWORD dwAckType
DWORD dwBufSize = DWORD(buf.Len() + 128);
lpszBuf.Truncate(dwBufSize);
if (compress2((LPBYTE)(LPCSTR)lpszBuf, &dwBufSize, buf.Data(), (int)buf.Len(), Z_BEST_COMPRESSION) == Z_OK) {
- lpszMessageRTF = mir_base64_encode((LPBYTE)(LPCSTR)lpszBuf, dwBufSize);
+ lpszMessageRTF = mir_base64_encode(lpszBuf, dwBufSize);
dwMessageRTFSize = mir_strlen(lpszMessageRTF);
}
}
@@ -129,7 +129,7 @@ DWORD CMraProto::MraMessage(BOOL bAddToQueue, MCONTACT hContact, DWORD dwAckType
DWORD dwRTFDataSize = lpbRTFData.GetLength();
if (compress2((LPBYTE)(LPCSTR)lpbRTFData, &dwRTFDataSize, buf.Data(), (int)buf.Len(), Z_BEST_COMPRESSION) == Z_OK) {
- lpszMessageRTF = mir_base64_encode((LPBYTE)(LPCSTR)lpbRTFData, dwRTFDataSize);
+ lpszMessageRTF = mir_base64_encode(lpbRTFData, dwRTFDataSize);
dwMessageRTFSize = mir_strlen(lpszMessageRTF);
}
}
@@ -205,7 +205,7 @@ DWORD CMraProto::MraAddContact(MCONTACT hContact, DWORD dwContactFlag, DWORD dwG
buf2.SetUL(2);
buf2.SetLPSW(L"");//***deb possible nick here
buf2.SetLPSW((wszAuthMessage == NULL) ? L"" : *wszAuthMessage);
- buf.SetLPS(CMStringA(ptrA(mir_base64_encode(buf2.Data(), (int)buf2.Len()))));
+ buf.SetLPS(CMStringA(ptrA(mir_base64_encode(buf2.Data(), buf2.Len()))));
buf.SetUL(0);
diff --git a/protocols/MRA/src/Mra_functions.cpp b/protocols/MRA/src/Mra_functions.cpp
index 9339d5f94c..dd1768c5c3 100644
--- a/protocols/MRA/src/Mra_functions.cpp
+++ b/protocols/MRA/src/Mra_functions.cpp
@@ -1337,7 +1337,7 @@ bool CMraProto::GetPassDB(CMStringA &res)
dwPassSize = (*btCryptedPass);
btCryptedPass[dwPassSize + 1 + MIR_SHA1_HASH_SIZE] = 0;
- unsigned dwDecodedSize;
+ size_t dwDecodedSize;
mir_ptr<BYTE> pDecoded((PBYTE)mir_base64_decode((LPCSTR)&btCryptedPass[1 + MIR_SHA1_HASH_SIZE], &dwDecodedSize));
SHA1GetDigest(pDecoded, dwDecodedSize, btRandomData);
if (0 != memcmp(&btCryptedPass[1], btRandomData, MIR_SHA1_HASH_SIZE))
diff --git a/protocols/MRA/src/Mra_proto.cpp b/protocols/MRA/src/Mra_proto.cpp
index 5f48fdac43..0cf552080d 100644
--- a/protocols/MRA/src/Mra_proto.cpp
+++ b/protocols/MRA/src/Mra_proto.cpp
@@ -1570,7 +1570,7 @@ DWORD CMraProto::MraRecvCommand_Message(DWORD dwTime, DWORD dwFlags, CMStringA &
// pre processing - extracting/decoding
if (dwFlags & MESSAGE_FLAG_AUTHORIZE) { // extract auth message из обычного текÑта
- unsigned dwAuthDataSize;
+ size_t dwAuthDataSize;
LPBYTE lpbAuthData = (LPBYTE)mir_base64_decode(plpsText, &dwAuthDataSize);
if (lpbAuthData) {
BinBuffer buf(lpbAuthData, dwAuthDataSize);
@@ -1607,7 +1607,7 @@ DWORD CMraProto::MraRecvCommand_Message(DWORD dwTime, DWORD dwFlags, CMStringA &
mir_ptr<BYTE> lpbRTFData((LPBYTE)mir_calloc(dwRFTBuffSize));
if (lpbRTFData) {
- unsigned dwCompressedSize;
+ size_t dwCompressedSize;
mir_ptr<BYTE> lpbCompressed((LPBYTE)mir_base64_decode(plpsRFTText, &dwCompressedSize));
DWORD dwRTFDataSize = (DWORD)dwRFTBuffSize;
if (uncompress(lpbRTFData, &dwRTFDataSize, lpbCompressed, dwCompressedSize) == Z_OK) {
diff --git a/protocols/MRA/src/version.h b/protocols/MRA/src/version.h
index 6efeb18fb4..f4b3ea91c7 100644
--- a/protocols/MRA/src/version.h
+++ b/protocols/MRA/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "MRA.dll"
#define __DESCRIPTION "Miranda Mail.ru Agent protocol plugin."
#define __AUTHOR "Rozhuk Ivan"
-#define __AUTHOREMAIL "Rozhuk_I@mail.ru"
#define __AUTHORWEB "https://miranda-ng.org/p/MRA/"
#define __COPYRIGHT "© 2005-17 Rozhuk Ivan"
diff --git a/protocols/MSN/src/msn.cpp b/protocols/MSN/src/msn.cpp
index 5ff0f96647..00a3434bb0 100644
--- a/protocols/MSN/src/msn.cpp
+++ b/protocols/MSN/src/msn.cpp
@@ -47,7 +47,6 @@ static const PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/protocols/MSN/src/msn_auth.cpp b/protocols/MSN/src/msn_auth.cpp
index df0e2542fe..228792b274 100644
--- a/protocols/MSN/src/msn_auth.cpp
+++ b/protocols/MSN/src/msn_auth.cpp
@@ -543,7 +543,7 @@ CMStringA CMsnProto::HotmailLogin(const char* url)
unsigned char nonce[24];
Utils_GetRandom(nonce, sizeof(nonce));
- unsigned key1len;
+ size_t key1len;
mir_ptr<BYTE> key1((BYTE*)mir_base64_decode(hotSecretToken, &key1len));
static const unsigned char encdata[] = "WS-SecureConversation";
diff --git a/protocols/MSN/src/msn_links.cpp b/protocols/MSN/src/msn_links.cpp
index e6bf5641b8..3be384196a 100644
--- a/protocols/MSN/src/msn_links.cpp
+++ b/protocols/MSN/src/msn_links.cpp
@@ -21,8 +21,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdafx.h"
#include "msn_proto.h"
-#include <m_addcontact.h>
-
#include "m_assocmgr.h"
static MCONTACT GetContact(wchar_t *arg, wchar_t **pemail, CMsnProto *proto)
@@ -96,12 +94,7 @@ static INT_PTR ServiceParseMsnimLink(WPARAM, LPARAM lParam)
psr.flags = PSR_UNICODE;
psr.nick.w = email;
psr.email.w = email;
-
- ADDCONTACTSTRUCT acs = { 0 };
- acs.handleType = HANDLE_SEARCHRESULT;
- acs.szProto = proto->m_szModuleName;
- acs.psr = &psr;
- CallService(MS_ADDCONTACT_SHOW, 0, (LPARAM)&acs);
+ Contact_AddBySearch(proto->m_szModuleName, &psr);
}
return 0;
}
diff --git a/protocols/MSN/src/msn_misc.cpp b/protocols/MSN/src/msn_misc.cpp
index 5bf2bb2aa3..9a7f7157bf 100644
--- a/protocols/MSN/src/msn_misc.cpp
+++ b/protocols/MSN/src/msn_misc.cpp
@@ -119,7 +119,7 @@ char* MSN_GetAvatarHash(char* szContext, char** pszUrl)
ezxml_t xmli = ezxml_parse_str(NEWSTR_ALLOCA(szContext), mir_strlen(szContext));
const char *szAvatarHash = ezxml_attr(xmli, "SHA1D");
if (szAvatarHash != nullptr) {
- unsigned hashLen;
+ size_t hashLen;
mir_ptr<BYTE> hash((BYTE*)mir_base64_decode(szAvatarHash, &hashLen));
if (hash)
res = arrayToHex(hash, hashLen);
@@ -217,7 +217,7 @@ int CMsnProto::MSN_SetMyAvatar(const wchar_t* sztFname, void* pData, size_t cbLe
mir_sha1_append(&sha1ctx, (BYTE*)pData, (int)cbLen);
mir_sha1_finish(&sha1ctx, sha1d);
- ptrA szSha1d(mir_base64_encode((PBYTE)sha1d, sizeof(sha1d)));
+ ptrA szSha1d(mir_base64_encode(sha1d, sizeof(sha1d)));
mir_sha1_init(&sha1ctx);
ezxml_t xmlp = ezxml_new("msnobj");
@@ -250,7 +250,7 @@ int CMsnProto::MSN_SetMyAvatar(const wchar_t* sztFname, void* pData, size_t cbLe
mir_sha1_finish(&sha1ctx, sha1c);
- ptrA szSha1c(mir_base64_encode((PBYTE)sha1c, sizeof(sha1c)));
+ ptrA szSha1c(mir_base64_encode(sha1c, sizeof(sha1c)));
// ezxml_set_attr(xmlp, "SHA1C", szSha1c);
diff --git a/protocols/MSN/src/msn_soapab.cpp b/protocols/MSN/src/msn_soapab.cpp
index 2f82ab7a1c..ee13208804 100644
--- a/protocols/MSN/src/msn_soapab.cpp
+++ b/protocols/MSN/src/msn_soapab.cpp
@@ -812,7 +812,7 @@ bool CMsnProto::MSN_ABFind(const char* szMethod, const char* szGuid, bool deltas
}
if (!msnLoggedIn && msnNsThread) {
char *szCircleTicket = ezxml_txt(ezxml_get(body, "CircleResult", 0, "CircleTicket", -1));
- ptrA szCircleTicketEnc(mir_base64_encode((PBYTE)szCircleTicket, (unsigned)mir_strlen(szCircleTicket)));
+ ptrA szCircleTicketEnc(mir_base64_encode(szCircleTicket, mir_strlen(szCircleTicket)));
if (szCircleTicketEnc)
msnNsThread->sendPacket("USR", "SHA A %s", szCircleTicketEnc);
}
@@ -858,7 +858,7 @@ bool CMsnProto::MSN_ABRefreshClist(unsigned int nTry)
nlhr.headers[0].szValue = (char*)MSN_USER_AGENT;
nlhr.headers[1].szName = "Cookie";
nlhr.headers[1].szValue = authCookies;
- nlhr.szUrl = "https://people.directory.live.com/people/abcore?SerializeAs=xml&market=en-gb&appid=3C48F07D-DE71-490C-B263-A78CFB1CA351&version=W5.M2";
+ nlhr.szUrl = "https://people.directory.live.com/people/abcore?SerializeAs=xml&market=en-gb&appid=369bdc41-b51e-46e0-a40e-d4b2b5e09a7c&version=W5.M2";
// Query addressbook
mHttpsTS = clock();
diff --git a/protocols/MSN/src/msn_srv.cpp b/protocols/MSN/src/msn_srv.cpp
index 35401b533a..35e35259e8 100644
--- a/protocols/MSN/src/msn_srv.cpp
+++ b/protocols/MSN/src/msn_srv.cpp
@@ -296,7 +296,7 @@ void CMsnProto::msn_storeAvatarThread(void* arg)
ptrA szEncBuf;
if (dat)
- szEncBuf = mir_base64_encode(dat->data, (unsigned)dat->dataSize);
+ szEncBuf = mir_base64_encode(dat->data, dat->dataSize);
if (photoid[0] && dat)
MSN_StoreUpdateDocument(dat->szName, dat->szMimeType, szEncBuf);
diff --git a/protocols/MSN/src/version.h b/protocols/MSN/src/version.h
index c09ba146f9..06c8468cd3 100644
--- a/protocols/MSN/src/version.h
+++ b/protocols/MSN/src/version.h
@@ -28,6 +28,5 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define __PLUGIN_NAME "MSN protocol"
#define __DESCRIPTION "Microsoft Network (MSN) protocol support for Miranda NG."
#define __AUTHOR "Boris Krasnovskiy, George Hazan, Richard Hughes, leecher"
-#define __AUTHOREMAIL "borkra@miranda-im.org"
#define __COPYRIGHT "© 2001-17 Richard Hughes, George Hazan, Boris Krasnovskiy, leecher"
#define __AUTHORWEB "https://miranda-ng.org/p/MSN/"
diff --git a/protocols/MinecraftDynmap/src/main.cpp b/protocols/MinecraftDynmap/src/main.cpp
index 8052741d6f..877ae13baa 100644
--- a/protocols/MinecraftDynmap/src/main.cpp
+++ b/protocols/MinecraftDynmap/src/main.cpp
@@ -35,7 +35,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/protocols/MinecraftDynmap/src/version.h b/protocols/MinecraftDynmap/src/version.h
index 91e46601e4..a35871c9ae 100644
--- a/protocols/MinecraftDynmap/src/version.h
+++ b/protocols/MinecraftDynmap/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "MinecraftDynmap.dll"
#define __DESCRIPTION "Minecraft Dynmap support for Miranda NG."
#define __AUTHOR "Robert Pösel"
-#define __AUTHOREMAIL "robyer@seznam.cz"
#define __AUTHORWEB "https://miranda-ng.org/p/MinecraftDynmap/"
#define __COPYRIGHT "© 2015-17 Robert Pösel"
diff --git a/protocols/Omegle/src/main.cpp b/protocols/Omegle/src/main.cpp
index d4fa415f4f..542a14d774 100644
--- a/protocols/Omegle/src/main.cpp
+++ b/protocols/Omegle/src/main.cpp
@@ -37,7 +37,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/protocols/Omegle/src/version.h b/protocols/Omegle/src/version.h
index e5ffe14f16..40ec242129 100644
--- a/protocols/Omegle/src/version.h
+++ b/protocols/Omegle/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Omegle.dll"
#define __DESCRIPTION "Omegle protocol support for Miranda NG."
#define __AUTHOR "Robert Pösel"
-#define __AUTHOREMAIL "robyer@seznam.cz"
#define __AUTHORWEB "https://miranda-ng.org/p/Omegle/"
#define __COPYRIGHT "© 2011-17 Robert Pösel"
diff --git a/protocols/Sametime/src/StdAfx.h b/protocols/Sametime/src/StdAfx.h
index 3eae2826f9..5fa7d2b4d3 100644
--- a/protocols/Sametime/src/StdAfx.h
+++ b/protocols/Sametime/src/StdAfx.h
@@ -69,7 +69,7 @@ extern "C" {
#include <m_clc.h>
#include <m_utils.h>
#include <m_idle.h>
-#include <m_addcontact.h>
+#include <m_contacts.h>
#include <m_popup.h>
#include <m_chat.h>
#include <m_genmenu.h>
diff --git a/protocols/Sametime/src/sametime.cpp b/protocols/Sametime/src/sametime.cpp
index 0987008bec..978a5d6fce 100644
--- a/protocols/Sametime/src/sametime.cpp
+++ b/protocols/Sametime/src/sametime.cpp
@@ -10,7 +10,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/protocols/Sametime/src/version.h b/protocols/Sametime/src/version.h
index fc60a0cfff..aac68342d9 100644
--- a/protocols/Sametime/src/version.h
+++ b/protocols/Sametime/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Sametime.dll"
#define __DESCRIPTION "Implementation of instant messaging for the Lotus Sametime protocol."
#define __AUTHOR "Scott Ellis, Szymon Tokarz"
-#define __AUTHOREMAIL "mail"/*antispam*/"@"/*antispam*/"scottellis.com.au, wsx22"/*antispam*/"@"/*antispam*/"o2.pl"
#define __COPYRIGHT "© 2005 Scott Ellis, 2014-2017 wsx22"
#define __AUTHORWEB "https://miranda-ng.org/p/Sametime/"
diff --git a/protocols/SkypeWeb/src/main.cpp b/protocols/SkypeWeb/src/main.cpp
index 37b2ba5a97..ebc7de2a55 100644
--- a/protocols/SkypeWeb/src/main.cpp
+++ b/protocols/SkypeWeb/src/main.cpp
@@ -32,7 +32,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/protocols/SkypeWeb/src/skype_utils.cpp b/protocols/SkypeWeb/src/skype_utils.cpp
index 6c9e1fe6cc..3317a79973 100644
--- a/protocols/SkypeWeb/src/skype_utils.cpp
+++ b/protocols/SkypeWeb/src/skype_utils.cpp
@@ -573,13 +573,7 @@ INT_PTR CSkypeProto::ParseSkypeUriService(WPARAM, LPARAM lParam)
psr.id.w = mir_wstrdup(szJid);
psr.nick.w = mir_wstrdup(szJid);
psr.flags = PSR_UNICODE;
-
- ADDCONTACTSTRUCT acs = { 0 };
- acs.handleType = HANDLE_SEARCHRESULT;
- acs.szProto = m_szModuleName;
- acs.psr = &psr;
-
- CallService(MS_ADDCONTACT_SHOW, 0, (LPARAM)&acs);
+ Contact_AddBySearch(m_szModuleName, &psr);
}
return 0;
}
diff --git a/protocols/SkypeWeb/src/stdafx.h b/protocols/SkypeWeb/src/stdafx.h
index eccbf4789c..dc054583da 100644
--- a/protocols/SkypeWeb/src/stdafx.h
+++ b/protocols/SkypeWeb/src/stdafx.h
@@ -40,7 +40,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <m_popup.h>
#include <m_icolib.h>
#include <m_userinfo.h>
-#include <m_addcontact.h>
+#include <m_contacts.h>
#include <m_message.h>
#include <m_avatars.h>
#include <m_skin.h>
diff --git a/protocols/SkypeWeb/src/version.h b/protocols/SkypeWeb/src/version.h
index aad66dc7d6..c4a396d0f3 100644
--- a/protocols/SkypeWeb/src/version.h
+++ b/protocols/SkypeWeb/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "SkypeWeb.dll"
#define __DESCRIPTION "Skype protocol support for Miranda NG. Based on new Skype for Web."
#define __AUTHOR "Miranda NG Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/SkypeWeb/"
#define __COPYRIGHT "© 2015-17 Miranda NG Team"
diff --git a/protocols/Steam/src/main.cpp b/protocols/Steam/src/main.cpp
index 4010b9e46f..0f14e6ec0e 100644
--- a/protocols/Steam/src/main.cpp
+++ b/protocols/Steam/src/main.cpp
@@ -12,7 +12,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/protocols/Steam/src/steam_events.cpp b/protocols/Steam/src/steam_events.cpp
index 3697689ca4..ef2d59ed40 100644
--- a/protocols/Steam/src/steam_events.cpp
+++ b/protocols/Steam/src/steam_events.cpp
@@ -65,8 +65,8 @@ int CSteamProto::OnIdleChanged(WPARAM, LPARAM lParam)
if (idle)
{
// User started being idle
- MIRANDA_IDLE_INFO mii = { sizeof(mii) };
- CallService(MS_IDLE_GETIDLEINFO, 0, (LPARAM)&mii);
+ MIRANDA_IDLE_INFO mii;
+ Idle_GetInfo(mii);
// Compute time when user really became idle
m_idleTS = time(nullptr) - mii.idleTime * 60;
diff --git a/protocols/Steam/src/version.h b/protocols/Steam/src/version.h
index 52650230ab..3c8a5e4a9b 100644
--- a/protocols/Steam/src/version.h
+++ b/protocols/Steam/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Steam.dll"
#define __DESCRIPTION "Steam protocol support for Miranda NG."
#define __AUTHOR "Miranda NG Team, Robert Pösel"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/Steam/"
#define __COPYRIGHT "© 2014-17 Miranda NG team"
diff --git a/protocols/Tox/Tox.vcxproj b/protocols/Tox/Tox.vcxproj
index 622d96816b..bc607b076a 100644
--- a/protocols/Tox/Tox.vcxproj
+++ b/protocols/Tox/Tox.vcxproj
@@ -27,20 +27,13 @@
</ImportGroup>
<ItemDefinitionGroup>
<ClCompile>
- <AdditionalIncludeDirectories>include;..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>..\..\include;libtox\src\toxcore;libtox\src\toxdns;libtox\src\toxencryptsave;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>Winmm.lib;dnsapi.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
- <PostBuildEvent Condition="'$(Platform)'=='Win32'">
- <Command>call copydll.cmd x86 "$(OutputPath)..\Libs"</Command>
- </PostBuildEvent>
- <PostBuildEvent Condition="'$(Platform)'=='x64'">
- <Command>call copydll.cmd x64 "$(OutputPath)..\Libs"</Command>
- </PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
- <None Include="include\*.h" />
<None Include="res\Icons\*.ico" />
</ItemGroup>
<ItemDefinitionGroup>
@@ -52,5 +45,8 @@
<ProjectReference Include="..\..\libs\libjson\libjson.vcxproj">
<Project>{f6a9340e-b8d9-4c75-be30-47dc66d0abc7}</Project>
</ProjectReference>
+ <ProjectReference Include="libtox\libtox.vcxproj">
+ <Project>{a21c50cd-28a6-481a-a12b-47189fe66641}</Project>
+ </ProjectReference>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/protocols/Tox/bin/x64/libtox.dll b/protocols/Tox/bin/x64/libtox.dll
deleted file mode 100644
index 17fde89b19..0000000000
--- a/protocols/Tox/bin/x64/libtox.dll
+++ /dev/null
Binary files differ
diff --git a/protocols/Tox/bin/x86/libtox.dll b/protocols/Tox/bin/x86/libtox.dll
deleted file mode 100644
index 7e392e4665..0000000000
--- a/protocols/Tox/bin/x86/libtox.dll
+++ /dev/null
Binary files differ
diff --git a/protocols/Tox/copydll.cmd b/protocols/Tox/copydll.cmd
deleted file mode 100644
index dffde39b53..0000000000
--- a/protocols/Tox/copydll.cmd
+++ /dev/null
@@ -1,7 +0,0 @@
-@echo off
-set p1=%1
-set p2=%2
-set p3="%~2\libtox.dll"
-copy /y bin\%p1%\libtox.dll %p2%
-tools\cv2pdb.exe %p3%
-exit 0
diff --git a/protocols/Tox/include/toxav.h b/protocols/Tox/include/toxav.h
deleted file mode 100644
index 2a8b90fa5e..0000000000
--- a/protocols/Tox/include/toxav.h
+++ /dev/null
@@ -1,763 +0,0 @@
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013-2015 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef TOXAV_H
-#define TOXAV_H
-
-#include <msapi/stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** \page av Public audio/video API for Tox clients.
- *
- * This API can handle multiple calls. Each call has its state, in very rare
- * occasions the library can change the state of the call without apps knowledge.
- *
- */
-/** \subsection events Events and callbacks
- *
- * As in Core API, events are handled by callbacks. One callback can be
- * registered per event. All events have a callback function type named
- * `toxav_{event}_cb` and a function to register it named `toxav_callback_{event}`.
- * Passing a NULL callback will result in no callback being registered for that
- * event. Only one callback per event can be registered, so if a client needs
- * multiple event listeners, it needs to implement the dispatch functionality
- * itself. Unlike Core API, lack of some event handlers will cause the the
- * library to drop calls before they are started. Hanging up call from a
- * callback causes undefined behaviour.
- *
- */
-/** \subsection threading Threading implications
- *
- * Unlike the Core API, this API is fully thread-safe. The library will ensure
- * the proper synchronization of parallel calls.
- *
- * A common way to run ToxAV (multiple or single instance) is to have a thread,
- * separate from tox instance thread, running a simple toxav_iterate loop,
- * sleeping for toxav_iteration_interval * milliseconds on each iteration.
- *
- * An important thing to note is that events are triggered from both tox and
- * toxav thread (see above). Audio and video receive frame events are triggered
- * from toxav thread while all the other events are triggered from tox thread.
- *
- * Tox thread has priority with mutex mechanisms. Any api function can
- * fail if mutexes are held by tox thread in which case they will set SYNC
- * error code.
- */
-/**
- * External Tox type.
- */
-#ifndef TOX_DEFINED
-#define TOX_DEFINED
-typedef struct Tox Tox;
-#endif /* TOX_DEFINED */
-
-/**
- * ToxAV.
- */
-/**
- * The ToxAV instance type. Each ToxAV instance can be bound to only one Tox
- * instance, and Tox instance can have only one ToxAV instance. One must make
- * sure to close ToxAV instance prior closing Tox instance otherwise undefined
- * behaviour occurs. Upon closing of ToxAV instance, all active calls will be
- * forcibly terminated without notifying peers.
- *
- */
-#ifndef TOXAV_DEFINED
-#define TOXAV_DEFINED
-typedef struct ToxAV ToxAV;
-#endif /* TOXAV_DEFINED */
-
-
-/*******************************************************************************
- *
- * :: Creation and destruction
- *
- ******************************************************************************/
-
-
-
-typedef enum TOXAV_ERR_NEW {
-
- /**
- * The function returned successfully.
- */
- TOXAV_ERR_NEW_OK,
-
- /**
- * One of the arguments to the function was NULL when it was not expected.
- */
- TOXAV_ERR_NEW_NULL,
-
- /**
- * Memory allocation failure while trying to allocate structures required for
- * the A/V session.
- */
- TOXAV_ERR_NEW_MALLOC,
-
- /**
- * Attempted to create a second session for the same Tox instance.
- */
- TOXAV_ERR_NEW_MULTIPLE,
-
-} TOXAV_ERR_NEW;
-
-
-/**
- * Start new A/V session. There can only be only one session per Tox instance.
- */
-ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error);
-
-/**
- * Releases all resources associated with the A/V session.
- *
- * If any calls were ongoing, these will be forcibly terminated without
- * notifying peers. After calling this function, no other functions may be
- * called and the av pointer becomes invalid.
- */
-void toxav_kill(ToxAV *av);
-
-/**
- * Returns the Tox instance the A/V object was created for.
- */
-Tox *toxav_get_tox(const ToxAV *av);
-
-
-/*******************************************************************************
- *
- * :: A/V event loop
- *
- ******************************************************************************/
-
-
-
-/**
- * Returns the interval in milliseconds when the next toxav_iterate call should
- * be. If no call is active at the moment, this function returns 200.
- */
-uint32_t toxav_iteration_interval(const ToxAV *av);
-
-/**
- * Main loop for the session. This function needs to be called in intervals of
- * toxav_iteration_interval() milliseconds. It is best called in the separate
- * thread from tox_iterate.
- */
-void toxav_iterate(ToxAV *av);
-
-
-/*******************************************************************************
- *
- * :: Call setup
- *
- ******************************************************************************/
-
-
-
-typedef enum TOXAV_ERR_CALL {
-
- /**
- * The function returned successfully.
- */
- TOXAV_ERR_CALL_OK,
-
- /**
- * A resource allocation error occurred while trying to create the structures
- * required for the call.
- */
- TOXAV_ERR_CALL_MALLOC,
-
- /**
- * Synchronization error occurred.
- */
- TOXAV_ERR_CALL_SYNC,
-
- /**
- * The friend number did not designate a valid friend.
- */
- TOXAV_ERR_CALL_FRIEND_NOT_FOUND,
-
- /**
- * The friend was valid, but not currently connected.
- */
- TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED,
-
- /**
- * Attempted to call a friend while already in an audio or video call with
- * them.
- */
- TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL,
-
- /**
- * Audio or video bit rate is invalid.
- */
- TOXAV_ERR_CALL_INVALID_BIT_RATE,
-
-} TOXAV_ERR_CALL;
-
-
-/**
- * Call a friend. This will start ringing the friend.
- *
- * It is the client's responsibility to stop ringing after a certain timeout,
- * if such behaviour is desired. If the client does not stop ringing, the
- * library will not stop until the friend is disconnected. Audio and video
- * receiving are both enabled by default.
- *
- * @param friend_number The friend number of the friend that should be called.
- * @param audio_bit_rate Audio bit rate in Kb/sec. Set this to 0 to disable
- * audio sending.
- * @param video_bit_rate Video bit rate in Kb/sec. Set this to 0 to disable
- * video sending.
- */
-bool toxav_call(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate,
- TOXAV_ERR_CALL *error);
-
-/**
- * The function type for the call callback.
- *
- * @param friend_number The friend number from which the call is incoming.
- * @param audio_enabled True if friend is sending audio.
- * @param video_enabled True if friend is sending video.
- */
-typedef void toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data);
-
-
-/**
- * Set the callback for the `call` event. Pass NULL to unset.
- *
- */
-void toxav_callback_call(ToxAV *av, toxav_call_cb *callback, void *user_data);
-
-typedef enum TOXAV_ERR_ANSWER {
-
- /**
- * The function returned successfully.
- */
- TOXAV_ERR_ANSWER_OK,
-
- /**
- * Synchronization error occurred.
- */
- TOXAV_ERR_ANSWER_SYNC,
-
- /**
- * Failed to initialize codecs for call session. Note that codec initiation
- * will fail if there is no receive callback registered for either audio or
- * video.
- */
- TOXAV_ERR_ANSWER_CODEC_INITIALIZATION,
-
- /**
- * The friend number did not designate a valid friend.
- */
- TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND,
-
- /**
- * The friend was valid, but they are not currently trying to initiate a call.
- * This is also returned if this client is already in a call with the friend.
- */
- TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING,
-
- /**
- * Audio or video bit rate is invalid.
- */
- TOXAV_ERR_ANSWER_INVALID_BIT_RATE,
-
-} TOXAV_ERR_ANSWER;
-
-
-/**
- * Accept an incoming call.
- *
- * If answering fails for any reason, the call will still be pending and it is
- * possible to try and answer it later. Audio and video receiving are both
- * enabled by default.
- *
- * @param friend_number The friend number of the friend that is calling.
- * @param audio_bit_rate Audio bit rate in Kb/sec. Set this to 0 to disable
- * audio sending.
- * @param video_bit_rate Video bit rate in Kb/sec. Set this to 0 to disable
- * video sending.
- */
-bool toxav_answer(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate,
- TOXAV_ERR_ANSWER *error);
-
-
-/*******************************************************************************
- *
- * :: Call state graph
- *
- ******************************************************************************/
-
-
-
-enum TOXAV_FRIEND_CALL_STATE {
-
- /**
- * The empty bit mask. None of the bits specified below are set.
- */
- TOXAV_FRIEND_CALL_STATE_NONE = 0,
-
- /**
- * Set by the AV core if an error occurred on the remote end or if friend
- * timed out. This is the final state after which no more state
- * transitions can occur for the call. This call state will never be triggered
- * in combination with other call states.
- */
- TOXAV_FRIEND_CALL_STATE_ERROR = 1,
-
- /**
- * The call has finished. This is the final state after which no more state
- * transitions can occur for the call. This call state will never be
- * triggered in combination with other call states.
- */
- TOXAV_FRIEND_CALL_STATE_FINISHED = 2,
-
- /**
- * The flag that marks that friend is sending audio.
- */
- TOXAV_FRIEND_CALL_STATE_SENDING_A = 4,
-
- /**
- * The flag that marks that friend is sending video.
- */
- TOXAV_FRIEND_CALL_STATE_SENDING_V = 8,
-
- /**
- * The flag that marks that friend is receiving audio.
- */
- TOXAV_FRIEND_CALL_STATE_ACCEPTING_A = 16,
-
- /**
- * The flag that marks that friend is receiving video.
- */
- TOXAV_FRIEND_CALL_STATE_ACCEPTING_V = 32,
-
-};
-
-
-/**
- * The function type for the call_state callback.
- *
- * @param friend_number The friend number for which the call state changed.
- * @param state The bitmask of the new call state which is guaranteed to be
- * different than the previous state. The state is set to 0 when the call is
- * paused. The bitmask represents all the activities currently performed by the
- * friend.
- */
-typedef void toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data);
-
-
-/**
- * Set the callback for the `call_state` event. Pass NULL to unset.
- *
- */
-void toxav_callback_call_state(ToxAV *av, toxav_call_state_cb *callback, void *user_data);
-
-
-/*******************************************************************************
- *
- * :: Call control
- *
- ******************************************************************************/
-
-
-
-typedef enum TOXAV_CALL_CONTROL {
-
- /**
- * Resume a previously paused call. Only valid if the pause was caused by this
- * client, if not, this control is ignored. Not valid before the call is accepted.
- */
- TOXAV_CALL_CONTROL_RESUME,
-
- /**
- * Put a call on hold. Not valid before the call is accepted.
- */
- TOXAV_CALL_CONTROL_PAUSE,
-
- /**
- * Reject a call if it was not answered, yet. Cancel a call after it was
- * answered.
- */
- TOXAV_CALL_CONTROL_CANCEL,
-
- /**
- * Request that the friend stops sending audio. Regardless of the friend's
- * compliance, this will cause the audio_receive_frame event to stop being
- * triggered on receiving an audio frame from the friend.
- */
- TOXAV_CALL_CONTROL_MUTE_AUDIO,
-
- /**
- * Calling this control will notify client to start sending audio again.
- */
- TOXAV_CALL_CONTROL_UNMUTE_AUDIO,
-
- /**
- * Request that the friend stops sending video. Regardless of the friend's
- * compliance, this will cause the video_receive_frame event to stop being
- * triggered on receiving a video frame from the friend.
- */
- TOXAV_CALL_CONTROL_HIDE_VIDEO,
-
- /**
- * Calling this control will notify client to start sending video again.
- */
- TOXAV_CALL_CONTROL_SHOW_VIDEO,
-
-} TOXAV_CALL_CONTROL;
-
-
-typedef enum TOXAV_ERR_CALL_CONTROL {
-
- /**
- * The function returned successfully.
- */
- TOXAV_ERR_CALL_CONTROL_OK,
-
- /**
- * Synchronization error occurred.
- */
- TOXAV_ERR_CALL_CONTROL_SYNC,
-
- /**
- * The friend_number passed did not designate a valid friend.
- */
- TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_FOUND,
-
- /**
- * This client is currently not in a call with the friend. Before the call is
- * answered, only CANCEL is a valid control.
- */
- TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL,
-
- /**
- * Happens if user tried to pause an already paused call or if trying to
- * resume a call that is not paused.
- */
- TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION,
-
-} TOXAV_ERR_CALL_CONTROL;
-
-
-/**
- * Sends a call control command to a friend.
- *
- * @param friend_number The friend number of the friend this client is in a call
- * with.
- * @param control The control command to send.
- *
- * @return true on success.
- */
-bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error);
-
-
-/*******************************************************************************
- *
- * :: Controlling bit rates
- *
- ******************************************************************************/
-
-
-
-typedef enum TOXAV_ERR_BIT_RATE_SET {
-
- /**
- * The function returned successfully.
- */
- TOXAV_ERR_BIT_RATE_SET_OK,
-
- /**
- * Synchronization error occurred.
- */
- TOXAV_ERR_BIT_RATE_SET_SYNC,
-
- /**
- * The audio bit rate passed was not one of the supported values.
- */
- TOXAV_ERR_BIT_RATE_SET_INVALID_AUDIO_BIT_RATE,
-
- /**
- * The video bit rate passed was not one of the supported values.
- */
- TOXAV_ERR_BIT_RATE_SET_INVALID_VIDEO_BIT_RATE,
-
- /**
- * The friend_number passed did not designate a valid friend.
- */
- TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_FOUND,
-
- /**
- * This client is currently not in a call with the friend.
- */
- TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_IN_CALL,
-
-} TOXAV_ERR_BIT_RATE_SET;
-
-
-/**
- * Set the bit rate to be used in subsequent audio/video frames.
- *
- * @param friend_number The friend number of the friend for which to set the
- * bit rate.
- * @param audio_bit_rate The new audio bit rate in Kb/sec. Set to 0 to disable
- * audio sending. Set to -1 to leave unchanged.
- * @param video_bit_rate The new video bit rate in Kb/sec. Set to 0 to disable
- * video sending. Set to -1 to leave unchanged.
- *
- */
-bool toxav_bit_rate_set(ToxAV *av, uint32_t friend_number, int32_t audio_bit_rate, int32_t video_bit_rate,
- TOXAV_ERR_BIT_RATE_SET *error);
-
-/**
- * The function type for the bit_rate_status callback. The event is triggered
- * when the network becomes too saturated for current bit rates at which
- * point core suggests new bit rates.
- *
- * @param friend_number The friend number of the friend for which to set the
- * bit rate.
- * @param audio_bit_rate Suggested maximum audio bit rate in Kb/sec.
- * @param video_bit_rate Suggested maximum video bit rate in Kb/sec.
- */
-typedef void toxav_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate,
- uint32_t video_bit_rate, void *user_data);
-
-
-/**
- * Set the callback for the `bit_rate_status` event. Pass NULL to unset.
- *
- */
-void toxav_callback_bit_rate_status(ToxAV *av, toxav_bit_rate_status_cb *callback, void *user_data);
-
-
-/*******************************************************************************
- *
- * :: A/V sending
- *
- ******************************************************************************/
-
-
-
-typedef enum TOXAV_ERR_SEND_FRAME {
-
- /**
- * The function returned successfully.
- */
- TOXAV_ERR_SEND_FRAME_OK,
-
- /**
- * In case of video, one of Y, U, or V was NULL. In case of audio, the samples
- * data pointer was NULL.
- */
- TOXAV_ERR_SEND_FRAME_NULL,
-
- /**
- * The friend_number passed did not designate a valid friend.
- */
- TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND,
-
- /**
- * This client is currently not in a call with the friend.
- */
- TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL,
-
- /**
- * Synchronization error occurred.
- */
- TOXAV_ERR_SEND_FRAME_SYNC,
-
- /**
- * One of the frame parameters was invalid. E.g. the resolution may be too
- * small or too large, or the audio sampling rate may be unsupported.
- */
- TOXAV_ERR_SEND_FRAME_INVALID,
-
- /**
- * Either friend turned off audio or video receiving or we turned off sending
- * for the said payload.
- */
- TOXAV_ERR_SEND_FRAME_PAYLOAD_TYPE_DISABLED,
-
- /**
- * Failed to push frame through rtp interface.
- */
- TOXAV_ERR_SEND_FRAME_RTP_FAILED,
-
-} TOXAV_ERR_SEND_FRAME;
-
-
-/**
- * Send an audio frame to a friend.
- *
- * The expected format of the PCM data is: [s1c1][s1c2][...][s2c1][s2c2][...]...
- * Meaning: sample 1 for channel 1, sample 1 for channel 2, ...
- * For mono audio, this has no meaning, every sample is subsequent. For stereo,
- * this means the expected format is LRLRLR... with samples for left and right
- * alternating.
- *
- * @param friend_number The friend number of the friend to which to send an
- * audio frame.
- * @param pcm An array of audio samples. The size of this array must be
- * sample_count * channels.
- * @param sample_count Number of samples in this frame. Valid numbers here are
- * ((sample rate) * (audio length) / 1000), where audio length can be
- * 2.5, 5, 10, 20, 40 or 60 millseconds.
- * @param channels Number of audio channels. Supported values are 1 and 2.
- * @param sampling_rate Audio sampling rate used in this frame. Valid sampling
- * rates are 8000, 12000, 16000, 24000, or 48000.
- */
-bool toxav_audio_send_frame(ToxAV *av, uint32_t friend_number, const int16_t *pcm, size_t sample_count,
- uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME *error);
-
-/**
- * Send a video frame to a friend.
- *
- * Y - plane should be of size: height * width
- * U - plane should be of size: (height/2) * (width/2)
- * V - plane should be of size: (height/2) * (width/2)
- *
- * @param friend_number The friend number of the friend to which to send a video
- * frame.
- * @param width Width of the frame in pixels.
- * @param height Height of the frame in pixels.
- * @param y Y (Luminance) plane data.
- * @param u U (Chroma) plane data.
- * @param v V (Chroma) plane data.
- */
-bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t *y,
- const uint8_t *u, const uint8_t *v, TOXAV_ERR_SEND_FRAME *error);
-
-
-/*******************************************************************************
- *
- * :: A/V receiving
- *
- ******************************************************************************/
-
-
-
-/**
- * The function type for the audio_receive_frame callback. The callback can be
- * called multiple times per single iteration depending on the amount of queued
- * frames in the buffer. The received format is the same as in send function.
- *
- * @param friend_number The friend number of the friend who sent an audio frame.
- * @param pcm An array of audio samples (sample_count * channels elements).
- * @param sample_count The number of audio samples per channel in the PCM array.
- * @param channels Number of audio channels.
- * @param sampling_rate Sampling rate used in this frame.
- *
- */
-typedef void toxav_audio_receive_frame_cb(ToxAV *av, uint32_t friend_number, const int16_t *pcm, size_t sample_count,
- uint8_t channels, uint32_t sampling_rate, void *user_data);
-
-
-/**
- * Set the callback for the `audio_receive_frame` event. Pass NULL to unset.
- *
- */
-void toxav_callback_audio_receive_frame(ToxAV *av, toxav_audio_receive_frame_cb *callback, void *user_data);
-
-/**
- * The function type for the video_receive_frame callback.
- *
- * The size of plane data is derived from width and height as documented
- * below.
- *
- * Strides represent padding for each plane that may or may not be present.
- * You must handle strides in your image processing code. Strides are
- * negative if the image is bottom-up hence why you MUST abs() it when
- * calculating plane buffer size.
- *
- * @param friend_number The friend number of the friend who sent a video frame.
- * @param width Width of the frame in pixels.
- * @param height Height of the frame in pixels.
- * @param y Luminosity plane. Size = MAX(width, abs(ystride)) * height.
- * @param u U chroma plane. Size = MAX(width/2, abs(ustride)) * (height/2).
- * @param v V chroma plane. Size = MAX(width/2, abs(vstride)) * (height/2).
- *
- * @param ystride Luminosity plane stride.
- * @param ustride U chroma plane stride.
- * @param vstride V chroma plane stride.
- */
-typedef void toxav_video_receive_frame_cb(ToxAV *av, uint32_t friend_number, uint16_t width, uint16_t height,
- const uint8_t *y, const uint8_t *u, const uint8_t *v, int32_t ystride, int32_t ustride, int32_t vstride,
- void *user_data);
-
-
-/**
- * Set the callback for the `video_receive_frame` event. Pass NULL to unset.
- *
- */
-void toxav_callback_video_receive_frame(ToxAV *av, toxav_video_receive_frame_cb *callback, void *user_data);
-
-/**
- * NOTE Compatibility with old toxav group calls. TODO(iphydf): remove
- */
-/* Create a new toxav group.
- *
- * return group number on success.
- * return -1 on failure.
- *
- * Audio data callback format:
- * audio_callback(Tox *tox, int groupnumber, int peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate, void *userdata)
- *
- * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)).
- */
-int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(void *, int, int, const int16_t *, unsigned int, uint8_t,
- unsigned int, void *), void *userdata);
-
-/* Join a AV group (you need to have been invited first.)
- *
- * returns group number on success
- * returns -1 on failure.
- *
- * Audio data callback format (same as the one for toxav_add_av_groupchat()):
- * audio_callback(Tox *tox, int groupnumber, int peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate, void *userdata)
- *
- * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)).
- */
-int toxav_join_av_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length,
- void (*audio_callback)(void *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *), void *userdata);
-
-/* Send audio to the group chat.
- *
- * return 0 on success.
- * return -1 on failure.
- *
- * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)).
- *
- * Valid number of samples are ((sample rate) * (audio length (Valid ones are: 2.5, 5, 10, 20, 40 or 60 ms)) / 1000)
- * Valid number of channels are 1 or 2.
- * Valid sample rates are 8000, 12000, 16000, 24000, or 48000.
- *
- * Recommended values are: samples = 960, channels = 1, sample_rate = 48000
- */
-int toxav_group_send_audio(Tox *tox, int groupnumber, const int16_t *pcm, unsigned int samples, uint8_t channels,
- unsigned int sample_rate);
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* TOXAV_H */
diff --git a/protocols/Tox/include/vpx/vp8.h b/protocols/Tox/include/vpx/vp8.h
deleted file mode 100644
index 059c9d0f65..0000000000
--- a/protocols/Tox/include/vpx/vp8.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-/*!\defgroup vp8 VP8
- * \ingroup codecs
- * VP8 is vpx's newest video compression algorithm that uses motion
- * compensated prediction, Discrete Cosine Transform (DCT) coding of the
- * prediction error signal and context dependent entropy coding techniques
- * based on arithmetic principles. It features:
- * - YUV 4:2:0 image format
- * - Macro-block based coding (16x16 luma plus two 8x8 chroma)
- * - 1/4 (1/8) pixel accuracy motion compensated prediction
- * - 4x4 DCT transform
- * - 128 level linear quantizer
- * - In loop deblocking filter
- * - Context-based entropy coding
- *
- * @{
- */
-/*!\file
- * \brief Provides controls common to both the VP8 encoder and decoder.
- */
-#ifndef VPX_VP8_H_
-#define VPX_VP8_H_
-
-#include "./vpx_codec.h"
-#include "./vpx_image.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*!\brief Control functions
- *
- * The set of macros define the control functions of VP8 interface
- */
-enum vp8_com_control_id {
- /*!\brief pass in an external frame into decoder to be used as reference frame
- */
- VP8_SET_REFERENCE = 1,
- VP8_COPY_REFERENCE = 2, /**< get a copy of reference frame from the decoder */
- VP8_SET_POSTPROC = 3, /**< set the decoder's post processing settings */
- VP8_SET_DBG_COLOR_REF_FRAME = 4, /**< \deprecated */
- VP8_SET_DBG_COLOR_MB_MODES = 5, /**< \deprecated */
- VP8_SET_DBG_COLOR_B_MODES = 6, /**< \deprecated */
- VP8_SET_DBG_DISPLAY_MV = 7, /**< \deprecated */
-
- /* TODO(jkoleszar): The encoder incorrectly reuses some of these values (5+)
- * for its control ids. These should be migrated to something like the
- * VP8_DECODER_CTRL_ID_START range next time we're ready to break the ABI.
- */
- VP9_GET_REFERENCE = 128, /**< get a pointer to a reference frame */
- VP8_COMMON_CTRL_ID_MAX,
- VP8_DECODER_CTRL_ID_START = 256
-};
-
-/*!\brief post process flags
- *
- * The set of macros define VP8 decoder post processing flags
- */
-enum vp8_postproc_level {
- VP8_NOFILTERING = 0,
- VP8_DEBLOCK = 1 << 0,
- VP8_DEMACROBLOCK = 1 << 1,
- VP8_ADDNOISE = 1 << 2,
- VP8_DEBUG_TXT_FRAME_INFO = 1 << 3, /**< print frame information */
- VP8_DEBUG_TXT_MBLK_MODES =
- 1 << 4, /**< print macro block modes over each macro block */
- VP8_DEBUG_TXT_DC_DIFF = 1 << 5, /**< print dc diff for each macro block */
- VP8_DEBUG_TXT_RATE_INFO = 1 << 6, /**< print video rate info (encoder only) */
- VP8_MFQE = 1 << 10
-};
-
-/*!\brief post process flags
- *
- * This define a structure that describe the post processing settings. For
- * the best objective measure (using the PSNR metric) set post_proc_flag
- * to VP8_DEBLOCK and deblocking_level to 1.
- */
-
-typedef struct vp8_postproc_cfg {
- /*!\brief the types of post processing to be done, should be combination of
- * "vp8_postproc_level" */
- int post_proc_flag;
- int deblocking_level; /**< the strength of deblocking, valid range [0, 16] */
- int noise_level; /**< the strength of additive noise, valid range [0, 16] */
-} vp8_postproc_cfg_t;
-
-/*!\brief reference frame type
- *
- * The set of macros define the type of VP8 reference frames
- */
-typedef enum vpx_ref_frame_type {
- VP8_LAST_FRAME = 1,
- VP8_GOLD_FRAME = 2,
- VP8_ALTR_FRAME = 4
-} vpx_ref_frame_type_t;
-
-/*!\brief reference frame data struct
- *
- * Define the data struct to access vp8 reference frames.
- */
-typedef struct vpx_ref_frame {
- vpx_ref_frame_type_t frame_type; /**< which reference frame */
- vpx_image_t img; /**< reference frame data in image format */
-} vpx_ref_frame_t;
-
-/*!\brief VP9 specific reference frame data struct
- *
- * Define the data struct to access vp9 reference frames.
- */
-typedef struct vp9_ref_frame {
- int idx; /**< frame index to get (input) */
- vpx_image_t img; /**< img structure to populate (output) */
-} vp9_ref_frame_t;
-
-/*!\cond */
-/*!\brief vp8 decoder control function parameter type
- *
- * defines the data type for each of VP8 decoder control function requires
- */
-VPX_CTRL_USE_TYPE(VP8_SET_REFERENCE, vpx_ref_frame_t *)
-#define VPX_CTRL_VP8_SET_REFERENCE
-VPX_CTRL_USE_TYPE(VP8_COPY_REFERENCE, vpx_ref_frame_t *)
-#define VPX_CTRL_VP8_COPY_REFERENCE
-VPX_CTRL_USE_TYPE(VP8_SET_POSTPROC, vp8_postproc_cfg_t *)
-#define VPX_CTRL_VP8_SET_POSTPROC
-VPX_CTRL_USE_TYPE_DEPRECATED(VP8_SET_DBG_COLOR_REF_FRAME, int)
-#define VPX_CTRL_VP8_SET_DBG_COLOR_REF_FRAME
-VPX_CTRL_USE_TYPE_DEPRECATED(VP8_SET_DBG_COLOR_MB_MODES, int)
-#define VPX_CTRL_VP8_SET_DBG_COLOR_MB_MODES
-VPX_CTRL_USE_TYPE_DEPRECATED(VP8_SET_DBG_COLOR_B_MODES, int)
-#define VPX_CTRL_VP8_SET_DBG_COLOR_B_MODES
-VPX_CTRL_USE_TYPE_DEPRECATED(VP8_SET_DBG_DISPLAY_MV, int)
-#define VPX_CTRL_VP8_SET_DBG_DISPLAY_MV
-VPX_CTRL_USE_TYPE(VP9_GET_REFERENCE, vp9_ref_frame_t *)
-#define VPX_CTRL_VP9_GET_REFERENCE
-
-/*!\endcond */
-/*! @} - end defgroup vp8 */
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // VPX_VP8_H_
diff --git a/protocols/Tox/include/vpx/vp8cx.h b/protocols/Tox/include/vpx/vp8cx.h
deleted file mode 100644
index cc90159bc3..0000000000
--- a/protocols/Tox/include/vpx/vp8cx.h
+++ /dev/null
@@ -1,850 +0,0 @@
-/*
- * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-#ifndef VPX_VP8CX_H_
-#define VPX_VP8CX_H_
-
-/*!\defgroup vp8_encoder WebM VP8/VP9 Encoder
- * \ingroup vp8
- *
- * @{
- */
-#include "./vp8.h"
-#include "./vpx_encoder.h"
-
-/*!\file
- * \brief Provides definitions for using VP8 or VP9 encoder algorithm within the
- * vpx Codec Interface.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*!\name Algorithm interface for VP8
- *
- * This interface provides the capability to encode raw VP8 streams.
- * @{
- */
-extern vpx_codec_iface_t vpx_codec_vp8_cx_algo;
-extern vpx_codec_iface_t *vpx_codec_vp8_cx(void);
-/*!@} - end algorithm interface member group*/
-
-/*!\name Algorithm interface for VP9
- *
- * This interface provides the capability to encode raw VP9 streams.
- * @{
- */
-extern vpx_codec_iface_t vpx_codec_vp9_cx_algo;
-extern vpx_codec_iface_t *vpx_codec_vp9_cx(void);
-/*!@} - end algorithm interface member group*/
-
-/*
- * Algorithm Flags
- */
-
-/*!\brief Don't reference the last frame
- *
- * When this flag is set, the encoder will not use the last frame as a
- * predictor. When not set, the encoder will choose whether to use the
- * last frame or not automatically.
- */
-#define VP8_EFLAG_NO_REF_LAST (1 << 16)
-
-/*!\brief Don't reference the golden frame
- *
- * When this flag is set, the encoder will not use the golden frame as a
- * predictor. When not set, the encoder will choose whether to use the
- * golden frame or not automatically.
- */
-#define VP8_EFLAG_NO_REF_GF (1 << 17)
-
-/*!\brief Don't reference the alternate reference frame
- *
- * When this flag is set, the encoder will not use the alt ref frame as a
- * predictor. When not set, the encoder will choose whether to use the
- * alt ref frame or not automatically.
- */
-#define VP8_EFLAG_NO_REF_ARF (1 << 21)
-
-/*!\brief Don't update the last frame
- *
- * When this flag is set, the encoder will not update the last frame with
- * the contents of the current frame.
- */
-#define VP8_EFLAG_NO_UPD_LAST (1 << 18)
-
-/*!\brief Don't update the golden frame
- *
- * When this flag is set, the encoder will not update the golden frame with
- * the contents of the current frame.
- */
-#define VP8_EFLAG_NO_UPD_GF (1 << 22)
-
-/*!\brief Don't update the alternate reference frame
- *
- * When this flag is set, the encoder will not update the alt ref frame with
- * the contents of the current frame.
- */
-#define VP8_EFLAG_NO_UPD_ARF (1 << 23)
-
-/*!\brief Force golden frame update
- *
- * When this flag is set, the encoder copy the contents of the current frame
- * to the golden frame buffer.
- */
-#define VP8_EFLAG_FORCE_GF (1 << 19)
-
-/*!\brief Force alternate reference frame update
- *
- * When this flag is set, the encoder copy the contents of the current frame
- * to the alternate reference frame buffer.
- */
-#define VP8_EFLAG_FORCE_ARF (1 << 24)
-
-/*!\brief Disable entropy update
- *
- * When this flag is set, the encoder will not update its internal entropy
- * model based on the entropy of this frame.
- */
-#define VP8_EFLAG_NO_UPD_ENTROPY (1 << 20)
-
-/*!\brief VPx encoder control functions
- *
- * This set of macros define the control functions available for VPx
- * encoder interface.
- *
- * \sa #vpx_codec_control
- */
-enum vp8e_enc_control_id {
- /*!\brief Codec control function to pass an ROI map to encoder.
- *
- * Supported in codecs: VP8, VP9
- */
- VP8E_SET_ROI_MAP = 8,
-
- /*!\brief Codec control function to pass an Active map to encoder.
- *
- * Supported in codecs: VP8, VP9
- */
- VP8E_SET_ACTIVEMAP,
-
- /*!\brief Codec control function to set encoder scaling mode.
- *
- * Supported in codecs: VP8, VP9
- */
- VP8E_SET_SCALEMODE = 11,
-
- /*!\brief Codec control function to set encoder internal speed settings.
- *
- * Changes in this value influences, among others, the encoder's selection
- * of motion estimation methods. Values greater than 0 will increase encoder
- * speed at the expense of quality.
- *
- * \note Valid range for VP8: -16..16
- * \note Valid range for VP9: -8..8
- *
- * Supported in codecs: VP8, VP9
- */
- VP8E_SET_CPUUSED = 13,
-
- /*!\brief Codec control function to enable automatic set and use alf frames.
- *
- * Supported in codecs: VP8, VP9
- */
- VP8E_SET_ENABLEAUTOALTREF,
-
- /*!\brief control function to set noise sensitivity
- *
- * 0: off, 1: OnYOnly, 2: OnYUV,
- * 3: OnYUVAggressive, 4: Adaptive
- *
- * Supported in codecs: VP8
- */
- VP8E_SET_NOISE_SENSITIVITY,
-
- /*!\brief Codec control function to set sharpness.
- *
- * Supported in codecs: VP8, VP9
- */
- VP8E_SET_SHARPNESS,
-
- /*!\brief Codec control function to set the threshold for MBs treated static.
- *
- * Supported in codecs: VP8, VP9
- */
- VP8E_SET_STATIC_THRESHOLD,
-
- /*!\brief Codec control function to set the number of token partitions.
- *
- * Supported in codecs: VP8
- */
- VP8E_SET_TOKEN_PARTITIONS,
-
- /*!\brief Codec control function to get last quantizer chosen by the encoder.
- *
- * Return value uses internal quantizer scale defined by the codec.
- *
- * Supported in codecs: VP8, VP9
- */
- VP8E_GET_LAST_QUANTIZER,
-
- /*!\brief Codec control function to get last quantizer chosen by the encoder.
- *
- * Return value uses the 0..63 scale as used by the rc_*_quantizer config
- * parameters.
- *
- * Supported in codecs: VP8, VP9
- */
- VP8E_GET_LAST_QUANTIZER_64,
-
- /*!\brief Codec control function to set the max no of frames to create arf.
- *
- * Supported in codecs: VP8, VP9
- */
- VP8E_SET_ARNR_MAXFRAMES,
-
- /*!\brief Codec control function to set the filter strength for the arf.
- *
- * Supported in codecs: VP8, VP9
- */
- VP8E_SET_ARNR_STRENGTH,
-
- /*!\deprecated control function to set the filter type to use for the arf. */
- VP8E_SET_ARNR_TYPE,
-
- /*!\brief Codec control function to set visual tuning.
- *
- * Supported in codecs: VP8, VP9
- */
- VP8E_SET_TUNING,
-
- /*!\brief Codec control function to set constrained quality level.
- *
- * \attention For this value to be used vpx_codec_enc_cfg_t::g_usage must be
- * set to #VPX_CQ.
- * \note Valid range: 0..63
- *
- * Supported in codecs: VP8, VP9
- */
- VP8E_SET_CQ_LEVEL,
-
- /*!\brief Codec control function to set Max data rate for Intra frames.
- *
- * This value controls additional clamping on the maximum size of a
- * keyframe. It is expressed as a percentage of the average
- * per-frame bitrate, with the special (and default) value 0 meaning
- * unlimited, or no additional clamping beyond the codec's built-in
- * algorithm.
- *
- * For example, to allocate no more than 4.5 frames worth of bitrate
- * to a keyframe, set this to 450.
- *
- * Supported in codecs: VP8, VP9
- */
- VP8E_SET_MAX_INTRA_BITRATE_PCT,
-
- /*!\brief Codec control function to set reference and update frame flags.
- *
- * Supported in codecs: VP8
- */
- VP8E_SET_FRAME_FLAGS,
-
- /*!\brief Codec control function to set max data rate for Inter frames.
- *
- * This value controls additional clamping on the maximum size of an
- * inter frame. It is expressed as a percentage of the average
- * per-frame bitrate, with the special (and default) value 0 meaning
- * unlimited, or no additional clamping beyond the codec's built-in
- * algorithm.
- *
- * For example, to allow no more than 4.5 frames worth of bitrate
- * to an inter frame, set this to 450.
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_MAX_INTER_BITRATE_PCT,
-
- /*!\brief Boost percentage for Golden Frame in CBR mode.
- *
- * This value controls the amount of boost given to Golden Frame in
- * CBR mode. It is expressed as a percentage of the average
- * per-frame bitrate, with the special (and default) value 0 meaning
- * the feature is off, i.e., no golden frame boost in CBR mode and
- * average bitrate target is used.
- *
- * For example, to allow 100% more bits, i.e, 2X, in a golden frame
- * than average frame, set this to 100.
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_GF_CBR_BOOST_PCT,
-
- /*!\brief Codec control function to set the temporal layer id.
- *
- * For temporal scalability: this control allows the application to set the
- * layer id for each frame to be encoded. Note that this control must be set
- * for every frame prior to encoding. The usage of this control function
- * supersedes the internal temporal pattern counter, which is now deprecated.
- *
- * Supported in codecs: VP8
- */
- VP8E_SET_TEMPORAL_LAYER_ID,
-
- /*!\brief Codec control function to set encoder screen content mode.
- *
- * 0: off, 1: On, 2: On with more aggressive rate control.
- *
- * Supported in codecs: VP8
- */
- VP8E_SET_SCREEN_CONTENT_MODE,
-
- /*!\brief Codec control function to set lossless encoding mode.
- *
- * VP9 can operate in lossless encoding mode, in which the bitstream
- * produced will be able to decode and reconstruct a perfect copy of
- * input source. This control function provides a mean to switch encoder
- * into lossless coding mode(1) or normal coding mode(0) that may be lossy.
- * 0 = lossy coding mode
- * 1 = lossless coding mode
- *
- * By default, encoder operates in normal coding mode (maybe lossy).
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_LOSSLESS,
-
- /*!\brief Codec control function to set number of tile columns.
- *
- * In encoding and decoding, VP9 allows an input image frame be partitioned
- * into separated vertical tile columns, which can be encoded or decoded
- * independently. This enables easy implementation of parallel encoding and
- * decoding. This control requests the encoder to use column tiles in
- * encoding an input frame, with number of tile columns (in Log2 unit) as
- * the parameter:
- * 0 = 1 tile column
- * 1 = 2 tile columns
- * 2 = 4 tile columns
- * .....
- * n = 2**n tile columns
- * The requested tile columns will be capped by encoder based on image size
- * limitation (The minimum width of a tile column is 256 pixel, the maximum
- * is 4096).
- *
- * By default, the value is 0, i.e. one single column tile for entire image.
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_TILE_COLUMNS,
-
- /*!\brief Codec control function to set number of tile rows.
- *
- * In encoding and decoding, VP9 allows an input image frame be partitioned
- * into separated horizontal tile rows. Tile rows are encoded or decoded
- * sequentially. Even though encoding/decoding of later tile rows depends on
- * earlier ones, this allows the encoder to output data packets for tile rows
- * prior to completely processing all tile rows in a frame, thereby reducing
- * the latency in processing between input and output. The parameter
- * for this control describes the number of tile rows, which has a valid
- * range [0, 2]:
- * 0 = 1 tile row
- * 1 = 2 tile rows
- * 2 = 4 tile rows
- *
- * By default, the value is 0, i.e. one single row tile for entire image.
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_TILE_ROWS,
-
- /*!\brief Codec control function to enable frame parallel decoding feature.
- *
- * VP9 has a bitstream feature to reduce decoding dependency between frames
- * by turning off backward update of probability context used in encoding
- * and decoding. This allows staged parallel processing of more than one
- * video frames in the decoder. This control function provides a mean to
- * turn this feature on or off for bitstreams produced by encoder.
- *
- * By default, this feature is off.
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_FRAME_PARALLEL_DECODING,
-
- /*!\brief Codec control function to set adaptive quantization mode.
- *
- * VP9 has a segment based feature that allows encoder to adaptively change
- * quantization parameter for each segment within a frame to improve the
- * subjective quality. This control makes encoder operate in one of the
- * several AQ_modes supported.
- *
- * By default, encoder operates with AQ_Mode 0(adaptive quantization off).
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_AQ_MODE,
-
- /*!\brief Codec control function to enable/disable periodic Q boost.
- *
- * One VP9 encoder speed feature is to enable quality boost by lowering
- * frame level Q periodically. This control function provides a mean to
- * turn on/off this feature.
- * 0 = off
- * 1 = on
- *
- * By default, the encoder is allowed to use this feature for appropriate
- * encoding modes.
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_FRAME_PERIODIC_BOOST,
-
- /*!\brief Codec control function to set noise sensitivity.
- *
- * 0: off, 1: On(YOnly)
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_NOISE_SENSITIVITY,
-
- /*!\brief Codec control function to turn on/off SVC in encoder.
- * \note Return value is VPX_CODEC_INVALID_PARAM if the encoder does not
- * support SVC in its current encoding mode
- * 0: off, 1: on
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_SVC,
-
- /*!\brief Codec control function to set parameters for SVC.
- * \note Parameters contain min_q, max_q, scaling factor for each of the
- * SVC layers.
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_SVC_PARAMETERS,
-
- /*!\brief Codec control function to set svc layer for spatial and temporal.
- * \note Valid ranges: 0..#vpx_codec_enc_cfg::ss_number_layers for spatial
- * layer and 0..#vpx_codec_enc_cfg::ts_number_layers for
- * temporal layer.
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_SVC_LAYER_ID,
-
- /*!\brief Codec control function to set content type.
- * \note Valid parameter range:
- * VP9E_CONTENT_DEFAULT = Regular video content (Default)
- * VP9E_CONTENT_SCREEN = Screen capture content
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_TUNE_CONTENT,
-
- /*!\brief Codec control function to get svc layer ID.
- * \note The layer ID returned is for the data packet from the registered
- * callback function.
- *
- * Supported in codecs: VP9
- */
- VP9E_GET_SVC_LAYER_ID,
-
- /*!\brief Codec control function to register callback to get per layer packet.
- * \note Parameter for this control function is a structure with a callback
- * function and a pointer to private data used by the callback.
- *
- * Supported in codecs: VP9
- */
- VP9E_REGISTER_CX_CALLBACK,
-
- /*!\brief Codec control function to set color space info.
- * \note Valid ranges: 0..7, default is "UNKNOWN".
- * 0 = UNKNOWN,
- * 1 = BT_601
- * 2 = BT_709
- * 3 = SMPTE_170
- * 4 = SMPTE_240
- * 5 = BT_2020
- * 6 = RESERVED
- * 7 = SRGB
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_COLOR_SPACE,
-
- /*!\brief Codec control function to set temporal layering mode.
- * \note Valid ranges: 0..3, default is "0"
- * (VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING).
- * 0 = VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING
- * 1 = VP9E_TEMPORAL_LAYERING_MODE_BYPASS
- * 2 = VP9E_TEMPORAL_LAYERING_MODE_0101
- * 3 = VP9E_TEMPORAL_LAYERING_MODE_0212
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_TEMPORAL_LAYERING_MODE,
-
- /*!\brief Codec control function to set minimum interval between GF/ARF frames
- *
- * By default the value is set as 4.
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_MIN_GF_INTERVAL,
-
- /*!\brief Codec control function to set minimum interval between GF/ARF frames
- *
- * By default the value is set as 16.
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_MAX_GF_INTERVAL,
-
- /*!\brief Codec control function to get an Active map back from the encoder.
- *
- * Supported in codecs: VP9
- */
- VP9E_GET_ACTIVEMAP,
-
- /*!\brief Codec control function to set color range bit.
- * \note Valid ranges: 0..1, default is 0
- * 0 = Limited range (16..235 or HBD equivalent)
- * 1 = Full range (0..255 or HBD equivalent)
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_COLOR_RANGE,
-
- /*!\brief Codec control function to set the frame flags and buffer indices
- * for spatial layers. The frame flags and buffer indices are set using the
- * struct #vpx_svc_ref_frame_config defined below.
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_SVC_REF_FRAME_CONFIG,
-
- /*!\brief Codec control function to set intended rendering image size.
- *
- * By default, this is identical to the image size in pixels.
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_RENDER_SIZE,
-
- /*!\brief Codec control function to set target level.
- *
- * 255: off (default); 0: only keep level stats; 10: target for level 1.0;
- * 11: target for level 1.1; ... 62: target for level 6.2
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_TARGET_LEVEL,
-
- /*!\brief Codec control function to get bitstream level.
- *
- * Supported in codecs: VP9
- */
- VP9E_GET_LEVEL,
-
- /*!\brief Codec control function to enable/disable special mode for altref
- * adaptive quantization. You can use it with --aq-mode concurrently.
- *
- * Enable special adaptive quantization for altref frames based on their
- * expected prediction quality for the future frames.
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_ALT_REF_AQ,
-
- /*!\brief Boost percentage for Golden Frame in CBR mode.
- *
- * This value controls the amount of boost given to Golden Frame in
- * CBR mode. It is expressed as a percentage of the average
- * per-frame bitrate, with the special (and default) value 0 meaning
- * the feature is off, i.e., no golden frame boost in CBR mode and
- * average bitrate target is used.
- *
- * For example, to allow 100% more bits, i.e, 2X, in a golden frame
- * than average frame, set this to 100.
- *
- * Supported in codecs: VP8
- */
- VP8E_SET_GF_CBR_BOOST_PCT,
-};
-
-/*!\brief vpx 1-D scaling mode
- *
- * This set of constants define 1-D vpx scaling modes
- */
-typedef enum vpx_scaling_mode_1d {
- VP8E_NORMAL = 0,
- VP8E_FOURFIVE = 1,
- VP8E_THREEFIVE = 2,
- VP8E_ONETWO = 3
-} VPX_SCALING_MODE;
-
-/*!\brief Temporal layering mode enum for VP9 SVC.
- *
- * This set of macros define the different temporal layering modes.
- * Supported codecs: VP9 (in SVC mode)
- *
- */
-typedef enum vp9e_temporal_layering_mode {
- /*!\brief No temporal layering.
- * Used when only spatial layering is used.
- */
- VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING = 0,
-
- /*!\brief Bypass mode.
- * Used when application needs to control temporal layering.
- * This will only work when the number of spatial layers equals 1.
- */
- VP9E_TEMPORAL_LAYERING_MODE_BYPASS = 1,
-
- /*!\brief 0-1-0-1... temporal layering scheme with two temporal layers.
- */
- VP9E_TEMPORAL_LAYERING_MODE_0101 = 2,
-
- /*!\brief 0-2-1-2... temporal layering scheme with three temporal layers.
- */
- VP9E_TEMPORAL_LAYERING_MODE_0212 = 3
-} VP9E_TEMPORAL_LAYERING_MODE;
-
-/*!\brief vpx region of interest map
- *
- * These defines the data structures for the region of interest map
- *
- */
-
-typedef struct vpx_roi_map {
- /*! An id between 0 and 3 for each 16x16 region within a frame. */
- unsigned char *roi_map;
- unsigned int rows; /**< Number of rows. */
- unsigned int cols; /**< Number of columns. */
- // TODO(paulwilkins): broken for VP9 which has 8 segments
- // q and loop filter deltas for each segment
- // (see MAX_MB_SEGMENTS)
- int delta_q[4]; /**< Quantizer deltas. */
- int delta_lf[4]; /**< Loop filter deltas. */
- /*! Static breakout threshold for each segment. */
- unsigned int static_threshold[4];
-} vpx_roi_map_t;
-
-/*!\brief vpx active region map
- *
- * These defines the data structures for active region map
- *
- */
-
-typedef struct vpx_active_map {
- /*!\brief specify an on (1) or off (0) each 16x16 region within a frame */
- unsigned char *active_map;
- unsigned int rows; /**< number of rows */
- unsigned int cols; /**< number of cols */
-} vpx_active_map_t;
-
-/*!\brief vpx image scaling mode
- *
- * This defines the data structure for image scaling mode
- *
- */
-typedef struct vpx_scaling_mode {
- VPX_SCALING_MODE h_scaling_mode; /**< horizontal scaling mode */
- VPX_SCALING_MODE v_scaling_mode; /**< vertical scaling mode */
-} vpx_scaling_mode_t;
-
-/*!\brief VP8 token partition mode
- *
- * This defines VP8 partitioning mode for compressed data, i.e., the number of
- * sub-streams in the bitstream. Used for parallelized decoding.
- *
- */
-
-typedef enum {
- VP8_ONE_TOKENPARTITION = 0,
- VP8_TWO_TOKENPARTITION = 1,
- VP8_FOUR_TOKENPARTITION = 2,
- VP8_EIGHT_TOKENPARTITION = 3
-} vp8e_token_partitions;
-
-/*!brief VP9 encoder content type */
-typedef enum {
- VP9E_CONTENT_DEFAULT,
- VP9E_CONTENT_SCREEN,
- VP9E_CONTENT_INVALID
-} vp9e_tune_content;
-
-/*!\brief VP8 model tuning parameters
- *
- * Changes the encoder to tune for certain types of input material.
- *
- */
-typedef enum { VP8_TUNE_PSNR, VP8_TUNE_SSIM } vp8e_tuning;
-
-/*!\brief vp9 svc layer parameters
- *
- * This defines the spatial and temporal layer id numbers for svc encoding.
- * This is used with the #VP9E_SET_SVC_LAYER_ID control to set the spatial and
- * temporal layer id for the current frame.
- *
- */
-typedef struct vpx_svc_layer_id {
- int spatial_layer_id; /**< Spatial layer id number. */
- int temporal_layer_id; /**< Temporal layer id number. */
-} vpx_svc_layer_id_t;
-
-/*!\brief vp9 svc frame flag parameters.
- *
- * This defines the frame flags and buffer indices for each spatial layer for
- * svc encoding.
- * This is used with the #VP9E_SET_SVC_REF_FRAME_CONFIG control to set frame
- * flags and buffer indices for each spatial layer for the current (super)frame.
- *
- */
-typedef struct vpx_svc_ref_frame_config {
- int frame_flags[VPX_TS_MAX_LAYERS]; /**< Frame flags. */
- int lst_fb_idx[VPX_TS_MAX_LAYERS]; /**< Last buffer index. */
- int gld_fb_idx[VPX_TS_MAX_LAYERS]; /**< Golden buffer index. */
- int alt_fb_idx[VPX_TS_MAX_LAYERS]; /**< Altref buffer index. */
-} vpx_svc_ref_frame_config_t;
-
-/*!\cond */
-/*!\brief VP8 encoder control function parameter type
- *
- * Defines the data types that VP8E control functions take. Note that
- * additional common controls are defined in vp8.h
- *
- */
-
-VPX_CTRL_USE_TYPE(VP8E_SET_FRAME_FLAGS, int)
-#define VPX_CTRL_VP8E_SET_FRAME_FLAGS
-VPX_CTRL_USE_TYPE(VP8E_SET_TEMPORAL_LAYER_ID, int)
-#define VPX_CTRL_VP8E_SET_TEMPORAL_LAYER_ID
-VPX_CTRL_USE_TYPE(VP8E_SET_ROI_MAP, vpx_roi_map_t *)
-#define VPX_CTRL_VP8E_SET_ROI_MAP
-VPX_CTRL_USE_TYPE(VP8E_SET_ACTIVEMAP, vpx_active_map_t *)
-#define VPX_CTRL_VP8E_SET_ACTIVEMAP
-VPX_CTRL_USE_TYPE(VP8E_SET_SCALEMODE, vpx_scaling_mode_t *)
-#define VPX_CTRL_VP8E_SET_SCALEMODE
-
-VPX_CTRL_USE_TYPE(VP9E_SET_SVC, int)
-#define VPX_CTRL_VP9E_SET_SVC
-VPX_CTRL_USE_TYPE(VP9E_SET_SVC_PARAMETERS, void *)
-#define VPX_CTRL_VP9E_SET_SVC_PARAMETERS
-VPX_CTRL_USE_TYPE(VP9E_REGISTER_CX_CALLBACK, void *)
-#define VPX_CTRL_VP9E_REGISTER_CX_CALLBACK
-VPX_CTRL_USE_TYPE(VP9E_SET_SVC_LAYER_ID, vpx_svc_layer_id_t *)
-#define VPX_CTRL_VP9E_SET_SVC_LAYER_ID
-
-VPX_CTRL_USE_TYPE(VP8E_SET_CPUUSED, int)
-#define VPX_CTRL_VP8E_SET_CPUUSED
-VPX_CTRL_USE_TYPE(VP8E_SET_ENABLEAUTOALTREF, unsigned int)
-#define VPX_CTRL_VP8E_SET_ENABLEAUTOALTREF
-VPX_CTRL_USE_TYPE(VP8E_SET_NOISE_SENSITIVITY, unsigned int)
-#define VPX_CTRL_VP8E_SET_NOISE_SENSITIVITY
-VPX_CTRL_USE_TYPE(VP8E_SET_SHARPNESS, unsigned int)
-#define VPX_CTRL_VP8E_SET_SHARPNESS
-VPX_CTRL_USE_TYPE(VP8E_SET_STATIC_THRESHOLD, unsigned int)
-#define VPX_CTRL_VP8E_SET_STATIC_THRESHOLD
-VPX_CTRL_USE_TYPE(VP8E_SET_TOKEN_PARTITIONS, int) /* vp8e_token_partitions */
-#define VPX_CTRL_VP8E_SET_TOKEN_PARTITIONS
-
-VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_MAXFRAMES, unsigned int)
-#define VPX_CTRL_VP8E_SET_ARNR_MAXFRAMES
-VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_STRENGTH, unsigned int)
-#define VPX_CTRL_VP8E_SET_ARNR_STRENGTH
-VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_SET_ARNR_TYPE, unsigned int)
-#define VPX_CTRL_VP8E_SET_ARNR_TYPE
-VPX_CTRL_USE_TYPE(VP8E_SET_TUNING, int) /* vp8e_tuning */
-#define VPX_CTRL_VP8E_SET_TUNING
-VPX_CTRL_USE_TYPE(VP8E_SET_CQ_LEVEL, unsigned int)
-#define VPX_CTRL_VP8E_SET_CQ_LEVEL
-
-VPX_CTRL_USE_TYPE(VP9E_SET_TILE_COLUMNS, int)
-#define VPX_CTRL_VP9E_SET_TILE_COLUMNS
-VPX_CTRL_USE_TYPE(VP9E_SET_TILE_ROWS, int)
-#define VPX_CTRL_VP9E_SET_TILE_ROWS
-
-VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER, int *)
-#define VPX_CTRL_VP8E_GET_LAST_QUANTIZER
-VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER_64, int *)
-#define VPX_CTRL_VP8E_GET_LAST_QUANTIZER_64
-VPX_CTRL_USE_TYPE(VP9E_GET_SVC_LAYER_ID, vpx_svc_layer_id_t *)
-#define VPX_CTRL_VP9E_GET_SVC_LAYER_ID
-
-VPX_CTRL_USE_TYPE(VP8E_SET_MAX_INTRA_BITRATE_PCT, unsigned int)
-#define VPX_CTRL_VP8E_SET_MAX_INTRA_BITRATE_PCT
-VPX_CTRL_USE_TYPE(VP8E_SET_MAX_INTER_BITRATE_PCT, unsigned int)
-#define VPX_CTRL_VP8E_SET_MAX_INTER_BITRATE_PCT
-
-VPX_CTRL_USE_TYPE(VP8E_SET_GF_CBR_BOOST_PCT, unsigned int)
-#define VPX_CTRL_VP8E_SET_GF_CBR_BOOST_PCT
-
-VPX_CTRL_USE_TYPE(VP8E_SET_SCREEN_CONTENT_MODE, unsigned int)
-#define VPX_CTRL_VP8E_SET_SCREEN_CONTENT_MODE
-
-VPX_CTRL_USE_TYPE(VP9E_SET_GF_CBR_BOOST_PCT, unsigned int)
-#define VPX_CTRL_VP9E_SET_GF_CBR_BOOST_PCT
-
-VPX_CTRL_USE_TYPE(VP9E_SET_LOSSLESS, unsigned int)
-#define VPX_CTRL_VP9E_SET_LOSSLESS
-
-VPX_CTRL_USE_TYPE(VP9E_SET_FRAME_PARALLEL_DECODING, unsigned int)
-#define VPX_CTRL_VP9E_SET_FRAME_PARALLEL_DECODING
-
-VPX_CTRL_USE_TYPE(VP9E_SET_AQ_MODE, unsigned int)
-#define VPX_CTRL_VP9E_SET_AQ_MODE
-
-VPX_CTRL_USE_TYPE(VP9E_SET_ALT_REF_AQ, int)
-#define VPX_CTRL_VP9E_SET_ALT_REF_AQ
-
-VPX_CTRL_USE_TYPE(VP9E_SET_FRAME_PERIODIC_BOOST, unsigned int)
-#define VPX_CTRL_VP9E_SET_FRAME_PERIODIC_BOOST
-
-VPX_CTRL_USE_TYPE(VP9E_SET_NOISE_SENSITIVITY, unsigned int)
-#define VPX_CTRL_VP9E_SET_NOISE_SENSITIVITY
-
-VPX_CTRL_USE_TYPE(VP9E_SET_TUNE_CONTENT, int) /* vp9e_tune_content */
-#define VPX_CTRL_VP9E_SET_TUNE_CONTENT
-
-VPX_CTRL_USE_TYPE(VP9E_SET_COLOR_SPACE, int)
-#define VPX_CTRL_VP9E_SET_COLOR_SPACE
-
-VPX_CTRL_USE_TYPE(VP9E_SET_MIN_GF_INTERVAL, unsigned int)
-#define VPX_CTRL_VP9E_SET_MIN_GF_INTERVAL
-
-VPX_CTRL_USE_TYPE(VP9E_SET_MAX_GF_INTERVAL, unsigned int)
-#define VPX_CTRL_VP9E_SET_MAX_GF_INTERVAL
-
-VPX_CTRL_USE_TYPE(VP9E_GET_ACTIVEMAP, vpx_active_map_t *)
-#define VPX_CTRL_VP9E_GET_ACTIVEMAP
-
-VPX_CTRL_USE_TYPE(VP9E_SET_COLOR_RANGE, int)
-#define VPX_CTRL_VP9E_SET_COLOR_RANGE
-
-VPX_CTRL_USE_TYPE(VP9E_SET_SVC_REF_FRAME_CONFIG, vpx_svc_ref_frame_config_t *)
-#define VPX_CTRL_VP9E_SET_SVC_REF_FRAME_CONFIG
-
-VPX_CTRL_USE_TYPE(VP9E_SET_RENDER_SIZE, int *)
-#define VPX_CTRL_VP9E_SET_RENDER_SIZE
-
-VPX_CTRL_USE_TYPE(VP9E_SET_TARGET_LEVEL, unsigned int)
-#define VPX_CTRL_VP9E_SET_TARGET_LEVEL
-
-VPX_CTRL_USE_TYPE(VP9E_GET_LEVEL, int *)
-#define VPX_CTRL_VP9E_GET_LEVEL
-
-/*!\endcond */
-/*! @} - end defgroup vp8_encoder */
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // VPX_VP8CX_H_
diff --git a/protocols/Tox/include/vpx/vp8dx.h b/protocols/Tox/include/vpx/vp8dx.h
deleted file mode 100644
index 0d7759eb25..0000000000
--- a/protocols/Tox/include/vpx/vp8dx.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-/*!\defgroup vp8_decoder WebM VP8/VP9 Decoder
- * \ingroup vp8
- *
- * @{
- */
-/*!\file
- * \brief Provides definitions for using VP8 or VP9 within the vpx Decoder
- * interface.
- */
-#ifndef VPX_VP8DX_H_
-#define VPX_VP8DX_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Include controls common to both the encoder and decoder */
-#include "./vp8.h"
-
-/*!\name Algorithm interface for VP8
- *
- * This interface provides the capability to decode VP8 streams.
- * @{
- */
-extern vpx_codec_iface_t vpx_codec_vp8_dx_algo;
-extern vpx_codec_iface_t *vpx_codec_vp8_dx(void);
-/*!@} - end algorithm interface member group*/
-
-/*!\name Algorithm interface for VP9
- *
- * This interface provides the capability to decode VP9 streams.
- * @{
- */
-extern vpx_codec_iface_t vpx_codec_vp9_dx_algo;
-extern vpx_codec_iface_t *vpx_codec_vp9_dx(void);
-/*!@} - end algorithm interface member group*/
-
-/*!\enum vp8_dec_control_id
- * \brief VP8 decoder control functions
- *
- * This set of macros define the control functions available for the VP8
- * decoder interface.
- *
- * \sa #vpx_codec_control
- */
-enum vp8_dec_control_id {
- /** control function to get info on which reference frames were updated
- * by the last decode
- */
- VP8D_GET_LAST_REF_UPDATES = VP8_DECODER_CTRL_ID_START,
-
- /** check if the indicated frame is corrupted */
- VP8D_GET_FRAME_CORRUPTED,
-
- /** control function to get info on which reference frames were used
- * by the last decode
- */
- VP8D_GET_LAST_REF_USED,
-
- /** decryption function to decrypt encoded buffer data immediately
- * before decoding. Takes a vpx_decrypt_init, which contains
- * a callback function and opaque context pointer.
- */
- VPXD_SET_DECRYPTOR,
- VP8D_SET_DECRYPTOR = VPXD_SET_DECRYPTOR,
-
- /** control function to get the dimensions that the current frame is decoded
- * at. This may be different to the intended display size for the frame as
- * specified in the wrapper or frame header (see VP9D_GET_DISPLAY_SIZE). */
- VP9D_GET_FRAME_SIZE,
-
- /** control function to get the current frame's intended display dimensions
- * (as specified in the wrapper or frame header). This may be different to
- * the decoded dimensions of this frame (see VP9D_GET_FRAME_SIZE). */
- VP9D_GET_DISPLAY_SIZE,
-
- /** control function to get the bit depth of the stream. */
- VP9D_GET_BIT_DEPTH,
-
- /** control function to set the byte alignment of the planes in the reference
- * buffers. Valid values are power of 2, from 32 to 1024. A value of 0 sets
- * legacy alignment. I.e. Y plane is aligned to 32 bytes, U plane directly
- * follows Y plane, and V plane directly follows U plane. Default value is 0.
- */
- VP9_SET_BYTE_ALIGNMENT,
-
- /** control function to invert the decoding order to from right to left. The
- * function is used in a test to confirm the decoding independence of tile
- * columns. The function may be used in application where this order
- * of decoding is desired.
- *
- * TODO(yaowu): Rework the unit test that uses this control, and in a future
- * release, this test-only control shall be removed.
- */
- VP9_INVERT_TILE_DECODE_ORDER,
-
- /** control function to set the skip loop filter flag. Valid values are
- * integers. The decoder will skip the loop filter when its value is set to
- * nonzero. If the loop filter is skipped the decoder may accumulate decode
- * artifacts. The default value is 0.
- */
- VP9_SET_SKIP_LOOP_FILTER,
-
- /** control function to decode SVC stream up to the x spatial layers,
- * where x is passed in through the control, and is 0 for base layer.
- */
- VP9_DECODE_SVC_SPATIAL_LAYER,
-
- VP8_DECODER_CTRL_ID_MAX
-};
-
-/** Decrypt n bytes of data from input -> output, using the decrypt_state
- * passed in VPXD_SET_DECRYPTOR.
- */
-typedef void (*vpx_decrypt_cb)(void *decrypt_state, const unsigned char *input,
- unsigned char *output, int count);
-
-/*!\brief Structure to hold decryption state
- *
- * Defines a structure to hold the decryption state and access function.
- */
-typedef struct vpx_decrypt_init {
- /*! Decrypt callback. */
- vpx_decrypt_cb decrypt_cb;
-
- /*! Decryption state. */
- void *decrypt_state;
-} vpx_decrypt_init;
-
-/*!\brief A deprecated alias for vpx_decrypt_init.
- */
-typedef vpx_decrypt_init vp8_decrypt_init;
-
-/*!\cond */
-/*!\brief VP8 decoder control function parameter type
- *
- * Defines the data types that VP8D control functions take. Note that
- * additional common controls are defined in vp8.h
- *
- */
-
-VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_UPDATES, int *)
-#define VPX_CTRL_VP8D_GET_LAST_REF_UPDATES
-VPX_CTRL_USE_TYPE(VP8D_GET_FRAME_CORRUPTED, int *)
-#define VPX_CTRL_VP8D_GET_FRAME_CORRUPTED
-VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_USED, int *)
-#define VPX_CTRL_VP8D_GET_LAST_REF_USED
-VPX_CTRL_USE_TYPE(VPXD_SET_DECRYPTOR, vpx_decrypt_init *)
-#define VPX_CTRL_VPXD_SET_DECRYPTOR
-VPX_CTRL_USE_TYPE(VP8D_SET_DECRYPTOR, vpx_decrypt_init *)
-#define VPX_CTRL_VP8D_SET_DECRYPTOR
-VPX_CTRL_USE_TYPE(VP9D_GET_DISPLAY_SIZE, int *)
-#define VPX_CTRL_VP9D_GET_DISPLAY_SIZE
-VPX_CTRL_USE_TYPE(VP9D_GET_BIT_DEPTH, unsigned int *)
-#define VPX_CTRL_VP9D_GET_BIT_DEPTH
-VPX_CTRL_USE_TYPE(VP9D_GET_FRAME_SIZE, int *)
-#define VPX_CTRL_VP9D_GET_FRAME_SIZE
-VPX_CTRL_USE_TYPE(VP9_INVERT_TILE_DECODE_ORDER, int)
-#define VPX_CTRL_VP9_INVERT_TILE_DECODE_ORDER
-#define VPX_CTRL_VP9_DECODE_SVC_SPATIAL_LAYER
-VPX_CTRL_USE_TYPE(VP9_DECODE_SVC_SPATIAL_LAYER, int)
-
-/*!\endcond */
-/*! @} - end defgroup vp8_decoder */
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // VPX_VP8DX_H_
diff --git a/protocols/Tox/include/vpx/vpx_codec.h b/protocols/Tox/include/vpx/vpx_codec.h
deleted file mode 100644
index fe75d23872..0000000000
--- a/protocols/Tox/include/vpx/vpx_codec.h
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-/*!\defgroup codec Common Algorithm Interface
- * This abstraction allows applications to easily support multiple video
- * formats with minimal code duplication. This section describes the interface
- * common to all codecs (both encoders and decoders).
- * @{
- */
-
-/*!\file
- * \brief Describes the codec algorithm interface to applications.
- *
- * This file describes the interface between an application and a
- * video codec algorithm.
- *
- * An application instantiates a specific codec instance by using
- * vpx_codec_init() and a pointer to the algorithm's interface structure:
- * <pre>
- * my_app.c:
- * extern vpx_codec_iface_t my_codec;
- * {
- * vpx_codec_ctx_t algo;
- * res = vpx_codec_init(&algo, &my_codec);
- * }
- * </pre>
- *
- * Once initialized, the instance is manged using other functions from
- * the vpx_codec_* family.
- */
-#ifndef VPX_VPX_CODEC_H_
-#define VPX_VPX_CODEC_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "./vpx_integer.h"
-#include "./vpx_image.h"
-
-/*!\brief Decorator indicating a function is deprecated */
-#ifndef DEPRECATED
-#if defined(__GNUC__) && __GNUC__
-#define DEPRECATED __attribute__((deprecated))
-#elif defined(_MSC_VER)
-#define DEPRECATED
-#else
-#define DEPRECATED
-#endif
-#endif /* DEPRECATED */
-
-#ifndef DECLSPEC_DEPRECATED
-#if defined(__GNUC__) && __GNUC__
-#define DECLSPEC_DEPRECATED /**< \copydoc #DEPRECATED */
-#elif defined(_MSC_VER)
-/*!\brief \copydoc #DEPRECATED */
-#define DECLSPEC_DEPRECATED __declspec(deprecated)
-#else
-#define DECLSPEC_DEPRECATED /**< \copydoc #DEPRECATED */
-#endif
-#endif /* DECLSPEC_DEPRECATED */
-
-/*!\brief Decorator indicating a function is potentially unused */
-#ifdef UNUSED
-#elif defined(__GNUC__) || defined(__clang__)
-#define UNUSED __attribute__((unused))
-#else
-#define UNUSED
-#endif
-
-/*!\brief Current ABI version number
- *
- * \internal
- * If this file is altered in any way that changes the ABI, this value
- * must be bumped. Examples include, but are not limited to, changing
- * types, removing or reassigning enums, adding/removing/rearranging
- * fields to structures
- */
-#define VPX_CODEC_ABI_VERSION (3 + VPX_IMAGE_ABI_VERSION) /**<\hideinitializer*/
-
-/*!\brief Algorithm return codes */
-typedef enum {
- /*!\brief Operation completed without error */
- VPX_CODEC_OK,
-
- /*!\brief Unspecified error */
- VPX_CODEC_ERROR,
-
- /*!\brief Memory operation failed */
- VPX_CODEC_MEM_ERROR,
-
- /*!\brief ABI version mismatch */
- VPX_CODEC_ABI_MISMATCH,
-
- /*!\brief Algorithm does not have required capability */
- VPX_CODEC_INCAPABLE,
-
- /*!\brief The given bitstream is not supported.
- *
- * The bitstream was unable to be parsed at the highest level. The decoder
- * is unable to proceed. This error \ref SHOULD be treated as fatal to the
- * stream. */
- VPX_CODEC_UNSUP_BITSTREAM,
-
- /*!\brief Encoded bitstream uses an unsupported feature
- *
- * The decoder does not implement a feature required by the encoder. This
- * return code should only be used for features that prevent future
- * pictures from being properly decoded. This error \ref MAY be treated as
- * fatal to the stream or \ref MAY be treated as fatal to the current GOP.
- */
- VPX_CODEC_UNSUP_FEATURE,
-
- /*!\brief The coded data for this stream is corrupt or incomplete
- *
- * There was a problem decoding the current frame. This return code
- * should only be used for failures that prevent future pictures from
- * being properly decoded. This error \ref MAY be treated as fatal to the
- * stream or \ref MAY be treated as fatal to the current GOP. If decoding
- * is continued for the current GOP, artifacts may be present.
- */
- VPX_CODEC_CORRUPT_FRAME,
-
- /*!\brief An application-supplied parameter is not valid.
- *
- */
- VPX_CODEC_INVALID_PARAM,
-
- /*!\brief An iterator reached the end of list.
- *
- */
- VPX_CODEC_LIST_END
-
-} vpx_codec_err_t;
-
-/*! \brief Codec capabilities bitfield
- *
- * Each codec advertises the capabilities it supports as part of its
- * ::vpx_codec_iface_t interface structure. Capabilities are extra interfaces
- * or functionality, and are not required to be supported.
- *
- * The available flags are specified by VPX_CODEC_CAP_* defines.
- */
-typedef long vpx_codec_caps_t;
-#define VPX_CODEC_CAP_DECODER 0x1 /**< Is a decoder */
-#define VPX_CODEC_CAP_ENCODER 0x2 /**< Is an encoder */
-
-/*! \brief Initialization-time Feature Enabling
- *
- * Certain codec features must be known at initialization time, to allow for
- * proper memory allocation.
- *
- * The available flags are specified by VPX_CODEC_USE_* defines.
- */
-typedef long vpx_codec_flags_t;
-
-/*!\brief Codec interface structure.
- *
- * Contains function pointers and other data private to the codec
- * implementation. This structure is opaque to the application.
- */
-typedef const struct vpx_codec_iface vpx_codec_iface_t;
-
-/*!\brief Codec private data structure.
- *
- * Contains data private to the codec implementation. This structure is opaque
- * to the application.
- */
-typedef struct vpx_codec_priv vpx_codec_priv_t;
-
-/*!\brief Iterator
- *
- * Opaque storage used for iterating over lists.
- */
-typedef const void *vpx_codec_iter_t;
-
-/*!\brief Codec context structure
- *
- * All codecs \ref MUST support this context structure fully. In general,
- * this data should be considered private to the codec algorithm, and
- * not be manipulated or examined by the calling application. Applications
- * may reference the 'name' member to get a printable description of the
- * algorithm.
- */
-typedef struct vpx_codec_ctx {
- const char *name; /**< Printable interface name */
- vpx_codec_iface_t *iface; /**< Interface pointers */
- vpx_codec_err_t err; /**< Last returned error */
- const char *err_detail; /**< Detailed info, if available */
- vpx_codec_flags_t init_flags; /**< Flags passed at init time */
- union {
- /**< Decoder Configuration Pointer */
- const struct vpx_codec_dec_cfg *dec;
- /**< Encoder Configuration Pointer */
- const struct vpx_codec_enc_cfg *enc;
- const void *raw;
- } config; /**< Configuration pointer aliasing union */
- vpx_codec_priv_t *priv; /**< Algorithm private storage */
-} vpx_codec_ctx_t;
-
-/*!\brief Bit depth for codec
- * *
- * This enumeration determines the bit depth of the codec.
- */
-typedef enum vpx_bit_depth {
- VPX_BITS_8 = 8, /**< 8 bits */
- VPX_BITS_10 = 10, /**< 10 bits */
- VPX_BITS_12 = 12, /**< 12 bits */
-} vpx_bit_depth_t;
-
-/*
- * Library Version Number Interface
- *
- * For example, see the following sample return values:
- * vpx_codec_version() (1<<16 | 2<<8 | 3)
- * vpx_codec_version_str() "v1.2.3-rc1-16-gec6a1ba"
- * vpx_codec_version_extra_str() "rc1-16-gec6a1ba"
- */
-
-/*!\brief Return the version information (as an integer)
- *
- * Returns a packed encoding of the library version number. This will only
- * include
- * the major.minor.patch component of the version number. Note that this encoded
- * value should be accessed through the macros provided, as the encoding may
- * change
- * in the future.
- *
- */
-int vpx_codec_version(void);
-#define VPX_VERSION_MAJOR(v) \
- ((v >> 16) & 0xff) /**< extract major from packed version */
-#define VPX_VERSION_MINOR(v) \
- ((v >> 8) & 0xff) /**< extract minor from packed version */
-#define VPX_VERSION_PATCH(v) \
- ((v >> 0) & 0xff) /**< extract patch from packed version */
-
-/*!\brief Return the version major number */
-#define vpx_codec_version_major() ((vpx_codec_version() >> 16) & 0xff)
-
-/*!\brief Return the version minor number */
-#define vpx_codec_version_minor() ((vpx_codec_version() >> 8) & 0xff)
-
-/*!\brief Return the version patch number */
-#define vpx_codec_version_patch() ((vpx_codec_version() >> 0) & 0xff)
-
-/*!\brief Return the version information (as a string)
- *
- * Returns a printable string containing the full library version number. This
- * may
- * contain additional text following the three digit version number, as to
- * indicate
- * release candidates, prerelease versions, etc.
- *
- */
-const char *vpx_codec_version_str(void);
-
-/*!\brief Return the version information (as a string)
- *
- * Returns a printable "extra string". This is the component of the string
- * returned
- * by vpx_codec_version_str() following the three digit version number.
- *
- */
-const char *vpx_codec_version_extra_str(void);
-
-/*!\brief Return the build configuration
- *
- * Returns a printable string containing an encoded version of the build
- * configuration. This may be useful to vpx support.
- *
- */
-const char *vpx_codec_build_config(void);
-
-/*!\brief Return the name for a given interface
- *
- * Returns a human readable string for name of the given codec interface.
- *
- * \param[in] iface Interface pointer
- *
- */
-const char *vpx_codec_iface_name(vpx_codec_iface_t *iface);
-
-/*!\brief Convert error number to printable string
- *
- * Returns a human readable string for the last error returned by the
- * algorithm. The returned error will be one line and will not contain
- * any newline characters.
- *
- *
- * \param[in] err Error number.
- *
- */
-const char *vpx_codec_err_to_string(vpx_codec_err_t err);
-
-/*!\brief Retrieve error synopsis for codec context
- *
- * Returns a human readable string for the last error returned by the
- * algorithm. The returned error will be one line and will not contain
- * any newline characters.
- *
- *
- * \param[in] ctx Pointer to this instance's context.
- *
- */
-const char *vpx_codec_error(vpx_codec_ctx_t *ctx);
-
-/*!\brief Retrieve detailed error information for codec context
- *
- * Returns a human readable string providing detailed information about
- * the last error.
- *
- * \param[in] ctx Pointer to this instance's context.
- *
- * \retval NULL
- * No detailed information is available.
- */
-const char *vpx_codec_error_detail(vpx_codec_ctx_t *ctx);
-
-/* REQUIRED FUNCTIONS
- *
- * The following functions are required to be implemented for all codecs.
- * They represent the base case functionality expected of all codecs.
- */
-
-/*!\brief Destroy a codec instance
- *
- * Destroys a codec context, freeing any associated memory buffers.
- *
- * \param[in] ctx Pointer to this instance's context
- *
- * \retval #VPX_CODEC_OK
- * The codec algorithm initialized.
- * \retval #VPX_CODEC_MEM_ERROR
- * Memory allocation failed.
- */
-vpx_codec_err_t vpx_codec_destroy(vpx_codec_ctx_t *ctx);
-
-/*!\brief Get the capabilities of an algorithm.
- *
- * Retrieves the capabilities bitfield from the algorithm's interface.
- *
- * \param[in] iface Pointer to the algorithm interface
- *
- */
-vpx_codec_caps_t vpx_codec_get_caps(vpx_codec_iface_t *iface);
-
-/*!\brief Control algorithm
- *
- * This function is used to exchange algorithm specific data with the codec
- * instance. This can be used to implement features specific to a particular
- * algorithm.
- *
- * This wrapper function dispatches the request to the helper function
- * associated with the given ctrl_id. It tries to call this function
- * transparently, but will return #VPX_CODEC_ERROR if the request could not
- * be dispatched.
- *
- * Note that this function should not be used directly. Call the
- * #vpx_codec_control wrapper macro instead.
- *
- * \param[in] ctx Pointer to this instance's context
- * \param[in] ctrl_id Algorithm specific control identifier
- *
- * \retval #VPX_CODEC_OK
- * The control request was processed.
- * \retval #VPX_CODEC_ERROR
- * The control request was not processed.
- * \retval #VPX_CODEC_INVALID_PARAM
- * The data was not valid.
- */
-vpx_codec_err_t vpx_codec_control_(vpx_codec_ctx_t *ctx, int ctrl_id, ...);
-#if defined(VPX_DISABLE_CTRL_TYPECHECKS) && VPX_DISABLE_CTRL_TYPECHECKS
-#define vpx_codec_control(ctx, id, data) vpx_codec_control_(ctx, id, data)
-#define VPX_CTRL_USE_TYPE(id, typ)
-#define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ)
-#define VPX_CTRL_VOID(id, typ)
-
-#else
-/*!\brief vpx_codec_control wrapper macro
- *
- * This macro allows for type safe conversions across the variadic parameter
- * to vpx_codec_control_().
- *
- * \internal
- * It works by dispatching the call to the control function through a wrapper
- * function named with the id parameter.
- */
-#define vpx_codec_control(ctx, id, data) \
- vpx_codec_control_##id(ctx, id, data) /**<\hideinitializer*/
-
-/*!\brief vpx_codec_control type definition macro
- *
- * This macro allows for type safe conversions across the variadic parameter
- * to vpx_codec_control_(). It defines the type of the argument for a given
- * control identifier.
- *
- * \internal
- * It defines a static function with
- * the correctly typed arguments as a wrapper to the type-unsafe internal
- * function.
- */
-#define VPX_CTRL_USE_TYPE(id, typ) \
- static vpx_codec_err_t vpx_codec_control_##id(vpx_codec_ctx_t *, int, typ) \
- UNUSED; \
- \
- static vpx_codec_err_t vpx_codec_control_##id(vpx_codec_ctx_t *ctx, \
- int ctrl_id, typ data) { \
- return vpx_codec_control_(ctx, ctrl_id, data); \
- } /**<\hideinitializer*/
-
-/*!\brief vpx_codec_control deprecated type definition macro
- *
- * Like #VPX_CTRL_USE_TYPE, but indicates that the specified control is
- * deprecated and should not be used. Consult the documentation for your
- * codec for more information.
- *
- * \internal
- * It defines a static function with the correctly typed arguments as a
- * wrapper to the type-unsafe internal function.
- */
-#define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ) \
- DECLSPEC_DEPRECATED static vpx_codec_err_t vpx_codec_control_##id( \
- vpx_codec_ctx_t *, int, typ) DEPRECATED UNUSED; \
- \
- DECLSPEC_DEPRECATED static vpx_codec_err_t vpx_codec_control_##id( \
- vpx_codec_ctx_t *ctx, int ctrl_id, typ data) { \
- return vpx_codec_control_(ctx, ctrl_id, data); \
- } /**<\hideinitializer*/
-
-/*!\brief vpx_codec_control void type definition macro
- *
- * This macro allows for type safe conversions across the variadic parameter
- * to vpx_codec_control_(). It indicates that a given control identifier takes
- * no argument.
- *
- * \internal
- * It defines a static function without a data argument as a wrapper to the
- * type-unsafe internal function.
- */
-#define VPX_CTRL_VOID(id) \
- static vpx_codec_err_t vpx_codec_control_##id(vpx_codec_ctx_t *, int) \
- UNUSED; \
- \
- static vpx_codec_err_t vpx_codec_control_##id(vpx_codec_ctx_t *ctx, \
- int ctrl_id) { \
- return vpx_codec_control_(ctx, ctrl_id); \
- } /**<\hideinitializer*/
-
-#endif
-
-/*!@} - end defgroup codec*/
-#ifdef __cplusplus
-}
-#endif
-#endif // VPX_VPX_CODEC_H_
diff --git a/protocols/Tox/include/vpx/vpx_decoder.h b/protocols/Tox/include/vpx/vpx_decoder.h
deleted file mode 100644
index 2ff12112bc..0000000000
--- a/protocols/Tox/include/vpx/vpx_decoder.h
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-#ifndef VPX_VPX_DECODER_H_
-#define VPX_VPX_DECODER_H_
-
-/*!\defgroup decoder Decoder Algorithm Interface
- * \ingroup codec
- * This abstraction allows applications using this decoder to easily support
- * multiple video formats with minimal code duplication. This section describes
- * the interface common to all decoders.
- * @{
- */
-
-/*!\file
- * \brief Describes the decoder algorithm interface to applications.
- *
- * This file describes the interface between an application and a
- * video decoder algorithm.
- *
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "./vpx_codec.h"
-#include "./vpx_frame_buffer.h"
-
-/*!\brief Current ABI version number
- *
- * \internal
- * If this file is altered in any way that changes the ABI, this value
- * must be bumped. Examples include, but are not limited to, changing
- * types, removing or reassigning enums, adding/removing/rearranging
- * fields to structures
- */
-#define VPX_DECODER_ABI_VERSION \
- (3 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/
-
-/*! \brief Decoder capabilities bitfield
- *
- * Each decoder advertises the capabilities it supports as part of its
- * ::vpx_codec_iface_t interface structure. Capabilities are extra interfaces
- * or functionality, and are not required to be supported by a decoder.
- *
- * The available flags are specified by VPX_CODEC_CAP_* defines.
- */
-#define VPX_CODEC_CAP_PUT_SLICE 0x10000 /**< Will issue put_slice callbacks */
-#define VPX_CODEC_CAP_PUT_FRAME 0x20000 /**< Will issue put_frame callbacks */
-#define VPX_CODEC_CAP_POSTPROC 0x40000 /**< Can postprocess decoded frame */
-/*!\brief Can conceal errors due to packet loss */
-#define VPX_CODEC_CAP_ERROR_CONCEALMENT 0x80000
-/*!\brief Can receive encoded frames one fragment at a time */
-#define VPX_CODEC_CAP_INPUT_FRAGMENTS 0x100000
-
-/*! \brief Initialization-time Feature Enabling
- *
- * Certain codec features must be known at initialization time, to allow for
- * proper memory allocation.
- *
- * The available flags are specified by VPX_CODEC_USE_* defines.
- */
-/*!\brief Can support frame-based multi-threading */
-#define VPX_CODEC_CAP_FRAME_THREADING 0x200000
-/*!brief Can support external frame buffers */
-#define VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER 0x400000
-
-#define VPX_CODEC_USE_POSTPROC 0x10000 /**< Postprocess decoded frame */
-/*!\brief Conceal errors in decoded frames */
-#define VPX_CODEC_USE_ERROR_CONCEALMENT 0x20000
-/*!\brief The input frame should be passed to the decoder one fragment at a
- * time */
-#define VPX_CODEC_USE_INPUT_FRAGMENTS 0x40000
-/*!\brief Enable frame-based multi-threading */
-#define VPX_CODEC_USE_FRAME_THREADING 0x80000
-
-/*!\brief Stream properties
- *
- * This structure is used to query or set properties of the decoded
- * stream. Algorithms may extend this structure with data specific
- * to their bitstream by setting the sz member appropriately.
- */
-typedef struct vpx_codec_stream_info {
- unsigned int sz; /**< Size of this structure */
- unsigned int w; /**< Width (or 0 for unknown/default) */
- unsigned int h; /**< Height (or 0 for unknown/default) */
- unsigned int is_kf; /**< Current frame is a keyframe */
-} vpx_codec_stream_info_t;
-
-/* REQUIRED FUNCTIONS
- *
- * The following functions are required to be implemented for all decoders.
- * They represent the base case functionality expected of all decoders.
- */
-
-/*!\brief Initialization Configurations
- *
- * This structure is used to pass init time configuration options to the
- * decoder.
- */
-typedef struct vpx_codec_dec_cfg {
- unsigned int threads; /**< Maximum number of threads to use, default 1 */
- unsigned int w; /**< Width */
- unsigned int h; /**< Height */
-} vpx_codec_dec_cfg_t; /**< alias for struct vpx_codec_dec_cfg */
-
-/*!\brief Initialize a decoder instance
- *
- * Initializes a decoder context using the given interface. Applications
- * should call the vpx_codec_dec_init convenience macro instead of this
- * function directly, to ensure that the ABI version number parameter
- * is properly initialized.
- *
- * If the library was configured with --disable-multithread, this call
- * is not thread safe and should be guarded with a lock if being used
- * in a multithreaded context.
- *
- * \param[in] ctx Pointer to this instance's context.
- * \param[in] iface Pointer to the algorithm interface to use.
- * \param[in] cfg Configuration to use, if known. May be NULL.
- * \param[in] flags Bitfield of VPX_CODEC_USE_* flags
- * \param[in] ver ABI version number. Must be set to
- * VPX_DECODER_ABI_VERSION
- * \retval #VPX_CODEC_OK
- * The decoder algorithm initialized.
- * \retval #VPX_CODEC_MEM_ERROR
- * Memory allocation failed.
- */
-vpx_codec_err_t vpx_codec_dec_init_ver(vpx_codec_ctx_t *ctx,
- vpx_codec_iface_t *iface,
- const vpx_codec_dec_cfg_t *cfg,
- vpx_codec_flags_t flags, int ver);
-
-/*!\brief Convenience macro for vpx_codec_dec_init_ver()
- *
- * Ensures the ABI version parameter is properly set.
- */
-#define vpx_codec_dec_init(ctx, iface, cfg, flags) \
- vpx_codec_dec_init_ver(ctx, iface, cfg, flags, VPX_DECODER_ABI_VERSION)
-
-/*!\brief Parse stream info from a buffer
- *
- * Performs high level parsing of the bitstream. Construction of a decoder
- * context is not necessary. Can be used to determine if the bitstream is
- * of the proper format, and to extract information from the stream.
- *
- * \param[in] iface Pointer to the algorithm interface
- * \param[in] data Pointer to a block of data to parse
- * \param[in] data_sz Size of the data buffer
- * \param[in,out] si Pointer to stream info to update. The size member
- * \ref MUST be properly initialized, but \ref MAY be
- * clobbered by the algorithm. This parameter \ref MAY
- * be NULL.
- *
- * \retval #VPX_CODEC_OK
- * Bitstream is parsable and stream information updated
- */
-vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t *iface,
- const uint8_t *data,
- unsigned int data_sz,
- vpx_codec_stream_info_t *si);
-
-/*!\brief Return information about the current stream.
- *
- * Returns information about the stream that has been parsed during decoding.
- *
- * \param[in] ctx Pointer to this instance's context
- * \param[in,out] si Pointer to stream info to update. The size member
- * \ref MUST be properly initialized, but \ref MAY be
- * clobbered by the algorithm. This parameter \ref MAY
- * be NULL.
- *
- * \retval #VPX_CODEC_OK
- * Bitstream is parsable and stream information updated
- */
-vpx_codec_err_t vpx_codec_get_stream_info(vpx_codec_ctx_t *ctx,
- vpx_codec_stream_info_t *si);
-
-/*!\brief Decode data
- *
- * Processes a buffer of coded data. If the processing results in a new
- * decoded frame becoming available, PUT_SLICE and PUT_FRAME events may be
- * generated, as appropriate. Encoded data \ref MUST be passed in DTS (decode
- * time stamp) order. Frames produced will always be in PTS (presentation
- * time stamp) order.
- * If the decoder is configured with VPX_CODEC_USE_INPUT_FRAGMENTS enabled,
- * data and data_sz can contain a fragment of the encoded frame. Fragment
- * \#n must contain at least partition \#n, but can also contain subsequent
- * partitions (\#n+1 - \#n+i), and if so, fragments \#n+1, .., \#n+i must
- * be empty. When no more data is available, this function should be called
- * with NULL as data and 0 as data_sz. The memory passed to this function
- * must be available until the frame has been decoded.
- *
- * \param[in] ctx Pointer to this instance's context
- * \param[in] data Pointer to this block of new coded data. If
- * NULL, a VPX_CODEC_CB_PUT_FRAME event is posted
- * for the previously decoded frame.
- * \param[in] data_sz Size of the coded data, in bytes.
- * \param[in] user_priv Application specific data to associate with
- * this frame.
- * \param[in] deadline Soft deadline the decoder should attempt to meet,
- * in us. Set to zero for unlimited.
- *
- * \return Returns #VPX_CODEC_OK if the coded data was processed completely
- * and future pictures can be decoded without error. Otherwise,
- * see the descriptions of the other error codes in ::vpx_codec_err_t
- * for recoverability capabilities.
- */
-vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t *ctx, const uint8_t *data,
- unsigned int data_sz, void *user_priv,
- long deadline);
-
-/*!\brief Decoded frames iterator
- *
- * Iterates over a list of the frames available for display. The iterator
- * storage should be initialized to NULL to start the iteration. Iteration is
- * complete when this function returns NULL.
- *
- * The list of available frames becomes valid upon completion of the
- * vpx_codec_decode call, and remains valid until the next call to
- * vpx_codec_decode.
- *
- * \param[in] ctx Pointer to this instance's context
- * \param[in,out] iter Iterator storage, initialized to NULL
- *
- * \return Returns a pointer to an image, if one is ready for display. Frames
- * produced will always be in PTS (presentation time stamp) order.
- */
-vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t *ctx, vpx_codec_iter_t *iter);
-
-/*!\defgroup cap_put_frame Frame-Based Decoding Functions
- *
- * The following functions are required to be implemented for all decoders
- * that advertise the VPX_CODEC_CAP_PUT_FRAME capability. Calling these
- * functions
- * for codecs that don't advertise this capability will result in an error
- * code being returned, usually VPX_CODEC_ERROR
- * @{
- */
-
-/*!\brief put frame callback prototype
- *
- * This callback is invoked by the decoder to notify the application of
- * the availability of decoded image data.
- */
-typedef void (*vpx_codec_put_frame_cb_fn_t)(void *user_priv,
- const vpx_image_t *img);
-
-/*!\brief Register for notification of frame completion.
- *
- * Registers a given function to be called when a decoded frame is
- * available.
- *
- * \param[in] ctx Pointer to this instance's context
- * \param[in] cb Pointer to the callback function
- * \param[in] user_priv User's private data
- *
- * \retval #VPX_CODEC_OK
- * Callback successfully registered.
- * \retval #VPX_CODEC_ERROR
- * Decoder context not initialized, or algorithm not capable of
- * posting slice completion.
- */
-vpx_codec_err_t vpx_codec_register_put_frame_cb(vpx_codec_ctx_t *ctx,
- vpx_codec_put_frame_cb_fn_t cb,
- void *user_priv);
-
-/*!@} - end defgroup cap_put_frame */
-
-/*!\defgroup cap_put_slice Slice-Based Decoding Functions
- *
- * The following functions are required to be implemented for all decoders
- * that advertise the VPX_CODEC_CAP_PUT_SLICE capability. Calling these
- * functions
- * for codecs that don't advertise this capability will result in an error
- * code being returned, usually VPX_CODEC_ERROR
- * @{
- */
-
-/*!\brief put slice callback prototype
- *
- * This callback is invoked by the decoder to notify the application of
- * the availability of partially decoded image data. The
- */
-typedef void (*vpx_codec_put_slice_cb_fn_t)(void *user_priv,
- const vpx_image_t *img,
- const vpx_image_rect_t *valid,
- const vpx_image_rect_t *update);
-
-/*!\brief Register for notification of slice completion.
- *
- * Registers a given function to be called when a decoded slice is
- * available.
- *
- * \param[in] ctx Pointer to this instance's context
- * \param[in] cb Pointer to the callback function
- * \param[in] user_priv User's private data
- *
- * \retval #VPX_CODEC_OK
- * Callback successfully registered.
- * \retval #VPX_CODEC_ERROR
- * Decoder context not initialized, or algorithm not capable of
- * posting slice completion.
- */
-vpx_codec_err_t vpx_codec_register_put_slice_cb(vpx_codec_ctx_t *ctx,
- vpx_codec_put_slice_cb_fn_t cb,
- void *user_priv);
-
-/*!@} - end defgroup cap_put_slice*/
-
-/*!\defgroup cap_external_frame_buffer External Frame Buffer Functions
- *
- * The following section is required to be implemented for all decoders
- * that advertise the VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER capability.
- * Calling this function for codecs that don't advertise this capability
- * will result in an error code being returned, usually VPX_CODEC_ERROR.
- *
- * \note
- * Currently this only works with VP9.
- * @{
- */
-
-/*!\brief Pass in external frame buffers for the decoder to use.
- *
- * Registers functions to be called when libvpx needs a frame buffer
- * to decode the current frame and a function to be called when libvpx does
- * not internally reference the frame buffer. This set function must
- * be called before the first call to decode or libvpx will assume the
- * default behavior of allocating frame buffers internally.
- *
- * \param[in] ctx Pointer to this instance's context
- * \param[in] cb_get Pointer to the get callback function
- * \param[in] cb_release Pointer to the release callback function
- * \param[in] cb_priv Callback's private data
- *
- * \retval #VPX_CODEC_OK
- * External frame buffers will be used by libvpx.
- * \retval #VPX_CODEC_INVALID_PARAM
- * One or more of the callbacks were NULL.
- * \retval #VPX_CODEC_ERROR
- * Decoder context not initialized, or algorithm not capable of
- * using external frame buffers.
- *
- * \note
- * When decoding VP9, the application may be required to pass in at least
- * #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS external frame
- * buffers.
- */
-vpx_codec_err_t vpx_codec_set_frame_buffer_functions(
- vpx_codec_ctx_t *ctx, vpx_get_frame_buffer_cb_fn_t cb_get,
- vpx_release_frame_buffer_cb_fn_t cb_release, void *cb_priv);
-
-/*!@} - end defgroup cap_external_frame_buffer */
-
-/*!@} - end defgroup decoder*/
-#ifdef __cplusplus
-}
-#endif
-#endif // VPX_VPX_DECODER_H_
diff --git a/protocols/Tox/include/vpx/vpx_encoder.h b/protocols/Tox/include/vpx/vpx_encoder.h
deleted file mode 100644
index 28fcd5f999..0000000000
--- a/protocols/Tox/include/vpx/vpx_encoder.h
+++ /dev/null
@@ -1,980 +0,0 @@
-/*
- * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-#ifndef VPX_VPX_ENCODER_H_
-#define VPX_VPX_ENCODER_H_
-
-/*!\defgroup encoder Encoder Algorithm Interface
- * \ingroup codec
- * This abstraction allows applications using this encoder to easily support
- * multiple video formats with minimal code duplication. This section describes
- * the interface common to all encoders.
- * @{
- */
-
-/*!\file
- * \brief Describes the encoder algorithm interface to applications.
- *
- * This file describes the interface between an application and a
- * video encoder algorithm.
- *
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "./vpx_codec.h"
-
-/*! Temporal Scalability: Maximum length of the sequence defining frame
- * layer membership
- */
-#define VPX_TS_MAX_PERIODICITY 16
-
-/*! Temporal Scalability: Maximum number of coding layers */
-#define VPX_TS_MAX_LAYERS 5
-
-/*!\deprecated Use #VPX_TS_MAX_PERIODICITY instead. */
-#define MAX_PERIODICITY VPX_TS_MAX_PERIODICITY
-
-/*! Temporal+Spatial Scalability: Maximum number of coding layers */
-#define VPX_MAX_LAYERS 12 // 3 temporal + 4 spatial layers are allowed.
-
-/*!\deprecated Use #VPX_MAX_LAYERS instead. */
-#define MAX_LAYERS VPX_MAX_LAYERS // 3 temporal + 4 spatial layers allowed.
-
-/*! Spatial Scalability: Maximum number of coding layers */
-#define VPX_SS_MAX_LAYERS 5
-
-/*! Spatial Scalability: Default number of coding layers */
-#define VPX_SS_DEFAULT_LAYERS 1
-
-/*!\brief Current ABI version number
- *
- * \internal
- * If this file is altered in any way that changes the ABI, this value
- * must be bumped. Examples include, but are not limited to, changing
- * types, removing or reassigning enums, adding/removing/rearranging
- * fields to structures
- */
-#define VPX_ENCODER_ABI_VERSION \
- (5 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/
-
-/*! \brief Encoder capabilities bitfield
- *
- * Each encoder advertises the capabilities it supports as part of its
- * ::vpx_codec_iface_t interface structure. Capabilities are extra
- * interfaces or functionality, and are not required to be supported
- * by an encoder.
- *
- * The available flags are specified by VPX_CODEC_CAP_* defines.
- */
-#define VPX_CODEC_CAP_PSNR 0x10000 /**< Can issue PSNR packets */
-
-/*! Can output one partition at a time. Each partition is returned in its
- * own VPX_CODEC_CX_FRAME_PKT, with the FRAME_IS_FRAGMENT flag set for
- * every partition but the last. In this mode all frames are always
- * returned partition by partition.
- */
-#define VPX_CODEC_CAP_OUTPUT_PARTITION 0x20000
-
-/*! Can support input images at greater than 8 bitdepth.
- */
-#define VPX_CODEC_CAP_HIGHBITDEPTH 0x40000
-
-/*! \brief Initialization-time Feature Enabling
- *
- * Certain codec features must be known at initialization time, to allow
- * for proper memory allocation.
- *
- * The available flags are specified by VPX_CODEC_USE_* defines.
- */
-#define VPX_CODEC_USE_PSNR 0x10000 /**< Calculate PSNR on each frame */
-/*!\brief Make the encoder output one partition at a time. */
-#define VPX_CODEC_USE_OUTPUT_PARTITION 0x20000
-#define VPX_CODEC_USE_HIGHBITDEPTH 0x40000 /**< Use high bitdepth */
-
-/*!\brief Generic fixed size buffer structure
- *
- * This structure is able to hold a reference to any fixed size buffer.
- */
-typedef struct vpx_fixed_buf {
- void *buf; /**< Pointer to the data */
- size_t sz; /**< Length of the buffer, in chars */
-} vpx_fixed_buf_t; /**< alias for struct vpx_fixed_buf */
-
-/*!\brief Time Stamp Type
- *
- * An integer, which when multiplied by the stream's time base, provides
- * the absolute time of a sample.
- */
-typedef int64_t vpx_codec_pts_t;
-
-/*!\brief Compressed Frame Flags
- *
- * This type represents a bitfield containing information about a compressed
- * frame that may be useful to an application. The most significant 16 bits
- * can be used by an algorithm to provide additional detail, for example to
- * support frame types that are codec specific (MPEG-1 D-frames for example)
- */
-typedef uint32_t vpx_codec_frame_flags_t;
-#define VPX_FRAME_IS_KEY 0x1 /**< frame is the start of a GOP */
-/*!\brief frame can be dropped without affecting the stream (no future frame
- * depends on this one) */
-#define VPX_FRAME_IS_DROPPABLE 0x2
-/*!\brief frame should be decoded but will not be shown */
-#define VPX_FRAME_IS_INVISIBLE 0x4
-/*!\brief this is a fragment of the encoded frame */
-#define VPX_FRAME_IS_FRAGMENT 0x8
-
-/*!\brief Error Resilient flags
- *
- * These flags define which error resilient features to enable in the
- * encoder. The flags are specified through the
- * vpx_codec_enc_cfg::g_error_resilient variable.
- */
-typedef uint32_t vpx_codec_er_flags_t;
-/*!\brief Improve resiliency against losses of whole frames */
-#define VPX_ERROR_RESILIENT_DEFAULT 0x1
-/*!\brief The frame partitions are independently decodable by the bool decoder,
- * meaning that partitions can be decoded even though earlier partitions have
- * been lost. Note that intra prediction is still done over the partition
- * boundary. */
-#define VPX_ERROR_RESILIENT_PARTITIONS 0x2
-
-/*!\brief Encoder output packet variants
- *
- * This enumeration lists the different kinds of data packets that can be
- * returned by calls to vpx_codec_get_cx_data(). Algorithms \ref MAY
- * extend this list to provide additional functionality.
- */
-enum vpx_codec_cx_pkt_kind {
- VPX_CODEC_CX_FRAME_PKT, /**< Compressed video frame */
- VPX_CODEC_STATS_PKT, /**< Two-pass statistics for this frame */
- VPX_CODEC_FPMB_STATS_PKT, /**< first pass mb statistics for this frame */
- VPX_CODEC_PSNR_PKT, /**< PSNR statistics for this frame */
-// Spatial SVC is still experimental and may be removed before the next ABI
-// bump.
-#if VPX_ENCODER_ABI_VERSION > (5 + VPX_CODEC_ABI_VERSION)
- VPX_CODEC_SPATIAL_SVC_LAYER_SIZES, /**< Sizes for each layer in this frame*/
- VPX_CODEC_SPATIAL_SVC_LAYER_PSNR, /**< PSNR for each layer in this frame*/
-#endif
- VPX_CODEC_CUSTOM_PKT = 256 /**< Algorithm extensions */
-};
-
-/*!\brief Encoder output packet
- *
- * This structure contains the different kinds of output data the encoder
- * may produce while compressing a frame.
- */
-typedef struct vpx_codec_cx_pkt {
- enum vpx_codec_cx_pkt_kind kind; /**< packet variant */
- union {
- struct {
- void *buf; /**< compressed data buffer */
- size_t sz; /**< length of compressed data */
- /*!\brief time stamp to show frame (in timebase units) */
- vpx_codec_pts_t pts;
- /*!\brief duration to show frame (in timebase units) */
- unsigned long duration;
- vpx_codec_frame_flags_t flags; /**< flags for this frame */
- /*!\brief the partition id defines the decoding order of the partitions.
- * Only applicable when "output partition" mode is enabled. First
- * partition has id 0.*/
- int partition_id;
- } frame; /**< data for compressed frame packet */
- vpx_fixed_buf_t twopass_stats; /**< data for two-pass packet */
- vpx_fixed_buf_t firstpass_mb_stats; /**< first pass mb packet */
- struct vpx_psnr_pkt {
- unsigned int samples[4]; /**< Number of samples, total/y/u/v */
- uint64_t sse[4]; /**< sum squared error, total/y/u/v */
- double psnr[4]; /**< PSNR, total/y/u/v */
- } psnr; /**< data for PSNR packet */
- vpx_fixed_buf_t raw; /**< data for arbitrary packets */
-// Spatial SVC is still experimental and may be removed before the next
-// ABI bump.
-#if VPX_ENCODER_ABI_VERSION > (5 + VPX_CODEC_ABI_VERSION)
- size_t layer_sizes[VPX_SS_MAX_LAYERS];
- struct vpx_psnr_pkt layer_psnr[VPX_SS_MAX_LAYERS];
-#endif
-
- /* This packet size is fixed to allow codecs to extend this
- * interface without having to manage storage for raw packets,
- * i.e., if it's smaller than 128 bytes, you can store in the
- * packet list directly.
- */
- char pad[128 - sizeof(enum vpx_codec_cx_pkt_kind)]; /**< fixed sz */
- } data; /**< packet data */
-} vpx_codec_cx_pkt_t; /**< alias for struct vpx_codec_cx_pkt */
-
-/*!\brief Encoder return output buffer callback
- *
- * This callback function, when registered, returns with packets when each
- * spatial layer is encoded.
- */
-// putting the definitions here for now. (agrange: find if there
-// is a better place for this)
-typedef void (*vpx_codec_enc_output_cx_pkt_cb_fn_t)(vpx_codec_cx_pkt_t *pkt,
- void *user_data);
-
-/*!\brief Callback function pointer / user data pair storage */
-typedef struct vpx_codec_enc_output_cx_cb_pair {
- vpx_codec_enc_output_cx_pkt_cb_fn_t output_cx_pkt; /**< Callback function */
- void *user_priv; /**< Pointer to private data */
-} vpx_codec_priv_output_cx_pkt_cb_pair_t;
-
-/*!\brief Rational Number
- *
- * This structure holds a fractional value.
- */
-typedef struct vpx_rational {
- int num; /**< fraction numerator */
- int den; /**< fraction denominator */
-} vpx_rational_t; /**< alias for struct vpx_rational */
-
-/*!\brief Multi-pass Encoding Pass */
-enum vpx_enc_pass {
- VPX_RC_ONE_PASS, /**< Single pass mode */
- VPX_RC_FIRST_PASS, /**< First pass of multi-pass mode */
- VPX_RC_LAST_PASS /**< Final pass of multi-pass mode */
-};
-
-/*!\brief Rate control mode */
-enum vpx_rc_mode {
- VPX_VBR, /**< Variable Bit Rate (VBR) mode */
- VPX_CBR, /**< Constant Bit Rate (CBR) mode */
- VPX_CQ, /**< Constrained Quality (CQ) mode */
- VPX_Q, /**< Constant Quality (Q) mode */
-};
-
-/*!\brief Keyframe placement mode.
- *
- * This enumeration determines whether keyframes are placed automatically by
- * the encoder or whether this behavior is disabled. Older releases of this
- * SDK were implemented such that VPX_KF_FIXED meant keyframes were disabled.
- * This name is confusing for this behavior, so the new symbols to be used
- * are VPX_KF_AUTO and VPX_KF_DISABLED.
- */
-enum vpx_kf_mode {
- VPX_KF_FIXED, /**< deprecated, implies VPX_KF_DISABLED */
- VPX_KF_AUTO, /**< Encoder determines optimal placement automatically */
- VPX_KF_DISABLED = 0 /**< Encoder does not place keyframes. */
-};
-
-/*!\brief Encoded Frame Flags
- *
- * This type indicates a bitfield to be passed to vpx_codec_encode(), defining
- * per-frame boolean values. By convention, bits common to all codecs will be
- * named VPX_EFLAG_*, and bits specific to an algorithm will be named
- * /algo/_eflag_*. The lower order 16 bits are reserved for common use.
- */
-typedef long vpx_enc_frame_flags_t;
-#define VPX_EFLAG_FORCE_KF (1 << 0) /**< Force this frame to be a keyframe */
-
-/*!\brief Encoder configuration structure
- *
- * This structure contains the encoder settings that have common representations
- * across all codecs. This doesn't imply that all codecs support all features,
- * however.
- */
-typedef struct vpx_codec_enc_cfg {
- /*
- * generic settings (g)
- */
-
- /*!\brief Algorithm specific "usage" value
- *
- * Algorithms may define multiple values for usage, which may convey the
- * intent of how the application intends to use the stream. If this value
- * is non-zero, consult the documentation for the codec to determine its
- * meaning.
- */
- unsigned int g_usage;
-
- /*!\brief Maximum number of threads to use
- *
- * For multi-threaded implementations, use no more than this number of
- * threads. The codec may use fewer threads than allowed. The value
- * 0 is equivalent to the value 1.
- */
- unsigned int g_threads;
-
- /*!\brief Bitstream profile to use
- *
- * Some codecs support a notion of multiple bitstream profiles. Typically
- * this maps to a set of features that are turned on or off. Often the
- * profile to use is determined by the features of the intended decoder.
- * Consult the documentation for the codec to determine the valid values
- * for this parameter, or set to zero for a sane default.
- */
- unsigned int g_profile; /**< profile of bitstream to use */
-
- /*!\brief Width of the frame
- *
- * This value identifies the presentation resolution of the frame,
- * in pixels. Note that the frames passed as input to the encoder must
- * have this resolution. Frames will be presented by the decoder in this
- * resolution, independent of any spatial resampling the encoder may do.
- */
- unsigned int g_w;
-
- /*!\brief Height of the frame
- *
- * This value identifies the presentation resolution of the frame,
- * in pixels. Note that the frames passed as input to the encoder must
- * have this resolution. Frames will be presented by the decoder in this
- * resolution, independent of any spatial resampling the encoder may do.
- */
- unsigned int g_h;
-
- /*!\brief Bit-depth of the codec
- *
- * This value identifies the bit_depth of the codec,
- * Only certain bit-depths are supported as identified in the
- * vpx_bit_depth_t enum.
- */
- vpx_bit_depth_t g_bit_depth;
-
- /*!\brief Bit-depth of the input frames
- *
- * This value identifies the bit_depth of the input frames in bits.
- * Note that the frames passed as input to the encoder must have
- * this bit-depth.
- */
- unsigned int g_input_bit_depth;
-
- /*!\brief Stream timebase units
- *
- * Indicates the smallest interval of time, in seconds, used by the stream.
- * For fixed frame rate material, or variable frame rate material where
- * frames are timed at a multiple of a given clock (ex: video capture),
- * the \ref RECOMMENDED method is to set the timebase to the reciprocal
- * of the frame rate (ex: 1001/30000 for 29.970 Hz NTSC). This allows the
- * pts to correspond to the frame number, which can be handy. For
- * re-encoding video from containers with absolute time timestamps, the
- * \ref RECOMMENDED method is to set the timebase to that of the parent
- * container or multimedia framework (ex: 1/1000 for ms, as in FLV).
- */
- struct vpx_rational g_timebase;
-
- /*!\brief Enable error resilient modes.
- *
- * The error resilient bitfield indicates to the encoder which features
- * it should enable to take measures for streaming over lossy or noisy
- * links.
- */
- vpx_codec_er_flags_t g_error_resilient;
-
- /*!\brief Multi-pass Encoding Mode
- *
- * This value should be set to the current phase for multi-pass encoding.
- * For single pass, set to #VPX_RC_ONE_PASS.
- */
- enum vpx_enc_pass g_pass;
-
- /*!\brief Allow lagged encoding
- *
- * If set, this value allows the encoder to consume a number of input
- * frames before producing output frames. This allows the encoder to
- * base decisions for the current frame on future frames. This does
- * increase the latency of the encoding pipeline, so it is not appropriate
- * in all situations (ex: realtime encoding).
- *
- * Note that this is a maximum value -- the encoder may produce frames
- * sooner than the given limit. Set this value to 0 to disable this
- * feature.
- */
- unsigned int g_lag_in_frames;
-
- /*
- * rate control settings (rc)
- */
-
- /*!\brief Temporal resampling configuration, if supported by the codec.
- *
- * Temporal resampling allows the codec to "drop" frames as a strategy to
- * meet its target data rate. This can cause temporal discontinuities in
- * the encoded video, which may appear as stuttering during playback. This
- * trade-off is often acceptable, but for many applications is not. It can
- * be disabled in these cases.
- *
- * Note that not all codecs support this feature. All vpx VPx codecs do.
- * For other codecs, consult the documentation for that algorithm.
- *
- * This threshold is described as a percentage of the target data buffer.
- * When the data buffer falls below this percentage of fullness, a
- * dropped frame is indicated. Set the threshold to zero (0) to disable
- * this feature.
- */
- unsigned int rc_dropframe_thresh;
-
- /*!\brief Enable/disable spatial resampling, if supported by the codec.
- *
- * Spatial resampling allows the codec to compress a lower resolution
- * version of the frame, which is then upscaled by the encoder to the
- * correct presentation resolution. This increases visual quality at
- * low data rates, at the expense of CPU time on the encoder/decoder.
- */
- unsigned int rc_resize_allowed;
-
- /*!\brief Internal coded frame width.
- *
- * If spatial resampling is enabled this specifies the width of the
- * encoded frame.
- */
- unsigned int rc_scaled_width;
-
- /*!\brief Internal coded frame height.
- *
- * If spatial resampling is enabled this specifies the height of the
- * encoded frame.
- */
- unsigned int rc_scaled_height;
-
- /*!\brief Spatial resampling up watermark.
- *
- * This threshold is described as a percentage of the target data buffer.
- * When the data buffer rises above this percentage of fullness, the
- * encoder will step up to a higher resolution version of the frame.
- */
- unsigned int rc_resize_up_thresh;
-
- /*!\brief Spatial resampling down watermark.
- *
- * This threshold is described as a percentage of the target data buffer.
- * When the data buffer falls below this percentage of fullness, the
- * encoder will step down to a lower resolution version of the frame.
- */
- unsigned int rc_resize_down_thresh;
-
- /*!\brief Rate control algorithm to use.
- *
- * Indicates whether the end usage of this stream is to be streamed over
- * a bandwidth constrained link, indicating that Constant Bit Rate (CBR)
- * mode should be used, or whether it will be played back on a high
- * bandwidth link, as from a local disk, where higher variations in
- * bitrate are acceptable.
- */
- enum vpx_rc_mode rc_end_usage;
-
- /*!\brief Two-pass stats buffer.
- *
- * A buffer containing all of the stats packets produced in the first
- * pass, concatenated.
- */
- vpx_fixed_buf_t rc_twopass_stats_in;
-
- /*!\brief first pass mb stats buffer.
- *
- * A buffer containing all of the first pass mb stats packets produced
- * in the first pass, concatenated.
- */
- vpx_fixed_buf_t rc_firstpass_mb_stats_in;
-
- /*!\brief Target data rate
- *
- * Target bandwidth to use for this stream, in kilobits per second.
- */
- unsigned int rc_target_bitrate;
-
- /*
- * quantizer settings
- */
-
- /*!\brief Minimum (Best Quality) Quantizer
- *
- * The quantizer is the most direct control over the quality of the
- * encoded image. The range of valid values for the quantizer is codec
- * specific. Consult the documentation for the codec to determine the
- * values to use. To determine the range programmatically, call
- * vpx_codec_enc_config_default() with a usage value of 0.
- */
- unsigned int rc_min_quantizer;
-
- /*!\brief Maximum (Worst Quality) Quantizer
- *
- * The quantizer is the most direct control over the quality of the
- * encoded image. The range of valid values for the quantizer is codec
- * specific. Consult the documentation for the codec to determine the
- * values to use. To determine the range programmatically, call
- * vpx_codec_enc_config_default() with a usage value of 0.
- */
- unsigned int rc_max_quantizer;
-
- /*
- * bitrate tolerance
- */
-
- /*!\brief Rate control adaptation undershoot control
- *
- * This value, expressed as a percentage of the target bitrate,
- * controls the maximum allowed adaptation speed of the codec.
- * This factor controls the maximum amount of bits that can
- * be subtracted from the target bitrate in order to compensate
- * for prior overshoot.
- *
- * Valid values in the range 0-1000.
- */
- unsigned int rc_undershoot_pct;
-
- /*!\brief Rate control adaptation overshoot control
- *
- * This value, expressed as a percentage of the target bitrate,
- * controls the maximum allowed adaptation speed of the codec.
- * This factor controls the maximum amount of bits that can
- * be added to the target bitrate in order to compensate for
- * prior undershoot.
- *
- * Valid values in the range 0-1000.
- */
- unsigned int rc_overshoot_pct;
-
- /*
- * decoder buffer model parameters
- */
-
- /*!\brief Decoder Buffer Size
- *
- * This value indicates the amount of data that may be buffered by the
- * decoding application. Note that this value is expressed in units of
- * time (milliseconds). For example, a value of 5000 indicates that the
- * client will buffer (at least) 5000ms worth of encoded data. Use the
- * target bitrate (#rc_target_bitrate) to convert to bits/bytes, if
- * necessary.
- */
- unsigned int rc_buf_sz;
-
- /*!\brief Decoder Buffer Initial Size
- *
- * This value indicates the amount of data that will be buffered by the
- * decoding application prior to beginning playback. This value is
- * expressed in units of time (milliseconds). Use the target bitrate
- * (#rc_target_bitrate) to convert to bits/bytes, if necessary.
- */
- unsigned int rc_buf_initial_sz;
-
- /*!\brief Decoder Buffer Optimal Size
- *
- * This value indicates the amount of data that the encoder should try
- * to maintain in the decoder's buffer. This value is expressed in units
- * of time (milliseconds). Use the target bitrate (#rc_target_bitrate)
- * to convert to bits/bytes, if necessary.
- */
- unsigned int rc_buf_optimal_sz;
-
- /*
- * 2 pass rate control parameters
- */
-
- /*!\brief Two-pass mode CBR/VBR bias
- *
- * Bias, expressed on a scale of 0 to 100, for determining target size
- * for the current frame. The value 0 indicates the optimal CBR mode
- * value should be used. The value 100 indicates the optimal VBR mode
- * value should be used. Values in between indicate which way the
- * encoder should "lean."
- */
- unsigned int rc_2pass_vbr_bias_pct;
-
- /*!\brief Two-pass mode per-GOP minimum bitrate
- *
- * This value, expressed as a percentage of the target bitrate, indicates
- * the minimum bitrate to be used for a single GOP (aka "section")
- */
- unsigned int rc_2pass_vbr_minsection_pct;
-
- /*!\brief Two-pass mode per-GOP maximum bitrate
- *
- * This value, expressed as a percentage of the target bitrate, indicates
- * the maximum bitrate to be used for a single GOP (aka "section")
- */
- unsigned int rc_2pass_vbr_maxsection_pct;
-
- /*
- * keyframing settings (kf)
- */
-
- /*!\brief Keyframe placement mode
- *
- * This value indicates whether the encoder should place keyframes at a
- * fixed interval, or determine the optimal placement automatically
- * (as governed by the #kf_min_dist and #kf_max_dist parameters)
- */
- enum vpx_kf_mode kf_mode;
-
- /*!\brief Keyframe minimum interval
- *
- * This value, expressed as a number of frames, prevents the encoder from
- * placing a keyframe nearer than kf_min_dist to the previous keyframe. At
- * least kf_min_dist frames non-keyframes will be coded before the next
- * keyframe. Set kf_min_dist equal to kf_max_dist for a fixed interval.
- */
- unsigned int kf_min_dist;
-
- /*!\brief Keyframe maximum interval
- *
- * This value, expressed as a number of frames, forces the encoder to code
- * a keyframe if one has not been coded in the last kf_max_dist frames.
- * A value of 0 implies all frames will be keyframes. Set kf_min_dist
- * equal to kf_max_dist for a fixed interval.
- */
- unsigned int kf_max_dist;
-
- /*
- * Spatial scalability settings (ss)
- */
-
- /*!\brief Number of spatial coding layers.
- *
- * This value specifies the number of spatial coding layers to be used.
- */
- unsigned int ss_number_layers;
-
- /*!\brief Enable auto alt reference flags for each spatial layer.
- *
- * These values specify if auto alt reference frame is enabled for each
- * spatial layer.
- */
- int ss_enable_auto_alt_ref[VPX_SS_MAX_LAYERS];
-
- /*!\brief Target bitrate for each spatial layer.
- *
- * These values specify the target coding bitrate to be used for each
- * spatial layer.
- */
- unsigned int ss_target_bitrate[VPX_SS_MAX_LAYERS];
-
- /*!\brief Number of temporal coding layers.
- *
- * This value specifies the number of temporal layers to be used.
- */
- unsigned int ts_number_layers;
-
- /*!\brief Target bitrate for each temporal layer.
- *
- * These values specify the target coding bitrate to be used for each
- * temporal layer.
- */
- unsigned int ts_target_bitrate[VPX_TS_MAX_LAYERS];
-
- /*!\brief Frame rate decimation factor for each temporal layer.
- *
- * These values specify the frame rate decimation factors to apply
- * to each temporal layer.
- */
- unsigned int ts_rate_decimator[VPX_TS_MAX_LAYERS];
-
- /*!\brief Length of the sequence defining frame temporal layer membership.
- *
- * This value specifies the length of the sequence that defines the
- * membership of frames to temporal layers. For example, if the
- * ts_periodicity = 8, then the frames are assigned to coding layers with a
- * repeated sequence of length 8.
- */
- unsigned int ts_periodicity;
-
- /*!\brief Template defining the membership of frames to temporal layers.
- *
- * This array defines the membership of frames to temporal coding layers.
- * For a 2-layer encoding that assigns even numbered frames to one temporal
- * layer (0) and odd numbered frames to a second temporal layer (1) with
- * ts_periodicity=8, then ts_layer_id = (0,1,0,1,0,1,0,1).
- */
- unsigned int ts_layer_id[VPX_TS_MAX_PERIODICITY];
-
- /*!\brief Target bitrate for each spatial/temporal layer.
- *
- * These values specify the target coding bitrate to be used for each
- * spatial/temporal layer.
- *
- */
- unsigned int layer_target_bitrate[VPX_MAX_LAYERS];
-
- /*!\brief Temporal layering mode indicating which temporal layering scheme to
- * use.
- *
- * The value (refer to VP9E_TEMPORAL_LAYERING_MODE) specifies the
- * temporal layering mode to use.
- *
- */
- int temporal_layering_mode;
-} vpx_codec_enc_cfg_t; /**< alias for struct vpx_codec_enc_cfg */
-
-/*!\brief vp9 svc extra configure parameters
- *
- * This defines max/min quantizers and scale factors for each layer
- *
- */
-typedef struct vpx_svc_parameters {
- int max_quantizers[VPX_MAX_LAYERS]; /**< Max Q for each layer */
- int min_quantizers[VPX_MAX_LAYERS]; /**< Min Q for each layer */
- int scaling_factor_num[VPX_MAX_LAYERS]; /**< Scaling factor-numerator */
- int scaling_factor_den[VPX_MAX_LAYERS]; /**< Scaling factor-denominator */
- int speed_per_layer[VPX_MAX_LAYERS]; /**< Speed setting for each sl */
- int temporal_layering_mode; /**< Temporal layering mode */
-} vpx_svc_extra_cfg_t;
-
-/*!\brief Initialize an encoder instance
- *
- * Initializes a encoder context using the given interface. Applications
- * should call the vpx_codec_enc_init convenience macro instead of this
- * function directly, to ensure that the ABI version number parameter
- * is properly initialized.
- *
- * If the library was configured with --disable-multithread, this call
- * is not thread safe and should be guarded with a lock if being used
- * in a multithreaded context.
- *
- * \param[in] ctx Pointer to this instance's context.
- * \param[in] iface Pointer to the algorithm interface to use.
- * \param[in] cfg Configuration to use, if known. May be NULL.
- * \param[in] flags Bitfield of VPX_CODEC_USE_* flags
- * \param[in] ver ABI version number. Must be set to
- * VPX_ENCODER_ABI_VERSION
- * \retval #VPX_CODEC_OK
- * The decoder algorithm initialized.
- * \retval #VPX_CODEC_MEM_ERROR
- * Memory allocation failed.
- */
-vpx_codec_err_t vpx_codec_enc_init_ver(vpx_codec_ctx_t *ctx,
- vpx_codec_iface_t *iface,
- const vpx_codec_enc_cfg_t *cfg,
- vpx_codec_flags_t flags, int ver);
-
-/*!\brief Convenience macro for vpx_codec_enc_init_ver()
- *
- * Ensures the ABI version parameter is properly set.
- */
-#define vpx_codec_enc_init(ctx, iface, cfg, flags) \
- vpx_codec_enc_init_ver(ctx, iface, cfg, flags, VPX_ENCODER_ABI_VERSION)
-
-/*!\brief Initialize multi-encoder instance
- *
- * Initializes multi-encoder context using the given interface.
- * Applications should call the vpx_codec_enc_init_multi convenience macro
- * instead of this function directly, to ensure that the ABI version number
- * parameter is properly initialized.
- *
- * \param[in] ctx Pointer to this instance's context.
- * \param[in] iface Pointer to the algorithm interface to use.
- * \param[in] cfg Configuration to use, if known. May be NULL.
- * \param[in] num_enc Total number of encoders.
- * \param[in] flags Bitfield of VPX_CODEC_USE_* flags
- * \param[in] dsf Pointer to down-sampling factors.
- * \param[in] ver ABI version number. Must be set to
- * VPX_ENCODER_ABI_VERSION
- * \retval #VPX_CODEC_OK
- * The decoder algorithm initialized.
- * \retval #VPX_CODEC_MEM_ERROR
- * Memory allocation failed.
- */
-vpx_codec_err_t vpx_codec_enc_init_multi_ver(
- vpx_codec_ctx_t *ctx, vpx_codec_iface_t *iface, vpx_codec_enc_cfg_t *cfg,
- int num_enc, vpx_codec_flags_t flags, vpx_rational_t *dsf, int ver);
-
-/*!\brief Convenience macro for vpx_codec_enc_init_multi_ver()
- *
- * Ensures the ABI version parameter is properly set.
- */
-#define vpx_codec_enc_init_multi(ctx, iface, cfg, num_enc, flags, dsf) \
- vpx_codec_enc_init_multi_ver(ctx, iface, cfg, num_enc, flags, dsf, \
- VPX_ENCODER_ABI_VERSION)
-
-/*!\brief Get a default configuration
- *
- * Initializes a encoder configuration structure with default values. Supports
- * the notion of "usages" so that an algorithm may offer different default
- * settings depending on the user's intended goal. This function \ref SHOULD
- * be called by all applications to initialize the configuration structure
- * before specializing the configuration with application specific values.
- *
- * \param[in] iface Pointer to the algorithm interface to use.
- * \param[out] cfg Configuration buffer to populate.
- * \param[in] reserved Must set to 0 for VP8 and VP9.
- *
- * \retval #VPX_CODEC_OK
- * The configuration was populated.
- * \retval #VPX_CODEC_INCAPABLE
- * Interface is not an encoder interface.
- * \retval #VPX_CODEC_INVALID_PARAM
- * A parameter was NULL, or the usage value was not recognized.
- */
-vpx_codec_err_t vpx_codec_enc_config_default(vpx_codec_iface_t *iface,
- vpx_codec_enc_cfg_t *cfg,
- unsigned int reserved);
-
-/*!\brief Set or change configuration
- *
- * Reconfigures an encoder instance according to the given configuration.
- *
- * \param[in] ctx Pointer to this instance's context
- * \param[in] cfg Configuration buffer to use
- *
- * \retval #VPX_CODEC_OK
- * The configuration was populated.
- * \retval #VPX_CODEC_INCAPABLE
- * Interface is not an encoder interface.
- * \retval #VPX_CODEC_INVALID_PARAM
- * A parameter was NULL, or the usage value was not recognized.
- */
-vpx_codec_err_t vpx_codec_enc_config_set(vpx_codec_ctx_t *ctx,
- const vpx_codec_enc_cfg_t *cfg);
-
-/*!\brief Get global stream headers
- *
- * Retrieves a stream level global header packet, if supported by the codec.
- *
- * \param[in] ctx Pointer to this instance's context
- *
- * \retval NULL
- * Encoder does not support global header
- * \retval Non-NULL
- * Pointer to buffer containing global header packet
- */
-vpx_fixed_buf_t *vpx_codec_get_global_headers(vpx_codec_ctx_t *ctx);
-
-/*!\brief deadline parameter analogous to VPx REALTIME mode. */
-#define VPX_DL_REALTIME (1)
-/*!\brief deadline parameter analogous to VPx GOOD QUALITY mode. */
-#define VPX_DL_GOOD_QUALITY (1000000)
-/*!\brief deadline parameter analogous to VPx BEST QUALITY mode. */
-#define VPX_DL_BEST_QUALITY (0)
-/*!\brief Encode a frame
- *
- * Encodes a video frame at the given "presentation time." The presentation
- * time stamp (PTS) \ref MUST be strictly increasing.
- *
- * The encoder supports the notion of a soft real-time deadline. Given a
- * non-zero value to the deadline parameter, the encoder will make a "best
- * effort" guarantee to return before the given time slice expires. It is
- * implicit that limiting the available time to encode will degrade the
- * output quality. The encoder can be given an unlimited time to produce the
- * best possible frame by specifying a deadline of '0'. This deadline
- * supercedes the VPx notion of "best quality, good quality, realtime".
- * Applications that wish to map these former settings to the new deadline
- * based system can use the symbols #VPX_DL_REALTIME, #VPX_DL_GOOD_QUALITY,
- * and #VPX_DL_BEST_QUALITY.
- *
- * When the last frame has been passed to the encoder, this function should
- * continue to be called, with the img parameter set to NULL. This will
- * signal the end-of-stream condition to the encoder and allow it to encode
- * any held buffers. Encoding is complete when vpx_codec_encode() is called
- * and vpx_codec_get_cx_data() returns no data.
- *
- * \param[in] ctx Pointer to this instance's context
- * \param[in] img Image data to encode, NULL to flush.
- * \param[in] pts Presentation time stamp, in timebase units.
- * \param[in] duration Duration to show frame, in timebase units.
- * \param[in] flags Flags to use for encoding this frame.
- * \param[in] deadline Time to spend encoding, in microseconds. (0=infinite)
- *
- * \retval #VPX_CODEC_OK
- * The configuration was populated.
- * \retval #VPX_CODEC_INCAPABLE
- * Interface is not an encoder interface.
- * \retval #VPX_CODEC_INVALID_PARAM
- * A parameter was NULL, the image format is unsupported, etc.
- */
-vpx_codec_err_t vpx_codec_encode(vpx_codec_ctx_t *ctx, const vpx_image_t *img,
- vpx_codec_pts_t pts, unsigned long duration,
- vpx_enc_frame_flags_t flags,
- unsigned long deadline);
-
-/*!\brief Set compressed data output buffer
- *
- * Sets the buffer that the codec should output the compressed data
- * into. This call effectively sets the buffer pointer returned in the
- * next VPX_CODEC_CX_FRAME_PKT packet. Subsequent packets will be
- * appended into this buffer. The buffer is preserved across frames,
- * so applications must periodically call this function after flushing
- * the accumulated compressed data to disk or to the network to reset
- * the pointer to the buffer's head.
- *
- * `pad_before` bytes will be skipped before writing the compressed
- * data, and `pad_after` bytes will be appended to the packet. The size
- * of the packet will be the sum of the size of the actual compressed
- * data, pad_before, and pad_after. The padding bytes will be preserved
- * (not overwritten).
- *
- * Note that calling this function does not guarantee that the returned
- * compressed data will be placed into the specified buffer. In the
- * event that the encoded data will not fit into the buffer provided,
- * the returned packet \ref MAY point to an internal buffer, as it would
- * if this call were never used. In this event, the output packet will
- * NOT have any padding, and the application must free space and copy it
- * to the proper place. This is of particular note in configurations
- * that may output multiple packets for a single encoded frame (e.g., lagged
- * encoding) or if the application does not reset the buffer periodically.
- *
- * Applications may restore the default behavior of the codec providing
- * the compressed data buffer by calling this function with a NULL
- * buffer.
- *
- * Applications \ref MUSTNOT call this function during iteration of
- * vpx_codec_get_cx_data().
- *
- * \param[in] ctx Pointer to this instance's context
- * \param[in] buf Buffer to store compressed data into
- * \param[in] pad_before Bytes to skip before writing compressed data
- * \param[in] pad_after Bytes to skip after writing compressed data
- *
- * \retval #VPX_CODEC_OK
- * The buffer was set successfully.
- * \retval #VPX_CODEC_INVALID_PARAM
- * A parameter was NULL, the image format is unsupported, etc.
- */
-vpx_codec_err_t vpx_codec_set_cx_data_buf(vpx_codec_ctx_t *ctx,
- const vpx_fixed_buf_t *buf,
- unsigned int pad_before,
- unsigned int pad_after);
-
-/*!\brief Encoded data iterator
- *
- * Iterates over a list of data packets to be passed from the encoder to the
- * application. The different kinds of packets available are enumerated in
- * #vpx_codec_cx_pkt_kind.
- *
- * #VPX_CODEC_CX_FRAME_PKT packets should be passed to the application's
- * muxer. Multiple compressed frames may be in the list.
- * #VPX_CODEC_STATS_PKT packets should be appended to a global buffer.
- *
- * The application \ref MUST silently ignore any packet kinds that it does
- * not recognize or support.
- *
- * The data buffers returned from this function are only guaranteed to be
- * valid until the application makes another call to any vpx_codec_* function.
- *
- * \param[in] ctx Pointer to this instance's context
- * \param[in,out] iter Iterator storage, initialized to NULL
- *
- * \return Returns a pointer to an output data packet (compressed frame data,
- * two-pass statistics, etc.) or NULL to signal end-of-list.
- *
- */
-const vpx_codec_cx_pkt_t *vpx_codec_get_cx_data(vpx_codec_ctx_t *ctx,
- vpx_codec_iter_t *iter);
-
-/*!\brief Get Preview Frame
- *
- * Returns an image that can be used as a preview. Shows the image as it would
- * exist at the decompressor. The application \ref MUST NOT write into this
- * image buffer.
- *
- * \param[in] ctx Pointer to this instance's context
- *
- * \return Returns a pointer to a preview image, or NULL if no image is
- * available.
- *
- */
-const vpx_image_t *vpx_codec_get_preview_frame(vpx_codec_ctx_t *ctx);
-
-/*!@} - end defgroup encoder*/
-#ifdef __cplusplus
-}
-#endif
-#endif // VPX_VPX_ENCODER_H_
diff --git a/protocols/Tox/include/vpx/vpx_frame_buffer.h b/protocols/Tox/include/vpx/vpx_frame_buffer.h
deleted file mode 100644
index ad70cdd572..0000000000
--- a/protocols/Tox/include/vpx/vpx_frame_buffer.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2014 The WebM project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef VPX_VPX_FRAME_BUFFER_H_
-#define VPX_VPX_FRAME_BUFFER_H_
-
-/*!\file
- * \brief Describes the decoder external frame buffer interface.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "./vpx_integer.h"
-
-/*!\brief The maximum number of work buffers used by libvpx.
- * Support maximum 4 threads to decode video in parallel.
- * Each thread will use one work buffer.
- * TODO(hkuang): Add support to set number of worker threads dynamically.
- */
-#define VPX_MAXIMUM_WORK_BUFFERS 8
-
-/*!\brief The maximum number of reference buffers that a VP9 encoder may use.
- */
-#define VP9_MAXIMUM_REF_BUFFERS 8
-
-/*!\brief External frame buffer
- *
- * This structure holds allocated frame buffers used by the decoder.
- */
-typedef struct vpx_codec_frame_buffer {
- uint8_t *data; /**< Pointer to the data buffer */
- size_t size; /**< Size of data in bytes */
- void *priv; /**< Frame's private data */
-} vpx_codec_frame_buffer_t;
-
-/*!\brief get frame buffer callback prototype
- *
- * This callback is invoked by the decoder to retrieve data for the frame
- * buffer in order for the decode call to complete. The callback must
- * allocate at least min_size in bytes and assign it to fb->data. The callback
- * must zero out all the data allocated. Then the callback must set fb->size
- * to the allocated size. The application does not need to align the allocated
- * data. The callback is triggered when the decoder needs a frame buffer to
- * decode a compressed image into. This function may be called more than once
- * for every call to vpx_codec_decode. The application may set fb->priv to
- * some data which will be passed back in the ximage and the release function
- * call. |fb| is guaranteed to not be NULL. On success the callback must
- * return 0. Any failure the callback must return a value less than 0.
- *
- * \param[in] priv Callback's private data
- * \param[in] new_size Size in bytes needed by the buffer
- * \param[in,out] fb Pointer to vpx_codec_frame_buffer_t
- */
-typedef int (*vpx_get_frame_buffer_cb_fn_t)(void *priv, size_t min_size,
- vpx_codec_frame_buffer_t *fb);
-
-/*!\brief release frame buffer callback prototype
- *
- * This callback is invoked by the decoder when the frame buffer is not
- * referenced by any other buffers. |fb| is guaranteed to not be NULL. On
- * success the callback must return 0. Any failure the callback must return
- * a value less than 0.
- *
- * \param[in] priv Callback's private data
- * \param[in] fb Pointer to vpx_codec_frame_buffer_t
- */
-typedef int (*vpx_release_frame_buffer_cb_fn_t)(void *priv,
- vpx_codec_frame_buffer_t *fb);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // VPX_VPX_FRAME_BUFFER_H_
diff --git a/protocols/Tox/include/vpx/vpx_image.h b/protocols/Tox/include/vpx/vpx_image.h
deleted file mode 100644
index d6d3166d2f..0000000000
--- a/protocols/Tox/include/vpx/vpx_image.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-/*!\file
- * \brief Describes the vpx image descriptor and associated operations
- *
- */
-#ifndef VPX_VPX_IMAGE_H_
-#define VPX_VPX_IMAGE_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*!\brief Current ABI version number
- *
- * \internal
- * If this file is altered in any way that changes the ABI, this value
- * must be bumped. Examples include, but are not limited to, changing
- * types, removing or reassigning enums, adding/removing/rearranging
- * fields to structures
- */
-#define VPX_IMAGE_ABI_VERSION (4) /**<\hideinitializer*/
-
-#define VPX_IMG_FMT_PLANAR 0x100 /**< Image is a planar format. */
-#define VPX_IMG_FMT_UV_FLIP 0x200 /**< V plane precedes U in memory. */
-#define VPX_IMG_FMT_HAS_ALPHA 0x400 /**< Image has an alpha channel. */
-#define VPX_IMG_FMT_HIGHBITDEPTH 0x800 /**< Image uses 16bit framebuffer. */
-
-/*!\brief List of supported image formats */
-typedef enum vpx_img_fmt {
- VPX_IMG_FMT_NONE,
- VPX_IMG_FMT_RGB24, /**< 24 bit per pixel packed RGB */
- VPX_IMG_FMT_RGB32, /**< 32 bit per pixel packed 0RGB */
- VPX_IMG_FMT_RGB565, /**< 16 bit per pixel, 565 */
- VPX_IMG_FMT_RGB555, /**< 16 bit per pixel, 555 */
- VPX_IMG_FMT_UYVY, /**< UYVY packed YUV */
- VPX_IMG_FMT_YUY2, /**< YUYV packed YUV */
- VPX_IMG_FMT_YVYU, /**< YVYU packed YUV */
- VPX_IMG_FMT_BGR24, /**< 24 bit per pixel packed BGR */
- VPX_IMG_FMT_RGB32_LE, /**< 32 bit packed BGR0 */
- VPX_IMG_FMT_ARGB, /**< 32 bit packed ARGB, alpha=255 */
- VPX_IMG_FMT_ARGB_LE, /**< 32 bit packed BGRA, alpha=255 */
- VPX_IMG_FMT_RGB565_LE, /**< 16 bit per pixel, gggbbbbb rrrrrggg */
- VPX_IMG_FMT_RGB555_LE, /**< 16 bit per pixel, gggbbbbb 0rrrrrgg */
- VPX_IMG_FMT_YV12 =
- VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_UV_FLIP | 1, /**< planar YVU */
- VPX_IMG_FMT_I420 = VPX_IMG_FMT_PLANAR | 2,
- VPX_IMG_FMT_VPXYV12 = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_UV_FLIP |
- 3, /** < planar 4:2:0 format with vpx color space */
- VPX_IMG_FMT_VPXI420 = VPX_IMG_FMT_PLANAR | 4,
- VPX_IMG_FMT_I422 = VPX_IMG_FMT_PLANAR | 5,
- VPX_IMG_FMT_I444 = VPX_IMG_FMT_PLANAR | 6,
- VPX_IMG_FMT_I440 = VPX_IMG_FMT_PLANAR | 7,
- VPX_IMG_FMT_444A = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_HAS_ALPHA | 6,
- VPX_IMG_FMT_I42016 = VPX_IMG_FMT_I420 | VPX_IMG_FMT_HIGHBITDEPTH,
- VPX_IMG_FMT_I42216 = VPX_IMG_FMT_I422 | VPX_IMG_FMT_HIGHBITDEPTH,
- VPX_IMG_FMT_I44416 = VPX_IMG_FMT_I444 | VPX_IMG_FMT_HIGHBITDEPTH,
- VPX_IMG_FMT_I44016 = VPX_IMG_FMT_I440 | VPX_IMG_FMT_HIGHBITDEPTH
-} vpx_img_fmt_t; /**< alias for enum vpx_img_fmt */
-
-/*!\brief List of supported color spaces */
-typedef enum vpx_color_space {
- VPX_CS_UNKNOWN = 0, /**< Unknown */
- VPX_CS_BT_601 = 1, /**< BT.601 */
- VPX_CS_BT_709 = 2, /**< BT.709 */
- VPX_CS_SMPTE_170 = 3, /**< SMPTE.170 */
- VPX_CS_SMPTE_240 = 4, /**< SMPTE.240 */
- VPX_CS_BT_2020 = 5, /**< BT.2020 */
- VPX_CS_RESERVED = 6, /**< Reserved */
- VPX_CS_SRGB = 7 /**< sRGB */
-} vpx_color_space_t; /**< alias for enum vpx_color_space */
-
-/*!\brief List of supported color range */
-typedef enum vpx_color_range {
- VPX_CR_STUDIO_RANGE = 0, /**< Y [16..235], UV [16..240] */
- VPX_CR_FULL_RANGE = 1 /**< YUV/RGB [0..255] */
-} vpx_color_range_t; /**< alias for enum vpx_color_range */
-
-/**\brief Image Descriptor */
-typedef struct vpx_image {
- vpx_img_fmt_t fmt; /**< Image Format */
- vpx_color_space_t cs; /**< Color Space */
- vpx_color_range_t range; /**< Color Range */
-
- /* Image storage dimensions */
- unsigned int w; /**< Stored image width */
- unsigned int h; /**< Stored image height */
- unsigned int bit_depth; /**< Stored image bit-depth */
-
- /* Image display dimensions */
- unsigned int d_w; /**< Displayed image width */
- unsigned int d_h; /**< Displayed image height */
-
- /* Image intended rendering dimensions */
- unsigned int r_w; /**< Intended rendering image width */
- unsigned int r_h; /**< Intended rendering image height */
-
- /* Chroma subsampling info */
- unsigned int x_chroma_shift; /**< subsampling order, X */
- unsigned int y_chroma_shift; /**< subsampling order, Y */
-
-/* Image data pointers. */
-#define VPX_PLANE_PACKED 0 /**< To be used for all packed formats */
-#define VPX_PLANE_Y 0 /**< Y (Luminance) plane */
-#define VPX_PLANE_U 1 /**< U (Chroma) plane */
-#define VPX_PLANE_V 2 /**< V (Chroma) plane */
-#define VPX_PLANE_ALPHA 3 /**< A (Transparency) plane */
- unsigned char *planes[4]; /**< pointer to the top left pixel for each plane */
- int stride[4]; /**< stride between rows for each plane */
-
- int bps; /**< bits per sample (for packed formats) */
-
- /*!\brief The following member may be set by the application to associate
- * data with this image.
- */
- void *user_priv;
-
- /* The following members should be treated as private. */
- unsigned char *img_data; /**< private */
- int img_data_owner; /**< private */
- int self_allocd; /**< private */
-
- void *fb_priv; /**< Frame buffer data associated with the image. */
-} vpx_image_t; /**< alias for struct vpx_image */
-
-/**\brief Representation of a rectangle on a surface */
-typedef struct vpx_image_rect {
- unsigned int x; /**< leftmost column */
- unsigned int y; /**< topmost row */
- unsigned int w; /**< width */
- unsigned int h; /**< height */
-} vpx_image_rect_t; /**< alias for struct vpx_image_rect */
-
-/*!\brief Open a descriptor, allocating storage for the underlying image
- *
- * Returns a descriptor for storing an image of the given format. The
- * storage for the descriptor is allocated on the heap.
- *
- * \param[in] img Pointer to storage for descriptor. If this parameter
- * is NULL, the storage for the descriptor will be
- * allocated on the heap.
- * \param[in] fmt Format for the image
- * \param[in] d_w Width of the image
- * \param[in] d_h Height of the image
- * \param[in] align Alignment, in bytes, of the image buffer and
- * each row in the image(stride).
- *
- * \return Returns a pointer to the initialized image descriptor. If the img
- * parameter is non-null, the value of the img parameter will be
- * returned.
- */
-vpx_image_t *vpx_img_alloc(vpx_image_t *img, vpx_img_fmt_t fmt,
- unsigned int d_w, unsigned int d_h,
- unsigned int align);
-
-/*!\brief Open a descriptor, using existing storage for the underlying image
- *
- * Returns a descriptor for storing an image of the given format. The
- * storage for descriptor has been allocated elsewhere, and a descriptor is
- * desired to "wrap" that storage.
- *
- * \param[in] img Pointer to storage for descriptor. If this parameter
- * is NULL, the storage for the descriptor will be
- * allocated on the heap.
- * \param[in] fmt Format for the image
- * \param[in] d_w Width of the image
- * \param[in] d_h Height of the image
- * \param[in] align Alignment, in bytes, of each row in the image.
- * \param[in] img_data Storage to use for the image
- *
- * \return Returns a pointer to the initialized image descriptor. If the img
- * parameter is non-null, the value of the img parameter will be
- * returned.
- */
-vpx_image_t *vpx_img_wrap(vpx_image_t *img, vpx_img_fmt_t fmt, unsigned int d_w,
- unsigned int d_h, unsigned int align,
- unsigned char *img_data);
-
-/*!\brief Set the rectangle identifying the displayed portion of the image
- *
- * Updates the displayed rectangle (aka viewport) on the image surface to
- * match the specified coordinates and size.
- *
- * \param[in] img Image descriptor
- * \param[in] x leftmost column
- * \param[in] y topmost row
- * \param[in] w width
- * \param[in] h height
- *
- * \return 0 if the requested rectangle is valid, nonzero otherwise.
- */
-int vpx_img_set_rect(vpx_image_t *img, unsigned int x, unsigned int y,
- unsigned int w, unsigned int h);
-
-/*!\brief Flip the image vertically (top for bottom)
- *
- * Adjusts the image descriptor's pointers and strides to make the image
- * be referenced upside-down.
- *
- * \param[in] img Image descriptor
- */
-void vpx_img_flip(vpx_image_t *img);
-
-/*!\brief Close an image descriptor
- *
- * Frees all allocated storage associated with an image descriptor.
- *
- * \param[in] img Image descriptor
- */
-void vpx_img_free(vpx_image_t *img);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // VPX_VPX_IMAGE_H_
diff --git a/protocols/Tox/include/vpx/vpx_integer.h b/protocols/Tox/include/vpx/vpx_integer.h
deleted file mode 100644
index 09bad9222d..0000000000
--- a/protocols/Tox/include/vpx/vpx_integer.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef VPX_VPX_INTEGER_H_
-#define VPX_VPX_INTEGER_H_
-
-/* get ptrdiff_t, size_t, wchar_t, NULL */
-#include <stddef.h>
-
-#if defined(_MSC_VER)
-#define VPX_FORCE_INLINE __forceinline
-#define VPX_INLINE __inline
-#else
-#define VPX_FORCE_INLINE __inline__ __attribute__(always_inline)
-// TODO(jbb): Allow a way to force inline off for older compilers.
-#define VPX_INLINE inline
-#endif
-
-#if defined(VPX_EMULATE_INTTYPES)
-typedef signed char int8_t;
-typedef signed short int16_t;
-typedef signed int int32_t;
-
-typedef unsigned char uint8_t;
-typedef unsigned short uint16_t;
-typedef unsigned int uint32_t;
-
-#ifndef _UINTPTR_T_DEFINED
-typedef size_t uintptr_t;
-#endif
-
-#else
-
-/* Most platforms have the C99 standard integer types. */
-
-#if defined(__cplusplus)
-#if !defined(__STDC_FORMAT_MACROS)
-#define __STDC_FORMAT_MACROS
-#endif
-#if !defined(__STDC_LIMIT_MACROS)
-#define __STDC_LIMIT_MACROS
-#endif
-#endif // __cplusplus
-
-#include <stdint.h>
-
-#endif
-
-/* VS2010 defines stdint.h, but not inttypes.h */
-#if defined(_MSC_VER) && _MSC_VER < 1800
-#define PRId64 "I64d"
-#else
-#include <inttypes.h>
-#endif
-
-#endif // VPX_VPX_INTEGER_H_
diff --git a/protocols/Tox/libtox/docs/CHANGELOG.md b/protocols/Tox/libtox/docs/CHANGELOG.md
new file mode 100644
index 0000000000..e3275a16df
--- /dev/null
+++ b/protocols/Tox/libtox/docs/CHANGELOG.md
@@ -0,0 +1,450 @@
+
+
+## v0.1.10
+
+### Merged PRs:
+
+- [#564](https://github.com/TokTok/c-toxcore/pull/564) Fix Windows build
+- [#542](https://github.com/TokTok/c-toxcore/pull/542) Save bandwidth by moderating onion pinging
+
+## v0.1.9
+
+### Merged PRs:
+
+- [#563](https://github.com/TokTok/c-toxcore/pull/563) Release v0.1.9
+- [#561](https://github.com/TokTok/c-toxcore/pull/561) Remove unused variable
+- [#560](https://github.com/TokTok/c-toxcore/pull/560) Fix non-portable zeroing out of doubles
+- [#559](https://github.com/TokTok/c-toxcore/pull/559) Fix theoretical memory leaks
+- [#557](https://github.com/TokTok/c-toxcore/pull/557) Document inverted mutex lock/unlock.
+- [#556](https://github.com/TokTok/c-toxcore/pull/556) Build tests on appveyor, the MSVC build, but don't run them yet.
+- [#555](https://github.com/TokTok/c-toxcore/pull/555) Fold hstox tests into the general linux test.
+- [#554](https://github.com/TokTok/c-toxcore/pull/554) Add a monolith_test that includes all toxcore sources.
+- [#553](https://github.com/TokTok/c-toxcore/pull/553) Factor out strict_abi cmake code into a separate module.
+- [#552](https://github.com/TokTok/c-toxcore/pull/552) Fix formatting and spelling in version-sync script.
+- [#551](https://github.com/TokTok/c-toxcore/pull/551) Forbid undefined symbols in shared libraries.
+- [#546](https://github.com/TokTok/c-toxcore/pull/546) Make variable names in file saving test less cryptic
+- [#539](https://github.com/TokTok/c-toxcore/pull/539) Make OSX test failures fail the Travis CI build.
+- [#537](https://github.com/TokTok/c-toxcore/pull/537) Fix TokTok/c-toxcore#535
+- [#534](https://github.com/TokTok/c-toxcore/pull/534) Fix markdown formatting
+- [#530](https://github.com/TokTok/c-toxcore/pull/530) Implement missing TES constant functions.
+- [#511](https://github.com/TokTok/c-toxcore/pull/511) Save bandwidth by avoiding superfluous Nodes Requests to peers already on the Close List
+- [#506](https://github.com/TokTok/c-toxcore/pull/506) Add test case for title change
+- [#498](https://github.com/TokTok/c-toxcore/pull/498) DHT refactoring
+- [#487](https://github.com/TokTok/c-toxcore/pull/487) Split daemon's logging backends in separate modules
+- [#468](https://github.com/TokTok/c-toxcore/pull/468) Test for memberlist not changing after changing own name
+- [#449](https://github.com/TokTok/c-toxcore/pull/449) Use new encoding of `Maybe` in msgpack results.
+
+### Closed issues:
+
+- [#482](https://github.com/TokTok/c-toxcore/issues/482) CMake can't detect and compile ToxAV on OSX
+
+## v0.1.8
+
+### Merged PRs:
+
+- [#538](https://github.com/TokTok/c-toxcore/pull/538) Reverting tox_loop PR changes
+- [#536](https://github.com/TokTok/c-toxcore/pull/536) Release v0.1.8
+- [#526](https://github.com/TokTok/c-toxcore/pull/526) Add TOX_NOSPAM_SIZE to the public API.
+- [#525](https://github.com/TokTok/c-toxcore/pull/525) Retry autotools tests the same way as cmake tests.
+- [#524](https://github.com/TokTok/c-toxcore/pull/524) Reduce ctest timeout to 2 minutes from 5 minutes.
+- [#512](https://github.com/TokTok/c-toxcore/pull/512) Add test for DHT pack_nodes and unpack_nodes
+- [#504](https://github.com/TokTok/c-toxcore/pull/504) CMake: install bootstrapd if it is built
+- [#488](https://github.com/TokTok/c-toxcore/pull/488) Save compiled Android artifacts after CircleCI builds.
+- [#473](https://github.com/TokTok/c-toxcore/pull/473) Added missing includes: <netinet/in.h> and <sys/socket.h>
+- [#335](https://github.com/TokTok/c-toxcore/pull/335) Implement tox_loop
+
+### Closed issues:
+
+- [#535](https://github.com/TokTok/c-toxcore/issues/535) OS X tests failing
+- [#503](https://github.com/TokTok/c-toxcore/issues/503) Undefined functions: tox_pass_salt_length, tox_pass_key_length, tox_pass_encryption_extra_length
+- [#456](https://github.com/TokTok/c-toxcore/issues/456) Tox.h doesn't expose the size of the nospam.
+- [#411](https://github.com/TokTok/c-toxcore/issues/411) Reduce CTest timeout to 2 minutes
+
+## v0.1.7
+
+### Merged PRs:
+
+- [#523](https://github.com/TokTok/c-toxcore/pull/523) Release v0.1.7
+- [#521](https://github.com/TokTok/c-toxcore/pull/521) Fix appveyor script: install curl from chocolatey.
+- [#510](https://github.com/TokTok/c-toxcore/pull/510) Fix list malloc(0) bug
+- [#509](https://github.com/TokTok/c-toxcore/pull/509) Fix network malloc(0) bug
+- [#497](https://github.com/TokTok/c-toxcore/pull/497) Fix network
+- [#496](https://github.com/TokTok/c-toxcore/pull/496) Fix Travis always succeeding despite tests failing
+- [#491](https://github.com/TokTok/c-toxcore/pull/491) Add crypto_memzero for temp buffer
+- [#490](https://github.com/TokTok/c-toxcore/pull/490) Move c_sleep to helpers.h and misc_tools.h
+- [#486](https://github.com/TokTok/c-toxcore/pull/486) Remove empty line in Messenger.c
+- [#483](https://github.com/TokTok/c-toxcore/pull/483) Make BUILD_TOXAV an option and fail if dependencies are missing
+- [#481](https://github.com/TokTok/c-toxcore/pull/481) Remove dependency on strings.h
+- [#480](https://github.com/TokTok/c-toxcore/pull/480) Use VLA macro
+- [#479](https://github.com/TokTok/c-toxcore/pull/479) Fix pthreads in AppVeyor build
+- [#471](https://github.com/TokTok/c-toxcore/pull/471) Remove statics used in onion comparison functions.
+- [#461](https://github.com/TokTok/c-toxcore/pull/461) Replace part of network functions on platform-independent implementation
+- [#452](https://github.com/TokTok/c-toxcore/pull/452) Add VLA compatibility macro for C89-ish compilers.
+
+### Closed issues:
+
+- [#474](https://github.com/TokTok/c-toxcore/issues/474) TOX_VERSION_PATCH isn't in sync with the version
+
+## v0.1.6
+
+### Merged PRs:
+
+- [#460](https://github.com/TokTok/c-toxcore/pull/460) Release v0.1.6.
+- [#459](https://github.com/TokTok/c-toxcore/pull/459) Add Android build to CI.
+- [#454](https://github.com/TokTok/c-toxcore/pull/454) Add appveyor build for native windows tests.
+- [#448](https://github.com/TokTok/c-toxcore/pull/448) Only retry failed tests on Circle CI instead of all.
+- [#434](https://github.com/TokTok/c-toxcore/pull/434) Replace redundant packet type check in handler with assert.
+- [#432](https://github.com/TokTok/c-toxcore/pull/432) Remove some static variables
+- [#385](https://github.com/TokTok/c-toxcore/pull/385) Add platform-independent Socket and IP implementation
+
+### Closed issues:
+
+- [#415](https://github.com/TokTok/c-toxcore/issues/415) Set up a native windows build on appveyor
+
+## v0.1.5
+
+### Merged PRs:
+
+- [#447](https://github.com/TokTok/c-toxcore/pull/447) Release v0.1.5.
+- [#446](https://github.com/TokTok/c-toxcore/pull/446) Limit number of retries to 3.
+- [#445](https://github.com/TokTok/c-toxcore/pull/445) Make Travis tests slightly more robust by re-running them.
+- [#443](https://github.com/TokTok/c-toxcore/pull/443) Make building `DHT_bootstrap` in cmake optional.
+- [#433](https://github.com/TokTok/c-toxcore/pull/433) Add tutorial and "danger: experimental" banner to README.
+- [#431](https://github.com/TokTok/c-toxcore/pull/431) Update license headers and remove redundant file name comment.
+- [#424](https://github.com/TokTok/c-toxcore/pull/424) Fixed the FreeBSD build failure due to the undefined MSG_NOSIGNAL.
+- [#420](https://github.com/TokTok/c-toxcore/pull/420) Setup autotools to read .so version info from a separate file
+- [#418](https://github.com/TokTok/c-toxcore/pull/418) Clarify how the autotools build is done on Travis.
+- [#414](https://github.com/TokTok/c-toxcore/pull/414) Explicitly check if compiler supports C99
+
+## v0.1.4
+
+### Merged PRs:
+
+- [#422](https://github.com/TokTok/c-toxcore/pull/422) Release v0.1.4.
+- [#410](https://github.com/TokTok/c-toxcore/pull/410) Fix NaCl build: tar was called incorrectly.
+- [#409](https://github.com/TokTok/c-toxcore/pull/409) Clarify that the pass key `new` function can fail.
+- [#407](https://github.com/TokTok/c-toxcore/pull/407) Don't use `git.depth=1` anymore.
+- [#404](https://github.com/TokTok/c-toxcore/pull/404) Issue 404: semicolon not found
+- [#403](https://github.com/TokTok/c-toxcore/pull/403) Warn on -pedantic, don't error yet.
+- [#401](https://github.com/TokTok/c-toxcore/pull/401) Add logging callback to messenger_test.
+- [#400](https://github.com/TokTok/c-toxcore/pull/400) Run windows tests but ignore their failures.
+- [#398](https://github.com/TokTok/c-toxcore/pull/398) Portability Fixes
+- [#397](https://github.com/TokTok/c-toxcore/pull/397) Replace make_quick_sort with qsort
+- [#396](https://github.com/TokTok/c-toxcore/pull/396) Add an OSX build that doesn't run tests.
+- [#394](https://github.com/TokTok/c-toxcore/pull/394) CMake: Add soversion to library files to generate proper symlinks
+- [#393](https://github.com/TokTok/c-toxcore/pull/393) Set up autotools build to build against vanilla NaCl.
+- [#392](https://github.com/TokTok/c-toxcore/pull/392) Check that TCP connections aren't dropped in callbacks.
+- [#391](https://github.com/TokTok/c-toxcore/pull/391) Minor simplification in `file_seek` code.
+- [#390](https://github.com/TokTok/c-toxcore/pull/390) Always kill invalid file transfers when receiving file controls.
+- [#388](https://github.com/TokTok/c-toxcore/pull/388) Fix logging condition for IPv6 client timestamp updates.
+- [#387](https://github.com/TokTok/c-toxcore/pull/387) Eliminate dead return statement.
+- [#386](https://github.com/TokTok/c-toxcore/pull/386) Avoid accessing uninitialised memory in `net_crypto`.
+- [#381](https://github.com/TokTok/c-toxcore/pull/381) Remove `TOX_DEBUG` and have asserts always enabled.
+
+### Closed issues:
+
+- [#378](https://github.com/TokTok/c-toxcore/issues/378) Replace all uses of `make_quick_sort` with `qsort`
+- [#364](https://github.com/TokTok/c-toxcore/issues/364) Delete misc_tools.h after replacing its use by qsort.
+- [#363](https://github.com/TokTok/c-toxcore/issues/363) Test against NaCl in addition to libsodium on Travis.
+
+## v0.1.3
+
+### Merged PRs:
+
+- [#395](https://github.com/TokTok/c-toxcore/pull/395) Revert "Portability fixes"
+- [#380](https://github.com/TokTok/c-toxcore/pull/380) Test a few cmake option combinations before the build.
+- [#377](https://github.com/TokTok/c-toxcore/pull/377) Fix SSL verification in coveralls.
+- [#376](https://github.com/TokTok/c-toxcore/pull/376) Bring back autotools instructions
+- [#373](https://github.com/TokTok/c-toxcore/pull/373) Only fetch 1 revision from git during Travis builds.
+- [#369](https://github.com/TokTok/c-toxcore/pull/369) Integrate with CircleCI to build artifacts in the future
+- [#366](https://github.com/TokTok/c-toxcore/pull/366) Release v0.1.3.
+- [#362](https://github.com/TokTok/c-toxcore/pull/362) Remove .cabal-sandbox option from tox-spectest find line.
+- [#361](https://github.com/TokTok/c-toxcore/pull/361) Simplify integration as a third-party lib in cmake projects
+- [#354](https://github.com/TokTok/c-toxcore/pull/354) Add secure memcmp and memzero implementation.
+- [#324](https://github.com/TokTok/c-toxcore/pull/324) Do not compile and install DHT_bootstrap if it was disabled in configure
+- [#297](https://github.com/TokTok/c-toxcore/pull/297) Portability fixes
+
+### Closed issues:
+
+- [#347](https://github.com/TokTok/c-toxcore/issues/347) Implement our own secure `memcmp` and `memzero` if libsodium isn't available
+- [#319](https://github.com/TokTok/c-toxcore/issues/319) toxcore installs `DHT_bootstrap` even though `--disable-daemon` is passed to `./configure`
+
+## v0.1.2
+
+### Merged PRs:
+
+- [#355](https://github.com/TokTok/c-toxcore/pull/355) Release v0.1.2
+- [#353](https://github.com/TokTok/c-toxcore/pull/353) Fix toxav use after free caused by premature MSI destruction
+- [#346](https://github.com/TokTok/c-toxcore/pull/346) Avoid array out of bounds read in friend saving.
+- [#344](https://github.com/TokTok/c-toxcore/pull/344) Remove unused get/set salt/key functions from toxencryptsave.
+- [#343](https://github.com/TokTok/c-toxcore/pull/343) Wrap all sodium/nacl functions in crypto_core.c.
+- [#341](https://github.com/TokTok/c-toxcore/pull/341) Add test to check if tox_new/tox_kill leaks.
+- [#336](https://github.com/TokTok/c-toxcore/pull/336) Correct TES docs to reflect how many bytes functions actually require.
+- [#333](https://github.com/TokTok/c-toxcore/pull/333) Use `tox_options_set_*` instead of direct member access.
+
+### Closed issues:
+
+- [#345](https://github.com/TokTok/c-toxcore/issues/345) Array out of bounds read in "save" function
+- [#342](https://github.com/TokTok/c-toxcore/issues/342) Wrap all libsodium functions we use in toxcore in `crypto_core`.
+- [#278](https://github.com/TokTok/c-toxcore/issues/278) ToxAV use-after-free bug
+
+## v0.1.1
+
+### Merged PRs:
+
+- [#337](https://github.com/TokTok/c-toxcore/pull/337) Release v0.1.1
+- [#332](https://github.com/TokTok/c-toxcore/pull/332) Add test for encrypted savedata.
+- [#330](https://github.com/TokTok/c-toxcore/pull/330) Strengthen the note about ABI compatibility in tox.h.
+- [#328](https://github.com/TokTok/c-toxcore/pull/328) Drop the broken `TOX_VERSION_REQUIRE` macro.
+- [#326](https://github.com/TokTok/c-toxcore/pull/326) Fix unresolved reference in toxencryptsave API docs.
+- [#309](https://github.com/TokTok/c-toxcore/pull/309) Fixed attempt to join detached threads (fixes toxav test crash)
+- [#306](https://github.com/TokTok/c-toxcore/pull/306) Add option to disable local peer discovery
+
+### Closed issues:
+
+- [#327](https://github.com/TokTok/c-toxcore/issues/327) The `TOX_VERSION_REQUIRE` macro is broken.
+- [#221](https://github.com/TokTok/c-toxcore/issues/221) Option to disable local peer detection
+
+## v0.1.0
+
+### Merged PRs:
+
+- [#325](https://github.com/TokTok/c-toxcore/pull/325) Fix Libs line in toxcore.pc pkg-config file.
+- [#322](https://github.com/TokTok/c-toxcore/pull/322) Add compatibility pkg-config modules: libtoxcore, libtoxav.
+- [#318](https://github.com/TokTok/c-toxcore/pull/318) Fix `--enable-logging` flag in autotools configure script.
+- [#316](https://github.com/TokTok/c-toxcore/pull/316) Release 0.1.0.
+- [#315](https://github.com/TokTok/c-toxcore/pull/315) Fix version compatibility test.
+- [#314](https://github.com/TokTok/c-toxcore/pull/314) Fix off by one error in saving our own status message.
+- [#313](https://github.com/TokTok/c-toxcore/pull/313) Fix padding being in the wrong place in `SAVED_FRIEND` struct
+- [#312](https://github.com/TokTok/c-toxcore/pull/312) Conditionally enable non-portable assert on LP64.
+- [#310](https://github.com/TokTok/c-toxcore/pull/310) Add apidsl file for toxencryptsave.
+- [#307](https://github.com/TokTok/c-toxcore/pull/307) Clarify toxencryptsave documentation regarding buffer sizes
+- [#305](https://github.com/TokTok/c-toxcore/pull/305) Fix static builds
+- [#303](https://github.com/TokTok/c-toxcore/pull/303) Don't build nTox by default.
+- [#301](https://github.com/TokTok/c-toxcore/pull/301) Renamed messenger functions, prepend `m_`.
+- [#299](https://github.com/TokTok/c-toxcore/pull/299) net_crypto give handle_data_packet_helper a better name
+- [#294](https://github.com/TokTok/c-toxcore/pull/294) Don't error on warnings by default
+
+### Closed issues:
+
+- [#317](https://github.com/TokTok/c-toxcore/issues/317) toxcore fails to build with autotools and debugging level enabled
+- [#311](https://github.com/TokTok/c-toxcore/issues/311) Incorrect padding
+- [#308](https://github.com/TokTok/c-toxcore/issues/308) Review TES and port it to APIDSL
+- [#293](https://github.com/TokTok/c-toxcore/issues/293) error building on ubuntu 14.04
+- [#292](https://github.com/TokTok/c-toxcore/issues/292) Don't build nTox by default with CMake
+- [#290](https://github.com/TokTok/c-toxcore/issues/290) User Feed
+- [#266](https://github.com/TokTok/c-toxcore/issues/266) Support all levels listed in TOX_DHT_NAT_LEVEL
+- [#216](https://github.com/TokTok/c-toxcore/issues/216) When v0.1 release?
+
+## v0.0.5
+
+### Merged PRs:
+
+- [#289](https://github.com/TokTok/c-toxcore/pull/289) Version Patch v0.0.4 => v0.0.5
+- [#287](https://github.com/TokTok/c-toxcore/pull/287) Add CMake knobs to suppress building tests
+- [#286](https://github.com/TokTok/c-toxcore/pull/286) Support float32 and float64 in msgpack type printer.
+- [#285](https://github.com/TokTok/c-toxcore/pull/285) Mark `Tox_Options` struct as deprecated.
+- [#284](https://github.com/TokTok/c-toxcore/pull/284) Add NONE enumerator to bit mask.
+- [#281](https://github.com/TokTok/c-toxcore/pull/281) Made save format platform-independent
+- [#277](https://github.com/TokTok/c-toxcore/pull/277) Fix a memory leak in hstox interface
+- [#276](https://github.com/TokTok/c-toxcore/pull/276) Fix NULL pointer dereference in log calls
+- [#275](https://github.com/TokTok/c-toxcore/pull/275) Fix a memory leak in GroupAV
+- [#274](https://github.com/TokTok/c-toxcore/pull/274) Options in `new_messenger()` must never be null.
+- [#271](https://github.com/TokTok/c-toxcore/pull/271) Convert to and from network byte order in set/get nospam.
+- [#262](https://github.com/TokTok/c-toxcore/pull/262) Add ability to disable UDP hole punching
+
+### Closed issues:
+
+- [#254](https://github.com/TokTok/c-toxcore/issues/254) Add option to disable UDP hole punching
+- [#215](https://github.com/TokTok/c-toxcore/issues/215) The current tox save format is non-portable
+- [#205](https://github.com/TokTok/c-toxcore/issues/205) nospam value is reversed in array returned by `tox_self_get_address()`
+
+## v0.0.4
+
+### Merged PRs:
+
+- [#272](https://github.com/TokTok/c-toxcore/pull/272) v0.0.4
+- [#265](https://github.com/TokTok/c-toxcore/pull/265) Disable -Wunused-but-set-variable compiler warning flag.
+- [#261](https://github.com/TokTok/c-toxcore/pull/261) Work around Travis issue that causes build failures.
+- [#260](https://github.com/TokTok/c-toxcore/pull/260) Support arbitrary video resolutions in av_test
+- [#257](https://github.com/TokTok/c-toxcore/pull/257) Add decode/encode PlainText test support.
+- [#256](https://github.com/TokTok/c-toxcore/pull/256) Add spectest to the cmake test suite.
+- [#255](https://github.com/TokTok/c-toxcore/pull/255) Disable some gcc-specific warnings.
+- [#249](https://github.com/TokTok/c-toxcore/pull/249) Use apidsl for the crypto_core API.
+- [#248](https://github.com/TokTok/c-toxcore/pull/248) Remove new_nonce function in favour of random_nonce.
+- [#224](https://github.com/TokTok/c-toxcore/pull/224) Add DHT_create_packet, an abstraction for DHT RPC packets
+
+## v0.0.3
+
+### Merged PRs:
+
+- [#251](https://github.com/TokTok/c-toxcore/pull/251) Rename log levels to remove the extra "LOG" prefix.
+- [#250](https://github.com/TokTok/c-toxcore/pull/250) Release v0.0.3.
+- [#245](https://github.com/TokTok/c-toxcore/pull/245) Change packet kind enum to use hex constants.
+- [#243](https://github.com/TokTok/c-toxcore/pull/243) Enable address sanitizer on the cmake build.
+- [#242](https://github.com/TokTok/c-toxcore/pull/242) Remove assoc
+- [#241](https://github.com/TokTok/c-toxcore/pull/241) Move log callback to options.
+- [#233](https://github.com/TokTok/c-toxcore/pull/233) Enable all possible C compiler warning flags.
+- [#230](https://github.com/TokTok/c-toxcore/pull/230) Move packing and unpacking DHT request packets to DHT module.
+- [#228](https://github.com/TokTok/c-toxcore/pull/228) Remove unimplemented "time delta" parameter.
+- [#227](https://github.com/TokTok/c-toxcore/pull/227) Compile as C++ for windows builds.
+- [#223](https://github.com/TokTok/c-toxcore/pull/223) TravisCI shorten IRC message
+- [#220](https://github.com/TokTok/c-toxcore/pull/220) toxav renaming: group.{h,c} -> groupav.{h,c}
+- [#218](https://github.com/TokTok/c-toxcore/pull/218) Rename some internal "group chat" thing to "conference".
+- [#212](https://github.com/TokTok/c-toxcore/pull/212) Convert series of `NET_PACKET_*` defines into a typedef enum
+- [#196](https://github.com/TokTok/c-toxcore/pull/196) Update readme, moved the roadmap to a higher position
+- [#193](https://github.com/TokTok/c-toxcore/pull/193) Remove duplicate tests: split tests part 2.
+
+### Closed issues:
+
+- [#40](https://github.com/TokTok/c-toxcore/issues/40) Stateless callbacks in toxcore's public API
+
+## v0.0.2
+
+### Merged PRs:
+
+- [#207](https://github.com/TokTok/c-toxcore/pull/207) docs: correct instructions for cloning & harden agains repo name changes
+- [#206](https://github.com/TokTok/c-toxcore/pull/206) Corrected libsodium tag
+- [#204](https://github.com/TokTok/c-toxcore/pull/204) Error if format_test can't be executed.
+- [#202](https://github.com/TokTok/c-toxcore/pull/202) Version Patch v0.0.2
+- [#190](https://github.com/TokTok/c-toxcore/pull/190) Install libraries with RPATH.
+- [#189](https://github.com/TokTok/c-toxcore/pull/189) Use `socklen_t` instead of `unsigned int` in call to `accept`.
+- [#188](https://github.com/TokTok/c-toxcore/pull/188) Add option to set test timeout
+- [#187](https://github.com/TokTok/c-toxcore/pull/187) Add option to build tox-bootstrapd
+- [#185](https://github.com/TokTok/c-toxcore/pull/185) Import the hstox SUT interface from hstox.
+- [#183](https://github.com/TokTok/c-toxcore/pull/183) Set log level for DEBUG=ON to LOG_DEBUG.
+- [#182](https://github.com/TokTok/c-toxcore/pull/182) Remove return after no-return situation.
+- [#181](https://github.com/TokTok/c-toxcore/pull/181) Minor documentation fixes.
+- [#180](https://github.com/TokTok/c-toxcore/pull/180) Add the 'Tox' context object to the logger.
+- [#179](https://github.com/TokTok/c-toxcore/pull/179) Remove the `_test` suffix in `auto_test` calls.
+- [#178](https://github.com/TokTok/c-toxcore/pull/178) Rebuild apidsl'd headers in cmake.
+- [#177](https://github.com/TokTok/c-toxcore/pull/177) docs(INSTALL): update compiling instructions for Linux
+- [#176](https://github.com/TokTok/c-toxcore/pull/176) Merge irungentoo/toxcore into TokTok/c-toxcore.
+- [#173](https://github.com/TokTok/c-toxcore/pull/173) Duplicate tox_test to 4 other files.
+
+### Closed issues:
+
+- [#201](https://github.com/TokTok/c-toxcore/issues/201) Logging callback was broken
+
+## v0.0.1
+
+### Merged PRs:
+
+- [#174](https://github.com/TokTok/c-toxcore/pull/174) Remove redundant callback objects.
+- [#171](https://github.com/TokTok/c-toxcore/pull/171) Simple Version tick to v0.0.1
+- [#170](https://github.com/TokTok/c-toxcore/pull/170) C++ the second round.
+- [#166](https://github.com/TokTok/c-toxcore/pull/166) Add version-sync script.
+- [#164](https://github.com/TokTok/c-toxcore/pull/164) Replace `void*` with `RingBuffer*` to avoid conversions.
+- [#163](https://github.com/TokTok/c-toxcore/pull/163) Move ring buffer out of toxcore/util into toxav.
+- [#162](https://github.com/TokTok/c-toxcore/pull/162) Allow the OSX build to fail on travis.
+- [#161](https://github.com/TokTok/c-toxcore/pull/161) Minor cleanups: unused vars, unreachable code, static globals.
+- [#160](https://github.com/TokTok/c-toxcore/pull/160) Work around bug in opencv3 headers.
+- [#157](https://github.com/TokTok/c-toxcore/pull/157) Make TCP_Connections module-private.
+- [#156](https://github.com/TokTok/c-toxcore/pull/156) Make TCP_Server opaque.
+- [#153](https://github.com/TokTok/c-toxcore/pull/153) Fix strict-ld grep expressions to include digits.
+- [#151](https://github.com/TokTok/c-toxcore/pull/151) Revert #130 "Make ToxAV stateless"
+- [#148](https://github.com/TokTok/c-toxcore/pull/148) Added UB comment r/t deleting a friend w/ active call
+- [#146](https://github.com/TokTok/c-toxcore/pull/146) Make group callbacks stateless
+- [#145](https://github.com/TokTok/c-toxcore/pull/145) Make internal chat list function take uint32_t* as well.
+- [#144](https://github.com/TokTok/c-toxcore/pull/144) Only build toxav if opus and vpx are found.
+- [#143](https://github.com/TokTok/c-toxcore/pull/143) Make toxcore code C++ compatible.
+- [#142](https://github.com/TokTok/c-toxcore/pull/142) Fix for windows dynamic libraries.
+- [#141](https://github.com/TokTok/c-toxcore/pull/141) const-correctness in windows code.
+- [#140](https://github.com/TokTok/c-toxcore/pull/140) Use C99 %zu format conversion in printf for size_t.
+- [#139](https://github.com/TokTok/c-toxcore/pull/139) Clean up Travis build a bit in preparation for osx/win.
+- [#138](https://github.com/TokTok/c-toxcore/pull/138) Remove format-source from travis script.
+- [#135](https://github.com/TokTok/c-toxcore/pull/135) Convert old groupchats to new API format
+- [#134](https://github.com/TokTok/c-toxcore/pull/134) Add some astyle options to make it do more.
+- [#133](https://github.com/TokTok/c-toxcore/pull/133) Ensure that all TODOs have an owner.
+- [#132](https://github.com/TokTok/c-toxcore/pull/132) Remove `else` directly after `return`.
+- [#130](https://github.com/TokTok/c-toxcore/pull/130) Make ToxAV stateless
+- [#129](https://github.com/TokTok/c-toxcore/pull/129) Use TokTok's apidsl instead of the iphydf one.
+- [#127](https://github.com/TokTok/c-toxcore/pull/127) Use "phase" script for travis build phases.
+- [#126](https://github.com/TokTok/c-toxcore/pull/126) Add option to build static libraries.
+- [#125](https://github.com/TokTok/c-toxcore/pull/125) Group #include directives in 3-4 groups.
+- [#123](https://github.com/TokTok/c-toxcore/pull/123) Use correct logical operator for tox_test
+- [#120](https://github.com/TokTok/c-toxcore/pull/120) make the majority of the callbacks stateless and add some status to a testcase
+- [#118](https://github.com/TokTok/c-toxcore/pull/118) Use `const` for version numbers.
+- [#117](https://github.com/TokTok/c-toxcore/pull/117) Add STRICT_ABI cmake flag to generate export lists.
+- [#116](https://github.com/TokTok/c-toxcore/pull/116) Fix potential null pointer dereference.
+- [#115](https://github.com/TokTok/c-toxcore/pull/115) Fix memory leak on error paths in tox_new.
+- [#114](https://github.com/TokTok/c-toxcore/pull/114) Fix compilation for Windows.
+- [#111](https://github.com/TokTok/c-toxcore/pull/111) Add debugging option to autotools configuration
+- [#110](https://github.com/TokTok/c-toxcore/pull/110) Comment intentional switch fallthroughs
+- [#109](https://github.com/TokTok/c-toxcore/pull/109) Separate ip_port packing from pack_nodes() and unpack_nodes()
+- [#108](https://github.com/TokTok/c-toxcore/pull/108) Prevent `<winsock.h>` inclusion by `<windows.h>`.
+- [#107](https://github.com/TokTok/c-toxcore/pull/107) Print a message about missing astyle in format-source.
+- [#104](https://github.com/TokTok/c-toxcore/pull/104) Merge with irungentoo/master
+- [#103](https://github.com/TokTok/c-toxcore/pull/103) Allocate `sizeof(IP_ADAPTER_INFO)` bytes instead of `sizeof(T*)`.
+- [#101](https://github.com/TokTok/c-toxcore/pull/101) Add TODO for @mannol.
+- [#100](https://github.com/TokTok/c-toxcore/pull/100) Remove the packet mutation in toxav's bwcontroller.
+- [#99](https://github.com/TokTok/c-toxcore/pull/99) Make packet data a ptr-to-const.
+- [#97](https://github.com/TokTok/c-toxcore/pull/97) Improve static and const correctness.
+- [#96](https://github.com/TokTok/c-toxcore/pull/96) Improve C standard compliance.
+- [#94](https://github.com/TokTok/c-toxcore/pull/94) Rearrange fields to decrease size of structure
+- [#84](https://github.com/TokTok/c-toxcore/pull/84) Remove useless casts.
+- [#82](https://github.com/TokTok/c-toxcore/pull/82) Add missing #include <pthread.h> to av_test.c.
+- [#81](https://github.com/TokTok/c-toxcore/pull/81) Match parameter names in declarations with their definitions.
+- [#80](https://github.com/TokTok/c-toxcore/pull/80) Sort #includes in all source files.
+- [#79](https://github.com/TokTok/c-toxcore/pull/79) Remove redundant `return` statements.
+- [#78](https://github.com/TokTok/c-toxcore/pull/78) Do not use `else` after `return`.
+- [#77](https://github.com/TokTok/c-toxcore/pull/77) Add OSX and Windows build to travis config.
+- [#76](https://github.com/TokTok/c-toxcore/pull/76) Remove unused and bit-rotten friends_test.
+- [#75](https://github.com/TokTok/c-toxcore/pull/75) Enable build of av_test.
+- [#74](https://github.com/TokTok/c-toxcore/pull/74) Add missing #includes to headers and rename tox_old to tox_group.
+- [#73](https://github.com/TokTok/c-toxcore/pull/73) Add braces to all if statements.
+- [#72](https://github.com/TokTok/c-toxcore/pull/72) Add getters/setters for options.
+- [#70](https://github.com/TokTok/c-toxcore/pull/70) Expose constants as functions.
+- [#68](https://github.com/TokTok/c-toxcore/pull/68) Add address sanitizer option to cmake file.
+- [#66](https://github.com/TokTok/c-toxcore/pull/66) Fix plane size calculation in test
+- [#65](https://github.com/TokTok/c-toxcore/pull/65) Avoid large stack allocations on thread stacks.
+- [#64](https://github.com/TokTok/c-toxcore/pull/64) Comment out useless TODO'd if block.
+- [#63](https://github.com/TokTok/c-toxcore/pull/63) Initialise the id in assoc_test.
+- [#62](https://github.com/TokTok/c-toxcore/pull/62) Reduce the timeout on travis to something much more reasonable
+- [#60](https://github.com/TokTok/c-toxcore/pull/60) Make friend requests stateless
+- [#59](https://github.com/TokTok/c-toxcore/pull/59) Replace uint with unsigned int in assoc.c.
+- [#58](https://github.com/TokTok/c-toxcore/pull/58) Make Message received receipts stateless
+- [#57](https://github.com/TokTok/c-toxcore/pull/57) Make Friend User Status stateless
+- [#55](https://github.com/TokTok/c-toxcore/pull/55) docs(INSTALL.md): update instructions for Gentoo
+- [#54](https://github.com/TokTok/c-toxcore/pull/54) Make typing change callback stateless
+- [#53](https://github.com/TokTok/c-toxcore/pull/53) Add format-source script.
+- [#52](https://github.com/TokTok/c-toxcore/pull/52) Build assoc DHT code on travis.
+- [#51](https://github.com/TokTok/c-toxcore/pull/51) Fix operation sequencing in TCP_test.
+- [#49](https://github.com/TokTok/c-toxcore/pull/49) Apidsl test
+- [#48](https://github.com/TokTok/c-toxcore/pull/48) Make friend message callback stateless
+- [#46](https://github.com/TokTok/c-toxcore/pull/46) Move logging to a callback.
+- [#45](https://github.com/TokTok/c-toxcore/pull/45) Stateless friend status message
+- [#43](https://github.com/TokTok/c-toxcore/pull/43) Allow NULL as argument to tox_kill.
+- [#41](https://github.com/TokTok/c-toxcore/pull/41) Fix warnings
+- [#39](https://github.com/TokTok/c-toxcore/pull/39) Merge irungentoo/toxcore into TokTok/c-toxcore.
+- [#38](https://github.com/TokTok/c-toxcore/pull/38) Try searching for libsodium with pkg-config in ./configure.
+- [#37](https://github.com/TokTok/c-toxcore/pull/37) Add missing DHT_bootstrap to CMakeLists.txt.
+- [#36](https://github.com/TokTok/c-toxcore/pull/36) Make tox_callback_friend_name stateless.
+- [#33](https://github.com/TokTok/c-toxcore/pull/33) Update readme with tentative roadmap, removed old todo.md
+- [#32](https://github.com/TokTok/c-toxcore/pull/32) Fix a bug I introduced that would make toxcore fail to initialise a second time
+- [#31](https://github.com/TokTok/c-toxcore/pull/31) 7. Travis envs
+- [#30](https://github.com/TokTok/c-toxcore/pull/30) 2. Hstox test
+- [#29](https://github.com/TokTok/c-toxcore/pull/29) 1. Move toxcore travis build scripts out of .travis.yml.
+- [#27](https://github.com/TokTok/c-toxcore/pull/27) 8. Stateless
+- [#26](https://github.com/TokTok/c-toxcore/pull/26) 6. Cmake bootstrapd
+- [#25](https://github.com/TokTok/c-toxcore/pull/25) 5. Coverage clang
+- [#24](https://github.com/TokTok/c-toxcore/pull/24) Silence/fix some compiler warnings.
+- [#23](https://github.com/TokTok/c-toxcore/pull/23) 4. Cmake
+- [#20](https://github.com/TokTok/c-toxcore/pull/20) 3. Travis astyle
+- [#13](https://github.com/TokTok/c-toxcore/pull/13) Enable, and report test status
+- [#12](https://github.com/TokTok/c-toxcore/pull/12) Fix readme for TokTok
+- [#11](https://github.com/TokTok/c-toxcore/pull/11) Documentation: SysVInit workaround for <1024 ports
+- [#2](https://github.com/TokTok/c-toxcore/pull/2) Enable toxcore logging when building on Travis.
+- [#1](https://github.com/TokTok/c-toxcore/pull/1) Apidsl fixes and start tracking test coverage
+
+### Closed issues:
+
+- [#158](https://github.com/TokTok/c-toxcore/issues/158) Error while build with OpenCV 3.1
+- [#147](https://github.com/TokTok/c-toxcore/issues/147) Add comment to m_delfriend about the NULL passing to the internal conn status cb
+- [#136](https://github.com/TokTok/c-toxcore/issues/136) Replace astyle by clang-format
+- [#113](https://github.com/TokTok/c-toxcore/issues/113) Toxcore tests fail
+- [#83](https://github.com/TokTok/c-toxcore/issues/83) Travis tests are hard to quickly parse from their output.
+- [#22](https://github.com/TokTok/c-toxcore/issues/22) Make the current tests exercise both ipv4 and ipv6.
+- [#9](https://github.com/TokTok/c-toxcore/issues/9) Fix the failing test
+- [#8](https://github.com/TokTok/c-toxcore/issues/8) Toxcore should make more liberal use of assertions
+- [#4](https://github.com/TokTok/c-toxcore/issues/4) Integrate hstox tests with toxcore Travis build
diff --git a/protocols/Tox/libtox/docs/COPYING b/protocols/Tox/libtox/docs/COPYING
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/protocols/Tox/libtox/docs/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/protocols/Tox/libtox/docs/DONATORS b/protocols/Tox/libtox/docs/DONATORS
new file mode 100644
index 0000000000..dcce32c869
--- /dev/null
+++ b/protocols/Tox/libtox/docs/DONATORS
@@ -0,0 +1,7 @@
+Minnesota > Florida
+vdo <vdo@greyfaze.net>
+Spitfire is best technicolor horse.
+if bad people don't hate you, you're doing something wrong
+Pinkie Pie is best pony.
+JRS was here
+qTox is so bloated it doesn't even fit in a 64-bit address space
diff --git a/protocols/Tox/libtox/docs/README.md b/protocols/Tox/libtox/docs/README.md
new file mode 100644
index 0000000000..7a1ffe7ffa
--- /dev/null
+++ b/protocols/Tox/libtox/docs/README.md
@@ -0,0 +1,174 @@
+# ![Project Tox](https://raw.github.com/TokTok/toxcore/master/other/tox.png "Project Tox")
+
+**Current build status:** [![Build Status](https://travis-ci.org/TokTok/c-toxcore.svg?branch=master)](https://travis-ci.org/TokTok/c-toxcore)
+**Current Coverage:** [![Coverage Status](https://coveralls.io/repos/github/TokTok/toxcore/badge.svg?branch=master)](https://coveralls.io/github/TokTok/toxcore?branch=master)
+
+[**Website**](https://tox.chat) **|** [**Wiki**](https://wiki.tox.chat/) **|** [**Blog**](https://blog.tox.chat/) **|** [**FAQ**](https://wiki.tox.chat/doku.php?id=users:faq) **|** [**Binaries/Downloads**](https://wiki.tox.chat/Binaries) **|** [**Clients**](https://wiki.tox.chat/doku.php?id=clients) **|** [**Compiling**](/INSTALL.md)
+
+**IRC Channels:** Users: [#tox@freenode](https://webchat.freenode.net/?channels=tox), Developers: [#toktok@freenode](https://webchat.freenode.net/?channels=toktok)
+
+## What is Tox
+
+Tox is a peer to peer (serverless) instant messenger aimed at making security
+and privacy easy to obtain for regular users. It uses
+[NaCl](https://nacl.cr.yp.to/) for its encryption and authentication.
+
+## IMPORTANT!
+
+### ![Danger: Experimental](other/tox-warning.png)
+
+This is an **experimental** cryptographic network library. It has not been
+formally audited by an independent third party that specializes in
+cryptography or cryptanalysis. **Use this library at your own risk.**
+
+The underlying crypto library [NaCl](https://nacl.cr.yp.to/install.html)
+provides reliable encryption, but the security model has not yet been fully
+specified. See [issue 210](https://github.com/TokTok/c-toxcore/issues/210) for
+a discussion on developing a threat model. See other issues for known
+weaknesses (e.g. [issue 426](https://github.com/TokTok/c-toxcore/issues/426)
+describes what can happen if your secret key is stolen).
+
+## Toxcore Development Roadmap
+
+The roadmap and changelog are generated from GitHub issues. You may view them
+on the website, where they are updated at least once every 24 hours:
+
+- Changelog: https://toktok.ltd/changelog/c-toxcore
+- Roadmap: https://toktok.ltd/roadmap/c-toxcore
+
+## Installing toxcore
+
+Detailed installation instructions can be found in [INSTALL.md](INSTALL.md).
+
+In a nutshell, if you have [libsodium](https://github.com/jedisct1/libsodium)
+or [nacl](https://nacl.cr.yp.to/install.html) installed, run:
+
+```sh
+autoreconf -fi
+mkdir _build && cd _build
+../configure
+make
+sudo make install
+```
+
+If you have [libvpx](https://github.com/webmproject/libvpx) and
+[opus](https://github.com/xiph/opus) installed, the above will also build the
+A/V library for multimedia chats.
+
+## Using toxcore
+
+The simplest "hello world" example could be an echo bot. Here we will walk
+through the implementation of a simple bot.
+
+### Creating the tox instance
+
+All toxcore API functions work with error parameters. They are enums with one
+`OK` value and several error codes that describe the different situations in
+which the function might fail.
+
+```c
+TOX_ERR_NEW err_new;
+Tox *tox = tox_new(NULL, &err_new);
+if (err_new != TOX_ERR_NEW_OK) {
+ fprintf(stderr, "tox_new failed with error code %d\n", err_new);
+ exit(1);
+}
+```
+
+Here, we simply exit the program, but in a real client you will probably want
+to do some error handling and proper error reporting to the user. The `NULL`
+argument given to the first parameter of `tox_new` is the `Tox_Options`. It
+contains various write-once network settings and allows you to load a
+previously serialised instance. See [toxcore/tox.h](tox.h) for details.
+
+### Setting up callbacks
+
+Toxcore works with callbacks that you can register to listen for certain
+events. Examples of such events are "friend request received" or "friend sent
+a message". Search the API for `tox_callback_*` to find all of them.
+
+Here, we will set up callbacks for receiving friend requests and receiving
+messages. We will always accept any friend request (because we're a bot), and
+when we receive a message, we send it back to the sender.
+
+```c
+tox_callback_friend_request(tox, handle_friend_request);
+tox_callback_friend_message(tox, handle_friend_message);
+```
+
+These two function calls set up the callbacks. Now we also need to implement
+these "handle" functions.
+
+### Handle friend requests
+
+```c
+static void handle_friend_request(
+ Tox *tox, const uint8_t *public_key, const uint8_t *message, size_t length,
+ void *user_data) {
+ // Accept the friend request:
+ TOX_ERR_FRIEND_ADD err_friend_add;
+ tox_friend_add_norequest(tox, public_key, &err_friend_add);
+ if (err_friend_add != TOX_ERR_FRIEND_ADD_OK) {
+ fprintf(stderr, "unable to add friend: %d\n", err_friend_add);
+ }
+}
+```
+
+The `tox_friend_add_norequest` function adds the friend without sending them a
+friend request. Since we already got a friend request, this is the right thing
+to do. If you wanted to send a friend request yourself, you would use
+`tox_friend_add`, which has an extra parameter for the message.
+
+### Handle messages
+
+Now, when the friend sends us a message, we want to respond to them by sending
+them the same message back. This will be our "echo".
+
+```c
+static void handle_friend_message(
+ Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type,
+ const uint8_t *message, size_t length,
+ void *user_data) {
+ TOX_ERR_FRIEND_SEND_MESSAGE err_send;
+ tox_friend_send_message(tox, friend_number, type, message, length,
+ &err_send);
+ if (err_send != TOX_ERR_FRIEND_SEND_MESSAGE_OK) {
+ fprintf(stderr, "unable to send message back to friend %d: %d\n",
+ friend_number, err_send);
+ }
+}
+```
+
+That's it for the setup. Now we want to actually run the bot.
+
+### Main event loop
+
+Toxcore works with a main event loop function `tox_iterate` that you need to
+call at a certain frequency dictated by `tox_iteration_interval`. This is a
+polling function that receives new network messages and processes them.
+
+```c
+while (true) {
+ usleep(1000 * tox_iteration_interval(tox));
+ tox_iterate(tox, NULL);
+}
+```
+
+That's it! Now you have a working echo bot. The only problem is that since Tox
+works with public keys, and you can't really guess your bot's public key, you
+can't add it as a friend in your client. For this, we need to call another API
+function: `tox_self_get_address(tox, address)`. This will fill the 38 byte
+friend address into the `address` buffer. You can then display that binary
+string as hex and input it into your client. Writing a `bin2hex` function is
+left as exercise for the reader.
+
+We glossed over a lot of details, such as the user data which we passed to
+`tox_iterate` (passing `NULL`), bootstrapping into an actual network (this bot
+will work in the LAN, but not on an internet server) and the fact that we now
+have no clean way of stopping the bot (`while (true)`). If you want to write a
+real bot, you will probably want to read up on all the API functions. Consult
+the API documentation in [toxcore/tox.h](tox.h) for more information.
+
+### Other resources
+
+- [Another echo bot](https://wiki.tox.chat/developers/client_examples/echo_bot)
diff --git a/protocols/Tox/libtox/libtox.vcxproj b/protocols/Tox/libtox/libtox.vcxproj
new file mode 100644
index 0000000000..c4380e76d9
--- /dev/null
+++ b/protocols/Tox/libtox/libtox.vcxproj
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{A21C50CD-28A6-481A-A12B-47189FE66641}</ProjectGuid>
+ <ProjectName>libtox</ProjectName>
+ <GenerateManifest>false</GenerateManifest>
+ <EmbedManifest>false</EmbedManifest>
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <OutDir Condition="'$(Platform)'=='Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</OutDir>
+ <OutDir Condition="'$(Platform)'=='x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</OutDir>
+ </PropertyGroup>
+ <Import Project="..\..\..\build\vc.common\common.props" />
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\..\libs\pthreads\src;..\..\..\libs\libsodium\src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <ModuleDefinitionFile>src/libtox.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="src\toxcore\*.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\toxdns\*.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\toxencryptsave\*.c">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClInclude Include="src\toxcore\*.h" />
+ <ClInclude Include="src\toxencryptsave*.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\libs\libsodium\libsodium.vcxproj">
+ <Project>{a185b162-6cb6-4502-b03f-b56f7699a8d9}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\libs\pthreads\pthreads.vcxproj">
+ <Project>{e0ebb8a5-b577-414c-a5f9-9b4e2a0a66e9}</Project>
+ </ProjectReference>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/protocols/AimOscar/proto_aim/Proto_AIM.vcxproj.filters b/protocols/Tox/libtox/libtox.vcxproj.filters
index e39f86d5d6..5a8d37777a 100644
--- a/protocols/AimOscar/proto_aim/Proto_AIM.vcxproj.filters
+++ b/protocols/Tox/libtox/libtox.vcxproj.filters
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$(ProjectDir)..\..\..\build\vc.common\common.filters" />
-</Project> \ No newline at end of file
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(ProjectDir)..\..\..\build\vc.common\common.filters" />
+</Project>
diff --git a/protocols/Tox/libtox/src/libtox.def b/protocols/Tox/libtox/src/libtox.def
new file mode 100644
index 0000000000..e1706ad3ae
--- /dev/null
+++ b/protocols/Tox/libtox/src/libtox.def
@@ -0,0 +1,155 @@
+LIBRARY libtox.mir
+DESCRIPTION
+
+EXPORTS
+tox_add_tcp_relay
+tox_address_size
+tox_bootstrap
+tox_callback_conference_invite
+tox_callback_conference_message
+tox_callback_conference_namelist_change
+tox_callback_conference_title
+tox_callback_file_chunk_request
+tox_callback_file_recv
+tox_callback_file_recv_chunk
+tox_callback_file_recv_control
+tox_callback_friend_connection_status
+tox_callback_friend_lossless_packet
+tox_callback_friend_lossy_packet
+tox_callback_friend_message
+tox_callback_friend_name
+tox_callback_friend_read_receipt
+tox_callback_friend_request
+tox_callback_friend_status
+tox_callback_friend_status_message
+tox_callback_friend_typing
+tox_callback_self_connection_status
+tox_conference_delete
+tox_conference_get_chatlist
+tox_conference_get_chatlist_size
+tox_conference_get_title
+tox_conference_get_title_size
+tox_conference_get_type
+tox_conference_invite
+tox_conference_join
+tox_conference_new
+tox_conference_peer_count
+tox_conference_peer_get_name
+tox_conference_peer_get_name_size
+tox_conference_peer_get_public_key
+tox_conference_peer_number_is_ours
+tox_conference_send_message
+tox_conference_set_title
+tox_decrypt_dns3_TXT
+tox_dns3_kill
+tox_dns3_new
+tox_file_control
+tox_file_get_file_id
+tox_file_id_length
+tox_file_seek
+tox_file_send
+tox_file_send_chunk
+tox_friend_add
+tox_friend_add_norequest
+tox_friend_by_public_key
+tox_friend_delete
+tox_friend_exists
+tox_friend_get_connection_status
+tox_friend_get_last_online
+tox_friend_get_name
+tox_friend_get_name_size
+tox_friend_get_public_key
+tox_friend_get_status
+tox_friend_get_status_message
+tox_friend_get_status_message_size
+tox_friend_get_typing
+tox_friend_send_lossless_packet
+tox_friend_send_lossy_packet
+tox_friend_send_message
+tox_generate_dns3_string
+tox_get_salt
+tox_get_savedata
+tox_get_savedata_size
+tox_hash
+tox_hash_length
+tox_is_data_encrypted
+tox_iterate
+tox_iteration_interval
+tox_kill
+tox_max_custom_packet_size
+tox_max_filename_length
+tox_max_friend_request_length
+tox_max_message_length
+tox_max_name_length
+tox_max_status_message_length
+tox_new
+tox_options_default
+tox_options_free
+tox_options_get_end_port
+tox_options_get_hole_punching_enabled
+tox_options_get_ipv6_enabled
+tox_options_get_local_discovery_enabled
+tox_options_get_log_callback
+tox_options_get_log_user_data
+tox_options_get_proxy_host
+tox_options_get_proxy_port
+tox_options_get_proxy_type
+tox_options_get_savedata_data
+tox_options_get_savedata_length
+tox_options_get_savedata_type
+tox_options_get_start_port
+tox_options_get_tcp_port
+tox_options_get_udp_enabled
+tox_options_new
+tox_options_set_end_port
+tox_options_set_hole_punching_enabled
+tox_options_set_ipv6_enabled
+tox_options_set_local_discovery_enabled
+tox_options_set_log_callback
+tox_options_set_log_user_data
+tox_options_set_proxy_host
+tox_options_set_proxy_port
+tox_options_set_proxy_type
+tox_options_set_savedata_data
+tox_options_set_savedata_length
+tox_options_set_savedata_type
+tox_options_set_start_port
+tox_options_set_tcp_port
+tox_options_set_udp_enabled
+tox_pass_decrypt
+tox_pass_encrypt
+tox_pass_encryption_extra_length
+tox_pass_key_decrypt
+tox_pass_key_derive
+tox_pass_key_derive_with_salt
+tox_pass_key_encrypt
+tox_pass_key_free
+tox_pass_key_length
+tox_pass_key_new
+tox_pass_salt_length
+tox_public_key_size
+tox_secret_key_size
+tox_self_get_address
+tox_self_get_connection_status
+tox_self_get_dht_id
+tox_self_get_friend_list
+tox_self_get_friend_list_size
+tox_self_get_name
+tox_self_get_name_size
+tox_self_get_nospam
+tox_self_get_public_key
+tox_self_get_secret_key
+tox_self_get_status
+tox_self_get_status_message
+tox_self_get_status_message_size
+tox_self_get_tcp_port
+tox_self_get_udp_port
+tox_self_set_name
+tox_self_set_nospam
+tox_self_set_status
+tox_self_set_status_message
+tox_self_set_typing
+tox_version_is_compatible
+tox_version_major
+tox_version_minor
+tox_version_patch
diff --git a/protocols/Tox/libtox/src/stdafx.cxx b/protocols/Tox/libtox/src/stdafx.cxx
new file mode 100644
index 0000000000..1647228cd0
--- /dev/null
+++ b/protocols/Tox/libtox/src/stdafx.cxx
@@ -0,0 +1,2 @@
+
+#include "stdafx.h" \ No newline at end of file
diff --git a/protocols/Tox/libtox/src/stdafx.h b/protocols/Tox/libtox/src/stdafx.h
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/protocols/Tox/libtox/src/stdafx.h
diff --git a/protocols/Tox/libtox/src/toxcore/DHT.c b/protocols/Tox/libtox/src/toxcore/DHT.c
new file mode 100644
index 0000000000..4ebe7f3344
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/DHT.c
@@ -0,0 +1,2853 @@
+/*
+ * An implementation of the DHT as seen in docs/updates/DHT.md
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "DHT.h"
+
+#include "LAN_discovery.h"
+#include "logger.h"
+#include "network.h"
+#include "ping.h"
+#include "util.h"
+
+#include <assert.h>
+
+/* The timeout after which a node is discarded completely. */
+#define KILL_NODE_TIMEOUT (BAD_NODE_TIMEOUT + PING_INTERVAL)
+
+/* Ping interval in seconds for each random sending of a get nodes request. */
+#define GET_NODE_INTERVAL 20
+
+#define MAX_PUNCHING_PORTS 48
+
+/* Interval in seconds between punching attempts*/
+#define PUNCH_INTERVAL 3
+
+/* Time in seconds after which punching parameters will be reset */
+#define PUNCH_RESET_TIME 40
+
+#define MAX_NORMAL_PUNCHING_TRIES 5
+
+#define NAT_PING_REQUEST 0
+#define NAT_PING_RESPONSE 1
+
+/* Number of get node requests to send to quickly find close nodes. */
+#define MAX_BOOTSTRAP_TIMES 5
+
+#define ASSOC_COUNT 2
+
+/* Compares pk1 and pk2 with pk.
+ *
+ * return 0 if both are same distance.
+ * return 1 if pk1 is closer.
+ * return 2 if pk2 is closer.
+ */
+int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2)
+{
+ for (size_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; ++i) {
+
+ uint8_t distance1 = pk[i] ^ pk1[i];
+ uint8_t distance2 = pk[i] ^ pk2[i];
+
+ if (distance1 < distance2) {
+ return 1;
+ }
+
+ if (distance1 > distance2) {
+ return 2;
+ }
+ }
+
+ return 0;
+}
+
+/* Return index of first unequal bit number.
+ */
+static unsigned int bit_by_bit_cmp(const uint8_t *pk1, const uint8_t *pk2)
+{
+ unsigned int i;
+ unsigned int j = 0;
+
+ for (i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; ++i) {
+ if (pk1[i] == pk2[i]) {
+ continue;
+ }
+
+ for (j = 0; j < 8; ++j) {
+ uint8_t mask = 1 << (7 - j);
+
+ if ((pk1[i] & mask) != (pk2[i] & mask)) {
+ break;
+ }
+ }
+
+ break;
+ }
+
+ return i * 8 + j;
+}
+
+/* Shared key generations are costly, it is therefor smart to store commonly used
+ * ones so that they can re used later without being computed again.
+ *
+ * If shared key is already in shared_keys, copy it to shared_key.
+ * else generate it into shared_key and copy it to shared_keys
+ */
+void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t *secret_key, const uint8_t *public_key)
+{
+ uint32_t num = ~0;
+ uint32_t curr = 0;
+
+ for (uint32_t i = 0; i < MAX_KEYS_PER_SLOT; ++i) {
+ int index = public_key[30] * MAX_KEYS_PER_SLOT + i;
+ Shared_Key *key = &shared_keys->keys[index];
+
+ if (key->stored) {
+ if (id_equal(public_key, key->public_key)) {
+ memcpy(shared_key, key->shared_key, CRYPTO_SHARED_KEY_SIZE);
+ ++key->times_requested;
+ key->time_last_requested = unix_time();
+ return;
+ }
+
+ if (num != 0) {
+ if (is_timeout(key->time_last_requested, KEYS_TIMEOUT)) {
+ num = 0;
+ curr = index;
+ } else if (num > key->times_requested) {
+ num = key->times_requested;
+ curr = index;
+ }
+ }
+ } else if (num != 0) {
+ num = 0;
+ curr = index;
+ }
+ }
+
+ encrypt_precompute(public_key, secret_key, shared_key);
+
+ if (num != (uint32_t)~0) {
+ Shared_Key *key = &shared_keys->keys[curr];
+ key->stored = 1;
+ key->times_requested = 1;
+ memcpy(key->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(key->shared_key, shared_key, CRYPTO_SHARED_KEY_SIZE);
+ key->time_last_requested = unix_time();
+ }
+}
+
+/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key
+ * for packets that we receive.
+ */
+void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *public_key)
+{
+ get_shared_key(&dht->shared_keys_recv, shared_key, dht->self_secret_key, public_key);
+}
+
+/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key
+ * for packets that we send.
+ */
+void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *public_key)
+{
+ get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, public_key);
+}
+
+#define CRYPTO_SIZE 1 + CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE
+
+/* Create a request to peer.
+ * send_public_key and send_secret_key are the pub/secret keys of the sender.
+ * recv_public_key is public key of receiver.
+ * packet must be an array of MAX_CRYPTO_REQUEST_SIZE big.
+ * Data represents the data we send with the request with length being the length of the data.
+ * request_id is the id of the request (32 = friend request, 254 = ping request).
+ *
+ * return -1 on failure.
+ * return the length of the created packet on success.
+ */
+int create_request(const uint8_t *send_public_key, const uint8_t *send_secret_key, uint8_t *packet,
+ const uint8_t *recv_public_key, const uint8_t *data, uint32_t length, uint8_t request_id)
+{
+ if (!send_public_key || !packet || !recv_public_key || !data) {
+ return -1;
+ }
+
+ if (MAX_CRYPTO_REQUEST_SIZE < length + CRYPTO_SIZE + 1 + CRYPTO_MAC_SIZE) {
+ return -1;
+ }
+
+ uint8_t *nonce = packet + 1 + CRYPTO_PUBLIC_KEY_SIZE * 2;
+ random_nonce(nonce);
+ uint8_t temp[MAX_CRYPTO_REQUEST_SIZE];
+ memcpy(temp + 1, data, length);
+ temp[0] = request_id;
+ int len = encrypt_data(recv_public_key, send_secret_key, nonce, temp, length + 1,
+ CRYPTO_SIZE + packet);
+
+ if (len == -1) {
+ crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
+ return -1;
+ }
+
+ packet[0] = NET_PACKET_CRYPTO;
+ memcpy(packet + 1, recv_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, send_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+
+ crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
+ return len + CRYPTO_SIZE;
+}
+
+/* Puts the senders public key in the request in public_key, the data from the request
+ * in data if a friend or ping request was sent to us and returns the length of the data.
+ * packet is the request packet and length is its length.
+ *
+ * return -1 if not valid request.
+ */
+int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
+ uint8_t *request_id, const uint8_t *packet, uint16_t length)
+{
+ if (!self_public_key || !public_key || !data || !request_id || !packet) {
+ return -1;
+ }
+
+ if (length <= CRYPTO_SIZE + CRYPTO_MAC_SIZE || length > MAX_CRYPTO_REQUEST_SIZE) {
+ return -1;
+ }
+
+ if (!id_equal(packet + 1, self_public_key)) {
+ return -1;
+ }
+
+ memcpy(public_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE);
+ const uint8_t *nonce = packet + 1 + CRYPTO_PUBLIC_KEY_SIZE * 2;
+ uint8_t temp[MAX_CRYPTO_REQUEST_SIZE];
+ int len1 = decrypt_data(public_key, self_secret_key, nonce,
+ packet + CRYPTO_SIZE, length - CRYPTO_SIZE, temp);
+
+ if (len1 == -1 || len1 == 0) {
+ crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
+ return -1;
+ }
+
+ request_id[0] = temp[0];
+ --len1;
+ memcpy(data, temp + 1, len1);
+ crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
+ return len1;
+}
+
+#define PACKED_NODE_SIZE_IP4 (1 + SIZE_IP4 + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE)
+#define PACKED_NODE_SIZE_IP6 (1 + SIZE_IP6 + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE)
+
+/* Return packet size of packed node with ip_family on success.
+ * Return -1 on failure.
+ */
+int packed_node_size(uint8_t ip_family)
+{
+ switch (ip_family) {
+ case TOX_AF_INET:
+ case TCP_INET:
+ return PACKED_NODE_SIZE_IP4;
+
+ case TOX_AF_INET6:
+ case TCP_INET6:
+ return PACKED_NODE_SIZE_IP6;
+
+ default:
+ return -1;
+ }
+}
+
+
+/* Packs an IP_Port structure into data of max size length.
+ *
+ * Returns size of packed IP_Port data on success
+ * Return -1 on failure.
+ */
+static int pack_ip_port(uint8_t *data, uint16_t length, const IP_Port *ip_port)
+{
+ if (data == NULL) {
+ return -1;
+ }
+
+ bool is_ipv4;
+ uint8_t net_family;
+
+ if (ip_port->ip.family == TOX_AF_INET) {
+ // TODO(irungentoo): use functions to convert endianness
+ is_ipv4 = true;
+ net_family = TOX_AF_INET;
+ } else if (ip_port->ip.family == TCP_INET) {
+ is_ipv4 = true;
+ net_family = TOX_TCP_INET;
+ } else if (ip_port->ip.family == TOX_AF_INET6) {
+ is_ipv4 = false;
+ net_family = TOX_AF_INET6;
+ } else if (ip_port->ip.family == TCP_INET6) {
+ is_ipv4 = false;
+ net_family = TOX_TCP_INET6;
+ } else {
+ return -1;
+ }
+
+ if (is_ipv4) {
+ uint32_t size = 1 + SIZE_IP4 + sizeof(uint16_t);
+
+ if (size > length) {
+ return -1;
+ }
+
+ data[0] = net_family;
+ memcpy(data + 1, &ip_port->ip.ip4, SIZE_IP4);
+ memcpy(data + 1 + SIZE_IP4, &ip_port->port, sizeof(uint16_t));
+ return size;
+ } else {
+ uint32_t size = 1 + SIZE_IP6 + sizeof(uint16_t);
+
+ if (size > length) {
+ return -1;
+ }
+
+ data[0] = net_family;
+ memcpy(data + 1, &ip_port->ip.ip6, SIZE_IP6);
+ memcpy(data + 1 + SIZE_IP6, &ip_port->port, sizeof(uint16_t));
+ return size;
+ }
+}
+
+static int DHT_create_packet(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
+ const uint8_t *shared_key, const uint8_t type, uint8_t *plain, size_t plain_length, uint8_t *packet)
+{
+ VLA(uint8_t, encrypted, plain_length + CRYPTO_MAC_SIZE);
+ uint8_t nonce[CRYPTO_NONCE_SIZE];
+
+ random_nonce(nonce);
+
+ int encrypted_length = encrypt_data_symmetric(shared_key, nonce, plain, plain_length, encrypted);
+
+ if (encrypted_length == -1) {
+ return -1;
+ }
+
+ packet[0] = type;
+ memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
+ memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, encrypted, encrypted_length);
+
+ return 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + encrypted_length;
+}
+
+/* Unpack IP_Port structure from data of max size length into ip_port.
+ *
+ * Return size of unpacked ip_port on success.
+ * Return -1 on failure.
+ */
+static int unpack_ip_port(IP_Port *ip_port, const uint8_t *data, uint16_t length, uint8_t tcp_enabled)
+{
+ if (data == NULL) {
+ return -1;
+ }
+
+ bool is_ipv4;
+ uint8_t host_family;
+
+ if (data[0] == TOX_AF_INET) {
+ is_ipv4 = true;
+ host_family = TOX_AF_INET;
+ } else if (data[0] == TOX_TCP_INET) {
+ if (!tcp_enabled) {
+ return -1;
+ }
+
+ is_ipv4 = true;
+ host_family = TCP_INET;
+ } else if (data[0] == TOX_AF_INET6) {
+ is_ipv4 = false;
+ host_family = TOX_AF_INET6;
+ } else if (data[0] == TOX_TCP_INET6) {
+ if (!tcp_enabled) {
+ return -1;
+ }
+
+ is_ipv4 = false;
+ host_family = TCP_INET6;
+ } else {
+ return -1;
+ }
+
+ if (is_ipv4) {
+ uint32_t size = 1 + SIZE_IP4 + sizeof(uint16_t);
+
+ if (size > length) {
+ return -1;
+ }
+
+ ip_port->ip.family = host_family;
+ memcpy(&ip_port->ip.ip4, data + 1, SIZE_IP4);
+ memcpy(&ip_port->port, data + 1 + SIZE_IP4, sizeof(uint16_t));
+ return size;
+ } else {
+ uint32_t size = 1 + SIZE_IP6 + sizeof(uint16_t);
+
+ if (size > length) {
+ return -1;
+ }
+
+ ip_port->ip.family = host_family;
+ memcpy(&ip_port->ip.ip6, data + 1, SIZE_IP6);
+ memcpy(&ip_port->port, data + 1 + SIZE_IP6, sizeof(uint16_t));
+ return size;
+ }
+}
+
+/* Pack number of nodes into data of maxlength length.
+ *
+ * return length of packed nodes on success.
+ * return -1 on failure.
+ */
+int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_t number)
+{
+ uint32_t packed_length = 0;
+
+ for (uint32_t i = 0; i < number && packed_length < length; ++i) {
+ int ipp_size = pack_ip_port(data + packed_length, length - packed_length, &nodes[i].ip_port);
+
+ if (ipp_size == -1) {
+ return -1;
+ }
+
+ packed_length += ipp_size;
+
+ if (packed_length + CRYPTO_PUBLIC_KEY_SIZE > length) {
+ return -1;
+ }
+
+ memcpy(data + packed_length, nodes[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ packed_length += CRYPTO_PUBLIC_KEY_SIZE;
+
+ uint32_t increment = ipp_size + CRYPTO_PUBLIC_KEY_SIZE;
+ assert(increment == PACKED_NODE_SIZE_IP4 || increment == PACKED_NODE_SIZE_IP6);
+ }
+
+ return packed_length;
+}
+
+/* Unpack data of length into nodes of size max_num_nodes.
+ * Put the length of the data processed in processed_data_len.
+ * tcp_enabled sets if TCP nodes are expected (true) or not (false).
+ *
+ * return number of unpacked nodes on success.
+ * return -1 on failure.
+ */
+int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, const uint8_t *data,
+ uint16_t length, uint8_t tcp_enabled)
+{
+ uint32_t num = 0, len_processed = 0;
+
+ while (num < max_num_nodes && len_processed < length) {
+ int ipp_size = unpack_ip_port(&nodes[num].ip_port, data + len_processed, length - len_processed, tcp_enabled);
+
+ if (ipp_size == -1) {
+ return -1;
+ }
+
+ len_processed += ipp_size;
+
+ if (len_processed + CRYPTO_PUBLIC_KEY_SIZE > length) {
+ return -1;
+ }
+
+ memcpy(nodes[num].public_key, data + len_processed, CRYPTO_PUBLIC_KEY_SIZE);
+ len_processed += CRYPTO_PUBLIC_KEY_SIZE;
+ ++num;
+
+ uint32_t increment = ipp_size + CRYPTO_PUBLIC_KEY_SIZE;
+ assert(increment == PACKED_NODE_SIZE_IP4 || increment == PACKED_NODE_SIZE_IP6);
+ }
+
+ if (processed_data_len) {
+ *processed_data_len = len_processed;
+ }
+
+ return num;
+}
+
+/* Find index of ##type with public_key equal to pk.
+ *
+ * return index or UINT32_MAX if not found.
+ */
+#define INDEX_OF_PK \
+ for (uint32_t i = 0; i < size; i++) { \
+ if (id_equal(array[i].public_key, pk)) { \
+ return i; \
+ } \
+ } \
+ \
+ return UINT32_MAX;
+
+static uint32_t index_of_client_pk(const Client_data *array, uint32_t size, const uint8_t *pk)
+{
+ INDEX_OF_PK
+}
+
+static uint32_t index_of_friend_pk(const DHT_Friend *array, uint32_t size, const uint8_t *pk)
+{
+ INDEX_OF_PK
+}
+
+static uint32_t index_of_node_pk(const Node_format *array, uint32_t size, const uint8_t *pk)
+{
+ INDEX_OF_PK
+}
+
+/* Find index of Client_data with ip_port equal to param ip_port.
+ *
+ * return index or UINT32_MAX if not found.
+ */
+static uint32_t index_of_client_ip_port(const Client_data *array, uint32_t size, const IP_Port *ip_port)
+{
+ for (uint32_t i = 0; i < size; ++i) {
+ if (ip_port->ip.family == TOX_AF_INET && ipport_equal(&array[i].assoc4.ip_port, ip_port) ||
+ ip_port->ip.family == TOX_AF_INET6 && ipport_equal(&array[i].assoc6.ip_port, ip_port)) {
+ return i;
+ }
+ }
+
+ return UINT32_MAX;
+}
+
+/* Update ip_port of client if it's needed.
+ */
+static void update_client(Logger *log, int index, Client_data *client, IP_Port ip_port)
+{
+ IPPTsPng *assoc;
+ int ip_version;
+
+ if (ip_port.ip.family == TOX_AF_INET) {
+ assoc = &client->assoc4;
+ ip_version = 4;
+ } else if (ip_port.ip.family == TOX_AF_INET6) {
+ assoc = &client->assoc6;
+ ip_version = 6;
+ } else {
+ return;
+ }
+
+ if (!ipport_equal(&assoc->ip_port, &ip_port)) {
+ char ip_str[IP_NTOA_LEN];
+ LOGGER_TRACE(log, "coipil[%u]: switching ipv%d from %s:%u to %s:%u",
+ index, ip_version,
+ ip_ntoa(&assoc->ip_port.ip, ip_str, sizeof(ip_str)),
+ net_ntohs(assoc->ip_port.port),
+ ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)),
+ net_ntohs(ip_port.port));
+ }
+
+ if (LAN_ip(assoc->ip_port.ip) != 0 && LAN_ip(ip_port.ip) == 0) {
+ return;
+ }
+
+ assoc->ip_port = ip_port;
+ assoc->timestamp = unix_time();
+}
+
+/* Check if client with public_key is already in list of length length.
+ * If it is then set its corresponding timestamp to current time.
+ * If the id is already in the list with a different ip_port, update it.
+ * TODO(irungentoo): Maybe optimize this.
+ *
+ * return True(1) or False(0)
+ */
+static int client_or_ip_port_in_list(Logger *log, Client_data *list, uint16_t length, const uint8_t *public_key,
+ IP_Port ip_port)
+{
+ uint64_t temp_time = unix_time();
+ uint32_t index = index_of_client_pk(list, length, public_key);
+
+ /* if public_key is in list, find it and maybe overwrite ip_port */
+ if (index != UINT32_MAX) {
+ update_client(log, index, &list[index], ip_port);
+ return 1;
+ }
+
+ /* public_key not in list yet: see if we can find an identical ip_port, in
+ * that case we kill the old public_key by overwriting it with the new one
+ * TODO(irungentoo): maybe we SHOULDN'T do that if that public_key is in a friend_list
+ * and the one who is the actual friend's public_key/address set?
+ * MAYBE: check the other address, if valid, don't nuke? */
+ index = index_of_client_ip_port(list, length, &ip_port);
+
+ if (index == UINT32_MAX) {
+ return 0;
+ }
+
+ IPPTsPng *assoc;
+ int ip_version;
+
+ if (ip_port.ip.family == TOX_AF_INET) {
+ assoc = &list[index].assoc4;
+ ip_version = 4;
+ } else {
+ assoc = &list[index].assoc6;
+ ip_version = 6;
+ }
+
+ /* Initialize client timestamp. */
+ assoc->timestamp = temp_time;
+ memcpy(list[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+
+ LOGGER_DEBUG(log, "coipil[%u]: switching public_key (ipv%d)", index, ip_version);
+
+ /* kill the other address, if it was set */
+ memset(assoc, 0, sizeof(IPPTsPng));
+ return 1;
+}
+
+/* Add node to the node list making sure only the nodes closest to cmp_pk are in the list.
+ */
+bool add_to_list(Node_format *nodes_list, unsigned int length, const uint8_t *pk, IP_Port ip_port,
+ const uint8_t *cmp_pk)
+{
+ uint8_t pk_bak[CRYPTO_PUBLIC_KEY_SIZE];
+ IP_Port ip_port_bak;
+
+ for (size_t i = 0; i < length; ++i) {
+ if (id_closest(cmp_pk, nodes_list[i].public_key, pk) == 2) {
+ memcpy(pk_bak, nodes_list[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ ip_port_bak = nodes_list[i].ip_port;
+ memcpy(nodes_list[i].public_key, pk, CRYPTO_PUBLIC_KEY_SIZE);
+ nodes_list[i].ip_port = ip_port;
+
+ if (i != (length - 1)) {
+ add_to_list(nodes_list, length, pk_bak, ip_port_bak, cmp_pk);
+ }
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* TODO(irungentoo): change this to 7 when done*/
+#define HARDENING_ALL_OK 2
+/* return 0 if not.
+ * return 1 if route request are ok
+ * return 2 if it responds to send node packets correctly
+ * return 4 if it can test other nodes correctly
+ * return HARDENING_ALL_OK if all ok.
+ */
+static uint8_t hardening_correct(const Hardening *h)
+{
+ return h->routes_requests_ok + (h->send_nodes_ok << 1) + (h->testing_requests << 2);
+}
+/*
+ * helper for get_close_nodes(). argument list is a monster :D
+ */
+static void get_close_nodes_inner(const uint8_t *public_key, Node_format *nodes_list,
+ Family sa_family, const Client_data *client_list, uint32_t client_list_length,
+ uint32_t *num_nodes_ptr, uint8_t is_LAN, uint8_t want_good)
+{
+ if ((sa_family != TOX_AF_INET) && (sa_family != TOX_AF_INET6) && (sa_family != 0)) {
+ return;
+ }
+
+ uint32_t num_nodes = *num_nodes_ptr;
+
+ for (uint32_t i = 0; i < client_list_length; i++) {
+ const Client_data *client = &client_list[i];
+
+ /* node already in list? */
+ if (index_of_node_pk(nodes_list, MAX_SENT_NODES, client->public_key) != UINT32_MAX) {
+ continue;
+ }
+
+ const IPPTsPng *ipptp = NULL;
+
+ if (sa_family == TOX_AF_INET) {
+ ipptp = &client->assoc4;
+ } else if (sa_family == TOX_AF_INET6) {
+ ipptp = &client->assoc6;
+ } else if (client->assoc4.timestamp >= client->assoc6.timestamp) {
+ ipptp = &client->assoc4;
+ } else {
+ ipptp = &client->assoc6;
+ }
+
+ /* node not in a good condition? */
+ if (is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT)) {
+ continue;
+ }
+
+ /* don't send LAN ips to non LAN peers */
+ if (LAN_ip(ipptp->ip_port.ip) == 0 && !is_LAN) {
+ continue;
+ }
+
+ if (LAN_ip(ipptp->ip_port.ip) != 0 && want_good && hardening_correct(&ipptp->hardening) != HARDENING_ALL_OK
+ && !id_equal(public_key, client->public_key)) {
+ continue;
+ }
+
+ if (num_nodes < MAX_SENT_NODES) {
+ memcpy(nodes_list[num_nodes].public_key, client->public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ nodes_list[num_nodes].ip_port = ipptp->ip_port;
+ num_nodes++;
+ } else {
+ add_to_list(nodes_list, MAX_SENT_NODES, client->public_key, ipptp->ip_port, public_key);
+ }
+ }
+
+ *num_nodes_ptr = num_nodes;
+}
+
+/* Find MAX_SENT_NODES nodes closest to the public_key for the send nodes request:
+ * put them in the nodes_list and return how many were found.
+ *
+ * TODO(irungentoo): For the love of based <your favorite deity, in doubt use
+ * "love"> make this function cleaner and much more efficient.
+ *
+ * want_good : do we want only good nodes as checked with the hardening returned or not?
+ */
+static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list,
+ Family sa_family, uint8_t is_LAN, uint8_t want_good)
+{
+ uint32_t num_nodes = 0;
+ get_close_nodes_inner(public_key, nodes_list, sa_family,
+ dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, 0);
+
+ /* TODO(irungentoo): uncomment this when hardening is added to close friend clients */
+#if 0
+
+ for (uint32_t i = 0; i < dht->num_friends; ++i) {
+ get_close_nodes_inner(dht, public_key, nodes_list, sa_family,
+ dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
+ &num_nodes, is_LAN, want_good);
+ }
+
+#endif
+
+ for (uint32_t i = 0; i < dht->num_friends; ++i) {
+ get_close_nodes_inner(public_key, nodes_list, sa_family,
+ dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
+ &num_nodes, is_LAN, 0);
+ }
+
+ return num_nodes;
+}
+
+int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, Family sa_family,
+ uint8_t is_LAN, uint8_t want_good)
+{
+ memset(nodes_list, 0, MAX_SENT_NODES * sizeof(Node_format));
+ return get_somewhat_close_nodes(dht, public_key, nodes_list, sa_family, is_LAN, want_good);
+}
+
+typedef struct {
+ const uint8_t *base_public_key;
+ Client_data entry;
+} DHT_Cmp_data;
+
+static int cmp_dht_entry(const void *a, const void *b)
+{
+ DHT_Cmp_data cmp1, cmp2;
+ memcpy(&cmp1, a, sizeof(DHT_Cmp_data));
+ memcpy(&cmp2, b, sizeof(DHT_Cmp_data));
+ Client_data entry1 = cmp1.entry;
+ Client_data entry2 = cmp2.entry;
+ const uint8_t *cmp_public_key = cmp1.base_public_key;
+
+#define ASSOC_TIMEOUT(assoc) is_timeout((assoc).timestamp, BAD_NODE_TIMEOUT)
+
+ bool t1 = ASSOC_TIMEOUT(entry1.assoc4) && ASSOC_TIMEOUT(entry1.assoc6);
+ bool t2 = ASSOC_TIMEOUT(entry2.assoc4) && ASSOC_TIMEOUT(entry2.assoc6);
+
+ if (t1 && t2) {
+ return 0;
+ }
+
+ if (t1) {
+ return -1;
+ }
+
+ if (t2) {
+ return 1;
+ }
+
+#define INCORRECT_HARDENING(assoc) hardening_correct(&(assoc).hardening) != HARDENING_ALL_OK
+
+ t1 = INCORRECT_HARDENING(entry1.assoc4) && INCORRECT_HARDENING(entry1.assoc6);
+ t2 = INCORRECT_HARDENING(entry2.assoc4) && INCORRECT_HARDENING(entry2.assoc6);
+
+ if (t1 && !t2) {
+ return -1;
+ }
+
+ if (!t1 && t2) {
+ return 1;
+ }
+
+ int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);
+
+ if (close == 1) {
+ return 1;
+ }
+
+ if (close == 2) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Is it ok to store node with public_key in client.
+ *
+ * return 0 if node can't be stored.
+ * return 1 if it can.
+ */
+static unsigned int store_node_ok(const Client_data *client, const uint8_t *public_key, const uint8_t *comp_public_key)
+{
+ return is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) &&
+ is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT) ||
+ id_closest(comp_public_key, client->public_key, public_key) == 2;
+}
+
+static void sort_client_list(Client_data *list, unsigned int length, const uint8_t *comp_public_key)
+{
+ // Pass comp_public_key to qsort with each Client_data entry, so the
+ // comparison function can use it as the base of comparison.
+ VLA(DHT_Cmp_data, cmp_list, length);
+
+ for (uint32_t i = 0; i < length; i++) {
+ cmp_list[i].base_public_key = comp_public_key;
+ cmp_list[i].entry = list[i];
+ }
+
+ qsort(cmp_list, length, sizeof(DHT_Cmp_data), cmp_dht_entry);
+
+ for (uint32_t i = 0; i < length; i++) {
+ list[i] = cmp_list[i].entry;
+ }
+}
+
+static void update_client_with_reset(Client_data *client, const IP_Port *ip_port)
+{
+ IPPTsPng *ipptp_write = NULL;
+ IPPTsPng *ipptp_clear = NULL;
+
+ if (ip_port->ip.family == TOX_AF_INET) {
+ ipptp_write = &client->assoc4;
+ ipptp_clear = &client->assoc6;
+ } else {
+ ipptp_write = &client->assoc6;
+ ipptp_clear = &client->assoc4;
+ }
+
+ ipptp_write->ip_port = *ip_port;
+ ipptp_write->timestamp = unix_time();
+
+ ip_reset(&ipptp_write->ret_ip_port.ip);
+ ipptp_write->ret_ip_port.port = 0;
+ ipptp_write->ret_timestamp = 0;
+
+ /* zero out other address */
+ memset(ipptp_clear, 0, sizeof(*ipptp_clear));
+}
+
+/* Replace a first bad (or empty) node with this one
+ * or replace a possibly bad node (tests failed or not done yet)
+ * that is further than any other in the list
+ * from the comp_public_key
+ * or replace a good node that is further
+ * than any other in the list from the comp_public_key
+ * and further than public_key.
+ *
+ * Do not replace any node if the list has no bad or possibly bad nodes
+ * and all nodes in the list are closer to comp_public_key
+ * than public_key.
+ *
+ * returns True(1) when the item was stored, False(0) otherwise */
+static int replace_all(Client_data *list,
+ uint16_t length,
+ const uint8_t *public_key,
+ IP_Port ip_port,
+ const uint8_t *comp_public_key)
+{
+ if ((ip_port.ip.family != TOX_AF_INET) && (ip_port.ip.family != TOX_AF_INET6)) {
+ return 0;
+ }
+
+ if (!store_node_ok(&list[1], public_key, comp_public_key) &&
+ !store_node_ok(&list[0], public_key, comp_public_key)) {
+ return 0;
+ }
+
+ sort_client_list(list, length, comp_public_key);
+
+ Client_data *client = &list[0];
+ id_copy(client->public_key, public_key);
+
+ update_client_with_reset(client, &ip_port);
+ return 1;
+}
+
+/* Add node to close list.
+ *
+ * simulate is set to 1 if we want to check if a node can be added to the list without adding it.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, bool simulate)
+{
+ unsigned int index = bit_by_bit_cmp(public_key, dht->self_public_key);
+
+ if (index >= LCLIENT_LENGTH) {
+ index = LCLIENT_LENGTH - 1;
+ }
+
+ for (uint32_t i = 0; i < LCLIENT_NODES; ++i) {
+ /* TODO(iphydf): write bounds checking test to catch the case that
+ * index is left as >= LCLIENT_LENGTH */
+ Client_data *client = &dht->close_clientlist[(index * LCLIENT_NODES) + i];
+
+ if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) ||
+ !is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) {
+ continue;
+ }
+
+ if (simulate) {
+ return 0;
+ }
+
+ id_copy(client->public_key, public_key);
+ update_client_with_reset(client, &ip_port);
+ return 0;
+ }
+
+ return -1;
+}
+
+/* Return 1 if node can be added to close list, 0 if it can't.
+ */
+bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port)
+{
+ return add_to_close(dht, public_key, ip_port, 1) == 0;
+}
+
+static bool is_pk_in_client_list(Client_data *list, unsigned int client_list_length, const uint8_t *public_key,
+ IP_Port ip_port)
+{
+ uint32_t index = index_of_client_pk(list, client_list_length, public_key);
+
+ if (index == UINT32_MAX) {
+ return 0;
+ }
+
+ const IPPTsPng *assoc = ip_port.ip.family == TOX_AF_INET ?
+ &list[index].assoc4 :
+ &list[index].assoc6;
+
+ return !is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT);
+}
+
+static bool is_pk_in_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port)
+{
+ unsigned int index = bit_by_bit_cmp(public_key, dht->self_public_key);
+
+ if (index >= LCLIENT_LENGTH) {
+ index = LCLIENT_LENGTH - 1;
+ }
+
+ return is_pk_in_client_list(dht->close_clientlist + index * LCLIENT_NODES, LCLIENT_NODES, public_key, ip_port);
+}
+
+/* Check if the node obtained with a get_nodes with public_key should be pinged.
+ * NOTE: for best results call it after addto_lists;
+ *
+ * return 0 if the node should not be pinged.
+ * return 1 if it should.
+ */
+static unsigned int ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_key, IP_Port ip_port)
+{
+ bool ret = 0;
+
+ if (add_to_close(dht, public_key, ip_port, 1) == 0) {
+ ret = 1;
+ }
+
+ unsigned int *num = &dht->num_to_bootstrap;
+ uint32_t index = index_of_node_pk(dht->to_bootstrap, *num, public_key);
+ bool in_close_list = is_pk_in_close_list(dht, public_key, ip_port);
+
+ if (ret && index == UINT32_MAX && !in_close_list) {
+ if (*num < MAX_CLOSE_TO_BOOTSTRAP_NODES) {
+ memcpy(dht->to_bootstrap[*num].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ dht->to_bootstrap[*num].ip_port = ip_port;
+ ++*num;
+ } else {
+ // TODO(irungentoo): ipv6 vs v4
+ add_to_list(dht->to_bootstrap, MAX_CLOSE_TO_BOOTSTRAP_NODES, public_key, ip_port, dht->self_public_key);
+ }
+ }
+
+ for (uint32_t i = 0; i < dht->num_friends; ++i) {
+ bool store_ok = 0;
+
+ DHT_Friend *dht_friend = &dht->friends_list[i];
+
+ if (store_node_ok(&dht_friend->client_list[1], public_key, dht_friend->public_key)) {
+ store_ok = 1;
+ }
+
+ if (store_node_ok(&dht_friend->client_list[0], public_key, dht_friend->public_key)) {
+ store_ok = 1;
+ }
+
+ unsigned int *friend_num = &dht_friend->num_to_bootstrap;
+ const uint32_t index = index_of_node_pk(dht_friend->to_bootstrap, *friend_num, public_key);
+ const bool pk_in_list = is_pk_in_client_list(dht_friend->client_list, MAX_FRIEND_CLIENTS, public_key, ip_port);
+
+ if (store_ok && index == UINT32_MAX && !pk_in_list) {
+ if (*friend_num < MAX_SENT_NODES) {
+ Node_format *format = &dht_friend->to_bootstrap[*friend_num];
+ memcpy(format->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ format->ip_port = ip_port;
+ ++*friend_num;
+ } else {
+ add_to_list(dht_friend->to_bootstrap, MAX_SENT_NODES, public_key, ip_port, dht_friend->public_key);
+ }
+
+ ret = 1;
+ }
+ }
+
+ return ret;
+}
+
+/* Attempt to add client with ip_port and public_key to the friends client list
+ * and close_clientlist.
+ *
+ * returns 1+ if the item is used in any list, 0 else
+ */
+uint32_t addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key)
+{
+ uint32_t used = 0;
+
+ /* convert IPv4-in-IPv6 to IPv4 */
+ if ((ip_port.ip.family == TOX_AF_INET6) && IPV6_IPV4_IN_V6(ip_port.ip.ip6)) {
+ ip_port.ip.family = TOX_AF_INET;
+ ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3];
+ }
+
+ /* NOTE: Current behavior if there are two clients with the same id is
+ * to replace the first ip by the second.
+ */
+ const bool in_close_list = client_or_ip_port_in_list(dht->log, dht->close_clientlist,
+ LCLIENT_LIST, public_key, ip_port);
+
+ /* add_to_close should be called only if !in_list (don't extract to variable) */
+ if (in_close_list || add_to_close(dht, public_key, ip_port, 0)) {
+ used++;
+ }
+
+ DHT_Friend *friend_foundip = 0;
+
+ for (uint32_t i = 0; i < dht->num_friends; ++i) {
+ const bool in_list = client_or_ip_port_in_list(dht->log, dht->friends_list[i].client_list,
+ MAX_FRIEND_CLIENTS, public_key, ip_port);
+
+ /* replace_all should be called only if !in_list (don't extract to variable) */
+ if (in_list || replace_all(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, public_key,
+ ip_port, dht->friends_list[i].public_key)) {
+ DHT_Friend *dht_friend = &dht->friends_list[i];
+
+ if (id_equal(public_key, dht_friend->public_key)) {
+ friend_foundip = dht_friend;
+ }
+
+ used++;
+ }
+ }
+
+ if (!friend_foundip) {
+ return used;
+ }
+
+ for (uint32_t i = 0; i < friend_foundip->lock_count; ++i) {
+ if (friend_foundip->callbacks[i].ip_callback) {
+ friend_foundip->callbacks[i].ip_callback(friend_foundip->callbacks[i].data,
+ friend_foundip->callbacks[i].number, ip_port);
+ }
+ }
+
+ return used;
+}
+
+static bool update_client_data(Client_data *array, size_t size, IP_Port ip_port, const uint8_t *pk)
+{
+ uint64_t temp_time = unix_time();
+ uint32_t index = index_of_client_pk(array, size, pk);
+
+ if (index == UINT32_MAX) {
+ return false;
+ }
+
+ Client_data *data = &array[index];
+ IPPTsPng *assoc;
+
+ if (ip_port.ip.family == TOX_AF_INET) {
+ assoc = &data->assoc4;
+ } else if (ip_port.ip.family == TOX_AF_INET6) {
+ assoc = &data->assoc6;
+ } else {
+ return true;
+ }
+
+ assoc->ret_ip_port = ip_port;
+ assoc->ret_timestamp = temp_time;
+ return true;
+}
+
+/* If public_key is a friend or us, update ret_ip_port
+ * nodepublic_key is the id of the node that sent us this info.
+ */
+static void returnedip_ports(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const uint8_t *nodepublic_key)
+{
+ /* convert IPv4-in-IPv6 to IPv4 */
+ if ((ip_port.ip.family == TOX_AF_INET6) && IPV6_IPV4_IN_V6(ip_port.ip.ip6)) {
+ ip_port.ip.family = TOX_AF_INET;
+ ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3];
+ }
+
+ if (id_equal(public_key, dht->self_public_key)) {
+ update_client_data(dht->close_clientlist, LCLIENT_LIST, ip_port, nodepublic_key);
+ return;
+ }
+
+ for (uint32_t i = 0; i < dht->num_friends; ++i) {
+ if (id_equal(public_key, dht->friends_list[i].public_key)) {
+ Client_data *client_list = dht->friends_list[i].client_list;
+
+ if (update_client_data(client_list, MAX_FRIEND_CLIENTS, ip_port, nodepublic_key)) {
+ return;
+ }
+ }
+ }
+}
+
+/* Send a getnodes request.
+ sendback_node is the node that it will send back the response to (set to NULL to disable this) */
+static int getnodes(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const uint8_t *client_id,
+ const Node_format *sendback_node)
+{
+ /* Check if packet is going to be sent to ourself. */
+ if (id_equal(public_key, dht->self_public_key)) {
+ return -1;
+ }
+
+ uint8_t plain_message[sizeof(Node_format) * 2] = {0};
+
+ Node_format receiver;
+ memcpy(receiver.public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ receiver.ip_port = ip_port;
+ memcpy(plain_message, &receiver, sizeof(receiver));
+
+ uint64_t ping_id = 0;
+
+ if (sendback_node != NULL) {
+ memcpy(plain_message + sizeof(receiver), sendback_node, sizeof(Node_format));
+ ping_id = ping_array_add(&dht->dht_harden_ping_array, plain_message, sizeof(plain_message));
+ } else {
+ ping_id = ping_array_add(&dht->dht_ping_array, plain_message, sizeof(receiver));
+ }
+
+ if (ping_id == 0) {
+ return -1;
+ }
+
+ uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + sizeof(ping_id)];
+ uint8_t data[1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE];
+
+ memcpy(plain, client_id, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, &ping_id, sizeof(ping_id));
+
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
+ DHT_get_shared_key_sent(dht, shared_key, public_key);
+
+ int len = DHT_create_packet(dht->self_public_key, shared_key, NET_PACKET_GET_NODES,
+ plain, sizeof(plain), data);
+
+ if (len != sizeof(data)) {
+ return -1;
+ }
+
+ return sendpacket(dht->net, ip_port, data, len);
+}
+
+/* Send a send nodes response: message for IPv6 nodes */
+static int sendnodes_ipv6(const DHT *dht, IP_Port ip_port, const uint8_t *public_key, const uint8_t *client_id,
+ const uint8_t *sendback_data, uint16_t length, const uint8_t *shared_encryption_key)
+{
+ /* Check if packet is going to be sent to ourself. */
+ if (id_equal(public_key, dht->self_public_key)) {
+ return -1;
+ }
+
+ if (length != sizeof(uint64_t)) {
+ return -1;
+ }
+
+ size_t Node_format_size = sizeof(Node_format);
+
+ Node_format nodes_list[MAX_SENT_NODES];
+ uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, 0, LAN_ip(ip_port.ip) == 0, 1);
+
+ VLA(uint8_t, plain, 1 + Node_format_size * MAX_SENT_NODES + length);
+
+ int nodes_length = 0;
+
+ if (num_nodes) {
+ nodes_length = pack_nodes(plain + 1, Node_format_size * MAX_SENT_NODES, nodes_list, num_nodes);
+
+ if (nodes_length <= 0) {
+ return -1;
+ }
+ }
+
+ plain[0] = num_nodes;
+ memcpy(plain + 1 + nodes_length, sendback_data, length);
+
+ const uint32_t crypto_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE;
+ VLA(uint8_t, data, 1 + nodes_length + length + crypto_size);
+
+ int len = DHT_create_packet(dht->self_public_key, shared_encryption_key, NET_PACKET_SEND_NODES_IPV6,
+ plain, 1 + nodes_length + length, data);
+
+ if (len != SIZEOF_VLA(data)) {
+ return -1;
+ }
+
+ return sendpacket(dht->net, ip_port, data, len);
+}
+
+#define CRYPTO_NODE_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint64_t))
+
+static int handle_getnodes(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
+{
+ if (length != (CRYPTO_SIZE + CRYPTO_MAC_SIZE + sizeof(uint64_t))) {
+ return 1;
+ }
+
+ DHT *dht = (DHT *)object;
+
+ /* Check if packet is from ourself. */
+ if (id_equal(packet + 1, dht->self_public_key)) {
+ return 1;
+ }
+
+ uint8_t plain[CRYPTO_NODE_SIZE];
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
+
+ DHT_get_shared_key_recv(dht, shared_key, packet + 1);
+ int len = decrypt_data_symmetric(shared_key,
+ packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
+ packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
+ CRYPTO_NODE_SIZE + CRYPTO_MAC_SIZE,
+ plain);
+
+ if (len != CRYPTO_NODE_SIZE) {
+ return 1;
+ }
+
+ sendnodes_ipv6(dht, source, packet + 1, plain, plain + CRYPTO_PUBLIC_KEY_SIZE, sizeof(uint64_t), shared_key);
+
+ add_to_ping(dht->ping, packet + 1, source);
+
+ return 0;
+}
+/* return 0 if no
+ return 1 if yes */
+static uint8_t sent_getnode_to_node(DHT *dht, const uint8_t *public_key, IP_Port node_ip_port, uint64_t ping_id,
+ Node_format *sendback_node)
+{
+ uint8_t data[sizeof(Node_format) * 2];
+
+ if (ping_array_check(data, sizeof(data), &dht->dht_ping_array, ping_id) == sizeof(Node_format)) {
+ memset(sendback_node, 0, sizeof(Node_format));
+ } else if (ping_array_check(data, sizeof(data), &dht->dht_harden_ping_array, ping_id) == sizeof(data)) {
+ memcpy(sendback_node, data + sizeof(Node_format), sizeof(Node_format));
+ } else {
+ return 0;
+ }
+
+ Node_format test;
+ memcpy(&test, data, sizeof(Node_format));
+
+ if (!ipport_equal(&test.ip_port, &node_ip_port) || !id_equal(test.public_key, public_key)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Function is needed in following functions. */
+static int send_hardening_getnode_res(const DHT *dht, const Node_format *sendto, const uint8_t *queried_client_id,
+ const uint8_t *nodes_data, uint16_t nodes_data_length);
+
+static int handle_sendnodes_core(void *object, IP_Port source, const uint8_t *packet, uint16_t length,
+ Node_format *plain_nodes, uint16_t size_plain_nodes, uint32_t *num_nodes_out)
+{
+ DHT *dht = (DHT *)object;
+ uint32_t cid_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + 1 + sizeof(uint64_t) + CRYPTO_MAC_SIZE;
+
+ if (length < cid_size) { /* too short */
+ return 1;
+ }
+
+ uint32_t data_size = length - cid_size;
+
+ if (data_size == 0) {
+ return 1;
+ }
+
+ if (data_size > sizeof(Node_format) * MAX_SENT_NODES) { /* invalid length */
+ return 1;
+ }
+
+ VLA(uint8_t, plain, 1 + data_size + sizeof(uint64_t));
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
+ DHT_get_shared_key_sent(dht, shared_key, packet + 1);
+ int len = decrypt_data_symmetric(
+ shared_key,
+ packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
+ packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
+ 1 + data_size + sizeof(uint64_t) + CRYPTO_MAC_SIZE,
+ plain);
+
+ if ((unsigned int)len != SIZEOF_VLA(plain)) {
+ return 1;
+ }
+
+ if (plain[0] > size_plain_nodes) {
+ return 1;
+ }
+
+ Node_format sendback_node;
+
+ uint64_t ping_id;
+ memcpy(&ping_id, plain + 1 + data_size, sizeof(ping_id));
+
+ if (!sent_getnode_to_node(dht, packet + 1, source, ping_id, &sendback_node)) {
+ return 1;
+ }
+
+ uint16_t length_nodes = 0;
+ int num_nodes = unpack_nodes(plain_nodes, plain[0], &length_nodes, plain + 1, data_size, 0);
+
+ if (length_nodes != data_size) {
+ return 1;
+ }
+
+ if (num_nodes != plain[0]) {
+ return 1;
+ }
+
+ if (num_nodes < 0) {
+ return 1;
+ }
+
+ /* store the address the *request* was sent to */
+ addto_lists(dht, source, packet + 1);
+
+ *num_nodes_out = num_nodes;
+
+ send_hardening_getnode_res(dht, &sendback_node, packet + 1, plain + 1, data_size);
+ return 0;
+}
+
+static int handle_sendnodes_ipv6(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
+{
+ DHT *dht = (DHT *)object;
+ Node_format plain_nodes[MAX_SENT_NODES];
+ uint32_t num_nodes;
+
+ if (handle_sendnodes_core(object, source, packet, length, plain_nodes, MAX_SENT_NODES, &num_nodes)) {
+ return 1;
+ }
+
+ if (num_nodes == 0) {
+ return 0;
+ }
+
+ for (uint32_t i = 0; i < num_nodes; i++) {
+ if (ipport_isset(&plain_nodes[i].ip_port)) {
+ ping_node_from_getnodes_ok(dht, plain_nodes[i].public_key, plain_nodes[i].ip_port);
+ returnedip_ports(dht, plain_nodes[i].ip_port, plain_nodes[i].public_key, packet + 1);
+ }
+ }
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------------*/
+/*------------------------END of packet handling functions--------------------------*/
+
+int DHT_addfriend(DHT *dht, const uint8_t *public_key, void (*ip_callback)(void *data, int32_t number, IP_Port),
+ void *data, int32_t number, uint16_t *lock_count)
+{
+ uint32_t friend_num = index_of_friend_pk(dht->friends_list, dht->num_friends, public_key);
+
+ uint16_t lock_num;
+
+ if (friend_num != UINT32_MAX) { /* Is friend already in DHT? */
+ DHT_Friend *dht_friend = &dht->friends_list[friend_num];
+
+ if (dht_friend->lock_count == DHT_FRIEND_MAX_LOCKS) {
+ return -1;
+ }
+
+ lock_num = dht_friend->lock_count;
+ ++dht_friend->lock_count;
+ dht_friend->callbacks[lock_num].ip_callback = ip_callback;
+ dht_friend->callbacks[lock_num].data = data;
+ dht_friend->callbacks[lock_num].number = number;
+
+ if (lock_count) {
+ *lock_count = lock_num + 1;
+ }
+
+ return 0;
+ }
+
+ DHT_Friend *temp = (DHT_Friend *)realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends + 1));
+
+ if (temp == NULL) {
+ return -1;
+ }
+
+ dht->friends_list = temp;
+ DHT_Friend *dht_friend = &dht->friends_list[dht->num_friends];
+ memset(dht_friend, 0, sizeof(DHT_Friend));
+ memcpy(dht_friend->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+
+ dht_friend->nat.NATping_id = random_64b();
+ ++dht->num_friends;
+
+ lock_num = dht_friend->lock_count;
+ ++dht_friend->lock_count;
+ dht_friend->callbacks[lock_num].ip_callback = ip_callback;
+ dht_friend->callbacks[lock_num].data = data;
+ dht_friend->callbacks[lock_num].number = number;
+
+ if (lock_count) {
+ *lock_count = lock_num + 1;
+ }
+
+ dht_friend->num_to_bootstrap = get_close_nodes(dht, dht_friend->public_key, dht_friend->to_bootstrap, 0, 1, 0);
+
+ return 0;
+}
+
+int DHT_delfriend(DHT *dht, const uint8_t *public_key, uint16_t lock_count)
+{
+ uint32_t friend_num = index_of_friend_pk(dht->friends_list, dht->num_friends, public_key);
+
+ if (friend_num == UINT32_MAX) {
+ return -1;
+ }
+
+ DHT_Friend *dht_friend = &dht->friends_list[friend_num];
+ --dht_friend->lock_count;
+
+ if (dht_friend->lock_count && lock_count) { /* DHT friend is still in use.*/
+ --lock_count;
+ dht_friend->callbacks[lock_count].ip_callback = NULL;
+ dht_friend->callbacks[lock_count].data = NULL;
+ dht_friend->callbacks[lock_count].number = 0;
+ return 0;
+ }
+
+ --dht->num_friends;
+
+ if (dht->num_friends != friend_num) {
+ memcpy(&dht->friends_list[friend_num],
+ &dht->friends_list[dht->num_friends],
+ sizeof(DHT_Friend));
+ }
+
+ if (dht->num_friends == 0) {
+ free(dht->friends_list);
+ dht->friends_list = NULL;
+ return 0;
+ }
+
+ DHT_Friend *temp = (DHT_Friend *)realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends));
+
+ if (temp == NULL) {
+ return -1;
+ }
+
+ dht->friends_list = temp;
+ return 0;
+}
+
+/* TODO(irungentoo): Optimize this. */
+int DHT_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port)
+{
+ ip_reset(&ip_port->ip);
+ ip_port->port = 0;
+
+ uint32_t friend_index = index_of_friend_pk(dht->friends_list, dht->num_friends, public_key);
+
+ if (friend_index == UINT32_MAX) {
+ return -1;
+ }
+
+ DHT_Friend *frnd = &dht->friends_list[friend_index];
+ uint32_t client_index = index_of_client_pk(frnd->client_list, MAX_FRIEND_CLIENTS, public_key);
+
+ if (client_index == -1) {
+ return 0;
+ }
+
+ Client_data *client = &frnd->client_list[client_index];
+ IPPTsPng *assocs[ASSOC_COUNT] = { &client->assoc6, &client->assoc4 };
+
+ for (size_t i = 0; i < ASSOC_COUNT; i++) {
+ IPPTsPng *assoc = assocs[i];
+
+ if (!is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT)) {
+ *ip_port = assoc->ip_port;
+ return 1;
+ }
+ }
+
+ return -1;
+}
+
+/* returns number of nodes not in kill-timeout */
+static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, const uint8_t *public_key,
+ Client_data *list, uint32_t list_count, uint32_t *bootstrap_times, bool sortable)
+{
+ uint8_t not_kill = 0;
+ uint64_t temp_time = unix_time();
+
+ uint32_t num_nodes = 0;
+ VLA(Client_data *, client_list, list_count * 2);
+ VLA(IPPTsPng *, assoc_list, list_count * 2);
+ unsigned int sort = 0;
+ bool sort_ok = 0;
+
+ for (uint32_t i = 0; i < list_count; i++) {
+ /* If node is not dead. */
+ Client_data *client = &list[i];
+
+ IPPTsPng *assocs[ASSOC_COUNT] = { &client->assoc6, &client->assoc4 };
+
+ for (size_t i = 0; i < ASSOC_COUNT; i++) {
+ IPPTsPng *assoc = assocs[i];
+
+ if (!is_timeout(assoc->timestamp, KILL_NODE_TIMEOUT)) {
+ sort = 0;
+ not_kill++;
+
+ if (is_timeout(assoc->last_pinged, PING_INTERVAL)) {
+ getnodes(dht, assoc->ip_port, client->public_key, public_key, NULL);
+ assoc->last_pinged = temp_time;
+ }
+
+ /* If node is good. */
+ if (!is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT)) {
+ client_list[num_nodes] = client;
+ assoc_list[num_nodes] = assoc;
+ ++num_nodes;
+ }
+ } else {
+ ++sort;
+
+ /* Timed out should be at beginning, if they are not, sort the list. */
+ if (sort > 1 && sort < (((i + 1) * 2) - 1)) {
+ sort_ok = 1;
+ }
+ }
+ }
+ }
+
+ if (sortable && sort_ok) {
+ sort_client_list(list, list_count, public_key);
+ }
+
+ if ((num_nodes != 0) && (is_timeout(*lastgetnode, GET_NODE_INTERVAL) || *bootstrap_times < MAX_BOOTSTRAP_TIMES)) {
+ uint32_t rand_node = rand() % (num_nodes);
+
+ if ((num_nodes - 1) != rand_node) {
+ rand_node += rand() % (num_nodes - (rand_node + 1));
+ }
+
+ getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->public_key, public_key, NULL);
+
+ *lastgetnode = temp_time;
+ ++*bootstrap_times;
+ }
+
+ return not_kill;
+}
+
+/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request
+ * every GET_NODE_INTERVAL seconds to a random good node for each "friend" in our "friends" list.
+ */
+static void do_DHT_friends(DHT *dht)
+{
+ for (size_t i = 0; i < dht->num_friends; ++i) {
+ DHT_Friend *dht_friend = &dht->friends_list[i];
+
+ for (size_t j = 0; j < dht_friend->num_to_bootstrap; ++j) {
+ getnodes(dht, dht_friend->to_bootstrap[j].ip_port, dht_friend->to_bootstrap[j].public_key, dht_friend->public_key,
+ NULL);
+ }
+
+ dht_friend->num_to_bootstrap = 0;
+
+ do_ping_and_sendnode_requests(dht, &dht_friend->lastgetnode, dht_friend->public_key, dht_friend->client_list,
+ MAX_FRIEND_CLIENTS,
+ &dht_friend->bootstrap_times, 1);
+ }
+}
+
+/* Ping each client in the close nodes list every PING_INTERVAL seconds.
+ * Send a get nodes request every GET_NODE_INTERVAL seconds to a random good node in the list.
+ */
+static void do_Close(DHT *dht)
+{
+ for (size_t i = 0; i < dht->num_to_bootstrap; ++i) {
+ getnodes(dht, dht->to_bootstrap[i].ip_port, dht->to_bootstrap[i].public_key, dht->self_public_key, NULL);
+ }
+
+ dht->num_to_bootstrap = 0;
+
+ uint8_t not_killed = do_ping_and_sendnode_requests(dht, &dht->close_lastgetnodes, dht->self_public_key,
+ dht->close_clientlist, LCLIENT_LIST, &dht->close_bootstrap_times, 0);
+
+ if (!not_killed) {
+ /* all existing nodes are at least KILL_NODE_TIMEOUT,
+ * which means we are mute, as we only send packets to
+ * nodes NOT in KILL_NODE_TIMEOUT
+ *
+ * so: reset all nodes to be BAD_NODE_TIMEOUT, but not
+ * KILL_NODE_TIMEOUT, so we at least keep trying pings */
+ uint64_t badonly = unix_time() - BAD_NODE_TIMEOUT;
+
+ for (size_t i = 0; i < LCLIENT_LIST; i++) {
+ Client_data *client = &dht->close_clientlist[i];
+
+ IPPTsPng *assocs[ASSOC_COUNT] = { &client->assoc6, &client->assoc4 };
+
+ for (size_t j = 0; j < ASSOC_COUNT; j++) {
+ IPPTsPng *assoc = assocs[j];
+
+ if (assoc->timestamp) {
+ assoc->timestamp = badonly;
+ }
+ }
+ }
+ }
+}
+
+void DHT_getnodes(DHT *dht, const IP_Port *from_ipp, const uint8_t *from_id, const uint8_t *which_id)
+{
+ getnodes(dht, *from_ipp, from_id, which_id, NULL);
+}
+
+void DHT_bootstrap(DHT *dht, IP_Port ip_port, const uint8_t *public_key)
+{
+ getnodes(dht, ip_port, public_key, dht->self_public_key, NULL);
+}
+int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled,
+ uint16_t port, const uint8_t *public_key)
+{
+ IP_Port ip_port_v64;
+ IP *ip_extra = NULL;
+ IP_Port ip_port_v4;
+ ip_init(&ip_port_v64.ip, ipv6enabled);
+
+ if (ipv6enabled) {
+ /* setup for getting BOTH: an IPv6 AND an IPv4 address */
+ ip_port_v64.ip.family = TOX_AF_UNSPEC;
+ ip_reset(&ip_port_v4.ip);
+ ip_extra = &ip_port_v4.ip;
+ }
+
+ if (addr_resolve_or_parse_ip(address, &ip_port_v64.ip, ip_extra)) {
+ ip_port_v64.port = port;
+ DHT_bootstrap(dht, ip_port_v64, public_key);
+
+ if ((ip_extra != NULL) && ip_isset(ip_extra)) {
+ ip_port_v4.port = port;
+ DHT_bootstrap(dht, ip_port_v4, public_key);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Send the given packet to node with public_key
+ *
+ * return -1 if failure.
+ */
+int route_packet(const DHT *dht, const uint8_t *public_key, const uint8_t *packet, uint16_t length)
+{
+ for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
+ if (id_equal(public_key, dht->close_clientlist[i].public_key)) {
+ const Client_data *client = &dht->close_clientlist[i];
+ const IPPTsPng *assocs[ASSOC_COUNT] = { &client->assoc6, &client->assoc4 };
+
+ for (size_t j = 0; j < ASSOC_COUNT; j++) {
+ const IPPTsPng *assoc = assocs[j];
+
+ if (ip_isset(&assoc->ip_port.ip)) {
+ return sendpacket(dht->net, assoc->ip_port, packet, length);
+ }
+ }
+
+ break;
+ }
+ }
+
+ return -1;
+}
+
+/* Puts all the different ips returned by the nodes for a friend_num into array ip_portlist.
+ * ip_portlist must be at least MAX_FRIEND_CLIENTS big.
+ *
+ * return the number of ips returned.
+ * return 0 if we are connected to friend or if no ips were found.
+ * return -1 if no such friend.
+ */
+static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_num)
+{
+ if (friend_num >= dht->num_friends) {
+ return -1;
+ }
+
+ DHT_Friend *dht_friend = &dht->friends_list[friend_num];
+ Client_data *client;
+ IP_Port ipv4s[MAX_FRIEND_CLIENTS];
+ int num_ipv4s = 0;
+ IP_Port ipv6s[MAX_FRIEND_CLIENTS];
+ int num_ipv6s = 0;
+
+ for (size_t i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
+ client = &(dht_friend->client_list[i]);
+
+ /* If ip is not zero and node is good. */
+ if (ip_isset(&client->assoc4.ret_ip_port.ip) && !is_timeout(client->assoc4.ret_timestamp, BAD_NODE_TIMEOUT)) {
+ ipv4s[num_ipv4s] = client->assoc4.ret_ip_port;
+ ++num_ipv4s;
+ }
+
+ if (ip_isset(&client->assoc6.ret_ip_port.ip) && !is_timeout(client->assoc6.ret_timestamp, BAD_NODE_TIMEOUT)) {
+ ipv6s[num_ipv6s] = client->assoc6.ret_ip_port;
+ ++num_ipv6s;
+ }
+
+ if (id_equal(client->public_key, dht_friend->public_key)) {
+ if (!is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)
+ || !is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT)) {
+ return 0; /* direct connectivity */
+ }
+ }
+ }
+
+#ifdef FRIEND_IPLIST_PAD
+ memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port));
+
+ if (num_ipv6s == MAX_FRIEND_CLIENTS) {
+ return MAX_FRIEND_CLIENTS;
+ }
+
+ int num_ipv4s_used = MAX_FRIEND_CLIENTS - num_ipv6s;
+
+ if (num_ipv4s_used > num_ipv4s) {
+ num_ipv4s_used = num_ipv4s;
+ }
+
+ memcpy(&ip_portlist[num_ipv6s], ipv4s, num_ipv4s_used * sizeof(IP_Port));
+ return num_ipv6s + num_ipv4s_used;
+
+#else /* !FRIEND_IPLIST_PAD */
+
+ /* there must be some secret reason why we can't pad the longer list
+ * with the shorter one...
+ */
+ if (num_ipv6s >= num_ipv4s) {
+ memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port));
+ return num_ipv6s;
+ }
+
+ memcpy(ip_portlist, ipv4s, num_ipv4s * sizeof(IP_Port));
+ return num_ipv4s;
+
+#endif /* !FRIEND_IPLIST_PAD */
+}
+
+
+/* Send the following packet to everyone who tells us they are connected to friend_id.
+ *
+ * return ip for friend.
+ * return number of nodes the packet was sent to. (Only works if more than (MAX_FRIEND_CLIENTS / 4).
+ */
+int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length)
+{
+ uint32_t num = index_of_friend_pk(dht->friends_list, dht->num_friends, friend_id);
+
+ if (num == UINT32_MAX) {
+ return 0;
+ }
+
+ uint32_t sent = 0;
+ uint8_t friend_sent[MAX_FRIEND_CLIENTS] = {0};
+
+ IP_Port ip_list[MAX_FRIEND_CLIENTS];
+ int ip_num = friend_iplist(dht, ip_list, num);
+
+ if (ip_num < (MAX_FRIEND_CLIENTS / 4)) {
+ return 0; /* Reason for that? */
+ }
+
+ DHT_Friend *dht_friend = &dht->friends_list[num];
+ Client_data *client;
+
+ /* extra legwork, because having the outside allocating the space for us
+ * is *usually* good(tm) (bites us in the behind in this case though) */
+
+ for (uint32_t i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
+ if (friend_sent[i]) {/* Send one packet per client.*/
+ continue;
+ }
+
+ client = &dht_friend->client_list[i];
+
+ const IPPTsPng *assocs[ASSOC_COUNT] = { &client->assoc4, &client->assoc6 };
+
+ for (size_t j = 0; j < ASSOC_COUNT; j++) {
+ const IPPTsPng *assoc = assocs[j];
+
+ /* If ip is not zero and node is good. */
+ if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
+ int retval = sendpacket(dht->net, assoc->ip_port, packet, length);
+
+ if ((unsigned int)retval == length) {
+ ++sent;
+ friend_sent[i] = 1;
+ }
+ }
+ }
+ }
+
+ return sent;
+}
+
+/* Send the following packet to one random person who tells us they are connected to friend_id.
+ *
+ * return number of nodes the packet was sent to.
+ */
+static int routeone_tofriend(DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length)
+{
+ uint32_t num = index_of_friend_pk(dht->friends_list, dht->num_friends, friend_id);
+
+ if (num == UINT32_MAX) {
+ return 0;
+ }
+
+ DHT_Friend *dht_friend = &dht->friends_list[num];
+ Client_data *client;
+
+ IP_Port ip_list[MAX_FRIEND_CLIENTS * 2];
+ int n = 0;
+
+ /* extra legwork, because having the outside allocating the space for us
+ * is *usually* good(tm) (bites us in the behind in this case though) */
+
+ for (uint32_t i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
+ client = &dht_friend->client_list[i];
+
+ const IPPTsPng *assocs[ASSOC_COUNT] = { &client->assoc4, &client->assoc6 };
+
+ for (size_t j = 0; j < ASSOC_COUNT; j++) {
+ const IPPTsPng *assoc = assocs[j];
+
+ /* If ip is not zero and node is good. */
+ if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
+ ip_list[n] = assoc->ip_port;
+ ++n;
+ }
+ }
+ }
+
+ if (n < 1) {
+ return 0;
+ }
+
+ int retval = sendpacket(dht->net, ip_list[rand() % n], packet, length);
+
+ if ((unsigned int)retval == length) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------------*/
+/*---------------------BEGINNING OF NAT PUNCHING FUNCTIONS--------------------------*/
+
+static int send_NATping(DHT *dht, const uint8_t *public_key, uint64_t ping_id, uint8_t type)
+{
+ uint8_t data[sizeof(uint64_t) + 1];
+ uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
+
+ int num = 0;
+
+ data[0] = type;
+ memcpy(data + 1, &ping_id, sizeof(uint64_t));
+ /* 254 is NAT ping request packet id */
+ int len = create_request(dht->self_public_key, dht->self_secret_key, packet, public_key, data,
+ sizeof(uint64_t) + 1, CRYPTO_PACKET_NAT_PING);
+
+ if (len == -1) {
+ return -1;
+ }
+
+ if (type == 0) { /* If packet is request use many people to route it. */
+ num = route_tofriend(dht, public_key, packet, len);
+ } else if (type == 1) { /* If packet is response use only one person to route it */
+ num = routeone_tofriend(dht, public_key, packet, len);
+ }
+
+ if (num == 0) {
+ return -1;
+ }
+
+ return num;
+}
+
+/* Handle a received ping request for. */
+static int handle_NATping(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet,
+ uint16_t length, void *userdata)
+{
+ if (length != sizeof(uint64_t) + 1) {
+ return 1;
+ }
+
+ DHT *dht = (DHT *)object;
+ uint64_t ping_id;
+ memcpy(&ping_id, packet + 1, sizeof(uint64_t));
+
+ uint32_t friendnumber = index_of_friend_pk(dht->friends_list, dht->num_friends, source_pubkey);
+
+ if (friendnumber == UINT32_MAX) {
+ return 1;
+ }
+
+ DHT_Friend *dht_friend = &dht->friends_list[friendnumber];
+
+ if (packet[0] == NAT_PING_REQUEST) {
+ /* 1 is reply */
+ send_NATping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE);
+ dht_friend->nat.recvNATping_timestamp = unix_time();
+ return 0;
+ }
+
+ if (packet[0] == NAT_PING_RESPONSE) {
+ if (dht_friend->nat.NATping_id == ping_id) {
+ dht_friend->nat.NATping_id = random_64b();
+ dht_friend->nat.hole_punching = 1;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/* Get the most common ip in the ip_portlist.
+ * Only return ip if it appears in list min_num or more.
+ * len must not be bigger than MAX_FRIEND_CLIENTS.
+ *
+ * return ip of 0 if failure.
+ */
+static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
+{
+ IP zero;
+ ip_reset(&zero);
+
+ if (len > MAX_FRIEND_CLIENTS) {
+ return zero;
+ }
+
+ uint16_t numbers[MAX_FRIEND_CLIENTS] = {0};
+
+ for (uint32_t i = 0; i < len; ++i) {
+ for (uint32_t j = 0; j < len; ++j) {
+ if (ip_equal(&ip_portlist[i].ip, &ip_portlist[j].ip)) {
+ ++numbers[i];
+ }
+ }
+
+ if (numbers[i] >= min_num) {
+ return ip_portlist[i].ip;
+ }
+ }
+
+ return zero;
+}
+
+/* Return all the ports for one ip in a list.
+ * portlist must be at least len long,
+ * where len is the length of ip_portlist.
+ *
+ * return number of ports and puts the list of ports in portlist.
+ */
+static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t len, IP ip)
+{
+ uint16_t num = 0;
+
+ for (uint32_t i = 0; i < len; ++i) {
+ if (ip_equal(&ip_portlist[i].ip, &ip)) {
+ portlist[num] = net_ntohs(ip_portlist[i].port);
+ ++num;
+ }
+ }
+
+ return num;
+}
+
+static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num)
+{
+ if (!dht->hole_punching_enabled) {
+ return;
+ }
+
+ if (numports > MAX_FRIEND_CLIENTS || numports == 0) {
+ return;
+ }
+
+ uint16_t first_port = port_list[0];
+ uint32_t i;
+
+ for (i = 0; i < numports; ++i) {
+ if (first_port != port_list[i]) {
+ break;
+ }
+ }
+
+ if (i == numports) { /* If all ports are the same, only try that one port. */
+ IP_Port pinging;
+ ip_copy(&pinging.ip, &ip);
+ pinging.port = net_htons(first_port);
+ send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].public_key);
+ } else {
+ for (i = 0; i < MAX_PUNCHING_PORTS; ++i) {
+ /* TODO(irungentoo): Improve port guessing algorithm. */
+ uint32_t it = i + dht->friends_list[friend_num].nat.punching_index;
+ int8_t sign = (it % 2) ? -1 : 1;
+ uint32_t delta = sign * (it / (2 * numports));
+ uint32_t index = (it / 2) % numports;
+ uint16_t port = port_list[index] + delta;
+ IP_Port pinging;
+ ip_copy(&pinging.ip, &ip);
+ pinging.port = net_htons(port);
+ send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].public_key);
+ }
+
+ dht->friends_list[friend_num].nat.punching_index += i;
+ }
+
+ if (dht->friends_list[friend_num].nat.tries > MAX_NORMAL_PUNCHING_TRIES) {
+ uint16_t port = 1024;
+ IP_Port pinging;
+ ip_copy(&pinging.ip, &ip);
+
+ for (i = 0; i < MAX_PUNCHING_PORTS; ++i) {
+ uint32_t it = i + dht->friends_list[friend_num].nat.punching_index2;
+ pinging.port = net_htons(port + it);
+ send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].public_key);
+ }
+
+ dht->friends_list[friend_num].nat.punching_index2 += i - (MAX_PUNCHING_PORTS / 2);
+ }
+
+ ++dht->friends_list[friend_num].nat.tries;
+}
+
+static void do_NAT(DHT *dht)
+{
+ uint64_t temp_time = unix_time();
+
+ for (uint32_t i = 0; i < dht->num_friends; ++i) {
+ IP_Port ip_list[MAX_FRIEND_CLIENTS];
+ int num = friend_iplist(dht, ip_list, i);
+
+ /* If already connected or friend is not online don't try to hole punch. */
+ if (num < MAX_FRIEND_CLIENTS / 2) {
+ continue;
+ }
+
+ if (dht->friends_list[i].nat.NATping_timestamp + PUNCH_INTERVAL < temp_time) {
+ send_NATping(dht, dht->friends_list[i].public_key, dht->friends_list[i].nat.NATping_id, NAT_PING_REQUEST);
+ dht->friends_list[i].nat.NATping_timestamp = temp_time;
+ }
+
+ if (dht->friends_list[i].nat.hole_punching == 1 &&
+ dht->friends_list[i].nat.punching_timestamp + PUNCH_INTERVAL < temp_time &&
+ dht->friends_list[i].nat.recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) {
+
+ IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2);
+
+ if (!ip_isset(&ip)) {
+ continue;
+ }
+
+ if (dht->friends_list[i].nat.punching_timestamp + PUNCH_RESET_TIME < temp_time) {
+ dht->friends_list[i].nat.tries = 0;
+ dht->friends_list[i].nat.punching_index = 0;
+ dht->friends_list[i].nat.punching_index2 = 0;
+ }
+
+ uint16_t port_list[MAX_FRIEND_CLIENTS];
+ uint16_t numports = NAT_getports(port_list, ip_list, num, ip);
+ punch_holes(dht, ip, port_list, numports, i);
+
+ dht->friends_list[i].nat.punching_timestamp = temp_time;
+ dht->friends_list[i].nat.hole_punching = 0;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------------*/
+/*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/
+
+#define HARDREQ_DATA_SIZE 384 /* Attempt to prevent amplification/other attacks*/
+
+#define CHECK_TYPE_ROUTE_REQ 0
+#define CHECK_TYPE_ROUTE_RES 1
+#define CHECK_TYPE_GETNODE_REQ 2
+#define CHECK_TYPE_GETNODE_RES 3
+#define CHECK_TYPE_TEST_REQ 4
+#define CHECK_TYPE_TEST_RES 5
+
+#if DHT_HARDENING
+static int send_hardening_req(DHT *dht, Node_format *sendto, uint8_t type, uint8_t *contents, uint16_t length)
+{
+ if (length > HARDREQ_DATA_SIZE - 1) {
+ return -1;
+ }
+
+ uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
+ uint8_t data[HARDREQ_DATA_SIZE] = {0};
+ data[0] = type;
+ memcpy(data + 1, contents, length);
+ int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->public_key, data,
+ sizeof(data), CRYPTO_PACKET_HARDENING);
+
+ if (len == -1) {
+ return -1;
+ }
+
+ return sendpacket(dht->net, sendto->ip_port, packet, len);
+}
+
+/* Send a get node hardening request */
+static int send_hardening_getnode_req(DHT *dht, Node_format *dest, Node_format *node_totest, uint8_t *search_id)
+{
+ uint8_t data[sizeof(Node_format) + CRYPTO_PUBLIC_KEY_SIZE];
+ memcpy(data, node_totest, sizeof(Node_format));
+ memcpy(data + sizeof(Node_format), search_id, CRYPTO_PUBLIC_KEY_SIZE);
+ return send_hardening_req(dht, dest, CHECK_TYPE_GETNODE_REQ, data, sizeof(Node_format) + CRYPTO_PUBLIC_KEY_SIZE);
+}
+#endif
+
+/* Send a get node hardening response */
+static int send_hardening_getnode_res(const DHT *dht, const Node_format *sendto, const uint8_t *queried_client_id,
+ const uint8_t *nodes_data, uint16_t nodes_data_length)
+{
+ if (!ip_isset(&sendto->ip_port.ip)) {
+ return -1;
+ }
+
+ uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
+ VLA(uint8_t, data, 1 + CRYPTO_PUBLIC_KEY_SIZE + nodes_data_length);
+ data[0] = CHECK_TYPE_GETNODE_RES;
+ memcpy(data + 1, queried_client_id, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(data + 1 + CRYPTO_PUBLIC_KEY_SIZE, nodes_data, nodes_data_length);
+ int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->public_key, data,
+ SIZEOF_VLA(data), CRYPTO_PACKET_HARDENING);
+
+ if (len == -1) {
+ return -1;
+ }
+
+ return sendpacket(dht->net, sendto->ip_port, packet, len);
+}
+
+/* TODO(irungentoo): improve */
+static IPPTsPng *get_closelist_IPPTsPng(DHT *dht, const uint8_t *public_key, Family sa_family)
+{
+ for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
+ if (!id_equal(dht->close_clientlist[i].public_key, public_key)) {
+ continue;
+ }
+
+ if (sa_family == TOX_AF_INET) {
+ return &dht->close_clientlist[i].assoc4;
+ }
+
+ if (sa_family == TOX_AF_INET6) {
+ return &dht->close_clientlist[i].assoc6;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * check how many nodes in nodes are also present in the closelist.
+ * TODO(irungentoo): make this function better.
+ */
+static uint32_t have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num)
+{
+ uint32_t counter = 0;
+
+ for (uint32_t i = 0; i < num; ++i) {
+ if (id_equal(nodes[i].public_key, dht->self_public_key)) {
+ ++counter;
+ continue;
+ }
+
+ IPPTsPng *temp = get_closelist_IPPTsPng(dht, nodes[i].public_key, nodes[i].ip_port.ip.family);
+
+ if (temp) {
+ if (!is_timeout(temp->timestamp, BAD_NODE_TIMEOUT)) {
+ ++counter;
+ }
+ }
+ }
+
+ return counter;
+}
+
+/* Interval in seconds between hardening checks */
+#define HARDENING_INTERVAL 120
+#define HARDEN_TIMEOUT 1200
+
+/* Handle a received hardening packet */
+static int handle_hardening(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet,
+ uint16_t length, void *userdata)
+{
+ DHT *dht = (DHT *)object;
+
+ if (length < 2) {
+ return 1;
+ }
+
+ switch (packet[0]) {
+ case CHECK_TYPE_GETNODE_REQ: {
+ if (length != HARDREQ_DATA_SIZE) {
+ return 1;
+ }
+
+ Node_format node, tocheck_node;
+ node.ip_port = source;
+ memcpy(node.public_key, source_pubkey, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(&tocheck_node, packet + 1, sizeof(Node_format));
+
+ if (getnodes(dht, tocheck_node.ip_port, tocheck_node.public_key, packet + 1 + sizeof(Node_format), &node) == -1) {
+ return 1;
+ }
+
+ return 0;
+ }
+
+ case CHECK_TYPE_GETNODE_RES: {
+ if (length <= CRYPTO_PUBLIC_KEY_SIZE + 1) {
+ return 1;
+ }
+
+ if (length > 1 + CRYPTO_PUBLIC_KEY_SIZE + sizeof(Node_format) * MAX_SENT_NODES) {
+ return 1;
+ }
+
+ uint16_t length_nodes = length - 1 - CRYPTO_PUBLIC_KEY_SIZE;
+ Node_format nodes[MAX_SENT_NODES];
+ int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, length_nodes, 0);
+
+ /* TODO(irungentoo): MAX_SENT_NODES nodes should be returned at all times
+ (right now we have a small network size so it could cause problems for testing and etc..) */
+ if (num_nodes <= 0) {
+ return 1;
+ }
+
+ /* NOTE: This should work for now but should be changed to something better. */
+ if (have_nodes_closelist(dht, nodes, num_nodes) < (uint32_t)((num_nodes + 2) / 2)) {
+ return 1;
+ }
+
+ IPPTsPng *temp = get_closelist_IPPTsPng(dht, packet + 1, nodes[0].ip_port.ip.family);
+
+ if (temp == NULL) {
+ return 1;
+ }
+
+ if (is_timeout(temp->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) {
+ return 1;
+ }
+
+ if (!id_equal(temp->hardening.send_nodes_pingedid, source_pubkey)) {
+ return 1;
+ }
+
+ /* If Nodes look good and the request checks out */
+ temp->hardening.send_nodes_ok = 1;
+ return 0;/* success*/
+ }
+ }
+
+ return 1;
+}
+
+#if DHT_HARDENING
+/* Return a random node from all the nodes we are connected to.
+ * TODO(irungentoo): improve this function.
+ */
+static Node_format random_node(DHT *dht, Family sa_family)
+{
+ uint8_t id[CRYPTO_PUBLIC_KEY_SIZE];
+
+ for (uint32_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE / 4; ++i) { /* populate the id with pseudorandom bytes.*/
+ uint32_t t = rand();
+ memcpy(id + i * sizeof(t), &t, sizeof(t));
+ }
+
+ Node_format nodes_list[MAX_SENT_NODES];
+ memset(nodes_list, 0, sizeof(nodes_list));
+ uint32_t num_nodes = get_close_nodes(dht, id, nodes_list, sa_family, 1, 0);
+
+ if (num_nodes == 0) {
+ return nodes_list[0];
+ }
+
+ return nodes_list[rand() % num_nodes];
+}
+#endif
+
+/* Put up to max_num nodes in nodes from the closelist.
+ *
+ * return the number of nodes.
+ */
+static uint16_t list_nodes(Client_data *list, size_t length, Node_format *nodes, uint16_t max_num)
+{
+ if (max_num == 0) {
+ return 0;
+ }
+
+ uint16_t count = 0;
+
+ for (size_t i = length; i != 0; --i) {
+ IPPTsPng *assoc = NULL;
+
+ if (!is_timeout(list[i - 1].assoc4.timestamp, BAD_NODE_TIMEOUT)) {
+ assoc = &list[i - 1].assoc4;
+ }
+
+ if (!is_timeout(list[i - 1].assoc6.timestamp, BAD_NODE_TIMEOUT)) {
+ if (assoc == NULL) {
+ assoc = &list[i - 1].assoc6;
+ } else if (rand() % 2) {
+ assoc = &list[i - 1].assoc6;
+ }
+ }
+
+ if (assoc != NULL) {
+ memcpy(nodes[count].public_key, list[i - 1].public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ nodes[count].ip_port = assoc->ip_port;
+ ++count;
+
+ if (count >= max_num) {
+ return count;
+ }
+ }
+ }
+
+ return count;
+}
+
+/* Put up to max_num nodes in nodes from the random friends.
+ *
+ * return the number of nodes.
+ */
+uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)
+{
+ if (max_num == 0) {
+ return 0;
+ }
+
+ uint16_t count = 0;
+ unsigned int r = rand();
+
+ for (size_t i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) {
+ count += list_nodes(dht->friends_list[(i + r) % DHT_FAKE_FRIEND_NUMBER].client_list, MAX_FRIEND_CLIENTS, nodes + count,
+ max_num - count);
+
+ if (count >= max_num) {
+ break;
+ }
+ }
+
+ return count;
+}
+
+/* Put up to max_num nodes in nodes from the closelist.
+ *
+ * return the number of nodes.
+ */
+uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)
+{
+ return list_nodes(dht->close_clientlist, LCLIENT_LIST, nodes, max_num);
+}
+
+#if DHT_HARDENING
+static void do_hardening(DHT *dht)
+{
+ for (uint32_t i = 0; i < LCLIENT_LIST * 2; ++i) {
+ IPPTsPng *cur_iptspng;
+ Family sa_family;
+ uint8_t *public_key = dht->close_clientlist[i / 2].public_key;
+
+ if (i % 2 == 0) {
+ cur_iptspng = &dht->close_clientlist[i / 2].assoc4;
+ sa_family = TOX_AF_INET;
+ } else {
+ cur_iptspng = &dht->close_clientlist[i / 2].assoc6;
+ sa_family = TOX_AF_INET6;
+ }
+
+ if (is_timeout(cur_iptspng->timestamp, BAD_NODE_TIMEOUT)) {
+ continue;
+ }
+
+ if (cur_iptspng->hardening.send_nodes_ok == 0) {
+ if (is_timeout(cur_iptspng->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) {
+ Node_format rand_node = random_node(dht, sa_family);
+
+ if (!ipport_isset(&rand_node.ip_port)) {
+ continue;
+ }
+
+ if (id_equal(public_key, rand_node.public_key)) {
+ continue;
+ }
+
+ Node_format to_test;
+ to_test.ip_port = cur_iptspng->ip_port;
+ memcpy(to_test.public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+
+ // TODO(irungentoo): The search id should maybe not be ours?
+ if (send_hardening_getnode_req(dht, &rand_node, &to_test, dht->self_public_key) > 0) {
+ memcpy(cur_iptspng->hardening.send_nodes_pingedid, rand_node.public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ cur_iptspng->hardening.send_nodes_timestamp = unix_time();
+ }
+ }
+ } else {
+ if (is_timeout(cur_iptspng->hardening.send_nodes_timestamp, HARDEN_TIMEOUT)) {
+ cur_iptspng->hardening.send_nodes_ok = 0;
+ }
+ }
+
+ // TODO(irungentoo): add the 2 other testers.
+ }
+}
+#endif
+
+/*----------------------------------------------------------------------------------*/
+
+void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_callback cb, void *object)
+{
+ dht->cryptopackethandlers[byte].function = cb;
+ dht->cryptopackethandlers[byte].object = object;
+}
+
+static int cryptopacket_handle(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
+{
+ DHT *dht = (DHT *)object;
+
+ assert(packet[0] == NET_PACKET_CRYPTO);
+
+ if (length <= CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE + 1 + CRYPTO_MAC_SIZE ||
+ length > MAX_CRYPTO_REQUEST_SIZE + CRYPTO_MAC_SIZE) {
+ return 1;
+ }
+
+ // Check if request is for us.
+ if (id_equal(packet + 1, dht->self_public_key)) {
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t data[MAX_CRYPTO_REQUEST_SIZE];
+ uint8_t number;
+ int len = handle_request(dht->self_public_key, dht->self_secret_key, public_key, data, &number, packet, length);
+
+ if (len == -1 || len == 0) {
+ return 1;
+ }
+
+ if (!dht->cryptopackethandlers[number].function) {
+ return 1;
+ }
+
+ return dht->cryptopackethandlers[number].function(dht->cryptopackethandlers[number].object, source, public_key,
+ data, len, userdata);
+ }
+
+ /* If request is not for us, try routing it. */
+ int retval = route_packet(dht, packet + 1, packet, length);
+
+ if ((unsigned int)retval == length) {
+ return 0;
+ }
+
+ return 1;
+}
+
+/*----------------------------------------------------------------------------------*/
+
+DHT *new_DHT(Logger *log, Networking_Core *net, bool holepunching_enabled)
+{
+ /* init time */
+ unix_time_update();
+
+ if (net == NULL) {
+ return NULL;
+ }
+
+ DHT *dht = (DHT *)calloc(1, sizeof(DHT));
+
+ if (dht == NULL) {
+ return NULL;
+ }
+
+ dht->log = log;
+ dht->net = net;
+
+ dht->hole_punching_enabled = holepunching_enabled;
+
+ dht->ping = new_ping(dht);
+
+ if (dht->ping == NULL) {
+ kill_DHT(dht);
+ return NULL;
+ }
+
+ networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, dht);
+ networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht);
+ networking_registerhandler(dht->net, NET_PACKET_CRYPTO, &cryptopacket_handle, dht);
+ cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht);
+ cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, &handle_hardening, dht);
+
+ new_symmetric_key(dht->secret_symmetric_key);
+ crypto_new_keypair(dht->self_public_key, dht->self_secret_key);
+
+ ping_array_init(&dht->dht_ping_array, DHT_PING_ARRAY_SIZE, PING_TIMEOUT);
+ ping_array_init(&dht->dht_harden_ping_array, DHT_PING_ARRAY_SIZE, PING_TIMEOUT);
+
+ for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) {
+ uint8_t random_key_bytes[CRYPTO_PUBLIC_KEY_SIZE];
+ random_bytes(random_key_bytes, sizeof(random_key_bytes));
+
+ if (DHT_addfriend(dht, random_key_bytes, 0, 0, 0, 0) != 0) {
+ kill_DHT(dht);
+ return NULL;
+ }
+ }
+
+ return dht;
+}
+
+void do_DHT(DHT *dht)
+{
+ unix_time_update();
+
+ if (dht->last_run == unix_time()) {
+ return;
+ }
+
+ // Load friends/clients if first call to do_DHT
+ if (dht->loaded_num_nodes) {
+ DHT_connect_after_load(dht);
+ }
+
+ do_Close(dht);
+ do_DHT_friends(dht);
+ do_NAT(dht);
+ do_to_ping(dht->ping);
+#if DHT_HARDENING
+ do_hardening(dht);
+#endif
+ dht->last_run = unix_time();
+}
+void kill_DHT(DHT *dht)
+{
+ networking_registerhandler(dht->net, NET_PACKET_GET_NODES, NULL, NULL);
+ networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, NULL, NULL);
+ cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, NULL, NULL);
+ cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, NULL, NULL);
+ ping_array_free_all(&dht->dht_ping_array);
+ ping_array_free_all(&dht->dht_harden_ping_array);
+ kill_ping(dht->ping);
+ free(dht->friends_list);
+ free(dht->loaded_nodes_list);
+ free(dht);
+}
+
+/* new DHT format for load/save, more robust and forward compatible */
+// TODO(irungentoo): Move this closer to Messenger.
+#define DHT_STATE_COOKIE_GLOBAL 0x159000d
+
+#define DHT_STATE_COOKIE_TYPE 0x11ce
+#define DHT_STATE_TYPE_NODES 4
+
+#define MAX_SAVED_DHT_NODES (((DHT_FAKE_FRIEND_NUMBER * MAX_FRIEND_CLIENTS) + LCLIENT_LIST) * 2)
+
+/* Get the size of the DHT (for saving). */
+uint32_t DHT_size(const DHT *dht)
+{
+ uint32_t numv4 = 0, numv6 = 0;
+
+ for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
+ numv4 += (dht->close_clientlist[i].assoc4.timestamp != 0);
+ numv6 += (dht->close_clientlist[i].assoc6.timestamp != 0);
+ }
+
+ for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) {
+ DHT_Friend *fr = &dht->friends_list[i];
+
+ for (uint32_t j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
+ numv4 += (fr->client_list[j].assoc4.timestamp != 0);
+ numv6 += (fr->client_list[j].assoc6.timestamp != 0);
+ }
+ }
+
+ uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2;
+
+ return size32 + sizesubhead + (packed_node_size(TOX_AF_INET) * numv4) + (packed_node_size(TOX_AF_INET6) * numv6);
+}
+
+static uint8_t *DHT_save_subheader(uint8_t *data, uint32_t len, uint16_t type)
+{
+ host_to_lendian32(data, len);
+ data += sizeof(uint32_t);
+ host_to_lendian32(data, (host_tolendian16(DHT_STATE_COOKIE_TYPE) << 16) | host_tolendian16(type));
+ data += sizeof(uint32_t);
+ return data;
+}
+
+
+/* Save the DHT in data where data is an array of size DHT_size(). */
+void DHT_save(DHT *dht, uint8_t *data)
+{
+ host_to_lendian32(data, DHT_STATE_COOKIE_GLOBAL);
+ data += sizeof(uint32_t);
+
+ uint8_t *old_data = data;
+
+ /* get right offset. we write the actual header later. */
+ data = DHT_save_subheader(data, 0, 0);
+
+ Node_format clients[MAX_SAVED_DHT_NODES];
+
+ uint32_t num = 0;
+
+ for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
+ if (dht->close_clientlist[i].assoc4.timestamp != 0) {
+ memcpy(clients[num].public_key, dht->close_clientlist[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ clients[num].ip_port = dht->close_clientlist[i].assoc4.ip_port;
+ ++num;
+ }
+
+ if (dht->close_clientlist[i].assoc6.timestamp != 0) {
+ memcpy(clients[num].public_key, dht->close_clientlist[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ clients[num].ip_port = dht->close_clientlist[i].assoc6.ip_port;
+ ++num;
+ }
+ }
+
+ for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) {
+ DHT_Friend *fr = &dht->friends_list[i];
+
+ for (uint32_t j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
+ if (fr->client_list[j].assoc4.timestamp != 0) {
+ memcpy(clients[num].public_key, fr->client_list[j].public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ clients[num].ip_port = fr->client_list[j].assoc4.ip_port;
+ ++num;
+ }
+
+ if (fr->client_list[j].assoc6.timestamp != 0) {
+ memcpy(clients[num].public_key, fr->client_list[j].public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ clients[num].ip_port = fr->client_list[j].assoc6.ip_port;
+ ++num;
+ }
+ }
+ }
+
+ DHT_save_subheader(old_data, pack_nodes(data, sizeof(Node_format) * num, clients, num), DHT_STATE_TYPE_NODES);
+}
+
+/* Bootstrap from this number of nodes every time DHT_connect_after_load() is called */
+#define SAVE_BOOTSTAP_FREQUENCY 8
+
+/* Start sending packets after DHT loaded_friends_list and loaded_clients_list are set */
+int DHT_connect_after_load(DHT *dht)
+{
+ if (dht == NULL) {
+ return -1;
+ }
+
+ if (!dht->loaded_nodes_list) {
+ return -1;
+ }
+
+ /* DHT is connected, stop. */
+ if (DHT_non_lan_connected(dht)) {
+ free(dht->loaded_nodes_list);
+ dht->loaded_nodes_list = NULL;
+ dht->loaded_num_nodes = 0;
+ return 0;
+ }
+
+ for (uint32_t i = 0; i < dht->loaded_num_nodes && i < SAVE_BOOTSTAP_FREQUENCY; ++i) {
+ unsigned int index = dht->loaded_nodes_index % dht->loaded_num_nodes;
+ DHT_bootstrap(dht, dht->loaded_nodes_list[index].ip_port, dht->loaded_nodes_list[index].public_key);
+ ++dht->loaded_nodes_index;
+ }
+
+ return 0;
+}
+
+static int dht_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type)
+{
+ DHT *dht = (DHT *)outer;
+
+ switch (type) {
+ case DHT_STATE_TYPE_NODES:
+ if (length == 0) {
+ break;
+ }
+
+ {
+ free(dht->loaded_nodes_list);
+ // Copy to loaded_clients_list
+ dht->loaded_nodes_list = (Node_format *)calloc(MAX_SAVED_DHT_NODES, sizeof(Node_format));
+
+ int num = unpack_nodes(dht->loaded_nodes_list, MAX_SAVED_DHT_NODES, NULL, data, length, 0);
+
+ if (num > 0) {
+ dht->loaded_num_nodes = num;
+ } else {
+ dht->loaded_num_nodes = 0;
+ }
+ } /* localize declarations */
+
+ break;
+
+ default:
+ LOGGER_ERROR(dht->log, "Load state (DHT): contains unrecognized part (len %u, type %u)\n",
+ length, type);
+ break;
+ }
+
+ return 0;
+}
+
+/* Load the DHT from data of size size.
+ *
+ * return -1 if failure.
+ * return 0 if success.
+ */
+int DHT_load(DHT *dht, const uint8_t *data, uint32_t length)
+{
+ uint32_t cookie_len = sizeof(uint32_t);
+
+ if (length > cookie_len) {
+ uint32_t data32;
+ lendian_to_host32(&data32, data);
+
+ if (data32 == DHT_STATE_COOKIE_GLOBAL) {
+ return load_state(dht_load_state_callback, dht->log, dht, data + cookie_len,
+ length - cookie_len, DHT_STATE_COOKIE_TYPE);
+ }
+ }
+
+ return -1;
+}
+
+/* return 0 if we are not connected to the DHT.
+ * return 1 if we are.
+ */
+int DHT_isconnected(const DHT *dht)
+{
+ unix_time_update();
+
+ for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
+ const Client_data *client = &dht->close_clientlist[i];
+
+ if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) ||
+ !is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* return 0 if we are not connected or only connected to lan peers with the DHT.
+ * return 1 if we are.
+ */
+int DHT_non_lan_connected(const DHT *dht)
+{
+ unix_time_update();
+
+ for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
+ const Client_data *client = &dht->close_clientlist[i];
+
+ if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) && LAN_ip(client->assoc4.ip_port.ip) == -1) {
+ return 1;
+ }
+
+ if (!is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT) && LAN_ip(client->assoc6.ip_port.ip) == -1) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/protocols/Tox/libtox/src/toxcore/DHT.h b/protocols/Tox/libtox/src/toxcore/DHT.h
new file mode 100644
index 0000000000..510b3c5c92
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/DHT.h
@@ -0,0 +1,448 @@
+/*
+ * An implementation of the DHT as seen in docs/updates/DHT.md
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef DHT_H
+#define DHT_H
+
+#include "crypto_core.h"
+#include "logger.h"
+#include "network.h"
+#include "ping_array.h"
+
+#include <stdbool.h>
+
+/* Maximum number of clients stored per friend. */
+#define MAX_FRIEND_CLIENTS 8
+
+#define LCLIENT_NODES (MAX_FRIEND_CLIENTS)
+#define LCLIENT_LENGTH 128
+
+/* A list of the clients mathematically closest to ours. */
+#define LCLIENT_LIST (LCLIENT_LENGTH * LCLIENT_NODES)
+
+#define MAX_CLOSE_TO_BOOTSTRAP_NODES 8
+
+/* The max number of nodes to send with send nodes. */
+#define MAX_SENT_NODES 4
+
+/* Ping timeout in seconds */
+#define PING_TIMEOUT 5
+
+/* size of DHT ping arrays. */
+#define DHT_PING_ARRAY_SIZE 512
+
+/* Ping interval in seconds for each node in our lists. */
+#define PING_INTERVAL 60
+
+/* The number of seconds for a non responsive node to become bad. */
+#define PINGS_MISSED_NODE_GOES_BAD 1
+#define PING_ROUNDTRIP 2
+#define BAD_NODE_TIMEOUT (PING_INTERVAL + PINGS_MISSED_NODE_GOES_BAD * (PING_INTERVAL + PING_ROUNDTRIP))
+
+/* The number of "fake" friends to add (for optimization purposes and so our paths for the onion part are more random) */
+#define DHT_FAKE_FRIEND_NUMBER 2
+
+#define MAX_CRYPTO_REQUEST_SIZE 1024
+
+#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */
+#define CRYPTO_PACKET_HARDENING 48 /* Hardening crypto packet ID. */
+#define CRYPTO_PACKET_DHTPK 156
+#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */
+
+/* Create a request to peer.
+ * send_public_key and send_secret_key are the pub/secret keys of the sender.
+ * recv_public_key is public key of receiver.
+ * packet must be an array of MAX_CRYPTO_REQUEST_SIZE big.
+ * Data represents the data we send with the request with length being the length of the data.
+ * request_id is the id of the request (32 = friend request, 254 = ping request).
+ *
+ * return -1 on failure.
+ * return the length of the created packet on success.
+ */
+int create_request(const uint8_t *send_public_key, const uint8_t *send_secret_key, uint8_t *packet,
+ const uint8_t *recv_public_key, const uint8_t *data, uint32_t length, uint8_t request_id);
+
+/* puts the senders public key in the request in public_key, the data from the request
+ in data if a friend or ping request was sent to us and returns the length of the data.
+ packet is the request packet and length is its length
+ return -1 if not valid request. */
+int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
+ uint8_t *request_id, const uint8_t *packet, uint16_t length);
+
+typedef struct {
+ IP_Port ip_port;
+ uint64_t timestamp;
+} IPPTs;
+
+typedef struct {
+ /* Node routes request correctly (true (1) or false/didn't check (0)) */
+ uint8_t routes_requests_ok;
+ /* Time which we last checked this.*/
+ uint64_t routes_requests_timestamp;
+ uint8_t routes_requests_pingedid[CRYPTO_PUBLIC_KEY_SIZE];
+ /* Node sends correct send_node (true (1) or false/didn't check (0)) */
+ uint8_t send_nodes_ok;
+ /* Time which we last checked this.*/
+ uint64_t send_nodes_timestamp;
+ uint8_t send_nodes_pingedid[CRYPTO_PUBLIC_KEY_SIZE];
+ /* Node can be used to test other nodes (true (1) or false/didn't check (0)) */
+ uint8_t testing_requests;
+ /* Time which we last checked this.*/
+ uint64_t testing_timestamp;
+ uint8_t testing_pingedid[CRYPTO_PUBLIC_KEY_SIZE];
+} Hardening;
+
+typedef struct {
+ IP_Port ip_port;
+ uint64_t timestamp;
+ uint64_t last_pinged;
+
+ Hardening hardening;
+ /* Returned by this node. Either our friend or us. */
+ IP_Port ret_ip_port;
+ uint64_t ret_timestamp;
+} IPPTsPng;
+
+typedef struct {
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ IPPTsPng assoc4;
+ IPPTsPng assoc6;
+} Client_data;
+
+/*----------------------------------------------------------------------------------*/
+
+typedef struct {
+ /* 1 if currently hole punching, otherwise 0 */
+ uint8_t hole_punching;
+ uint32_t punching_index;
+ uint32_t tries;
+ uint32_t punching_index2;
+
+ uint64_t punching_timestamp;
+ uint64_t recvNATping_timestamp;
+ uint64_t NATping_id;
+ uint64_t NATping_timestamp;
+} NAT;
+
+#define DHT_FRIEND_MAX_LOCKS 32
+
+typedef struct {
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ IP_Port ip_port;
+}
+Node_format;
+
+typedef struct {
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ Client_data client_list[MAX_FRIEND_CLIENTS];
+
+ /* Time at which the last get_nodes request was sent. */
+ uint64_t lastgetnode;
+ /* number of times get_node packets were sent. */
+ uint32_t bootstrap_times;
+
+ /* Symetric NAT hole punching stuff. */
+ NAT nat;
+
+ uint16_t lock_count;
+ struct {
+ void (*ip_callback)(void *, int32_t, IP_Port);
+ void *data;
+ int32_t number;
+ } callbacks[DHT_FRIEND_MAX_LOCKS];
+
+ Node_format to_bootstrap[MAX_SENT_NODES];
+ unsigned int num_to_bootstrap;
+} DHT_Friend;
+
+/* Return packet size of packed node with ip_family on success.
+ * Return -1 on failure.
+ */
+int packed_node_size(uint8_t ip_family);
+
+/* Pack number of nodes into data of maxlength length.
+ *
+ * return length of packed nodes on success.
+ * return -1 on failure.
+ */
+int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_t number);
+
+/* Unpack data of length into nodes of size max_num_nodes.
+ * Put the length of the data processed in processed_data_len.
+ * tcp_enabled sets if TCP nodes are expected (true) or not (false).
+ *
+ * return number of unpacked nodes on success.
+ * return -1 on failure.
+ */
+int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, const uint8_t *data,
+ uint16_t length, uint8_t tcp_enabled);
+
+
+/*----------------------------------------------------------------------------------*/
+/* struct to store some shared keys so we don't have to regenerate them for each request. */
+#define MAX_KEYS_PER_SLOT 4
+#define KEYS_TIMEOUT 600
+
+typedef struct {
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
+ uint32_t times_requested;
+ uint8_t stored; /* 0 if not, 1 if is */
+ uint64_t time_last_requested;
+} Shared_Key;
+
+typedef struct {
+ Shared_Key keys[256 * MAX_KEYS_PER_SLOT];
+} Shared_Keys;
+
+/*----------------------------------------------------------------------------------*/
+
+typedef int (*cryptopacket_handler_callback)(void *object, IP_Port ip_port, const uint8_t *source_pubkey,
+ const uint8_t *data, uint16_t len, void *userdata);
+
+typedef struct {
+ cryptopacket_handler_callback function;
+ void *object;
+} Cryptopacket_Handles;
+
+typedef struct {
+ Logger *log;
+ Networking_Core *net;
+
+ bool hole_punching_enabled;
+
+ Client_data close_clientlist[LCLIENT_LIST];
+ uint64_t close_lastgetnodes;
+ uint32_t close_bootstrap_times;
+
+ /* Note: this key should not be/is not used to transmit any sensitive materials */
+ uint8_t secret_symmetric_key[CRYPTO_SYMMETRIC_KEY_SIZE];
+ /* DHT keypair */
+ uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
+
+ DHT_Friend *friends_list;
+ uint16_t num_friends;
+
+ Node_format *loaded_nodes_list;
+ uint32_t loaded_num_nodes;
+ unsigned int loaded_nodes_index;
+
+ Shared_Keys shared_keys_recv;
+ Shared_Keys shared_keys_sent;
+
+ struct PING *ping;
+ Ping_Array dht_ping_array;
+ Ping_Array dht_harden_ping_array;
+ uint64_t last_run;
+
+ Cryptopacket_Handles cryptopackethandlers[256];
+
+ Node_format to_bootstrap[MAX_CLOSE_TO_BOOTSTRAP_NODES];
+ unsigned int num_to_bootstrap;
+} DHT;
+/*----------------------------------------------------------------------------------*/
+
+/* Shared key generations are costly, it is therefor smart to store commonly used
+ * ones so that they can re used later without being computed again.
+ *
+ * If shared key is already in shared_keys, copy it to shared_key.
+ * else generate it into shared_key and copy it to shared_keys
+ */
+void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t *secret_key,
+ const uint8_t *public_key);
+
+/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key
+ * for packets that we receive.
+ */
+void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *public_key);
+
+/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key
+ * for packets that we send.
+ */
+void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *public_key);
+
+void DHT_getnodes(DHT *dht, const IP_Port *from_ipp, const uint8_t *from_id, const uint8_t *which_id);
+
+/* Add a new friend to the friends list.
+ * public_key must be CRYPTO_PUBLIC_KEY_SIZE bytes long.
+ *
+ * ip_callback is the callback of a function that will be called when the ip address
+ * is found along with arguments data and number.
+ *
+ * lock_count will be set to a non zero number that must be passed to DHT_delfriend()
+ * to properly remove the callback.
+ *
+ * return 0 if success.
+ * return -1 if failure (friends list is full).
+ */
+int DHT_addfriend(DHT *dht, const uint8_t *public_key, void (*ip_callback)(void *data, int32_t number, IP_Port),
+ void *data, int32_t number, uint16_t *lock_count);
+
+/* Delete a friend from the friends list.
+ * public_key must be CRYPTO_PUBLIC_KEY_SIZE bytes long.
+ *
+ * return 0 if success.
+ * return -1 if failure (public_key not in friends list).
+ */
+int DHT_delfriend(DHT *dht, const uint8_t *public_key, uint16_t lock_count);
+
+/* Get ip of friend.
+ * public_key must be CRYPTO_PUBLIC_KEY_SIZE bytes long.
+ * ip must be 4 bytes long.
+ * port must be 2 bytes long.
+ *
+ * int DHT_getfriendip(DHT *dht, uint8_t *public_key, IP_Port *ip_port);
+ *
+ * return -1, -- if public_key does NOT refer to a friend
+ * return 0, -- if public_key refers to a friend and we failed to find the friend (yet)
+ * return 1, ip if public_key refers to a friend and we found him
+ */
+int DHT_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port);
+
+/* Compares pk1 and pk2 with pk.
+ *
+ * return 0 if both are same distance.
+ * return 1 if pk1 is closer.
+ * return 2 if pk2 is closer.
+ */
+int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2);
+
+/* Add node to the node list making sure only the nodes closest to cmp_pk are in the list.
+ */
+bool add_to_list(Node_format *nodes_list, unsigned int length, const uint8_t *pk, IP_Port ip_port,
+ const uint8_t *cmp_pk);
+
+/* Return 1 if node can be added to close list, 0 if it can't.
+ */
+bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port);
+
+/* Get the (maximum MAX_SENT_NODES) closest nodes to public_key we know
+ * and put them in nodes_list (must be MAX_SENT_NODES big).
+ *
+ * sa_family = family (IPv4 or IPv6) (0 if we don't care)?
+ * is_LAN = return some LAN ips (true or false)
+ * want_good = do we want tested nodes or not? (TODO(irungentoo))
+ *
+ * return the number of nodes returned.
+ *
+ */
+int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, Family sa_family,
+ uint8_t is_LAN, uint8_t want_good);
+
+
+/* Put up to max_num nodes in nodes from the random friends.
+ *
+ * return the number of nodes.
+ */
+uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num);
+
+/* Put up to max_num nodes in nodes from the closelist.
+ *
+ * return the number of nodes.
+ */
+uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num);
+
+/* Run this function at least a couple times per second (It's the main loop). */
+void do_DHT(DHT *dht);
+
+/*
+ * Use these two functions to bootstrap the client.
+ */
+/* Sends a "get nodes" request to the given node with ip, port and public_key
+ * to setup connections
+ */
+void DHT_bootstrap(DHT *dht, IP_Port ip_port, const uint8_t *public_key);
+/* Resolves address into an IP address. If successful, sends a "get nodes"
+ * request to the given node with ip, port and public_key to setup connections
+ *
+ * address can be a hostname or an IP address (IPv4 or IPv6).
+ * if ipv6enabled is 0 (zero), the resolving sticks STRICTLY to IPv4 addresses
+ * if ipv6enabled is not 0 (zero), the resolving looks for IPv6 addresses first,
+ * then IPv4 addresses.
+ *
+ * returns 1 if the address could be converted into an IP address
+ * returns 0 otherwise
+ */
+int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled,
+ uint16_t port, const uint8_t *public_key);
+
+/* Start sending packets after DHT loaded_friends_list and loaded_clients_list are set.
+ *
+ * returns 0 if successful
+ * returns -1 otherwise
+ */
+int DHT_connect_after_load(DHT *dht);
+
+/* ROUTING FUNCTIONS */
+
+/* Send the given packet to node with public_key.
+ *
+ * return -1 if failure.
+ */
+int route_packet(const DHT *dht, const uint8_t *public_key, const uint8_t *packet, uint16_t length);
+
+/* Send the following packet to everyone who tells us they are connected to friend_id.
+ *
+ * return number of nodes it sent the packet to.
+ */
+int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length);
+
+/* Function to handle crypto packets.
+ */
+void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_callback cb, void *object);
+
+/* SAVE/LOAD functions */
+
+/* Get the size of the DHT (for saving). */
+uint32_t DHT_size(const DHT *dht);
+
+/* Save the DHT in data where data is an array of size DHT_size(). */
+void DHT_save(DHT *dht, uint8_t *data);
+
+/* Load the DHT from data of size size.
+ *
+ * return -1 if failure.
+ * return 0 if success.
+ */
+int DHT_load(DHT *dht, const uint8_t *data, uint32_t length);
+
+/* Initialize DHT. */
+DHT *new_DHT(Logger *log, Networking_Core *net, bool holepunching_enabled);
+
+void kill_DHT(DHT *dht);
+
+/* return 0 if we are not connected to the DHT.
+ * return 1 if we are.
+ */
+int DHT_isconnected(const DHT *dht);
+
+/* return 0 if we are not connected or only connected to lan peers with the DHT.
+ * return 1 if we are.
+ */
+int DHT_non_lan_connected(const DHT *dht);
+
+
+uint32_t addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key);
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxcore/LAN_discovery.c b/protocols/Tox/libtox/src/toxcore/LAN_discovery.c
new file mode 100644
index 0000000000..b95e401d05
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/LAN_discovery.c
@@ -0,0 +1,410 @@
+/*
+ * LAN discovery implementation.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "LAN_discovery.h"
+
+#include "util.h"
+
+/* Used for get_broadcast(). */
+#ifdef __linux
+#include <linux/netdevice.h>
+#include <sys/ioctl.h>
+#endif
+
+#define MAX_INTERFACES 16
+
+
+/* TODO: multiple threads might concurrently try to set these, and it isn't clear that this couldn't lead to undesirable
+ * behaviour. Consider storing the data in per-instance variables instead. */
+static int broadcast_count = -1;
+static IP_Port broadcast_ip_ports[MAX_INTERFACES];
+
+#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
+
+#include <iphlpapi.h>
+
+static void fetch_broadcast_info(uint16_t port)
+{
+ IP_ADAPTER_INFO *pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
+ unsigned long ulOutBufLen = sizeof(IP_ADAPTER_INFO);
+
+ if (pAdapterInfo == NULL) {
+ return;
+ }
+
+ if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
+ free(pAdapterInfo);
+ pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
+
+ if (pAdapterInfo == NULL) {
+ return;
+ }
+ }
+
+ /* We copy these to the static variables broadcast_* only at the end of fetch_broadcast_info().
+ * The intention is to ensure that even if multiple threads enter fetch_broadcast_info() concurrently, only valid
+ * interfaces will be set to be broadcast to.
+ * */
+ int count = 0;
+ IP_Port ip_ports[MAX_INTERFACES];
+
+ int ret;
+
+ if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) {
+ IP_ADAPTER_INFO *pAdapter = pAdapterInfo;
+
+ while (pAdapter) {
+ IP gateway = {0}, subnet_mask = {0};
+
+ if (addr_parse_ip(pAdapter->IpAddressList.IpMask.String, &subnet_mask)
+ && addr_parse_ip(pAdapter->GatewayList.IpAddress.String, &gateway)) {
+ if (gateway.family == TOX_AF_INET && subnet_mask.family == TOX_AF_INET) {
+ IP_Port *ip_port = &ip_ports[count];
+ ip_port->ip.family = TOX_AF_INET;
+ uint32_t gateway_ip = net_ntohl(gateway.ip4.uint32), subnet_ip = net_ntohl(subnet_mask.ip4.uint32);
+ uint32_t broadcast_ip = gateway_ip + ~subnet_ip - 1;
+ ip_port->ip.ip4.uint32 = net_htonl(broadcast_ip);
+ ip_port->port = port;
+ count++;
+
+ if (count >= MAX_INTERFACES) {
+ break;
+ }
+ }
+ }
+
+ pAdapter = pAdapter->Next;
+ }
+ }
+
+ if (pAdapterInfo) {
+ free(pAdapterInfo);
+ }
+
+ broadcast_count = count;
+
+ for (uint32_t i = 0; i < count; i++) {
+ broadcast_ip_ports[i] = ip_ports[i];
+ }
+}
+
+#elif defined(__linux__)
+
+static void fetch_broadcast_info(uint16_t port)
+{
+ /* Not sure how many platforms this will run on,
+ * so it's wrapped in __linux for now.
+ * Definitely won't work like this on Windows...
+ */
+ broadcast_count = 0;
+ Socket sock = 0;
+
+ if ((sock = net_socket(TOX_AF_INET, TOX_SOCK_STREAM, 0)) < 0) {
+ return;
+ }
+
+ /* Configure ifconf for the ioctl call. */
+ struct ifreq i_faces[MAX_INTERFACES];
+ memset(i_faces, 0, sizeof(struct ifreq) * MAX_INTERFACES);
+
+ struct ifconf ifconf;
+ ifconf.ifc_buf = (char *)i_faces;
+ ifconf.ifc_len = sizeof(i_faces);
+
+ if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0) {
+ close(sock);
+ return;
+ }
+
+ /* We copy these to the static variables broadcast_* only at the end of fetch_broadcast_info().
+ * The intention is to ensure that even if multiple threads enter fetch_broadcast_info() concurrently, only valid
+ * interfaces will be set to be broadcast to.
+ * */
+ int count = 0;
+ IP_Port ip_ports[MAX_INTERFACES];
+
+ /* ifconf.ifc_len is set by the ioctl() to the actual length used;
+ * on usage of the complete array the call should be repeated with
+ * a larger array, not done (640kB and 16 interfaces shall be
+ * enough, for everybody!)
+ */
+ int i, n = ifconf.ifc_len / sizeof(struct ifreq);
+
+ for (i = 0; i < n; i++) {
+ /* there are interfaces with are incapable of broadcast */
+ if (ioctl(sock, SIOCGIFBRDADDR, &i_faces[i]) < 0) {
+ continue;
+ }
+
+ /* moot check: only TOX_AF_INET returned (backwards compat.) */
+ if (i_faces[i].ifr_broadaddr.sa_family != TOX_AF_INET) {
+ continue;
+ }
+
+ struct sockaddr_in *sock4 = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr;
+
+ if (count >= MAX_INTERFACES) {
+ break;
+ }
+
+ IP_Port *ip_port = &ip_ports[count];
+ ip_port->ip.family = TOX_AF_INET;
+ ip_port->ip.ip4.uint32 = sock4->sin_addr.s_addr;
+
+ if (ip_port->ip.ip4.uint32 == 0) {
+ continue;
+ }
+
+ ip_port->port = port;
+ count++;
+ }
+
+ close(sock);
+
+ broadcast_count = count;
+
+ for (uint32_t i = 0; i < count; i++) {
+ broadcast_ip_ports[i] = ip_ports[i];
+ }
+}
+
+#else // TODO(irungentoo): Other platforms?
+
+static void fetch_broadcast_info(uint16_t port)
+{
+ broadcast_count = 0;
+}
+
+#endif
+/* Send packet to all IPv4 broadcast addresses
+ *
+ * return 1 if sent to at least one broadcast target.
+ * return 0 on failure to find any valid broadcast target.
+ */
+static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, const uint8_t *data, uint16_t length)
+{
+ /* fetch only once? on every packet? every X seconds?
+ * old: every packet, new: once */
+ if (broadcast_count < 0) {
+ fetch_broadcast_info(port);
+ }
+
+ if (!broadcast_count) {
+ return 0;
+ }
+
+ int i;
+
+ for (i = 0; i < broadcast_count; i++) {
+ sendpacket(net, broadcast_ip_ports[i], data, length);
+ }
+
+ return 1;
+}
+
+/* Return the broadcast ip. */
+static IP broadcast_ip(Family family_socket, Family family_broadcast)
+{
+ IP ip;
+ ip_reset(&ip);
+
+ if (family_socket == TOX_AF_INET6) {
+ if (family_broadcast == TOX_AF_INET6) {
+ ip.family = TOX_AF_INET6;
+ /* FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */
+ /* FE80::*: MUST be exact, for that we would need to look over all
+ * interfaces and check in which status they are */
+ ip.ip6.uint8[ 0] = 0xFF;
+ ip.ip6.uint8[ 1] = 0x02;
+ ip.ip6.uint8[15] = 0x01;
+ } else if (family_broadcast == TOX_AF_INET) {
+ ip.family = TOX_AF_INET6;
+ ip.ip6 = IP6_BROADCAST;
+ }
+ } else if (family_socket == TOX_AF_INET) {
+ if (family_broadcast == TOX_AF_INET) {
+ ip.family = TOX_AF_INET;
+ ip.ip4 = IP4_BROADCAST;
+ }
+ }
+
+ return ip;
+}
+
+/* Is IP a local ip or not. */
+bool Local_ip(IP ip)
+{
+ if (ip.family == TOX_AF_INET) {
+ IP4 ip4 = ip.ip4;
+
+ /* Loopback. */
+ if (ip4.uint8[0] == 127) {
+ return 1;
+ }
+ } else {
+ /* embedded IPv4-in-IPv6 */
+ if (IPV6_IPV4_IN_V6(ip.ip6)) {
+ IP ip4;
+ ip4.family = TOX_AF_INET;
+ ip4.ip4.uint32 = ip.ip6.uint32[3];
+ return Local_ip(ip4);
+ }
+
+ /* localhost in IPv6 (::1) */
+ if (ip.ip6.uint64[0] == 0 && ip.ip6.uint32[2] == 0 && ip.ip6.uint32[3] == net_htonl(1)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* return 0 if ip is a LAN ip.
+ * return -1 if it is not.
+ */
+int LAN_ip(IP ip)
+{
+ if (Local_ip(ip)) {
+ return 0;
+ }
+
+ if (ip.family == TOX_AF_INET) {
+ IP4 ip4 = ip.ip4;
+
+ /* 10.0.0.0 to 10.255.255.255 range. */
+ if (ip4.uint8[0] == 10) {
+ return 0;
+ }
+
+ /* 172.16.0.0 to 172.31.255.255 range. */
+ if (ip4.uint8[0] == 172 && ip4.uint8[1] >= 16 && ip4.uint8[1] <= 31) {
+ return 0;
+ }
+
+ /* 192.168.0.0 to 192.168.255.255 range. */
+ if (ip4.uint8[0] == 192 && ip4.uint8[1] == 168) {
+ return 0;
+ }
+
+ /* 169.254.1.0 to 169.254.254.255 range. */
+ if (ip4.uint8[0] == 169 && ip4.uint8[1] == 254 && ip4.uint8[2] != 0
+ && ip4.uint8[2] != 255) {
+ return 0;
+ }
+
+ /* RFC 6598: 100.64.0.0 to 100.127.255.255 (100.64.0.0/10)
+ * (shared address space to stack another layer of NAT) */
+ if ((ip4.uint8[0] == 100) && ((ip4.uint8[1] & 0xC0) == 0x40)) {
+ return 0;
+ }
+ } else if (ip.family == TOX_AF_INET6) {
+
+ /* autogenerated for each interface: FE80::* (up to FEBF::*)
+ FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */
+ if (((ip.ip6.uint8[0] == 0xFF) && (ip.ip6.uint8[1] < 3) && (ip.ip6.uint8[15] == 1)) ||
+ ((ip.ip6.uint8[0] == 0xFE) && ((ip.ip6.uint8[1] & 0xC0) == 0x80))) {
+ return 0;
+ }
+
+ /* embedded IPv4-in-IPv6 */
+ if (IPV6_IPV4_IN_V6(ip.ip6)) {
+ IP ip4;
+ ip4.family = TOX_AF_INET;
+ ip4.ip4.uint32 = ip.ip6.uint32[3];
+ return LAN_ip(ip4);
+ }
+ }
+
+ return -1;
+}
+
+static int handle_LANdiscovery(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
+{
+ DHT *dht = (DHT *)object;
+
+ if (LAN_ip(source.ip) == -1) {
+ return 1;
+ }
+
+ if (length != CRYPTO_PUBLIC_KEY_SIZE + 1) {
+ return 1;
+ }
+
+ char ip_str[IP_NTOA_LEN] = { 0 };
+ ip_ntoa(&source.ip, ip_str, sizeof(ip_str));
+ LOGGER_INFO(dht->log, "Found node in LAN: %s", ip_str);
+
+ DHT_bootstrap(dht, source, packet + 1);
+ return 0;
+}
+
+
+int send_LANdiscovery(uint16_t port, DHT *dht)
+{
+ uint8_t data[CRYPTO_PUBLIC_KEY_SIZE + 1];
+ data[0] = NET_PACKET_LAN_DISCOVERY;
+ id_copy(data + 1, dht->self_public_key);
+
+ send_broadcasts(dht->net, port, data, 1 + CRYPTO_PUBLIC_KEY_SIZE);
+
+ int res = -1;
+ IP_Port ip_port;
+ ip_port.port = port;
+
+ /* IPv6 multicast */
+ if (dht->net->family == TOX_AF_INET6) {
+ ip_port.ip = broadcast_ip(TOX_AF_INET6, TOX_AF_INET6);
+
+ if (ip_isset(&ip_port.ip)) {
+ if (sendpacket(dht->net, ip_port, data, 1 + CRYPTO_PUBLIC_KEY_SIZE) > 0) {
+ res = 1;
+ }
+ }
+ }
+
+ /* IPv4 broadcast (has to be IPv4-in-IPv6 mapping if socket is TOX_AF_INET6 */
+ ip_port.ip = broadcast_ip(dht->net->family, TOX_AF_INET);
+
+ if (ip_isset(&ip_port.ip)) {
+ if (sendpacket(dht->net, ip_port, data, 1 + CRYPTO_PUBLIC_KEY_SIZE)) {
+ res = 1;
+ }
+ }
+
+ return res;
+}
+
+
+void LANdiscovery_init(DHT *dht)
+{
+ networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, &handle_LANdiscovery, dht);
+}
+
+void LANdiscovery_kill(DHT *dht)
+{
+ networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, NULL, NULL);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/LAN_discovery.h b/protocols/Tox/libtox/src/toxcore/LAN_discovery.h
new file mode 100644
index 0000000000..753de5249f
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/LAN_discovery.h
@@ -0,0 +1,52 @@
+/*
+ * LAN discovery implementation.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef LAN_DISCOVERY_H
+#define LAN_DISCOVERY_H
+
+#include "DHT.h"
+
+/* Interval in seconds between LAN discovery packet sending. */
+#define LAN_DISCOVERY_INTERVAL 10
+
+/* Send a LAN discovery pcaket to the broadcast address with port port. */
+int send_LANdiscovery(uint16_t port, DHT *dht);
+
+/* Sets up packet handlers. */
+void LANdiscovery_init(DHT *dht);
+
+/* Clear packet handlers. */
+void LANdiscovery_kill(DHT *dht);
+
+/* Is IP a local ip or not. */
+bool Local_ip(IP ip);
+
+/* checks if a given IP isn't routable
+ *
+ * return 0 if ip is a LAN ip.
+ * return -1 if it is not.
+ */
+int LAN_ip(IP ip);
+
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxcore/Messenger.c b/protocols/Tox/libtox/src/toxcore/Messenger.c
new file mode 100644
index 0000000000..e821f53530
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/Messenger.c
@@ -0,0 +1,3157 @@
+/*
+ * An implementation of a simple text chat only messenger on the tox network core.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "Messenger.h"
+
+#include "logger.h"
+#include "network.h"
+#include "util.h"
+
+#include <assert.h>
+
+static void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status, void *userdata);
+static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data,
+ uint32_t length, uint8_t congestion_control);
+
+// friend_not_valid determines if the friendnumber passed is valid in the Messenger object
+static uint8_t friend_not_valid(const Messenger *m, int32_t friendnumber)
+{
+ if ((unsigned int)friendnumber < m->numfriends) {
+ if (m->friendlist[friendnumber].status != 0) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/* Set the size of the friend list to numfriends.
+ *
+ * return -1 if realloc fails.
+ */
+static int realloc_friendlist(Messenger *m, uint32_t num)
+{
+ if (num == 0) {
+ free(m->friendlist);
+ m->friendlist = NULL;
+ return 0;
+ }
+
+ Friend *newfriendlist = (Friend *)realloc(m->friendlist, num * sizeof(Friend));
+
+ if (newfriendlist == NULL) {
+ return -1;
+ }
+
+ m->friendlist = newfriendlist;
+ return 0;
+}
+
+/* return the friend id associated to that public key.
+ * return -1 if no such friend.
+ */
+int32_t getfriend_id(const Messenger *m, const uint8_t *real_pk)
+{
+ uint32_t i;
+
+ for (i = 0; i < m->numfriends; ++i) {
+ if (m->friendlist[i].status > 0) {
+ if (id_equal(real_pk, m->friendlist[i].real_pk)) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+}
+
+/* Copies the public key associated to that friend id into real_pk buffer.
+ * Make sure that real_pk is of size CRYPTO_PUBLIC_KEY_SIZE.
+ *
+ * return 0 if success.
+ * return -1 if failure.
+ */
+int get_real_pk(const Messenger *m, int32_t friendnumber, uint8_t *real_pk)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ memcpy(real_pk, m->friendlist[friendnumber].real_pk, CRYPTO_PUBLIC_KEY_SIZE);
+ return 0;
+}
+
+/* return friend connection id on success.
+ * return -1 if failure.
+ */
+int getfriendcon_id(const Messenger *m, int32_t friendnumber)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ return m->friendlist[friendnumber].friendcon_id;
+}
+
+/*
+ * return a uint16_t that represents the checksum of address of length len.
+ */
+static uint16_t address_checksum(const uint8_t *address, uint32_t len)
+{
+ uint8_t checksum[2] = {0};
+ uint16_t check;
+ uint32_t i;
+
+ for (i = 0; i < len; ++i) {
+ checksum[i % 2] ^= address[i];
+ }
+
+ memcpy(&check, checksum, sizeof(check));
+ return check;
+}
+
+/* Format: [real_pk (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
+ *
+ * return FRIEND_ADDRESS_SIZE byte address to give to others.
+ */
+void getaddress(const Messenger *m, uint8_t *address)
+{
+ id_copy(address, m->net_crypto->self_public_key);
+ uint32_t nospam = get_nospam(&(m->fr));
+ memcpy(address + CRYPTO_PUBLIC_KEY_SIZE, &nospam, sizeof(nospam));
+ uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum));
+ memcpy(address + CRYPTO_PUBLIC_KEY_SIZE + sizeof(nospam), &checksum, sizeof(checksum));
+}
+
+static int send_online_packet(Messenger *m, int32_t friendnumber)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return 0;
+ }
+
+ uint8_t packet = PACKET_ID_ONLINE;
+ return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
+ m->friendlist[friendnumber].friendcon_id), &packet, sizeof(packet), 0) != -1;
+}
+
+static int send_offline_packet(Messenger *m, int friendcon_id)
+{
+ uint8_t packet = PACKET_ID_OFFLINE;
+ return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, friendcon_id), &packet,
+ sizeof(packet), 0) != -1;
+}
+
+static int m_handle_status(void *object, int i, uint8_t status, void *userdata);
+static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t len, void *userdata);
+static int m_handle_custom_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length,
+ void *userdata);
+
+static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t status)
+{
+ /* Resize the friend list if necessary. */
+ if (realloc_friendlist(m, m->numfriends + 1) != 0) {
+ return FAERR_NOMEM;
+ }
+
+ memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend));
+
+ int friendcon_id = new_friend_connection(m->fr_c, real_pk);
+
+ if (friendcon_id == -1) {
+ return FAERR_NOMEM;
+ }
+
+ uint32_t i;
+
+ for (i = 0; i <= m->numfriends; ++i) {
+ if (m->friendlist[i].status == NOFRIEND) {
+ m->friendlist[i].status = status;
+ m->friendlist[i].friendcon_id = friendcon_id;
+ m->friendlist[i].friendrequest_lastsent = 0;
+ id_copy(m->friendlist[i].real_pk, real_pk);
+ m->friendlist[i].statusmessage_length = 0;
+ m->friendlist[i].userstatus = USERSTATUS_NONE;
+ m->friendlist[i].is_typing = 0;
+ m->friendlist[i].message_id = 0;
+ friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &m_handle_status, &m_handle_packet,
+ &m_handle_custom_lossy_packet, m, i);
+
+ if (m->numfriends == i) {
+ ++m->numfriends;
+ }
+
+ if (friend_con_connected(m->fr_c, friendcon_id) == FRIENDCONN_STATUS_CONNECTED) {
+ send_online_packet(m, i);
+ }
+
+ return i;
+ }
+ }
+
+ return FAERR_NOMEM;
+}
+
+/*
+ * Add a friend.
+ * Set the data that will be sent along with friend request.
+ * Address is the address of the friend (returned by getaddress of the friend you wish to add) it must be FRIEND_ADDRESS_SIZE bytes.
+ * data is the data and length is the length.
+ *
+ * return the friend number if success.
+ * return FA_TOOLONG if message length is too long.
+ * return FAERR_NOMESSAGE if no message (message length must be >= 1 byte).
+ * return FAERR_OWNKEY if user's own key.
+ * return FAERR_ALREADYSENT if friend request already sent or already a friend.
+ * return FAERR_BADCHECKSUM if bad checksum in address.
+ * return FAERR_SETNEWNOSPAM if the friend was already there but the nospam was different.
+ * (the nospam for that friend was set to the new one).
+ * return FAERR_NOMEM if increasing the friend list size fails.
+ */
+int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, uint16_t length)
+{
+ if (length > MAX_FRIEND_REQUEST_DATA_SIZE) {
+ return FAERR_TOOLONG;
+ }
+
+ uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ id_copy(real_pk, address);
+
+ if (!public_key_valid(real_pk)) {
+ return FAERR_BADCHECKSUM;
+ }
+
+ uint16_t check, checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum));
+ memcpy(&check, address + CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint32_t), sizeof(check));
+
+ if (check != checksum) {
+ return FAERR_BADCHECKSUM;
+ }
+
+ if (length < 1) {
+ return FAERR_NOMESSAGE;
+ }
+
+ if (id_equal(real_pk, m->net_crypto->self_public_key)) {
+ return FAERR_OWNKEY;
+ }
+
+ int32_t friend_id = getfriend_id(m, real_pk);
+
+ if (friend_id != -1) {
+ if (m->friendlist[friend_id].status >= FRIEND_CONFIRMED) {
+ return FAERR_ALREADYSENT;
+ }
+
+ uint32_t nospam;
+ memcpy(&nospam, address + CRYPTO_PUBLIC_KEY_SIZE, sizeof(nospam));
+
+ if (m->friendlist[friend_id].friendrequest_nospam == nospam) {
+ return FAERR_ALREADYSENT;
+ }
+
+ m->friendlist[friend_id].friendrequest_nospam = nospam;
+ return FAERR_SETNEWNOSPAM;
+ }
+
+ int32_t ret = init_new_friend(m, real_pk, FRIEND_ADDED);
+
+ if (ret < 0) {
+ return ret;
+ }
+
+ m->friendlist[ret].friendrequest_timeout = FRIENDREQUEST_TIMEOUT;
+ memcpy(m->friendlist[ret].info, data, length);
+ m->friendlist[ret].info_size = length;
+ memcpy(&(m->friendlist[ret].friendrequest_nospam), address + CRYPTO_PUBLIC_KEY_SIZE, sizeof(uint32_t));
+
+ return ret;
+}
+
+int32_t m_addfriend_norequest(Messenger *m, const uint8_t *real_pk)
+{
+ if (getfriend_id(m, real_pk) != -1) {
+ return FAERR_ALREADYSENT;
+ }
+
+ if (!public_key_valid(real_pk)) {
+ return FAERR_BADCHECKSUM;
+ }
+
+ if (id_equal(real_pk, m->net_crypto->self_public_key)) {
+ return FAERR_OWNKEY;
+ }
+
+ return init_new_friend(m, real_pk, FRIEND_CONFIRMED);
+}
+
+static int clear_receipts(Messenger *m, int32_t friendnumber)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ struct Receipts *receipts = m->friendlist[friendnumber].receipts_start;
+
+ while (receipts) {
+ struct Receipts *temp_r = receipts->next;
+ free(receipts);
+ receipts = temp_r;
+ }
+
+ m->friendlist[friendnumber].receipts_start = NULL;
+ m->friendlist[friendnumber].receipts_end = NULL;
+ return 0;
+}
+
+static int add_receipt(Messenger *m, int32_t friendnumber, uint32_t packet_num, uint32_t msg_id)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ struct Receipts *new_receipts = (struct Receipts *)calloc(1, sizeof(struct Receipts));
+
+ if (!new_receipts) {
+ return -1;
+ }
+
+ new_receipts->packet_num = packet_num;
+ new_receipts->msg_id = msg_id;
+
+ if (!m->friendlist[friendnumber].receipts_start) {
+ m->friendlist[friendnumber].receipts_start = new_receipts;
+ } else {
+ m->friendlist[friendnumber].receipts_end->next = new_receipts;
+ }
+
+ m->friendlist[friendnumber].receipts_end = new_receipts;
+ new_receipts->next = NULL;
+ return 0;
+}
+/*
+ * return -1 on failure.
+ * return 0 if packet was received.
+ */
+static int friend_received_packet(const Messenger *m, int32_t friendnumber, uint32_t number)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ return cryptpacket_received(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
+ m->friendlist[friendnumber].friendcon_id), number);
+}
+
+static int do_receipts(Messenger *m, int32_t friendnumber, void *userdata)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ struct Receipts *receipts = m->friendlist[friendnumber].receipts_start;
+
+ while (receipts) {
+ if (friend_received_packet(m, friendnumber, receipts->packet_num) == -1) {
+ break;
+ }
+
+ if (m->read_receipt) {
+ (*m->read_receipt)(m, friendnumber, receipts->msg_id, userdata);
+ }
+
+ struct Receipts *r_next = receipts->next;
+
+ free(receipts);
+
+ m->friendlist[friendnumber].receipts_start = r_next;
+
+ receipts = r_next;
+ }
+
+ if (!m->friendlist[friendnumber].receipts_start) {
+ m->friendlist[friendnumber].receipts_end = NULL;
+ }
+
+ return 0;
+}
+
+/* Remove a friend.
+ *
+ * return 0 if success.
+ * return -1 if failure.
+ */
+int m_delfriend(Messenger *m, int32_t friendnumber)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ if (m->friend_connectionstatuschange_internal) {
+ m->friend_connectionstatuschange_internal(m, friendnumber, 0, m->friend_connectionstatuschange_internal_userdata);
+ }
+
+ clear_receipts(m, friendnumber);
+ remove_request_received(&(m->fr), m->friendlist[friendnumber].real_pk);
+ friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, 0, 0, 0, 0, 0);
+
+ if (friend_con_connected(m->fr_c, m->friendlist[friendnumber].friendcon_id) == FRIENDCONN_STATUS_CONNECTED) {
+ send_offline_packet(m, m->friendlist[friendnumber].friendcon_id);
+ }
+
+ kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id);
+ memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend));
+ uint32_t i;
+
+ for (i = m->numfriends; i != 0; --i) {
+ if (m->friendlist[i - 1].status != NOFRIEND) {
+ break;
+ }
+ }
+
+ m->numfriends = i;
+
+ if (realloc_friendlist(m, m->numfriends) != 0) {
+ return FAERR_NOMEM;
+ }
+
+ return 0;
+}
+
+int m_get_friend_connectionstatus(const Messenger *m, int32_t friendnumber)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ if (m->friendlist[friendnumber].status == FRIEND_ONLINE) {
+ bool direct_connected = 0;
+ unsigned int num_online_relays = 0;
+ int crypt_conn_id = friend_connection_crypt_connection_id(m->fr_c, m->friendlist[friendnumber].friendcon_id);
+ crypto_connection_status(m->net_crypto, crypt_conn_id, &direct_connected, &num_online_relays);
+
+ if (direct_connected) {
+ return CONNECTION_UDP;
+ }
+
+ if (num_online_relays) {
+ return CONNECTION_TCP;
+ }
+
+ return CONNECTION_UNKNOWN;
+ }
+
+ return CONNECTION_NONE;
+}
+
+int m_friend_exists(const Messenger *m, int32_t friendnumber)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Send a message of type.
+ *
+ * return -1 if friend not valid.
+ * return -2 if too large.
+ * return -3 if friend not online.
+ * return -4 if send failed (because queue is full).
+ * return -5 if bad type.
+ * return 0 if success.
+ */
+int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, const uint8_t *message, uint32_t length,
+ uint32_t *message_id)
+{
+ if (type > MESSAGE_ACTION) {
+ return -5;
+ }
+
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ if (length >= MAX_CRYPTO_DATA_SIZE) {
+ return -2;
+ }
+
+ if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
+ return -3;
+ }
+
+ VLA(uint8_t, packet, length + 1);
+ packet[0] = type + PACKET_ID_MESSAGE;
+
+ if (length != 0) {
+ memcpy(packet + 1, message, length);
+ }
+
+ int64_t packet_num = write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
+ m->friendlist[friendnumber].friendcon_id), packet, length + 1, 0);
+
+ if (packet_num == -1) {
+ return -4;
+ }
+
+ uint32_t msg_id = ++m->friendlist[friendnumber].message_id;
+
+ add_receipt(m, friendnumber, packet_num, msg_id);
+
+ if (message_id) {
+ *message_id = msg_id;
+ }
+
+ return 0;
+}
+
+/* Send a name packet to friendnumber.
+ * length is the length with the NULL terminator.
+ */
+static int m_sendname(const Messenger *m, int32_t friendnumber, const uint8_t *name, uint16_t length)
+{
+ if (length > MAX_NAME_LENGTH) {
+ return 0;
+ }
+
+ return write_cryptpacket_id(m, friendnumber, PACKET_ID_NICKNAME, name, length, 0);
+}
+
+/* Set the name and name_length of a friend.
+ *
+ * return 0 if success.
+ * return -1 if failure.
+ */
+int setfriendname(Messenger *m, int32_t friendnumber, const uint8_t *name, uint16_t length)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ if (length > MAX_NAME_LENGTH || length == 0) {
+ return -1;
+ }
+
+ m->friendlist[friendnumber].name_length = length;
+ memcpy(m->friendlist[friendnumber].name, name, length);
+ return 0;
+}
+
+/* Set our nickname
+ * name must be a string of maximum MAX_NAME_LENGTH length.
+ * length must be at least 1 byte.
+ * length is the length of name with the NULL terminator.
+ *
+ * return 0 if success.
+ * return -1 if failure.
+ */
+int setname(Messenger *m, const uint8_t *name, uint16_t length)
+{
+ if (length > MAX_NAME_LENGTH) {
+ return -1;
+ }
+
+ if (m->name_length == length && (length == 0 || memcmp(name, m->name, length) == 0)) {
+ return 0;
+ }
+
+ if (length) {
+ memcpy(m->name, name, length);
+ }
+
+ m->name_length = length;
+ uint32_t i;
+
+ for (i = 0; i < m->numfriends; ++i) {
+ m->friendlist[i].name_sent = 0;
+ }
+
+ return 0;
+}
+
+/* Get our nickname and put it in name.
+ * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
+ *
+ * return the length of the name.
+ */
+uint16_t getself_name(const Messenger *m, uint8_t *name)
+{
+ if (name == NULL) {
+ return 0;
+ }
+
+ memcpy(name, m->name, m->name_length);
+
+ return m->name_length;
+}
+
+/* Get name of friendnumber and put it in name.
+ * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
+ *
+ * return length of name if success.
+ * return -1 if failure.
+ */
+int getname(const Messenger *m, int32_t friendnumber, uint8_t *name)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ memcpy(name, m->friendlist[friendnumber].name, m->friendlist[friendnumber].name_length);
+ return m->friendlist[friendnumber].name_length;
+}
+
+int m_get_name_size(const Messenger *m, int32_t friendnumber)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ return m->friendlist[friendnumber].name_length;
+}
+
+int m_get_self_name_size(const Messenger *m)
+{
+ return m->name_length;
+}
+
+int m_set_statusmessage(Messenger *m, const uint8_t *status, uint16_t length)
+{
+ if (length > MAX_STATUSMESSAGE_LENGTH) {
+ return -1;
+ }
+
+ if (m->statusmessage_length == length && (length == 0 || memcmp(m->statusmessage, status, length) == 0)) {
+ return 0;
+ }
+
+ if (length) {
+ memcpy(m->statusmessage, status, length);
+ }
+
+ m->statusmessage_length = length;
+
+ uint32_t i;
+
+ for (i = 0; i < m->numfriends; ++i) {
+ m->friendlist[i].statusmessage_sent = 0;
+ }
+
+ return 0;
+}
+
+int m_set_userstatus(Messenger *m, uint8_t status)
+{
+ if (status >= USERSTATUS_INVALID) {
+ return -1;
+ }
+
+ if (m->userstatus == status) {
+ return 0;
+ }
+
+ m->userstatus = (USERSTATUS)status;
+ uint32_t i;
+
+ for (i = 0; i < m->numfriends; ++i) {
+ m->friendlist[i].userstatus_sent = 0;
+ }
+
+ return 0;
+}
+
+/* return the size of friendnumber's user status.
+ * Guaranteed to be at most MAX_STATUSMESSAGE_LENGTH.
+ */
+int m_get_statusmessage_size(const Messenger *m, int32_t friendnumber)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ return m->friendlist[friendnumber].statusmessage_length;
+}
+
+/* Copy the user status of friendnumber into buf, truncating if needed to maxlen
+ * bytes, use m_get_statusmessage_size to find out how much you need to allocate.
+ */
+int m_copy_statusmessage(const Messenger *m, int32_t friendnumber, uint8_t *buf, uint32_t maxlen)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ int msglen = MIN(maxlen, m->friendlist[friendnumber].statusmessage_length);
+
+ memcpy(buf, m->friendlist[friendnumber].statusmessage, msglen);
+ memset(buf + msglen, 0, maxlen - msglen);
+ return msglen;
+}
+
+/* return the size of friendnumber's user status.
+ * Guaranteed to be at most MAX_STATUSMESSAGE_LENGTH.
+ */
+int m_get_self_statusmessage_size(const Messenger *m)
+{
+ return m->statusmessage_length;
+}
+
+int m_copy_self_statusmessage(const Messenger *m, uint8_t *buf)
+{
+ memcpy(buf, m->statusmessage, m->statusmessage_length);
+ return m->statusmessage_length;
+}
+
+uint8_t m_get_userstatus(const Messenger *m, int32_t friendnumber)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return USERSTATUS_INVALID;
+ }
+
+ uint8_t status = m->friendlist[friendnumber].userstatus;
+
+ if (status >= USERSTATUS_INVALID) {
+ status = USERSTATUS_NONE;
+ }
+
+ return status;
+}
+
+uint8_t m_get_self_userstatus(const Messenger *m)
+{
+ return m->userstatus;
+}
+
+uint64_t m_get_last_online(const Messenger *m, int32_t friendnumber)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return UINT64_MAX;
+ }
+
+ return m->friendlist[friendnumber].last_seen_time;
+}
+
+int m_set_usertyping(Messenger *m, int32_t friendnumber, uint8_t is_typing)
+{
+ if (is_typing != 0 && is_typing != 1) {
+ return -1;
+ }
+
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ if (m->friendlist[friendnumber].user_istyping == is_typing) {
+ return 0;
+ }
+
+ m->friendlist[friendnumber].user_istyping = is_typing;
+ m->friendlist[friendnumber].user_istyping_sent = 0;
+
+ return 0;
+}
+
+int m_get_istyping(const Messenger *m, int32_t friendnumber)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ return m->friendlist[friendnumber].is_typing;
+}
+
+static int send_statusmessage(const Messenger *m, int32_t friendnumber, const uint8_t *status, uint16_t length)
+{
+ return write_cryptpacket_id(m, friendnumber, PACKET_ID_STATUSMESSAGE, status, length, 0);
+}
+
+static int send_userstatus(const Messenger *m, int32_t friendnumber, uint8_t status)
+{
+ return write_cryptpacket_id(m, friendnumber, PACKET_ID_USERSTATUS, &status, sizeof(status), 0);
+}
+
+static int send_user_istyping(const Messenger *m, int32_t friendnumber, uint8_t is_typing)
+{
+ uint8_t typing = is_typing;
+ return write_cryptpacket_id(m, friendnumber, PACKET_ID_TYPING, &typing, sizeof(typing), 0);
+}
+
+static int set_friend_statusmessage(const Messenger *m, int32_t friendnumber, const uint8_t *status, uint16_t length)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ if (length > MAX_STATUSMESSAGE_LENGTH) {
+ return -1;
+ }
+
+ if (length) {
+ memcpy(m->friendlist[friendnumber].statusmessage, status, length);
+ }
+
+ m->friendlist[friendnumber].statusmessage_length = length;
+ return 0;
+}
+
+static void set_friend_userstatus(const Messenger *m, int32_t friendnumber, uint8_t status)
+{
+ m->friendlist[friendnumber].userstatus = (USERSTATUS)status;
+}
+
+static void set_friend_typing(const Messenger *m, int32_t friendnumber, uint8_t is_typing)
+{
+ m->friendlist[friendnumber].is_typing = is_typing;
+}
+
+void m_callback_log(Messenger *m, logger_cb *function, void *context, void *userdata)
+{
+ logger_callback_log(m->log, function, context, userdata);
+}
+
+/* Set the function that will be executed when a friend request is received. */
+void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const uint8_t *, const uint8_t *, size_t,
+ void *))
+{
+ callback_friendrequest(&(m->fr), (void (*)(void *, const uint8_t *, const uint8_t *, size_t, void *))function, m);
+}
+
+/* Set the function that will be executed when a message from a friend is received. */
+void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, const uint8_t *,
+ size_t, void *))
+{
+ m->friend_message = function;
+}
+
+void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *))
+{
+ m->friend_namechange = function;
+}
+
+void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *))
+{
+ m->friend_statusmessagechange = function;
+}
+
+void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *))
+{
+ m->friend_userstatuschange = function;
+}
+
+void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, uint32_t, bool, void *))
+{
+ m->friend_typingchange = function;
+}
+
+void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, void *))
+{
+ m->read_receipt = function;
+}
+
+void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *))
+{
+ m->friend_connectionstatuschange = function;
+}
+
+void m_callback_core_connection(Messenger *m, void (*function)(Messenger *m, unsigned int, void *))
+{
+ m->core_connection_change = function;
+}
+
+void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, void *),
+ void *userdata)
+{
+ m->friend_connectionstatuschange_internal = function;
+ m->friend_connectionstatuschange_internal_userdata = userdata;
+}
+
+static void check_friend_tcp_udp(Messenger *m, int32_t friendnumber, void *userdata)
+{
+ int last_connection_udp_tcp = m->friendlist[friendnumber].last_connection_udp_tcp;
+
+ int ret = m_get_friend_connectionstatus(m, friendnumber);
+
+ if (ret == -1) {
+ return;
+ }
+
+ if (ret == CONNECTION_UNKNOWN) {
+ if (last_connection_udp_tcp == CONNECTION_UDP) {
+ return;
+ }
+
+ ret = CONNECTION_TCP;
+ }
+
+ if (last_connection_udp_tcp != ret) {
+ if (m->friend_connectionstatuschange) {
+ m->friend_connectionstatuschange(m, friendnumber, ret, userdata);
+ }
+ }
+
+ m->friendlist[friendnumber].last_connection_udp_tcp = ret;
+}
+
+static void break_files(const Messenger *m, int32_t friendnumber);
+static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, uint8_t status, void *userdata)
+{
+ if (status == NOFRIEND) {
+ return;
+ }
+
+ const uint8_t was_online = m->friendlist[friendnumber].status == FRIEND_ONLINE;
+ const uint8_t is_online = status == FRIEND_ONLINE;
+
+ if (is_online != was_online) {
+ if (was_online) {
+ break_files(m, friendnumber);
+ clear_receipts(m, friendnumber);
+ } else {
+ m->friendlist[friendnumber].name_sent = 0;
+ m->friendlist[friendnumber].userstatus_sent = 0;
+ m->friendlist[friendnumber].statusmessage_sent = 0;
+ m->friendlist[friendnumber].user_istyping_sent = 0;
+ }
+
+ m->friendlist[friendnumber].status = status;
+
+ check_friend_tcp_udp(m, friendnumber, userdata);
+
+ if (m->friend_connectionstatuschange_internal) {
+ m->friend_connectionstatuschange_internal(m, friendnumber, is_online,
+ m->friend_connectionstatuschange_internal_userdata);
+ }
+ }
+}
+
+void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status, void *userdata)
+{
+ check_friend_connectionstatus(m, friendnumber, status, userdata);
+ m->friendlist[friendnumber].status = status;
+}
+
+static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data,
+ uint32_t length, uint8_t congestion_control)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return 0;
+ }
+
+ if (length >= MAX_CRYPTO_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE) {
+ return 0;
+ }
+
+ VLA(uint8_t, packet, length + 1);
+ packet[0] = packet_id;
+
+ if (length != 0) {
+ memcpy(packet + 1, data, length);
+ }
+
+ return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
+ m->friendlist[friendnumber].friendcon_id), packet, length + 1, congestion_control) != -1;
+}
+
+/**********CONFERENCES************/
+
+
+/* Set the callback for conference invites.
+ *
+ * Function(Messenger *m, uint32_t friendnumber, uint8_t *data, uint16_t length, void *userdata)
+ */
+void m_callback_conference_invite(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, uint16_t,
+ void *))
+{
+ m->conference_invite = function;
+}
+
+
+/* Send a conference invite packet.
+ *
+ * return 1 on success
+ * return 0 on failure
+ */
+int send_conference_invite_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length)
+{
+ return write_cryptpacket_id(m, friendnumber, PACKET_ID_INVITE_CONFERENCE, data, length, 0);
+}
+
+/****************FILE SENDING*****************/
+
+
+/* Set the callback for file send requests.
+ *
+ * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint32_t filetype, uint64_t filesize, uint8_t *filename, size_t filename_length, void *userdata)
+ */
+void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint32_t, uint64_t,
+ const uint8_t *, size_t, void *))
+{
+ m->file_sendrequest = function;
+}
+
+/* Set the callback for file control requests.
+ *
+ * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, unsigned int control_type, void *userdata)
+ *
+ */
+void callback_file_control(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, unsigned int, void *))
+{
+ m->file_filecontrol = function;
+}
+
+/* Set the callback for file data.
+ *
+ * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, uint8_t *data, size_t length, void *userdata)
+ *
+ */
+void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, const uint8_t *,
+ size_t, void *))
+{
+ m->file_filedata = function;
+}
+
+/* Set the callback for file request chunk.
+ *
+ * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length, void *userdata)
+ *
+ */
+void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *))
+{
+ m->file_reqchunk = function;
+}
+
+#define MAX_FILENAME_LENGTH 255
+
+/* Copy the file transfer file id to file_id
+ *
+ * return 0 on success.
+ * return -1 if friend not valid.
+ * return -2 if filenumber not valid
+ */
+int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint8_t *file_id)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
+ return -2;
+ }
+
+ uint32_t temp_filenum;
+ uint8_t send_receive, file_number;
+
+ if (filenumber >= (1 << 16)) {
+ send_receive = 1;
+ temp_filenum = (filenumber >> 16) - 1;
+ } else {
+ send_receive = 0;
+ temp_filenum = filenumber;
+ }
+
+ if (temp_filenum >= MAX_CONCURRENT_FILE_PIPES) {
+ return -2;
+ }
+
+ file_number = temp_filenum;
+
+ struct File_Transfers *ft;
+
+ if (send_receive) {
+ ft = &m->friendlist[friendnumber].file_receiving[file_number];
+ } else {
+ ft = &m->friendlist[friendnumber].file_sending[file_number];
+ }
+
+ if (ft->status == FILESTATUS_NONE) {
+ return -2;
+ }
+
+ memcpy(file_id, ft->id, FILE_ID_LENGTH);
+ return 0;
+}
+
+/* Send a file send request.
+ * Maximum filename length is 255 bytes.
+ * return 1 on success
+ * return 0 on failure
+ */
+static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint32_t file_type,
+ uint64_t filesize, const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return 0;
+ }
+
+ if (filename_length > MAX_FILENAME_LENGTH) {
+ return 0;
+ }
+
+ VLA(uint8_t, packet, 1 + sizeof(file_type) + sizeof(filesize) + FILE_ID_LENGTH + filename_length);
+ packet[0] = filenumber;
+ file_type = net_htonl(file_type);
+ memcpy(packet + 1, &file_type, sizeof(file_type));
+ host_to_net((uint8_t *)&filesize, sizeof(filesize));
+ memcpy(packet + 1 + sizeof(file_type), &filesize, sizeof(filesize));
+ memcpy(packet + 1 + sizeof(file_type) + sizeof(filesize), file_id, FILE_ID_LENGTH);
+
+ if (filename_length) {
+ memcpy(packet + 1 + sizeof(file_type) + sizeof(filesize) + FILE_ID_LENGTH, filename, filename_length);
+ }
+
+ return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_SENDREQUEST, packet, SIZEOF_VLA(packet), 0);
+}
+
+/* Send a file send request.
+ * Maximum filename length is 255 bytes.
+ * return file number on success
+ * return -1 if friend not found.
+ * return -2 if filename length invalid.
+ * return -3 if no more file sending slots left.
+ * return -4 if could not send packet (friend offline).
+ *
+ */
+long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_type, uint64_t filesize,
+ const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ if (filename_length > MAX_FILENAME_LENGTH) {
+ return -2;
+ }
+
+ uint32_t i;
+
+ for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) {
+ if (m->friendlist[friendnumber].file_sending[i].status == FILESTATUS_NONE) {
+ break;
+ }
+ }
+
+ if (i == MAX_CONCURRENT_FILE_PIPES) {
+ return -3;
+ }
+
+ if (file_sendrequest(m, friendnumber, i, file_type, filesize, file_id, filename, filename_length) == 0) {
+ return -4;
+ }
+
+ struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[i];
+
+ ft->status = FILESTATUS_NOT_ACCEPTED;
+
+ ft->size = filesize;
+
+ ft->transferred = 0;
+
+ ft->requested = 0;
+
+ ft->slots_allocated = 0;
+
+ ft->paused = FILE_PAUSE_NOT;
+
+ memcpy(ft->id, file_id, FILE_ID_LENGTH);
+
+ ++m->friendlist[friendnumber].num_sending_files;
+
+ return i;
+}
+
+static int send_file_control_packet(const Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber,
+ uint8_t control_type, uint8_t *data, uint16_t data_length)
+{
+ if ((unsigned int)(1 + 3 + data_length) > MAX_CRYPTO_DATA_SIZE) {
+ return -1;
+ }
+
+ VLA(uint8_t, packet, 3 + data_length);
+
+ packet[0] = send_receive;
+ packet[1] = filenumber;
+ packet[2] = control_type;
+
+ if (data_length) {
+ memcpy(packet + 3, data, data_length);
+ }
+
+ return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, SIZEOF_VLA(packet), 0);
+}
+
+/* Send a file control request.
+ *
+ * return 0 on success
+ * return -1 if friend not valid.
+ * return -2 if friend not online.
+ * return -3 if file number invalid.
+ * return -4 if file control is bad.
+ * return -5 if file already paused.
+ * return -6 if resume file failed because it was only paused by the other.
+ * return -7 if resume file failed because it wasn't paused.
+ * return -8 if packet failed to send.
+ */
+int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber, unsigned int control)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
+ return -2;
+ }
+
+ uint32_t temp_filenum;
+ uint8_t send_receive, file_number;
+
+ if (filenumber >= (1 << 16)) {
+ send_receive = 1;
+ temp_filenum = (filenumber >> 16) - 1;
+ } else {
+ send_receive = 0;
+ temp_filenum = filenumber;
+ }
+
+ if (temp_filenum >= MAX_CONCURRENT_FILE_PIPES) {
+ return -3;
+ }
+
+ file_number = temp_filenum;
+
+ struct File_Transfers *ft;
+
+ if (send_receive) {
+ ft = &m->friendlist[friendnumber].file_receiving[file_number];
+ } else {
+ ft = &m->friendlist[friendnumber].file_sending[file_number];
+ }
+
+ if (ft->status == FILESTATUS_NONE) {
+ return -3;
+ }
+
+ if (control > FILECONTROL_KILL) {
+ return -4;
+ }
+
+ if (control == FILECONTROL_PAUSE && ((ft->paused & FILE_PAUSE_US) || ft->status != FILESTATUS_TRANSFERRING)) {
+ return -5;
+ }
+
+ if (control == FILECONTROL_ACCEPT) {
+ if (ft->status == FILESTATUS_TRANSFERRING) {
+ if (!(ft->paused & FILE_PAUSE_US)) {
+ if (ft->paused & FILE_PAUSE_OTHER) {
+ return -6;
+ }
+
+ return -7;
+ }
+ } else {
+ if (ft->status != FILESTATUS_NOT_ACCEPTED) {
+ return -7;
+ }
+
+ if (!send_receive) {
+ return -6;
+ }
+ }
+ }
+
+ if (send_file_control_packet(m, friendnumber, send_receive, file_number, control, 0, 0)) {
+ if (control == FILECONTROL_KILL) {
+ ft->status = FILESTATUS_NONE;
+
+ if (send_receive == 0) {
+ --m->friendlist[friendnumber].num_sending_files;
+ }
+ } else if (control == FILECONTROL_PAUSE) {
+ ft->paused |= FILE_PAUSE_US;
+ } else if (control == FILECONTROL_ACCEPT) {
+ ft->status = FILESTATUS_TRANSFERRING;
+
+ if (ft->paused & FILE_PAUSE_US) {
+ ft->paused ^= FILE_PAUSE_US;
+ }
+ }
+ } else {
+ return -8;
+ }
+
+ return 0;
+}
+
+/* Send a seek file control request.
+ *
+ * return 0 on success
+ * return -1 if friend not valid.
+ * return -2 if friend not online.
+ * return -3 if file number invalid.
+ * return -4 if not receiving file.
+ * return -5 if file status wrong.
+ * return -6 if position bad.
+ * return -8 if packet failed to send.
+ */
+int file_seek(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
+ return -2;
+ }
+
+ if (filenumber < (1 << 16)) {
+ // Not receiving.
+ return -4;
+ }
+
+ uint32_t temp_filenum = (filenumber >> 16) - 1;
+
+ if (temp_filenum >= MAX_CONCURRENT_FILE_PIPES) {
+ return -3;
+ }
+
+ assert(temp_filenum <= UINT8_MAX);
+ uint8_t file_number = temp_filenum;
+
+ // We're always receiving at this point.
+ struct File_Transfers *ft = &m->friendlist[friendnumber].file_receiving[file_number];
+
+ if (ft->status == FILESTATUS_NONE) {
+ return -3;
+ }
+
+ if (ft->status != FILESTATUS_NOT_ACCEPTED) {
+ return -5;
+ }
+
+ if (position >= ft->size) {
+ return -6;
+ }
+
+ uint64_t sending_pos = position;
+ host_to_net((uint8_t *)&sending_pos, sizeof(sending_pos));
+
+ if (send_file_control_packet(m, friendnumber, 1, file_number, FILECONTROL_SEEK, (uint8_t *)&sending_pos,
+ sizeof(sending_pos))) {
+ ft->transferred = position;
+ } else {
+ return -8;
+ }
+
+ return 0;
+}
+
+/* return packet number on success.
+ * return -1 on failure.
+ */
+static int64_t send_file_data_packet(const Messenger *m, int32_t friendnumber, uint8_t filenumber, const uint8_t *data,
+ uint16_t length)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ VLA(uint8_t, packet, 2 + length);
+ packet[0] = PACKET_ID_FILE_DATA;
+ packet[1] = filenumber;
+
+ if (length) {
+ memcpy(packet + 2, data, length);
+ }
+
+ return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
+ m->friendlist[friendnumber].friendcon_id), packet, SIZEOF_VLA(packet), 1);
+}
+
+#define MAX_FILE_DATA_SIZE (MAX_CRYPTO_DATA_SIZE - 2)
+#define MIN_SLOTS_FREE (CRYPTO_MIN_QUEUE_LENGTH / 4)
+/* Send file data.
+ *
+ * return 0 on success
+ * return -1 if friend not valid.
+ * return -2 if friend not online.
+ * return -3 if filenumber invalid.
+ * return -4 if file transfer not transferring.
+ * return -5 if bad data size.
+ * return -6 if packet queue full.
+ * return -7 if wrong position.
+ */
+int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
+ uint16_t length)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
+ return -2;
+ }
+
+ if (filenumber >= MAX_CONCURRENT_FILE_PIPES) {
+ return -3;
+ }
+
+ struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[filenumber];
+
+ if (ft->status != FILESTATUS_TRANSFERRING) {
+ return -4;
+ }
+
+ if (length > MAX_FILE_DATA_SIZE) {
+ return -5;
+ }
+
+ if (ft->size - ft->transferred < length) {
+ return -5;
+ }
+
+ if (ft->size != UINT64_MAX && length != MAX_FILE_DATA_SIZE && (ft->transferred + length) != ft->size) {
+ return -5;
+ }
+
+ if (position != ft->transferred || (ft->requested <= position && ft->size != 0)) {
+ return -7;
+ }
+
+ /* Prevent file sending from filling up the entire buffer preventing messages from being sent.
+ * TODO(irungentoo): remove */
+ if (crypto_num_free_sendqueue_slots(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
+ m->friendlist[friendnumber].friendcon_id)) < MIN_SLOTS_FREE) {
+ return -6;
+ }
+
+ int64_t ret = send_file_data_packet(m, friendnumber, filenumber, data, length);
+
+ if (ret != -1) {
+ // TODO(irungentoo): record packet ids to check if other received complete file.
+ ft->transferred += length;
+
+ if (ft->slots_allocated) {
+ --ft->slots_allocated;
+ }
+
+ if (length != MAX_FILE_DATA_SIZE || ft->size == ft->transferred) {
+ ft->status = FILESTATUS_FINISHED;
+ ft->last_packet_number = ret;
+ }
+
+ return 0;
+ }
+
+ return -6;
+}
+
+/* Give the number of bytes left to be sent/received.
+ *
+ * send_receive is 0 if we want the sending files, 1 if we want the receiving.
+ *
+ * return number of bytes remaining to be sent/received on success
+ * return 0 on failure
+ */
+uint64_t file_dataremaining(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t send_receive)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return 0;
+ }
+
+ if (send_receive == 0) {
+ if (m->friendlist[friendnumber].file_sending[filenumber].status == FILESTATUS_NONE) {
+ return 0;
+ }
+
+ return m->friendlist[friendnumber].file_sending[filenumber].size -
+ m->friendlist[friendnumber].file_sending[filenumber].transferred;
+ }
+
+ if (m->friendlist[friendnumber].file_receiving[filenumber].status == FILESTATUS_NONE) {
+ return 0;
+ }
+
+ return m->friendlist[friendnumber].file_receiving[filenumber].size -
+ m->friendlist[friendnumber].file_receiving[filenumber].transferred;
+}
+
+static void do_reqchunk_filecb(Messenger *m, int32_t friendnumber, void *userdata)
+{
+ if (!m->friendlist[friendnumber].num_sending_files) {
+ return;
+ }
+
+ int free_slots = crypto_num_free_sendqueue_slots(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
+ m->friendlist[friendnumber].friendcon_id));
+
+ if (free_slots < MIN_SLOTS_FREE) {
+ free_slots = 0;
+ } else {
+ free_slots -= MIN_SLOTS_FREE;
+ }
+
+ unsigned int i, num = m->friendlist[friendnumber].num_sending_files;
+
+ for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) {
+ struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[i];
+
+ if (ft->status != FILESTATUS_NONE) {
+ --num;
+
+ if (ft->status == FILESTATUS_FINISHED) {
+ /* Check if file was entirely sent. */
+ if (friend_received_packet(m, friendnumber, ft->last_packet_number) == 0) {
+ if (m->file_reqchunk) {
+ (*m->file_reqchunk)(m, friendnumber, i, ft->transferred, 0, userdata);
+ }
+
+ ft->status = FILESTATUS_NONE;
+ --m->friendlist[friendnumber].num_sending_files;
+ }
+ }
+
+ /* TODO(irungentoo): if file is too slow, switch to the next. */
+ if (ft->slots_allocated > (unsigned int)free_slots) {
+ free_slots = 0;
+ } else {
+ free_slots -= ft->slots_allocated;
+ }
+ }
+
+ while (ft->status == FILESTATUS_TRANSFERRING && (ft->paused == FILE_PAUSE_NOT)) {
+ if (max_speed_reached(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
+ m->friendlist[friendnumber].friendcon_id))) {
+ free_slots = 0;
+ }
+
+ if (free_slots == 0) {
+ break;
+ }
+
+ uint16_t length = MAX_FILE_DATA_SIZE;
+
+ if (ft->size == 0) {
+ /* Send 0 data to friend if file is 0 length. */
+ file_data(m, friendnumber, i, 0, 0, 0);
+ break;
+ }
+
+ if (ft->size == ft->requested) {
+ break;
+ }
+
+ if (ft->size - ft->requested < length) {
+ length = ft->size - ft->requested;
+ }
+
+ ++ft->slots_allocated;
+
+ uint64_t position = ft->requested;
+ ft->requested += length;
+
+ if (m->file_reqchunk) {
+ (*m->file_reqchunk)(m, friendnumber, i, position, length, userdata);
+ }
+
+ --free_slots;
+ }
+
+ if (num == 0) {
+ break;
+ }
+ }
+}
+
+/* Run this when the friend disconnects.
+ * Kill all current file transfers.
+ */
+static void break_files(const Messenger *m, int32_t friendnumber)
+{
+ uint32_t i;
+
+ // TODO(irungentoo): Inform the client which file transfers get killed with a callback?
+ for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) {
+ if (m->friendlist[friendnumber].file_sending[i].status != FILESTATUS_NONE) {
+ m->friendlist[friendnumber].file_sending[i].status = FILESTATUS_NONE;
+ }
+
+ if (m->friendlist[friendnumber].file_receiving[i].status != FILESTATUS_NONE) {
+ m->friendlist[friendnumber].file_receiving[i].status = FILESTATUS_NONE;
+ }
+ }
+}
+
+static struct File_Transfers *get_file_transfer(uint8_t receive_send, uint8_t filenumber,
+ uint32_t *real_filenumber, Friend *sender)
+{
+ struct File_Transfers *ft;
+
+ if (receive_send == 0) {
+ *real_filenumber = (filenumber + 1) << 16;
+ ft = &sender->file_receiving[filenumber];
+ } else {
+ *real_filenumber = filenumber;
+ ft = &sender->file_sending[filenumber];
+ }
+
+ if (ft->status == FILESTATUS_NONE) {
+ return NULL;
+ }
+
+ return ft;
+}
+
+/* return -1 on failure, 0 on success.
+ */
+static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber,
+ uint8_t control_type, const uint8_t *data, uint16_t length, void *userdata)
+{
+ if (receive_send > 1) {
+ LOGGER_DEBUG(m->log, "file control (friend %d, file %d): receive_send value is invalid (should be 0 or 1): %d",
+ friendnumber, filenumber, receive_send);
+ return -1;
+ }
+
+ uint32_t real_filenumber;
+ struct File_Transfers *ft = get_file_transfer(receive_send, filenumber, &real_filenumber, &m->friendlist[friendnumber]);
+
+ if (ft == NULL) {
+ LOGGER_DEBUG(m->log, "file control (friend %d, file %d): file transfer does not exist; telling the other to kill it",
+ friendnumber, filenumber);
+ send_file_control_packet(m, friendnumber, !receive_send, filenumber, FILECONTROL_KILL, 0, 0);
+ return -1;
+ }
+
+ switch (control_type) {
+ case FILECONTROL_ACCEPT: {
+ if (receive_send && ft->status == FILESTATUS_NOT_ACCEPTED) {
+ ft->status = FILESTATUS_TRANSFERRING;
+ } else {
+ if (ft->paused & FILE_PAUSE_OTHER) {
+ ft->paused ^= FILE_PAUSE_OTHER;
+ } else {
+ LOGGER_DEBUG(m->log, "file control (friend %d, file %d): friend told us to resume file transfer that wasn't paused",
+ friendnumber, filenumber);
+ return -1;
+ }
+ }
+
+ if (m->file_filecontrol) {
+ m->file_filecontrol(m, friendnumber, real_filenumber, control_type, userdata);
+ }
+
+ return 0;
+ }
+
+ case FILECONTROL_PAUSE: {
+ if ((ft->paused & FILE_PAUSE_OTHER) || ft->status != FILESTATUS_TRANSFERRING) {
+ LOGGER_DEBUG(m->log, "file control (friend %d, file %d): friend told us to pause file transfer that is already paused",
+ friendnumber, filenumber);
+ return -1;
+ }
+
+ ft->paused |= FILE_PAUSE_OTHER;
+
+ if (m->file_filecontrol) {
+ m->file_filecontrol(m, friendnumber, real_filenumber, control_type, userdata);
+ }
+
+ return 0;
+ }
+
+ case FILECONTROL_KILL: {
+ if (m->file_filecontrol) {
+ m->file_filecontrol(m, friendnumber, real_filenumber, control_type, userdata);
+ }
+
+ ft->status = FILESTATUS_NONE;
+
+ if (receive_send) {
+ --m->friendlist[friendnumber].num_sending_files;
+ }
+
+ return 0;
+ }
+
+ case FILECONTROL_SEEK: {
+ uint64_t position;
+
+ if (length != sizeof(position)) {
+ LOGGER_DEBUG(m->log, "file control (friend %d, file %d): expected payload of length %d, but got %d",
+ friendnumber, filenumber, (uint32_t)sizeof(position), length);
+ return -1;
+ }
+
+ /* seek can only be sent by the receiver to seek before resuming broken transfers. */
+ if (ft->status != FILESTATUS_NOT_ACCEPTED || !receive_send) {
+ LOGGER_DEBUG(m->log,
+ "file control (friend %d, file %d): seek was either sent by a sender or by the receiver after accepting",
+ friendnumber, filenumber);
+ return -1;
+ }
+
+ memcpy(&position, data, sizeof(position));
+ net_to_host((uint8_t *) &position, sizeof(position));
+
+ if (position >= ft->size) {
+ LOGGER_DEBUG(m->log,
+ "file control (friend %d, file %d): seek position %lld exceeds file size %lld",
+ friendnumber, filenumber, (unsigned long long)position, (unsigned long long)ft->size);
+ return -1;
+ }
+
+ ft->transferred = ft->requested = position;
+ return 0;
+ }
+
+ default: {
+ LOGGER_DEBUG(m->log, "file control (friend %d, file %d): invalid file control: %d",
+ friendnumber, filenumber, control_type);
+ return -1;
+ }
+ }
+}
+
+/**************************************/
+
+/* Set the callback for msi packets.
+ *
+ * Function(Messenger *m, int friendnumber, uint8_t *data, uint16_t length, void *userdata)
+ */
+void m_callback_msi_packet(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, uint16_t, void *),
+ void *userdata)
+{
+ m->msi_packet = function;
+ m->msi_packet_userdata = userdata;
+}
+
+/* Send an msi packet.
+ *
+ * return 1 on success
+ * return 0 on failure
+ */
+int m_msi_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length)
+{
+ return write_cryptpacket_id(m, friendnumber, PACKET_ID_MSI, data, length, 0);
+}
+
+static int m_handle_custom_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length,
+ void *userdata)
+{
+ Messenger *m = (Messenger *)object;
+
+ if (friend_not_valid(m, friend_num)) {
+ return 1;
+ }
+
+ if (packet[0] < (PACKET_ID_LOSSY_RANGE_START + PACKET_LOSSY_AV_RESERVED)) {
+ if (m->friendlist[friend_num].lossy_rtp_packethandlers[packet[0] % PACKET_LOSSY_AV_RESERVED].function) {
+ return m->friendlist[friend_num].lossy_rtp_packethandlers[packet[0] % PACKET_LOSSY_AV_RESERVED].function(
+ m, friend_num, packet, length, m->friendlist[friend_num].lossy_rtp_packethandlers[packet[0] %
+ PACKET_LOSSY_AV_RESERVED].object);
+ }
+
+ return 1;
+ }
+
+ if (m->lossy_packethandler) {
+ m->lossy_packethandler(m, friend_num, packet, length, userdata);
+ }
+
+ return 1;
+}
+
+void custom_lossy_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m,
+ uint32_t friendnumber, const uint8_t *data, size_t len, void *object))
+{
+ m->lossy_packethandler = packet_handler_callback;
+}
+
+int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte, int (*packet_handler_callback)(Messenger *m,
+ uint32_t friendnumber, const uint8_t *data, uint16_t len, void *object), void *object)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ if (byte < PACKET_ID_LOSSY_RANGE_START) {
+ return -1;
+ }
+
+ if (byte >= (PACKET_ID_LOSSY_RANGE_START + PACKET_LOSSY_AV_RESERVED)) {
+ return -1;
+ }
+
+ m->friendlist[friendnumber].lossy_rtp_packethandlers[byte % PACKET_LOSSY_AV_RESERVED].function =
+ packet_handler_callback;
+ m->friendlist[friendnumber].lossy_rtp_packethandlers[byte % PACKET_LOSSY_AV_RESERVED].object = object;
+ return 0;
+}
+
+
+int m_send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
+ return -2;
+ }
+
+ if (data[0] < PACKET_ID_LOSSY_RANGE_START) {
+ return -3;
+ }
+
+ if (data[0] >= (PACKET_ID_LOSSY_RANGE_START + PACKET_ID_LOSSY_RANGE_SIZE)) {
+ return -3;
+ }
+
+ if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
+ return -4;
+ }
+
+ if (send_lossy_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
+ m->friendlist[friendnumber].friendcon_id), data, length) == -1) {
+ return -5;
+ }
+
+ return 0;
+}
+
+static int handle_custom_lossless_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length,
+ void *userdata)
+{
+ Messenger *m = (Messenger *)object;
+
+ if (friend_not_valid(m, friend_num)) {
+ return -1;
+ }
+
+ if (packet[0] < PACKET_ID_LOSSLESS_RANGE_START) {
+ return -1;
+ }
+
+ if (packet[0] >= (PACKET_ID_LOSSLESS_RANGE_START + PACKET_ID_LOSSLESS_RANGE_SIZE)) {
+ return -1;
+ }
+
+ if (m->lossless_packethandler) {
+ m->lossless_packethandler(m, friend_num, packet, length, userdata);
+ }
+
+ return 1;
+}
+
+void custom_lossless_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m,
+ uint32_t friendnumber, const uint8_t *data, size_t len, void *object))
+{
+ m->lossless_packethandler = packet_handler_callback;
+}
+
+int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length)
+{
+ if (friend_not_valid(m, friendnumber)) {
+ return -1;
+ }
+
+ if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
+ return -2;
+ }
+
+ if (data[0] < PACKET_ID_LOSSLESS_RANGE_START) {
+ return -3;
+ }
+
+ if (data[0] >= (PACKET_ID_LOSSLESS_RANGE_START + PACKET_ID_LOSSLESS_RANGE_SIZE)) {
+ return -3;
+ }
+
+ if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
+ return -4;
+ }
+
+ if (write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
+ m->friendlist[friendnumber].friendcon_id), data, length, 1) == -1) {
+ return -5;
+ }
+
+ return 0;
+}
+
+/* Function to filter out some friend requests*/
+static int friend_already_added(const uint8_t *real_pk, void *data)
+{
+ const Messenger *m = (const Messenger *)data;
+
+ if (getfriend_id(m, real_pk) == -1) {
+ return 0;
+ }
+
+ return -1;
+}
+
+/* Run this at startup. */
+Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
+{
+ if (!options) {
+ return NULL;
+ }
+
+ Messenger *m = (Messenger *)calloc(1, sizeof(Messenger));
+
+ if (error) {
+ *error = MESSENGER_ERROR_OTHER;
+ }
+
+ if (!m) {
+ return NULL;
+ }
+
+ Logger *log = NULL;
+
+ if (options->log_callback) {
+ log = logger_new();
+
+ if (log != NULL) {
+ logger_callback_log(log, options->log_callback, m, options->log_user_data);
+ }
+ }
+
+ m->log = log;
+
+ unsigned int net_err = 0;
+
+ if (options->udp_disabled) {
+ /* this is the easiest way to completely disable UDP without changing too much code. */
+ m->net = (Networking_Core *)calloc(1, sizeof(Networking_Core));
+ } else {
+ IP ip;
+ ip_init(&ip, options->ipv6enabled);
+ m->net = new_networking_ex(log, ip, options->port_range[0], options->port_range[1], &net_err);
+ }
+
+ if (m->net == NULL) {
+ free(m);
+
+ if (error && net_err == 1) {
+ *error = MESSENGER_ERROR_PORT;
+ }
+
+ return NULL;
+ }
+
+ m->dht = new_DHT(m->log, m->net, options->hole_punching_enabled);
+
+ if (m->dht == NULL) {
+ kill_networking(m->net);
+ free(m);
+ return NULL;
+ }
+
+ m->net_crypto = new_net_crypto(m->log, m->dht, &options->proxy_info);
+
+ if (m->net_crypto == NULL) {
+ kill_networking(m->net);
+ kill_DHT(m->dht);
+ free(m);
+ return NULL;
+ }
+
+ m->onion = new_onion(m->dht);
+ m->onion_a = new_onion_announce(m->dht);
+ m->onion_c = new_onion_client(m->net_crypto);
+ m->fr_c = new_friend_connections(m->onion_c, options->local_discovery_enabled);
+
+ if (!(m->onion && m->onion_a && m->onion_c)) {
+ kill_friend_connections(m->fr_c);
+ kill_onion(m->onion);
+ kill_onion_announce(m->onion_a);
+ kill_onion_client(m->onion_c);
+ kill_net_crypto(m->net_crypto);
+ kill_DHT(m->dht);
+ kill_networking(m->net);
+ free(m);
+ return NULL;
+ }
+
+ if (options->tcp_server_port) {
+ m->tcp_server = new_TCP_server(options->ipv6enabled, 1, &options->tcp_server_port, m->dht->self_secret_key, m->onion);
+
+ if (m->tcp_server == NULL) {
+ kill_friend_connections(m->fr_c);
+ kill_onion(m->onion);
+ kill_onion_announce(m->onion_a);
+ kill_onion_client(m->onion_c);
+ kill_net_crypto(m->net_crypto);
+ kill_DHT(m->dht);
+ kill_networking(m->net);
+ free(m);
+
+ if (error) {
+ *error = MESSENGER_ERROR_TCP_SERVER;
+ }
+
+ return NULL;
+ }
+ }
+
+ m->options = *options;
+ friendreq_init(&(m->fr), m->fr_c);
+ set_nospam(&(m->fr), random_int());
+ set_filter_function(&(m->fr), &friend_already_added, m);
+
+ m->lastdump = 0;
+
+ if (error) {
+ *error = MESSENGER_ERROR_NONE;
+ }
+
+ return m;
+}
+
+/* Run this before closing shop. */
+void kill_messenger(Messenger *m)
+{
+ if (!m) {
+ return;
+ }
+
+ uint32_t i;
+
+ if (m->tcp_server) {
+ kill_TCP_server(m->tcp_server);
+ }
+
+ kill_friend_connections(m->fr_c);
+ kill_onion(m->onion);
+ kill_onion_announce(m->onion_a);
+ kill_onion_client(m->onion_c);
+ kill_net_crypto(m->net_crypto);
+ kill_DHT(m->dht);
+ kill_networking(m->net);
+
+ for (i = 0; i < m->numfriends; ++i) {
+ clear_receipts(m, i);
+ }
+
+ logger_kill(m->log);
+ free(m->friendlist);
+ free(m);
+}
+
+/* Check for and handle a timed-out friend request. If the request has
+ * timed-out then the friend status is set back to FRIEND_ADDED.
+ * i: friendlist index of the timed-out friend
+ * t: time
+ */
+static void check_friend_request_timed_out(Messenger *m, uint32_t i, uint64_t t, void *userdata)
+{
+ Friend *f = &m->friendlist[i];
+
+ if (f->friendrequest_lastsent + f->friendrequest_timeout < t) {
+ set_friend_status(m, i, FRIEND_ADDED, userdata);
+ /* Double the default timeout every time if friendrequest is assumed
+ * to have been sent unsuccessfully.
+ */
+ f->friendrequest_timeout *= 2;
+ }
+}
+
+static int m_handle_status(void *object, int i, uint8_t status, void *userdata)
+{
+ Messenger *m = (Messenger *)object;
+
+ if (status) { /* Went online. */
+ send_online_packet(m, i);
+ } else { /* Went offline. */
+ if (m->friendlist[i].status == FRIEND_ONLINE) {
+ set_friend_status(m, i, FRIEND_CONFIRMED, userdata);
+ }
+ }
+
+ return 0;
+}
+
+static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t len, void *userdata)
+{
+ if (len == 0) {
+ return -1;
+ }
+
+ Messenger *m = (Messenger *)object;
+ uint8_t packet_id = temp[0];
+ const uint8_t *data = temp + 1;
+ uint32_t data_length = len - 1;
+
+ if (m->friendlist[i].status != FRIEND_ONLINE) {
+ if (packet_id == PACKET_ID_ONLINE && len == 1) {
+ set_friend_status(m, i, FRIEND_ONLINE, userdata);
+ send_online_packet(m, i);
+ } else {
+ return -1;
+ }
+ }
+
+ switch (packet_id) {
+ case PACKET_ID_OFFLINE: {
+ if (data_length != 0) {
+ break;
+ }
+
+ set_friend_status(m, i, FRIEND_CONFIRMED, userdata);
+ break;
+ }
+
+ case PACKET_ID_NICKNAME: {
+ if (data_length > MAX_NAME_LENGTH) {
+ break;
+ }
+
+ /* Make sure the NULL terminator is present. */
+ VLA(uint8_t, data_terminated, data_length + 1);
+ memcpy(data_terminated, data, data_length);
+ data_terminated[data_length] = 0;
+
+ /* inform of namechange before we overwrite the old name */
+ if (m->friend_namechange) {
+ m->friend_namechange(m, i, data_terminated, data_length, userdata);
+ }
+
+ memcpy(m->friendlist[i].name, data_terminated, data_length);
+ m->friendlist[i].name_length = data_length;
+
+ break;
+ }
+
+ case PACKET_ID_STATUSMESSAGE: {
+ if (data_length > MAX_STATUSMESSAGE_LENGTH) {
+ break;
+ }
+
+ /* Make sure the NULL terminator is present. */
+ VLA(uint8_t, data_terminated, data_length + 1);
+ memcpy(data_terminated, data, data_length);
+ data_terminated[data_length] = 0;
+
+ if (m->friend_statusmessagechange) {
+ m->friend_statusmessagechange(m, i, data_terminated, data_length, userdata);
+ }
+
+ set_friend_statusmessage(m, i, data_terminated, data_length);
+ break;
+ }
+
+ case PACKET_ID_USERSTATUS: {
+ if (data_length != 1) {
+ break;
+ }
+
+ USERSTATUS status = (USERSTATUS)data[0];
+
+ if (status >= USERSTATUS_INVALID) {
+ break;
+ }
+
+ if (m->friend_userstatuschange) {
+ m->friend_userstatuschange(m, i, status, userdata);
+ }
+
+ set_friend_userstatus(m, i, status);
+ break;
+ }
+
+ case PACKET_ID_TYPING: {
+ if (data_length != 1) {
+ break;
+ }
+
+ bool typing = !!data[0];
+
+ set_friend_typing(m, i, typing);
+
+ if (m->friend_typingchange) {
+ m->friend_typingchange(m, i, typing, userdata);
+ }
+
+ break;
+ }
+
+ case PACKET_ID_MESSAGE: // fall-through
+ case PACKET_ID_ACTION: {
+ if (data_length == 0) {
+ break;
+ }
+
+ const uint8_t *message = data;
+ uint16_t message_length = data_length;
+
+ /* Make sure the NULL terminator is present. */
+ VLA(uint8_t, message_terminated, message_length + 1);
+ memcpy(message_terminated, message, message_length);
+ message_terminated[message_length] = 0;
+ uint8_t type = packet_id - PACKET_ID_MESSAGE;
+
+ if (m->friend_message) {
+ (*m->friend_message)(m, i, type, message_terminated, message_length, userdata);
+ }
+
+ break;
+ }
+
+ case PACKET_ID_INVITE_CONFERENCE: {
+ if (data_length == 0) {
+ break;
+ }
+
+ if (m->conference_invite) {
+ (*m->conference_invite)(m, i, data, data_length, userdata);
+ }
+
+ break;
+ }
+
+ case PACKET_ID_FILE_SENDREQUEST: {
+ const unsigned int head_length = 1 + sizeof(uint32_t) + sizeof(uint64_t) + FILE_ID_LENGTH;
+
+ if (data_length < head_length) {
+ break;
+ }
+
+ uint8_t filenumber = data[0];
+
+ if (filenumber >= MAX_CONCURRENT_FILE_PIPES) {
+ break;
+ }
+
+ uint64_t filesize;
+ uint32_t file_type;
+ uint16_t filename_length = data_length - head_length;
+
+ if (filename_length > MAX_FILENAME_LENGTH) {
+ break;
+ }
+
+ memcpy(&file_type, data + 1, sizeof(file_type));
+ file_type = net_ntohl(file_type);
+
+ memcpy(&filesize, data + 1 + sizeof(uint32_t), sizeof(filesize));
+ net_to_host((uint8_t *) &filesize, sizeof(filesize));
+ struct File_Transfers *ft = &m->friendlist[i].file_receiving[filenumber];
+
+ if (ft->status != FILESTATUS_NONE) {
+ break;
+ }
+
+ ft->status = FILESTATUS_NOT_ACCEPTED;
+ ft->size = filesize;
+ ft->transferred = 0;
+ ft->paused = FILE_PAUSE_NOT;
+ memcpy(ft->id, data + 1 + sizeof(uint32_t) + sizeof(uint64_t), FILE_ID_LENGTH);
+
+ VLA(uint8_t, filename_terminated, filename_length + 1);
+ uint8_t *filename = NULL;
+
+ if (filename_length) {
+ /* Force NULL terminate file name. */
+ memcpy(filename_terminated, data + head_length, filename_length);
+ filename_terminated[filename_length] = 0;
+ filename = filename_terminated;
+ }
+
+ uint32_t real_filenumber = filenumber;
+ real_filenumber += 1;
+ real_filenumber <<= 16;
+
+ if (m->file_sendrequest) {
+ (*m->file_sendrequest)(m, i, real_filenumber, file_type, filesize, filename, filename_length,
+ userdata);
+ }
+
+ break;
+ }
+
+ case PACKET_ID_FILE_CONTROL: {
+ if (data_length < 3) {
+ break;
+ }
+
+ uint8_t send_receive = data[0];
+ uint8_t filenumber = data[1];
+ uint8_t control_type = data[2];
+
+ if (filenumber >= MAX_CONCURRENT_FILE_PIPES) {
+ break;
+ }
+
+ if (handle_filecontrol(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3, userdata) == -1) {
+ // TODO(iphydf): Do something different here? Right now, this
+ // check is pointless.
+ break;
+ }
+
+ break;
+ }
+
+ case PACKET_ID_FILE_DATA: {
+ if (data_length < 1) {
+ break;
+ }
+
+ uint8_t filenumber = data[0];
+
+ if (filenumber >= MAX_CONCURRENT_FILE_PIPES) {
+ break;
+ }
+
+ struct File_Transfers *ft = &m->friendlist[i].file_receiving[filenumber];
+
+ if (ft->status != FILESTATUS_TRANSFERRING) {
+ break;
+ }
+
+ uint64_t position = ft->transferred;
+ uint32_t real_filenumber = filenumber;
+ real_filenumber += 1;
+ real_filenumber <<= 16;
+ uint16_t file_data_length = (data_length - 1);
+ const uint8_t *file_data;
+
+ if (file_data_length == 0) {
+ file_data = NULL;
+ } else {
+ file_data = data + 1;
+ }
+
+ /* Prevent more data than the filesize from being passed to clients. */
+ if ((ft->transferred + file_data_length) > ft->size) {
+ file_data_length = ft->size - ft->transferred;
+ }
+
+ if (m->file_filedata) {
+ (*m->file_filedata)(m, i, real_filenumber, position, file_data, file_data_length, userdata);
+ }
+
+ ft->transferred += file_data_length;
+
+ if (file_data_length && (ft->transferred >= ft->size || file_data_length != MAX_FILE_DATA_SIZE)) {
+ file_data_length = 0;
+ file_data = NULL;
+ position = ft->transferred;
+
+ /* Full file received. */
+ if (m->file_filedata) {
+ (*m->file_filedata)(m, i, real_filenumber, position, file_data, file_data_length, userdata);
+ }
+ }
+
+ /* Data is zero, filetransfer is over. */
+ if (file_data_length == 0) {
+ ft->status = FILESTATUS_NONE;
+ }
+
+ break;
+ }
+
+ case PACKET_ID_MSI: {
+ if (data_length == 0) {
+ break;
+ }
+
+ if (m->msi_packet) {
+ (*m->msi_packet)(m, i, data, data_length, m->msi_packet_userdata);
+ }
+
+ break;
+ }
+
+ default: {
+ handle_custom_lossless_packet(object, i, temp, len, userdata);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static void do_friends(Messenger *m, void *userdata)
+{
+ uint32_t i;
+ uint64_t temp_time = unix_time();
+
+ for (i = 0; i < m->numfriends; ++i) {
+ if (m->friendlist[i].status == FRIEND_ADDED) {
+ int fr = send_friend_request_packet(m->fr_c, m->friendlist[i].friendcon_id, m->friendlist[i].friendrequest_nospam,
+ m->friendlist[i].info,
+ m->friendlist[i].info_size);
+
+ if (fr >= 0) {
+ set_friend_status(m, i, FRIEND_REQUESTED, userdata);
+ m->friendlist[i].friendrequest_lastsent = temp_time;
+ }
+ }
+
+ if (m->friendlist[i].status == FRIEND_REQUESTED
+ || m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online. */
+ if (m->friendlist[i].status == FRIEND_REQUESTED) {
+ /* If we didn't connect to friend after successfully sending him a friend request the request is deemed
+ * unsuccessful so we set the status back to FRIEND_ADDED and try again.
+ */
+ check_friend_request_timed_out(m, i, temp_time, userdata);
+ }
+ }
+
+ if (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */
+ if (m->friendlist[i].name_sent == 0) {
+ if (m_sendname(m, i, m->name, m->name_length)) {
+ m->friendlist[i].name_sent = 1;
+ }
+ }
+
+ if (m->friendlist[i].statusmessage_sent == 0) {
+ if (send_statusmessage(m, i, m->statusmessage, m->statusmessage_length)) {
+ m->friendlist[i].statusmessage_sent = 1;
+ }
+ }
+
+ if (m->friendlist[i].userstatus_sent == 0) {
+ if (send_userstatus(m, i, m->userstatus)) {
+ m->friendlist[i].userstatus_sent = 1;
+ }
+ }
+
+ if (m->friendlist[i].user_istyping_sent == 0) {
+ if (send_user_istyping(m, i, m->friendlist[i].user_istyping)) {
+ m->friendlist[i].user_istyping_sent = 1;
+ }
+ }
+
+ check_friend_tcp_udp(m, i, userdata);
+ do_receipts(m, i, userdata);
+ do_reqchunk_filecb(m, i, userdata);
+
+ m->friendlist[i].last_seen_time = (uint64_t) time(NULL);
+ }
+ }
+}
+
+static void connection_status_cb(Messenger *m, void *userdata)
+{
+ unsigned int conn_status = onion_connection_status(m->onion_c);
+
+ if (conn_status != m->last_connection_status) {
+ if (m->core_connection_change) {
+ (*m->core_connection_change)(m, conn_status, userdata);
+ }
+
+ m->last_connection_status = conn_status;
+ }
+}
+
+
+#define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL
+
+#define IDSTRING_LEN (CRYPTO_PUBLIC_KEY_SIZE * 2 + 1)
+/* id_str should be of length at least IDSTRING_LEN */
+static char *id_to_string(const uint8_t *pk, char *id_str, size_t length)
+{
+ if (length < IDSTRING_LEN) {
+ snprintf(id_str, length, "Bad buf length");
+ return id_str;
+ }
+
+ for (uint32_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; i++) {
+ sprintf(&id_str[i * 2], "%02X", pk[i]);
+ }
+
+ id_str[CRYPTO_PUBLIC_KEY_SIZE * 2] = 0;
+ return id_str;
+}
+
+/* Minimum messenger run interval in ms
+ TODO(mannol): A/V */
+#define MIN_RUN_INTERVAL 50
+
+/* Return the time in milliseconds before do_messenger() should be called again
+ * for optimal performance.
+ *
+ * returns time (in ms) before the next do_messenger() needs to be run on success.
+ */
+uint32_t messenger_run_interval(const Messenger *m)
+{
+ uint32_t crypto_interval = crypto_run_interval(m->net_crypto);
+
+ if (crypto_interval > MIN_RUN_INTERVAL) {
+ return MIN_RUN_INTERVAL;
+ }
+
+ return crypto_interval;
+}
+
+/* The main loop that needs to be run at least 20 times per second. */
+void do_messenger(Messenger *m, void *userdata)
+{
+ // Add the TCP relays, but only if this is the first time calling do_messenger
+ if (m->has_added_relays == 0) {
+ m->has_added_relays = 1;
+
+ int i;
+
+ for (i = 0; i < NUM_SAVED_TCP_RELAYS; ++i) {
+ add_tcp_relay(m->net_crypto, m->loaded_relays[i].ip_port, m->loaded_relays[i].public_key);
+ }
+
+ if (m->tcp_server) {
+ /* Add self tcp server. */
+ IP_Port local_ip_port;
+ local_ip_port.port = m->options.tcp_server_port;
+ local_ip_port.ip.family = TOX_AF_INET;
+ local_ip_port.ip.ip4 = get_ip4_loopback();
+ add_tcp_relay(m->net_crypto, local_ip_port,
+ tcp_server_public_key(m->tcp_server));
+ }
+ }
+
+ unix_time_update();
+
+ if (!m->options.udp_disabled) {
+ networking_poll(m->net, userdata);
+ do_DHT(m->dht);
+ }
+
+ if (m->tcp_server) {
+ do_TCP_server(m->tcp_server);
+ }
+
+ do_net_crypto(m->net_crypto, userdata);
+ do_onion_client(m->onion_c);
+ do_friend_connections(m->fr_c, userdata);
+ do_friends(m, userdata);
+ connection_status_cb(m, userdata);
+
+ if (unix_time() > m->lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) {
+ m->lastdump = unix_time();
+ uint32_t client, last_pinged;
+
+ for (client = 0; client < LCLIENT_LIST; client++) {
+ Client_data *cptr = &m->dht->close_clientlist[client];
+ IPPTsPng *assoc = NULL;
+ uint32_t a;
+
+ for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6) {
+ if (ip_isset(&assoc->ip_port.ip)) {
+ last_pinged = m->lastdump - assoc->last_pinged;
+
+ if (last_pinged > 999) {
+ last_pinged = 999;
+ }
+
+ char ip_str[IP_NTOA_LEN];
+ char id_str[IDSTRING_LEN];
+ LOGGER_TRACE(m->log, "C[%2u] %s:%u [%3u] %s",
+ client, ip_ntoa(&assoc->ip_port.ip, ip_str, sizeof(ip_str)),
+ net_ntohs(assoc->ip_port.port), last_pinged,
+ id_to_string(cptr->public_key, id_str, sizeof(id_str)));
+ }
+ }
+ }
+
+
+ uint32_t friend_idx, dhtfriend;
+
+ /* dht contains additional "friends" (requests) */
+ uint32_t num_dhtfriends = m->dht->num_friends;
+ VLA(int32_t, m2dht, num_dhtfriends);
+ VLA(int32_t, dht2m, num_dhtfriends);
+
+ for (friend_idx = 0; friend_idx < num_dhtfriends; friend_idx++) {
+ m2dht[friend_idx] = -1;
+ dht2m[friend_idx] = -1;
+
+ if (friend_idx >= m->numfriends) {
+ continue;
+ }
+
+ for (dhtfriend = 0; dhtfriend < m->dht->num_friends; dhtfriend++) {
+ if (id_equal(m->friendlist[friend_idx].real_pk, m->dht->friends_list[dhtfriend].public_key)) {
+ m2dht[friend_idx] = dhtfriend;
+ break;
+ }
+ }
+ }
+
+ for (friend_idx = 0; friend_idx < num_dhtfriends; friend_idx++) {
+ if (m2dht[friend_idx] >= 0) {
+ dht2m[m2dht[friend_idx]] = friend_idx;
+ }
+ }
+
+ if (m->numfriends != m->dht->num_friends) {
+ LOGGER_TRACE(m->log, "Friend num in DHT %u != friend num in msger %u\n", m->dht->num_friends, m->numfriends);
+ }
+
+ Friend *msgfptr;
+ DHT_Friend *dhtfptr;
+
+ for (friend_idx = 0; friend_idx < num_dhtfriends; friend_idx++) {
+ if (dht2m[friend_idx] >= 0) {
+ msgfptr = &m->friendlist[dht2m[friend_idx]];
+ } else {
+ msgfptr = NULL;
+ }
+
+ dhtfptr = &m->dht->friends_list[friend_idx];
+
+ if (msgfptr) {
+ char id_str[IDSTRING_LEN];
+ LOGGER_TRACE(m->log, "F[%2u:%2u] <%s> %s",
+ dht2m[friend_idx], friend_idx, msgfptr->name,
+ id_to_string(msgfptr->real_pk, id_str, sizeof(id_str)));
+ } else {
+ char id_str[IDSTRING_LEN];
+ LOGGER_TRACE(m->log, "F[--:%2u] %s", friend_idx,
+ id_to_string(dhtfptr->public_key, id_str, sizeof(id_str)));
+ }
+
+ for (client = 0; client < MAX_FRIEND_CLIENTS; client++) {
+ Client_data *cptr = &dhtfptr->client_list[client];
+ IPPTsPng *assoc = NULL;
+ uint32_t a;
+
+ for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6) {
+ if (ip_isset(&assoc->ip_port.ip)) {
+ last_pinged = m->lastdump - assoc->last_pinged;
+
+ if (last_pinged > 999) {
+ last_pinged = 999;
+ }
+
+ char ip_str[IP_NTOA_LEN];
+ char id_str[IDSTRING_LEN];
+ LOGGER_TRACE(m->log, "F[%2u] => C[%2u] %s:%u [%3u] %s",
+ friend_idx, client, ip_ntoa(&assoc->ip_port.ip, ip_str, sizeof(ip_str)),
+ net_ntohs(assoc->ip_port.port), last_pinged,
+ id_to_string(cptr->public_key, id_str, sizeof(id_str)));
+ }
+ }
+ }
+ }
+ }
+}
+
+/* new messenger format for load/save, more robust and forward compatible */
+
+#define MESSENGER_STATE_COOKIE_GLOBAL 0x15ed1b1f
+
+#define MESSENGER_STATE_COOKIE_TYPE 0x01ce
+#define MESSENGER_STATE_TYPE_NOSPAMKEYS 1
+#define MESSENGER_STATE_TYPE_DHT 2
+#define MESSENGER_STATE_TYPE_FRIENDS 3
+#define MESSENGER_STATE_TYPE_NAME 4
+#define MESSENGER_STATE_TYPE_STATUSMESSAGE 5
+#define MESSENGER_STATE_TYPE_STATUS 6
+#define MESSENGER_STATE_TYPE_TCP_RELAY 10
+#define MESSENGER_STATE_TYPE_PATH_NODE 11
+#define MESSENGER_STATE_TYPE_END 255
+
+#define SAVED_FRIEND_REQUEST_SIZE 1024
+#define NUM_SAVED_PATH_NODES 8
+
+struct SAVED_FRIEND {
+ uint8_t status;
+ uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t info[SAVED_FRIEND_REQUEST_SIZE]; // the data that is sent during the friend requests we do.
+ uint16_t info_size; // Length of the info.
+ uint8_t name[MAX_NAME_LENGTH];
+ uint16_t name_length;
+ uint8_t statusmessage[MAX_STATUSMESSAGE_LENGTH];
+ uint16_t statusmessage_length;
+ uint8_t userstatus;
+ uint32_t friendrequest_nospam;
+ uint64_t last_seen_time;
+};
+
+static uint32_t friend_size()
+{
+ uint32_t data = 0;
+ const struct SAVED_FRIEND temp = { 0 };
+
+#define VALUE_MEMBER(NAME) data += sizeof(temp.NAME)
+#define ARRAY_MEMBER(NAME) data += sizeof(temp.NAME)
+
+ // Exactly the same in friend_load, friend_save, and friend_size
+ VALUE_MEMBER(status);
+ ARRAY_MEMBER(real_pk);
+ ARRAY_MEMBER(info);
+ data++; // padding
+ VALUE_MEMBER(info_size);
+ ARRAY_MEMBER(name);
+ VALUE_MEMBER(name_length);
+ ARRAY_MEMBER(statusmessage);
+ data++; // padding
+ VALUE_MEMBER(statusmessage_length);
+ VALUE_MEMBER(userstatus);
+ data += 3; // padding
+ VALUE_MEMBER(friendrequest_nospam);
+ VALUE_MEMBER(last_seen_time);
+
+#undef VALUE_MEMBER
+#undef ARRAY_MEMBER
+
+ return data;
+}
+
+static uint32_t saved_friendslist_size(const Messenger *m)
+{
+ return count_friendlist(m) * friend_size();
+}
+
+static uint8_t *friend_save(const struct SAVED_FRIEND *temp, uint8_t *data)
+{
+#define VALUE_MEMBER(NAME) \
+ memcpy(data, &temp->NAME, sizeof(temp->NAME)); \
+ data += sizeof(temp->NAME)
+
+#define ARRAY_MEMBER(NAME) \
+ memcpy(data, temp->NAME, sizeof(temp->NAME)); \
+ data += sizeof(temp->NAME)
+
+ // Exactly the same in friend_load, friend_save, and friend_size
+ VALUE_MEMBER(status);
+ ARRAY_MEMBER(real_pk);
+ ARRAY_MEMBER(info);
+ data++; // padding
+ VALUE_MEMBER(info_size);
+ ARRAY_MEMBER(name);
+ VALUE_MEMBER(name_length);
+ ARRAY_MEMBER(statusmessage);
+ data++; // padding
+ VALUE_MEMBER(statusmessage_length);
+ VALUE_MEMBER(userstatus);
+ data += 3; // padding
+ VALUE_MEMBER(friendrequest_nospam);
+ VALUE_MEMBER(last_seen_time);
+
+#undef VALUE_MEMBER
+#undef ARRAY_MEMBER
+
+ return data;
+}
+
+static uint32_t friends_list_save(const Messenger *m, uint8_t *data)
+{
+ uint32_t i;
+ uint32_t num = 0;
+ uint8_t *cur_data = data;
+
+ for (i = 0; i < m->numfriends; i++) {
+ if (m->friendlist[i].status > 0) {
+ struct SAVED_FRIEND temp = { 0 };
+ temp.status = m->friendlist[i].status;
+ memcpy(temp.real_pk, m->friendlist[i].real_pk, CRYPTO_PUBLIC_KEY_SIZE);
+
+ if (temp.status < 3) {
+ const size_t friendrequest_length =
+ MIN(m->friendlist[i].info_size,
+ MIN(SAVED_FRIEND_REQUEST_SIZE, MAX_FRIEND_REQUEST_DATA_SIZE));
+ memcpy(temp.info, m->friendlist[i].info, friendrequest_length);
+
+ temp.info_size = net_htons(m->friendlist[i].info_size);
+ temp.friendrequest_nospam = m->friendlist[i].friendrequest_nospam;
+ } else {
+ memcpy(temp.name, m->friendlist[i].name, m->friendlist[i].name_length);
+ temp.name_length = net_htons(m->friendlist[i].name_length);
+ memcpy(temp.statusmessage, m->friendlist[i].statusmessage, m->friendlist[i].statusmessage_length);
+ temp.statusmessage_length = net_htons(m->friendlist[i].statusmessage_length);
+ temp.userstatus = m->friendlist[i].userstatus;
+
+ uint8_t last_seen_time[sizeof(uint64_t)];
+ memcpy(last_seen_time, &m->friendlist[i].last_seen_time, sizeof(uint64_t));
+ host_to_net(last_seen_time, sizeof(uint64_t));
+ memcpy(&temp.last_seen_time, last_seen_time, sizeof(uint64_t));
+ }
+
+ uint8_t *next_data = friend_save(&temp, cur_data);
+ assert(next_data - cur_data == friend_size());
+#ifdef __LP64__
+ assert(memcmp(cur_data, &temp, friend_size()) == 0);
+#endif
+ cur_data = next_data;
+ num++;
+ }
+ }
+
+ assert(cur_data - data == num * friend_size());
+ return cur_data - data;
+}
+
+static const uint8_t *friend_load(struct SAVED_FRIEND *temp, const uint8_t *data)
+{
+#define VALUE_MEMBER(NAME) \
+ memcpy(&temp->NAME, data, sizeof(temp->NAME)); \
+ data += sizeof(temp->NAME)
+
+#define ARRAY_MEMBER(NAME) \
+ memcpy(temp->NAME, data, sizeof(temp->NAME)); \
+ data += sizeof(temp->NAME)
+
+ // Exactly the same in friend_load, friend_save, and friend_size
+ VALUE_MEMBER(status);
+ ARRAY_MEMBER(real_pk);
+ ARRAY_MEMBER(info);
+ data++; // padding
+ VALUE_MEMBER(info_size);
+ ARRAY_MEMBER(name);
+ VALUE_MEMBER(name_length);
+ ARRAY_MEMBER(statusmessage);
+ data++; // padding
+ VALUE_MEMBER(statusmessage_length);
+ VALUE_MEMBER(userstatus);
+ data += 3; // padding
+ VALUE_MEMBER(friendrequest_nospam);
+ VALUE_MEMBER(last_seen_time);
+
+#undef VALUE_MEMBER
+#undef ARRAY_MEMBER
+
+ return data;
+}
+
+static int friends_list_load(Messenger *m, const uint8_t *data, uint32_t length)
+{
+ if (length % friend_size() != 0) {
+ return -1;
+ }
+
+ uint32_t num = length / friend_size();
+ uint32_t i;
+ const uint8_t *cur_data = data;
+
+ for (i = 0; i < num; ++i) {
+ struct SAVED_FRIEND temp = { 0 };
+ const uint8_t *next_data = friend_load(&temp, cur_data);
+ assert(next_data - cur_data == friend_size());
+#ifdef __LP64__
+ assert(memcmp(&temp, cur_data, friend_size()) == 0);
+#endif
+ cur_data = next_data;
+
+ if (temp.status >= 3) {
+ int fnum = m_addfriend_norequest(m, temp.real_pk);
+
+ if (fnum < 0) {
+ continue;
+ }
+
+ setfriendname(m, fnum, temp.name, net_ntohs(temp.name_length));
+ set_friend_statusmessage(m, fnum, temp.statusmessage, net_ntohs(temp.statusmessage_length));
+ set_friend_userstatus(m, fnum, temp.userstatus);
+ uint8_t last_seen_time[sizeof(uint64_t)];
+ memcpy(last_seen_time, &temp.last_seen_time, sizeof(uint64_t));
+ net_to_host(last_seen_time, sizeof(uint64_t));
+ memcpy(&m->friendlist[fnum].last_seen_time, last_seen_time, sizeof(uint64_t));
+ } else if (temp.status != 0) {
+ /* TODO(irungentoo): This is not a good way to do this. */
+ uint8_t address[FRIEND_ADDRESS_SIZE];
+ id_copy(address, temp.real_pk);
+ memcpy(address + CRYPTO_PUBLIC_KEY_SIZE, &(temp.friendrequest_nospam), sizeof(uint32_t));
+ uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum));
+ memcpy(address + CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint32_t), &checksum, sizeof(checksum));
+ m_addfriend(m, address, temp.info, net_ntohs(temp.info_size));
+ }
+ }
+
+ return num;
+}
+
+/* return size of the messenger data (for saving) */
+uint32_t messenger_size(const Messenger *m)
+{
+ uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2;
+ return size32 * 2 // global cookie
+ + sizesubhead + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE
+ + sizesubhead + DHT_size(m->dht) // DHT
+ + sizesubhead + saved_friendslist_size(m) // Friendlist itself.
+ + sizesubhead + m->name_length // Own nickname.
+ + sizesubhead + m->statusmessage_length // status message
+ + sizesubhead + 1 // status
+ + sizesubhead + NUM_SAVED_TCP_RELAYS * packed_node_size(TCP_INET6) //TCP relays
+ + sizesubhead + NUM_SAVED_PATH_NODES * packed_node_size(TCP_INET6) //saved path nodes
+ + sizesubhead;
+}
+
+static uint8_t *messenger_save_subheader(uint8_t *data, uint32_t len, uint16_t type)
+{
+ host_to_lendian32(data, len);
+ data += sizeof(uint32_t);
+ host_to_lendian32(data, (host_tolendian16(MESSENGER_STATE_COOKIE_TYPE) << 16) | host_tolendian16(type));
+ data += sizeof(uint32_t);
+ return data;
+}
+
+/* Save the messenger in data of size Messenger_size(). */
+void messenger_save(const Messenger *m, uint8_t *data)
+{
+ memset(data, 0, messenger_size(m));
+
+ uint32_t len;
+ uint16_t type;
+ uint32_t size32 = sizeof(uint32_t);
+
+ memset(data, 0, size32);
+ data += size32;
+ host_to_lendian32(data, MESSENGER_STATE_COOKIE_GLOBAL);
+ data += size32;
+
+ assert(sizeof(get_nospam(&m->fr)) == sizeof(uint32_t));
+ len = size32 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE;
+ type = MESSENGER_STATE_TYPE_NOSPAMKEYS;
+ data = messenger_save_subheader(data, len, type);
+ *(uint32_t *)data = get_nospam(&(m->fr));
+ save_keys(m->net_crypto, data + size32);
+ data += len;
+
+ len = saved_friendslist_size(m);
+ type = MESSENGER_STATE_TYPE_FRIENDS;
+ data = messenger_save_subheader(data, len, type);
+ friends_list_save(m, data);
+ data += len;
+
+ len = m->name_length;
+ type = MESSENGER_STATE_TYPE_NAME;
+ data = messenger_save_subheader(data, len, type);
+ memcpy(data, m->name, len);
+ data += len;
+
+ len = m->statusmessage_length;
+ type = MESSENGER_STATE_TYPE_STATUSMESSAGE;
+ data = messenger_save_subheader(data, len, type);
+ memcpy(data, m->statusmessage, len);
+ data += len;
+
+ len = 1;
+ type = MESSENGER_STATE_TYPE_STATUS;
+ data = messenger_save_subheader(data, len, type);
+ *data = m->userstatus;
+ data += len;
+
+ len = DHT_size(m->dht);
+ type = MESSENGER_STATE_TYPE_DHT;
+ data = messenger_save_subheader(data, len, type);
+ DHT_save(m->dht, data);
+ data += len;
+
+ Node_format relays[NUM_SAVED_TCP_RELAYS];
+ type = MESSENGER_STATE_TYPE_TCP_RELAY;
+ uint8_t *temp_data = data;
+ data = messenger_save_subheader(temp_data, 0, type);
+ unsigned int num = copy_connected_tcp_relays(m->net_crypto, relays, NUM_SAVED_TCP_RELAYS);
+ int l = pack_nodes(data, NUM_SAVED_TCP_RELAYS * packed_node_size(TCP_INET6), relays, num);
+
+ if (l > 0) {
+ len = l;
+ data = messenger_save_subheader(temp_data, len, type);
+ data += len;
+ }
+
+ Node_format nodes[NUM_SAVED_PATH_NODES];
+ type = MESSENGER_STATE_TYPE_PATH_NODE;
+ temp_data = data;
+ data = messenger_save_subheader(data, 0, type);
+ memset(nodes, 0, sizeof(nodes));
+ num = onion_backup_nodes(m->onion_c, nodes, NUM_SAVED_PATH_NODES);
+ l = pack_nodes(data, NUM_SAVED_PATH_NODES * packed_node_size(TCP_INET6), nodes, num);
+
+ if (l > 0) {
+ len = l;
+ data = messenger_save_subheader(temp_data, len, type);
+ data += len;
+ }
+
+ messenger_save_subheader(data, 0, MESSENGER_STATE_TYPE_END);
+}
+
+static int messenger_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type)
+{
+ Messenger *m = (Messenger *)outer;
+
+ switch (type) {
+ case MESSENGER_STATE_TYPE_NOSPAMKEYS:
+ if (length == CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE + sizeof(uint32_t)) {
+ set_nospam(&(m->fr), *(const uint32_t *)data);
+ load_secret_key(m->net_crypto, (&data[sizeof(uint32_t)]) + CRYPTO_PUBLIC_KEY_SIZE);
+
+ if (public_key_cmp((&data[sizeof(uint32_t)]), m->net_crypto->self_public_key) != 0) {
+ return -1;
+ }
+ } else {
+ return -1; /* critical */
+ }
+
+ break;
+
+ case MESSENGER_STATE_TYPE_DHT:
+ DHT_load(m->dht, data, length);
+ break;
+
+ case MESSENGER_STATE_TYPE_FRIENDS:
+ friends_list_load(m, data, length);
+ break;
+
+ case MESSENGER_STATE_TYPE_NAME:
+ if ((length > 0) && (length <= MAX_NAME_LENGTH)) {
+ setname(m, data, length);
+ }
+
+ break;
+
+ case MESSENGER_STATE_TYPE_STATUSMESSAGE:
+ if ((length > 0) && (length <= MAX_STATUSMESSAGE_LENGTH)) {
+ m_set_statusmessage(m, data, length);
+ }
+
+ break;
+
+ case MESSENGER_STATE_TYPE_STATUS:
+ if (length == 1) {
+ m_set_userstatus(m, *data);
+ }
+
+ break;
+
+ case MESSENGER_STATE_TYPE_TCP_RELAY: {
+ if (length == 0) {
+ break;
+ }
+
+ unpack_nodes(m->loaded_relays, NUM_SAVED_TCP_RELAYS, 0, data, length, 1);
+ m->has_added_relays = 0;
+
+ break;
+ }
+
+ case MESSENGER_STATE_TYPE_PATH_NODE: {
+ Node_format nodes[NUM_SAVED_PATH_NODES];
+
+ if (length == 0) {
+ break;
+ }
+
+ int i, num = unpack_nodes(nodes, NUM_SAVED_PATH_NODES, 0, data, length, 0);
+
+ for (i = 0; i < num; ++i) {
+ onion_add_bs_path_node(m->onion_c, nodes[i].ip_port, nodes[i].public_key);
+ }
+
+ break;
+ }
+
+ case MESSENGER_STATE_TYPE_END: {
+ if (length != 0) {
+ return -1;
+ }
+
+ return -2;
+ }
+
+ default:
+ LOGGER_ERROR(m->log, "Load state: contains unrecognized part (len %u, type %u)\n",
+ length, type);
+ break;
+ }
+
+ return 0;
+}
+
+/* Load the messenger from data of size length. */
+int messenger_load(Messenger *m, const uint8_t *data, uint32_t length)
+{
+ uint32_t data32[2];
+ uint32_t cookie_len = sizeof(data32);
+
+ if (length < cookie_len) {
+ return -1;
+ }
+
+ memcpy(data32, data, sizeof(uint32_t));
+ lendian_to_host32(data32 + 1, data + sizeof(uint32_t));
+
+ if (!data32[0] && (data32[1] == MESSENGER_STATE_COOKIE_GLOBAL)) {
+ return load_state(messenger_load_state_callback, m->log, m, data + cookie_len,
+ length - cookie_len, MESSENGER_STATE_COOKIE_TYPE);
+ }
+
+ return -1;
+}
+
+/* Return the number of friends in the instance m.
+ * You should use this to determine how much memory to allocate
+ * for copy_friendlist. */
+uint32_t count_friendlist(const Messenger *m)
+{
+ uint32_t ret = 0;
+ uint32_t i;
+
+ for (i = 0; i < m->numfriends; i++) {
+ if (m->friendlist[i].status > 0) {
+ ret++;
+ }
+ }
+
+ return ret;
+}
+
+/* Copy a list of valid friend IDs into the array out_list.
+ * If out_list is NULL, returns 0.
+ * Otherwise, returns the number of elements copied.
+ * If the array was too small, the contents
+ * of out_list will be truncated to list_size. */
+uint32_t copy_friendlist(Messenger const *m, uint32_t *out_list, uint32_t list_size)
+{
+ if (!out_list) {
+ return 0;
+ }
+
+ if (m->numfriends == 0) {
+ return 0;
+ }
+
+ uint32_t i;
+ uint32_t ret = 0;
+
+ for (i = 0; i < m->numfriends; i++) {
+ if (ret >= list_size) {
+ break; /* Abandon ship */
+ }
+
+ if (m->friendlist[i].status > 0) {
+ out_list[ret] = i;
+ ret++;
+ }
+ }
+
+ return ret;
+}
diff --git a/protocols/Tox/libtox/src/toxcore/Messenger.h b/protocols/Tox/libtox/src/toxcore/Messenger.h
new file mode 100644
index 0000000000..e1dba69886
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/Messenger.h
@@ -0,0 +1,777 @@
+/*
+ * An implementation of a simple text chat only messenger on the tox network
+ * core.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef MESSENGER_H
+#define MESSENGER_H
+
+#include "friend_connection.h"
+#include "friend_requests.h"
+#include "logger.h"
+
+#define MAX_NAME_LENGTH 128
+/* TODO(irungentoo): this must depend on other variable. */
+#define MAX_STATUSMESSAGE_LENGTH 1007
+/* Used for TCP relays in Messenger struct (may need to be % 2 == 0)*/
+#define NUM_SAVED_TCP_RELAYS 8
+/* This cannot be bigger than 256 */
+#define MAX_CONCURRENT_FILE_PIPES 256
+
+
+#define FRIEND_ADDRESS_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint32_t) + sizeof(uint16_t))
+
+enum {
+ MESSAGE_NORMAL,
+ MESSAGE_ACTION
+};
+
+/* NOTE: Packet ids below 24 must never be used. */
+#define PACKET_ID_ONLINE 24
+#define PACKET_ID_OFFLINE 25
+#define PACKET_ID_NICKNAME 48
+#define PACKET_ID_STATUSMESSAGE 49
+#define PACKET_ID_USERSTATUS 50
+#define PACKET_ID_TYPING 51
+#define PACKET_ID_MESSAGE 64
+#define PACKET_ID_ACTION (PACKET_ID_MESSAGE + MESSAGE_ACTION) /* 65 */
+#define PACKET_ID_MSI 69
+#define PACKET_ID_FILE_SENDREQUEST 80
+#define PACKET_ID_FILE_CONTROL 81
+#define PACKET_ID_FILE_DATA 82
+#define PACKET_ID_INVITE_CONFERENCE 96
+#define PACKET_ID_ONLINE_PACKET 97
+#define PACKET_ID_DIRECT_CONFERENCE 98
+#define PACKET_ID_MESSAGE_CONFERENCE 99
+#define PACKET_ID_LOSSY_CONFERENCE 199
+
+/* All packets starting with a byte in this range can be used for anything. */
+#define PACKET_ID_LOSSLESS_RANGE_START 160
+#define PACKET_ID_LOSSLESS_RANGE_SIZE 32
+#define PACKET_LOSSY_AV_RESERVED 8 /* Number of lossy packet types at start of range reserved for A/V. */
+
+typedef struct {
+ uint8_t ipv6enabled;
+ uint8_t udp_disabled;
+ TCP_Proxy_Info proxy_info;
+ uint16_t port_range[2];
+ uint16_t tcp_server_port;
+
+ uint8_t hole_punching_enabled;
+ bool local_discovery_enabled;
+
+ logger_cb *log_callback;
+ void *log_user_data;
+} Messenger_Options;
+
+
+struct Receipts {
+ uint32_t packet_num;
+ uint32_t msg_id;
+ struct Receipts *next;
+};
+
+/* Status definitions. */
+enum {
+ NOFRIEND,
+ FRIEND_ADDED,
+ FRIEND_REQUESTED,
+ FRIEND_CONFIRMED,
+ FRIEND_ONLINE,
+};
+
+/* Errors for m_addfriend
+ * FAERR - Friend Add Error
+ */
+enum {
+ FAERR_TOOLONG = -1,
+ FAERR_NOMESSAGE = -2,
+ FAERR_OWNKEY = -3,
+ FAERR_ALREADYSENT = -4,
+ FAERR_BADCHECKSUM = -6,
+ FAERR_SETNEWNOSPAM = -7,
+ FAERR_NOMEM = -8
+};
+
+
+/* Default start timeout in seconds between friend requests. */
+#define FRIENDREQUEST_TIMEOUT 5;
+
+enum {
+ CONNECTION_NONE,
+ CONNECTION_TCP,
+ CONNECTION_UDP,
+ CONNECTION_UNKNOWN
+};
+
+/* USERSTATUS -
+ * Represents userstatuses someone can have.
+ */
+
+typedef enum {
+ USERSTATUS_NONE,
+ USERSTATUS_AWAY,
+ USERSTATUS_BUSY,
+ USERSTATUS_INVALID
+}
+USERSTATUS;
+
+#define FILE_ID_LENGTH 32
+
+struct File_Transfers {
+ uint64_t size;
+ uint64_t transferred;
+ uint8_t status; /* 0 == no transfer, 1 = not accepted, 3 = transferring, 4 = broken, 5 = finished */
+ uint8_t paused; /* 0: not paused, 1 = paused by us, 2 = paused by other, 3 = paused by both. */
+ uint32_t last_packet_number; /* number of the last packet sent. */
+ uint64_t requested; /* total data requested by the request chunk callback */
+ unsigned int slots_allocated; /* number of slots allocated to this transfer. */
+ uint8_t id[FILE_ID_LENGTH];
+};
+enum {
+ FILESTATUS_NONE,
+ FILESTATUS_NOT_ACCEPTED,
+ FILESTATUS_TRANSFERRING,
+ //FILESTATUS_BROKEN,
+ FILESTATUS_FINISHED
+};
+
+enum {
+ FILE_PAUSE_NOT,
+ FILE_PAUSE_US,
+ FILE_PAUSE_OTHER,
+ FILE_PAUSE_BOTH
+};
+
+enum {
+ FILECONTROL_ACCEPT,
+ FILECONTROL_PAUSE,
+ FILECONTROL_KILL,
+ FILECONTROL_SEEK
+};
+
+enum {
+ FILEKIND_DATA,
+ FILEKIND_AVATAR
+};
+
+
+typedef struct Messenger Messenger;
+
+typedef struct {
+ uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ int friendcon_id;
+
+ uint64_t friendrequest_lastsent; // Time at which the last friend request was sent.
+ uint32_t friendrequest_timeout; // The timeout between successful friendrequest sending attempts.
+ uint8_t status; // 0 if no friend, 1 if added, 2 if friend request sent, 3 if confirmed friend, 4 if online.
+ uint8_t info[MAX_FRIEND_REQUEST_DATA_SIZE]; // the data that is sent during the friend requests we do.
+ uint8_t name[MAX_NAME_LENGTH];
+ uint16_t name_length;
+ uint8_t name_sent; // 0 if we didn't send our name to this friend 1 if we have.
+ uint8_t statusmessage[MAX_STATUSMESSAGE_LENGTH];
+ uint16_t statusmessage_length;
+ uint8_t statusmessage_sent;
+ USERSTATUS userstatus;
+ uint8_t userstatus_sent;
+ uint8_t user_istyping;
+ uint8_t user_istyping_sent;
+ uint8_t is_typing;
+ uint16_t info_size; // Length of the info.
+ uint32_t message_id; // a semi-unique id used in read receipts.
+ uint32_t friendrequest_nospam; // The nospam number used in the friend request.
+ uint64_t last_seen_time;
+ uint8_t last_connection_udp_tcp;
+ struct File_Transfers file_sending[MAX_CONCURRENT_FILE_PIPES];
+ unsigned int num_sending_files;
+ struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES];
+
+ struct {
+ int (*function)(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t len, void *object);
+ void *object;
+ } lossy_rtp_packethandlers[PACKET_LOSSY_AV_RESERVED];
+
+ struct Receipts *receipts_start;
+ struct Receipts *receipts_end;
+} Friend;
+
+struct Messenger {
+ Logger *log;
+
+ Networking_Core *net;
+ Net_Crypto *net_crypto;
+ DHT *dht;
+
+ Onion *onion;
+ Onion_Announce *onion_a;
+ Onion_Client *onion_c;
+
+ Friend_Connections *fr_c;
+
+ TCP_Server *tcp_server;
+ Friend_Requests fr;
+ uint8_t name[MAX_NAME_LENGTH];
+ uint16_t name_length;
+
+ uint8_t statusmessage[MAX_STATUSMESSAGE_LENGTH];
+ uint16_t statusmessage_length;
+
+ USERSTATUS userstatus;
+
+ Friend *friendlist;
+ uint32_t numfriends;
+
+ time_t lastdump;
+
+ uint8_t has_added_relays; // If the first connection has occurred in do_messenger
+ Node_format loaded_relays[NUM_SAVED_TCP_RELAYS]; // Relays loaded from config
+
+ void (*friend_message)(struct Messenger *m, uint32_t, unsigned int, const uint8_t *, size_t, void *);
+ void (*friend_namechange)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *);
+ void (*friend_statusmessagechange)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *);
+ void (*friend_userstatuschange)(struct Messenger *m, uint32_t, unsigned int, void *);
+ void (*friend_typingchange)(struct Messenger *m, uint32_t, bool, void *);
+ void (*read_receipt)(struct Messenger *m, uint32_t, uint32_t, void *);
+ void (*friend_connectionstatuschange)(struct Messenger *m, uint32_t, unsigned int, void *);
+ void (*friend_connectionstatuschange_internal)(struct Messenger *m, uint32_t, uint8_t, void *);
+ void *friend_connectionstatuschange_internal_userdata;
+
+ void *conferences_object; /* Set by new_groupchats()*/
+ void (*conference_invite)(struct Messenger *m, uint32_t, const uint8_t *, uint16_t, void *);
+
+ void (*file_sendrequest)(struct Messenger *m, uint32_t, uint32_t, uint32_t, uint64_t, const uint8_t *, size_t,
+ void *);
+ void (*file_filecontrol)(struct Messenger *m, uint32_t, uint32_t, unsigned int, void *);
+ void (*file_filedata)(struct Messenger *m, uint32_t, uint32_t, uint64_t, const uint8_t *, size_t, void *);
+ void (*file_reqchunk)(struct Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *);
+
+ void (*msi_packet)(struct Messenger *m, uint32_t, const uint8_t *, uint16_t, void *);
+ void *msi_packet_userdata;
+
+ void (*lossy_packethandler)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *);
+ void (*lossless_packethandler)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *);
+
+ void (*core_connection_change)(struct Messenger *m, unsigned int, void *);
+ unsigned int last_connection_status;
+
+ Messenger_Options options;
+};
+
+/* Format: [real_pk (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
+ *
+ * return FRIEND_ADDRESS_SIZE byte address to give to others.
+ */
+void getaddress(const Messenger *m, uint8_t *address);
+
+/* Add a friend.
+ * Set the data that will be sent along with friend request.
+ * address is the address of the friend (returned by getaddress of the friend
+ * you wish to add) it must be FRIEND_ADDRESS_SIZE bytes.
+ * TODO(irungentoo): add checksum.
+ * data is the data and length is the length.
+ *
+ * return the friend number if success.
+ * return -1 if message length is too long.
+ * return -2 if no message (message length must be >= 1 byte).
+ * return -3 if user's own key.
+ * return -4 if friend request already sent or already a friend.
+ * return -6 if bad checksum in address.
+ * return -7 if the friend was already there but the nospam was different.
+ * (the nospam for that friend was set to the new one).
+ * return -8 if increasing the friend list size fails.
+ */
+int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, uint16_t length);
+
+
+/* Add a friend without sending a friendrequest.
+ * return the friend number if success.
+ * return -3 if user's own key.
+ * return -4 if friend request already sent or already a friend.
+ * return -6 if bad checksum in address.
+ * return -8 if increasing the friend list size fails.
+ */
+int32_t m_addfriend_norequest(Messenger *m, const uint8_t *real_pk);
+
+/* return the friend number associated to that client id.
+ * return -1 if no such friend.
+ */
+int32_t getfriend_id(const Messenger *m, const uint8_t *real_pk);
+
+/* Copies the public key associated to that friend id into real_pk buffer.
+ * Make sure that real_pk is of size CRYPTO_PUBLIC_KEY_SIZE.
+ *
+ * return 0 if success
+ * return -1 if failure
+ */
+int get_real_pk(const Messenger *m, int32_t friendnumber, uint8_t *real_pk);
+
+/* return friend connection id on success.
+ * return -1 if failure.
+ */
+int getfriendcon_id(const Messenger *m, int32_t friendnumber);
+
+/* Remove a friend.
+ *
+ * return 0 if success
+ * return -1 if failure
+ */
+int m_delfriend(Messenger *m, int32_t friendnumber);
+
+/* Checks friend's connecting status.
+ *
+ * return CONNECTION_UDP (2) if friend is directly connected to us (Online UDP).
+ * return CONNECTION_TCP (1) if friend is connected to us (Online TCP).
+ * return CONNECTION_NONE (0) if friend is not connected to us (Offline).
+ * return -1 on failure.
+ */
+int m_get_friend_connectionstatus(const Messenger *m, int32_t friendnumber);
+
+/* Checks if there exists a friend with given friendnumber.
+ *
+ * return 1 if friend exists.
+ * return 0 if friend doesn't exist.
+ */
+int m_friend_exists(const Messenger *m, int32_t friendnumber);
+
+/* Send a message of type to an online friend.
+ *
+ * return -1 if friend not valid.
+ * return -2 if too large.
+ * return -3 if friend not online.
+ * return -4 if send failed (because queue is full).
+ * return -5 if bad type.
+ * return 0 if success.
+ *
+ * the value in message_id will be passed to your read_receipt callback when the other receives the message.
+ */
+int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, const uint8_t *message, uint32_t length,
+ uint32_t *message_id);
+
+
+/* Set the name and name_length of a friend.
+ * name must be a string of maximum MAX_NAME_LENGTH length.
+ * length must be at least 1 byte.
+ * length is the length of name with the NULL terminator.
+ *
+ * return 0 if success.
+ * return -1 if failure.
+ */
+int setfriendname(Messenger *m, int32_t friendnumber, const uint8_t *name, uint16_t length);
+
+/* Set our nickname.
+ * name must be a string of maximum MAX_NAME_LENGTH length.
+ * length must be at least 1 byte.
+ * length is the length of name with the NULL terminator.
+ *
+ * return 0 if success.
+ * return -1 if failure.
+ */
+int setname(Messenger *m, const uint8_t *name, uint16_t length);
+
+/*
+ * Get your nickname.
+ * m - The messenger context to use.
+ * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
+ *
+ * return length of the name.
+ * return 0 on error.
+ */
+uint16_t getself_name(const Messenger *m, uint8_t *name);
+
+/* Get name of friendnumber and put it in name.
+ * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
+ *
+ * return length of name if success.
+ * return -1 if failure.
+ */
+int getname(const Messenger *m, int32_t friendnumber, uint8_t *name);
+
+/* return the length of name, including null on success.
+ * return -1 on failure.
+ */
+int m_get_name_size(const Messenger *m, int32_t friendnumber);
+int m_get_self_name_size(const Messenger *m);
+
+/* Set our user status.
+ * You are responsible for freeing status after.
+ *
+ * returns 0 on success.
+ * returns -1 on failure.
+ */
+int m_set_statusmessage(Messenger *m, const uint8_t *status, uint16_t length);
+int m_set_userstatus(Messenger *m, uint8_t status);
+
+/* return the length of friendnumber's status message, including null on success.
+ * return -1 on failure.
+ */
+int m_get_statusmessage_size(const Messenger *m, int32_t friendnumber);
+int m_get_self_statusmessage_size(const Messenger *m);
+
+/* Copy friendnumber's status message into buf, truncating if size is over maxlen.
+ * Get the size you need to allocate from m_get_statusmessage_size.
+ * The self variant will copy our own status message.
+ *
+ * returns the length of the copied data on success
+ * retruns -1 on failure.
+ */
+int m_copy_statusmessage(const Messenger *m, int32_t friendnumber, uint8_t *buf, uint32_t maxlen);
+int m_copy_self_statusmessage(const Messenger *m, uint8_t *buf);
+
+/* return one of USERSTATUS values.
+ * Values unknown to your application should be represented as USERSTATUS_NONE.
+ * As above, the self variant will return our own USERSTATUS.
+ * If friendnumber is invalid, this shall return USERSTATUS_INVALID.
+ */
+uint8_t m_get_userstatus(const Messenger *m, int32_t friendnumber);
+uint8_t m_get_self_userstatus(const Messenger *m);
+
+
+/* returns timestamp of last time friendnumber was seen online or 0 if never seen.
+ * if friendnumber is invalid this function will return UINT64_MAX.
+ */
+uint64_t m_get_last_online(const Messenger *m, int32_t friendnumber);
+
+/* Set our typing status for a friend.
+ * You are responsible for turning it on or off.
+ *
+ * returns 0 on success.
+ * returns -1 on failure.
+ */
+int m_set_usertyping(Messenger *m, int32_t friendnumber, uint8_t is_typing);
+
+/* Get the typing status of a friend.
+ *
+ * returns 0 if friend is not typing.
+ * returns 1 if friend is typing.
+ */
+int m_get_istyping(const Messenger *m, int32_t friendnumber);
+
+/* Set the logger callback.
+ */
+void m_callback_log(Messenger *m, logger_cb *function, void *context, void *userdata);
+
+/* Set the function that will be executed when a friend request is received.
+ * Function format is function(uint8_t * public_key, uint8_t * data, size_t length)
+ */
+void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const uint8_t *, const uint8_t *, size_t,
+ void *));
+
+/* Set the function that will be executed when a message from a friend is received.
+ * Function format is: function(uint32_t friendnumber, unsigned int type, uint8_t * message, uint32_t length)
+ */
+void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, const uint8_t *,
+ size_t, void *));
+
+/* Set the callback for name changes.
+ * Function(uint32_t friendnumber, uint8_t *newname, size_t length)
+ * You are not responsible for freeing newname.
+ */
+void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *));
+
+/* Set the callback for status message changes.
+ * Function(uint32_t friendnumber, uint8_t *newstatus, size_t length)
+ *
+ * You are not responsible for freeing newstatus
+ */
+void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *));
+
+/* Set the callback for status type changes.
+ * Function(uint32_t friendnumber, USERSTATUS kind)
+ */
+void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *));
+
+/* Set the callback for typing changes.
+ * Function(uint32_t friendnumber, uint8_t is_typing)
+ */
+void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, uint32_t, bool, void *));
+
+/* Set the callback for read receipts.
+ * Function(uint32_t friendnumber, uint32_t receipt)
+ *
+ * If you are keeping a record of returns from m_sendmessage,
+ * receipt might be one of those values, meaning the message
+ * has been received on the other side.
+ * Since core doesn't track ids for you, receipt may not correspond to any message.
+ * In that case, you should discard it.
+ */
+void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, void *));
+
+/* Set the callback for connection status changes.
+ * function(uint32_t friendnumber, uint8_t status)
+ *
+ * Status:
+ * 0 -- friend went offline after being previously online.
+ * 1 -- friend went online.
+ *
+ * Note that this callback is not called when adding friends, thus the "after
+ * being previously online" part.
+ * It's assumed that when adding friends, their connection status is offline.
+ */
+void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *));
+
+/* Same as previous but for internal A/V core usage only */
+void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, void *),
+ void *userdata);
+
+
+/* Set the callback for typing changes.
+ * Function(unsigned int connection_status (0 = not connected, 1 = TCP only, 2 = UDP + TCP))
+ */
+void m_callback_core_connection(Messenger *m, void (*function)(Messenger *m, unsigned int, void *));
+
+/**********CONFERENCES************/
+
+/* Set the callback for conference invites.
+ *
+ * Function(Messenger *m, uint32_t friendnumber, uint8_t *data, uint16_t length, void *userdata)
+ */
+void m_callback_conference_invite(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, uint16_t,
+ void *));
+
+/* Send a conference invite packet.
+ *
+ * return 1 on success
+ * return 0 on failure
+ */
+int send_conference_invite_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length);
+
+/****************FILE SENDING*****************/
+
+
+/* Set the callback for file send requests.
+ *
+ * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint32_t filetype, uint64_t filesize, uint8_t *filename, size_t filename_length, void *userdata)
+ */
+void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint32_t, uint64_t,
+ const uint8_t *, size_t, void *));
+
+
+/* Set the callback for file control requests.
+ *
+ * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, unsigned int control_type, void *userdata)
+ *
+ */
+void callback_file_control(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, unsigned int, void *));
+
+/* Set the callback for file data.
+ *
+ * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, uint8_t *data, size_t length, void *userdata)
+ *
+ */
+void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, const uint8_t *,
+ size_t, void *));
+
+/* Set the callback for file request chunk.
+ *
+ * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length, void *userdata)
+ *
+ */
+void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *));
+
+
+/* Copy the file transfer file id to file_id
+ *
+ * return 0 on success.
+ * return -1 if friend not valid.
+ * return -2 if filenumber not valid
+ */
+int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint8_t *file_id);
+
+/* Send a file send request.
+ * Maximum filename length is 255 bytes.
+ * return file number on success
+ * return -1 if friend not found.
+ * return -2 if filename length invalid.
+ * return -3 if no more file sending slots left.
+ * return -4 if could not send packet (friend offline).
+ *
+ */
+long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_type, uint64_t filesize,
+ const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length);
+
+/* Send a file control request.
+ *
+ * return 0 on success
+ * return -1 if friend not valid.
+ * return -2 if friend not online.
+ * return -3 if file number invalid.
+ * return -4 if file control is bad.
+ * return -5 if file already paused.
+ * return -6 if resume file failed because it was only paused by the other.
+ * return -7 if resume file failed because it wasn't paused.
+ * return -8 if packet failed to send.
+ */
+int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber, unsigned int control);
+
+/* Send a seek file control request.
+ *
+ * return 0 on success
+ * return -1 if friend not valid.
+ * return -2 if friend not online.
+ * return -3 if file number invalid.
+ * return -4 if not receiving file.
+ * return -5 if file status wrong.
+ * return -6 if position bad.
+ * return -8 if packet failed to send.
+ */
+int file_seek(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position);
+
+/* Send file data.
+ *
+ * return 0 on success
+ * return -1 if friend not valid.
+ * return -2 if friend not online.
+ * return -3 if filenumber invalid.
+ * return -4 if file transfer not transferring.
+ * return -5 if bad data size.
+ * return -6 if packet queue full.
+ * return -7 if wrong position.
+ */
+int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
+ uint16_t length);
+
+/* Give the number of bytes left to be sent/received.
+ *
+ * send_receive is 0 if we want the sending files, 1 if we want the receiving.
+ *
+ * return number of bytes remaining to be sent/received on success
+ * return 0 on failure
+ */
+uint64_t file_dataremaining(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t send_receive);
+
+/*************** A/V related ******************/
+
+/* Set the callback for msi packets.
+ *
+ * Function(Messenger *m, uint32_t friendnumber, uint8_t *data, uint16_t length, void *userdata)
+ */
+void m_callback_msi_packet(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, uint16_t, void *),
+ void *userdata);
+
+/* Send an msi packet.
+ *
+ * return 1 on success
+ * return 0 on failure
+ */
+int m_msi_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length);
+
+/* Set handlers for lossy rtp packets.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte, int (*packet_handler_callback)(Messenger *m,
+ uint32_t friendnumber, const uint8_t *data, uint16_t len, void *object), void *object);
+
+/**********************************************/
+
+/* Set handlers for custom lossy packets.
+ *
+ */
+void custom_lossy_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m,
+ uint32_t friendnumber, const uint8_t *data, size_t len, void *object));
+
+/* High level function to send custom lossy packets.
+ *
+ * return -1 if friend invalid.
+ * return -2 if length wrong.
+ * return -3 if first byte invalid.
+ * return -4 if friend offline.
+ * return -5 if packet failed to send because of other error.
+ * return 0 on success.
+ */
+int m_send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length);
+
+
+/* Set handlers for custom lossless packets.
+ *
+ */
+void custom_lossless_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m,
+ uint32_t friendnumber, const uint8_t *data, size_t len, void *object));
+
+/* High level function to send custom lossless packets.
+ *
+ * return -1 if friend invalid.
+ * return -2 if length wrong.
+ * return -3 if first byte invalid.
+ * return -4 if friend offline.
+ * return -5 if packet failed to send because of other error.
+ * return 0 on success.
+ */
+int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length);
+
+/**********************************************/
+
+enum {
+ MESSENGER_ERROR_NONE,
+ MESSENGER_ERROR_PORT,
+ MESSENGER_ERROR_TCP_SERVER,
+ MESSENGER_ERROR_OTHER
+};
+
+/* Run this at startup.
+ * return allocated instance of Messenger on success.
+ * return 0 if there are problems.
+ *
+ * if error is not NULL it will be set to one of the values in the enum above.
+ */
+Messenger *new_messenger(Messenger_Options *options, unsigned int *error);
+
+/* Run this before closing shop
+ * Free all datastructures.
+ */
+void kill_messenger(Messenger *m);
+
+/* The main loop that needs to be run at least 20 times per second. */
+void do_messenger(Messenger *m, void *userdata);
+
+/* Return the time in milliseconds before do_messenger() should be called again
+ * for optimal performance.
+ *
+ * returns time (in ms) before the next do_messenger() needs to be run on success.
+ */
+uint32_t messenger_run_interval(const Messenger *m);
+
+/* SAVING AND LOADING FUNCTIONS: */
+
+/* return size of the messenger data (for saving). */
+uint32_t messenger_size(const Messenger *m);
+
+/* Save the messenger in data (must be allocated memory of size Messenger_size()) */
+void messenger_save(const Messenger *m, uint8_t *data);
+
+/* Load the messenger from data of size length. */
+int messenger_load(Messenger *m, const uint8_t *data, uint32_t length);
+
+/* Return the number of friends in the instance m.
+ * You should use this to determine how much memory to allocate
+ * for copy_friendlist. */
+uint32_t count_friendlist(const Messenger *m);
+
+/* Copy a list of valid friend IDs into the array out_list.
+ * If out_list is NULL, returns 0.
+ * Otherwise, returns the number of elements copied.
+ * If the array was too small, the contents
+ * of out_list will be truncated to list_size. */
+uint32_t copy_friendlist(const Messenger *m, uint32_t *out_list, uint32_t list_size);
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_client.c b/protocols/Tox/libtox/src/toxcore/TCP_client.c
new file mode 100644
index 0000000000..8a14c7cd70
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/TCP_client.c
@@ -0,0 +1,991 @@
+/*
+ * Implementation of the TCP relay client part of Tox.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2014 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "TCP_client.h"
+
+#include "util.h"
+
+#if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32)
+#include <sys/ioctl.h>
+#endif
+
+/* return 1 on success
+ * return 0 on failure
+ */
+static int connect_sock_to(Socket sock, IP_Port ip_port, TCP_Proxy_Info *proxy_info)
+{
+ if (proxy_info->proxy_type != TCP_PROXY_NONE) {
+ ip_port = proxy_info->ip_port;
+ }
+
+ /* nonblocking socket, connect will never return success */
+ net_connect(sock, ip_port);
+ return 1;
+}
+
+/* return 1 on success.
+ * return 0 on failure.
+ */
+static int proxy_http_generate_connection_request(TCP_Client_Connection *TCP_conn)
+{
+ char one[] = "CONNECT ";
+ char two[] = " HTTP/1.1\nHost: ";
+ char three[] = "\r\n\r\n";
+
+ char ip[TOX_INET6_ADDRSTRLEN];
+
+ if (!ip_parse_addr(&TCP_conn->ip_port.ip, ip, sizeof(ip))) {
+ return 0;
+ }
+
+ const uint16_t port = net_ntohs(TCP_conn->ip_port.port);
+ const int written = snprintf((char *)TCP_conn->last_packet, MAX_PACKET_SIZE, "%s%s:%hu%s%s:%hu%s", one, ip, port, two,
+ ip, port, three);
+
+ if (written < 0 || MAX_PACKET_SIZE < written) {
+ return 0;
+ }
+
+ TCP_conn->last_packet_length = written;
+ TCP_conn->last_packet_sent = 0;
+
+ return 1;
+}
+
+/* return 1 on success.
+ * return 0 if no data received.
+ * return -1 on failure (connection refused).
+ */
+static int proxy_http_read_connection_response(TCP_Client_Connection *TCP_conn)
+{
+ char success[] = "200";
+ uint8_t data[16]; // draining works the best if the length is a power of 2
+
+ int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data) - 1);
+
+ if (ret == -1) {
+ return 0;
+ }
+
+ data[sizeof(data) - 1] = 0;
+
+ if (strstr((char *)data, success)) {
+ // drain all data
+ unsigned int data_left = TCP_socket_data_recv_buffer(TCP_conn->sock);
+
+ if (data_left) {
+ VLA(uint8_t, temp_data, data_left);
+ read_TCP_packet(TCP_conn->sock, temp_data, data_left);
+ }
+
+ return 1;
+ }
+
+ return -1;
+}
+
+static void proxy_socks5_generate_handshake(TCP_Client_Connection *TCP_conn)
+{
+ TCP_conn->last_packet[0] = 5; /* SOCKSv5 */
+ TCP_conn->last_packet[1] = 1; /* number of authentication methods supported */
+ TCP_conn->last_packet[2] = 0; /* No authentication */
+
+ TCP_conn->last_packet_length = 3;
+ TCP_conn->last_packet_sent = 0;
+}
+
+/* return 1 on success.
+ * return 0 if no data received.
+ * return -1 on failure (connection refused).
+ */
+static int socks5_read_handshake_response(TCP_Client_Connection *TCP_conn)
+{
+ uint8_t data[2];
+ int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data));
+
+ if (ret == -1) {
+ return 0;
+ }
+
+ if (data[0] == 5 && data[1] == 0) { // TODO(irungentoo): magic numbers
+ return 1;
+ }
+
+ return -1;
+}
+
+static void proxy_socks5_generate_connection_request(TCP_Client_Connection *TCP_conn)
+{
+ TCP_conn->last_packet[0] = 5; /* SOCKSv5 */
+ TCP_conn->last_packet[1] = 1; /* command code: establish a TCP/IP stream connection */
+ TCP_conn->last_packet[2] = 0; /* reserved, must be 0 */
+ uint16_t length = 3;
+
+ if (TCP_conn->ip_port.ip.family == TOX_AF_INET) {
+ TCP_conn->last_packet[3] = 1; /* IPv4 address */
+ ++length;
+ memcpy(TCP_conn->last_packet + length, TCP_conn->ip_port.ip.ip4.uint8, sizeof(IP4));
+ length += sizeof(IP4);
+ } else {
+ TCP_conn->last_packet[3] = 4; /* IPv6 address */
+ ++length;
+ memcpy(TCP_conn->last_packet + length, TCP_conn->ip_port.ip.ip6.uint8, sizeof(IP6));
+ length += sizeof(IP6);
+ }
+
+ memcpy(TCP_conn->last_packet + length, &TCP_conn->ip_port.port, sizeof(uint16_t));
+ length += sizeof(uint16_t);
+
+ TCP_conn->last_packet_length = length;
+ TCP_conn->last_packet_sent = 0;
+}
+
+/* return 1 on success.
+ * return 0 if no data received.
+ * return -1 on failure (connection refused).
+ */
+static int proxy_socks5_read_connection_response(TCP_Client_Connection *TCP_conn)
+{
+ if (TCP_conn->ip_port.ip.family == TOX_AF_INET) {
+ uint8_t data[4 + sizeof(IP4) + sizeof(uint16_t)];
+ int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data));
+
+ if (ret == -1) {
+ return 0;
+ }
+
+ if (data[0] == 5 && data[1] == 0) {
+ return 1;
+ }
+ } else {
+ uint8_t data[4 + sizeof(IP6) + sizeof(uint16_t)];
+ int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data));
+
+ if (ret == -1) {
+ return 0;
+ }
+
+ if (data[0] == 5 && data[1] == 0) {
+ return 1;
+ }
+ }
+
+ return -1;
+}
+
+/* return 0 on success.
+ * return -1 on failure.
+ */
+static int generate_handshake(TCP_Client_Connection *TCP_conn)
+{
+ uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE];
+ crypto_new_keypair(plain, TCP_conn->temp_secret_key);
+ random_nonce(TCP_conn->sent_nonce);
+ memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, TCP_conn->sent_nonce, CRYPTO_NONCE_SIZE);
+ memcpy(TCP_conn->last_packet, TCP_conn->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ random_nonce(TCP_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE);
+ int len = encrypt_data_symmetric(TCP_conn->shared_key, TCP_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain,
+ sizeof(plain), TCP_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
+
+ if (len != sizeof(plain) + CRYPTO_MAC_SIZE) {
+ return -1;
+ }
+
+ TCP_conn->last_packet_length = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE;
+ TCP_conn->last_packet_sent = 0;
+ return 0;
+}
+
+/* data must be of length TCP_SERVER_HANDSHAKE_SIZE
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+static int handle_handshake(TCP_Client_Connection *TCP_conn, const uint8_t *data)
+{
+ uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE];
+ int len = decrypt_data_symmetric(TCP_conn->shared_key, data, data + CRYPTO_NONCE_SIZE,
+ TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, plain);
+
+ if (len != sizeof(plain)) {
+ return -1;
+ }
+
+ memcpy(TCP_conn->recv_nonce, plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_NONCE_SIZE);
+ encrypt_precompute(plain, TCP_conn->temp_secret_key, TCP_conn->shared_key);
+ crypto_memzero(TCP_conn->temp_secret_key, CRYPTO_SECRET_KEY_SIZE);
+ return 0;
+}
+
+/* return 0 if pending data was sent completely
+ * return -1 if it wasn't
+ */
+static int client_send_pending_data_nonpriority(TCP_Client_Connection *con)
+{
+ if (con->last_packet_length == 0) {
+ return 0;
+ }
+
+ uint16_t left = con->last_packet_length - con->last_packet_sent;
+ const char *data = (const char *)(con->last_packet + con->last_packet_sent);
+ int len = send(con->sock, data, left, MSG_NOSIGNAL);
+
+ if (len <= 0) {
+ return -1;
+ }
+
+ if (len == left) {
+ con->last_packet_length = 0;
+ con->last_packet_sent = 0;
+ return 0;
+ }
+
+ con->last_packet_sent += len;
+ return -1;
+}
+
+/* return 0 if pending data was sent completely
+ * return -1 if it wasn't
+ */
+static int client_send_pending_data(TCP_Client_Connection *con)
+{
+ /* finish sending current non-priority packet */
+ if (client_send_pending_data_nonpriority(con) == -1) {
+ return -1;
+ }
+
+ TCP_Priority_List *p = con->priority_queue_start;
+
+ while (p) {
+ uint16_t left = p->size - p->sent;
+ int len = send(con->sock, (const char *)(p->data + p->sent), left, MSG_NOSIGNAL);
+
+ if (len != left) {
+ if (len > 0) {
+ p->sent += len;
+ }
+
+ break;
+ }
+
+ TCP_Priority_List *pp = p;
+ p = p->next;
+ free(pp);
+ }
+
+ con->priority_queue_start = p;
+
+ if (!p) {
+ con->priority_queue_end = NULL;
+ return 0;
+ }
+
+ return -1;
+}
+
+/* return 0 on failure (only if malloc fails)
+ * return 1 on success
+ */
+static bool client_add_priority(TCP_Client_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent)
+{
+ TCP_Priority_List *p = con->priority_queue_end;
+ TCP_Priority_List *new_list = (TCP_Priority_List *)malloc(sizeof(TCP_Priority_List) + size);
+
+ if (!new_list) {
+ return 0;
+ }
+
+ new_list->next = NULL;
+ new_list->size = size;
+ new_list->sent = sent;
+ memcpy(new_list->data, packet, size);
+
+ if (p) {
+ p->next = new_list;
+ } else {
+ con->priority_queue_start = new_list;
+ }
+
+ con->priority_queue_end = new_list;
+ return 1;
+}
+
+static void wipe_priority_list(TCP_Client_Connection *con)
+{
+ TCP_Priority_List *p = con->priority_queue_start;
+
+ while (p) {
+ TCP_Priority_List *pp = p;
+ p = p->next;
+ free(pp);
+ }
+}
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure (connection must be killed).
+ */
+static int write_packet_TCP_client_secure_connection(TCP_Client_Connection *con, const uint8_t *data, uint16_t length,
+ bool priority)
+{
+ if (length + CRYPTO_MAC_SIZE > MAX_PACKET_SIZE) {
+ return -1;
+ }
+
+ bool sendpriority = 1;
+
+ if (client_send_pending_data(con) == -1) {
+ if (priority) {
+ sendpriority = 0;
+ } else {
+ return 0;
+ }
+ }
+
+ VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE);
+
+ uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE);
+ memcpy(packet, &c_length, sizeof(uint16_t));
+ int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));
+
+ if ((unsigned int)len != (SIZEOF_VLA(packet) - sizeof(uint16_t))) {
+ return -1;
+ }
+
+ if (priority) {
+ len = sendpriority ? send(con->sock, (const char *)packet, SIZEOF_VLA(packet), MSG_NOSIGNAL) : 0;
+
+ if (len <= 0) {
+ len = 0;
+ }
+
+ increment_nonce(con->sent_nonce);
+
+ if ((unsigned int)len == SIZEOF_VLA(packet)) {
+ return 1;
+ }
+
+ return client_add_priority(con, packet, SIZEOF_VLA(packet), len);
+ }
+
+ len = send(con->sock, (const char *)packet, SIZEOF_VLA(packet), MSG_NOSIGNAL);
+
+ if (len <= 0) {
+ return 0;
+ }
+
+ increment_nonce(con->sent_nonce);
+
+ if ((unsigned int)len == SIZEOF_VLA(packet)) {
+ return 1;
+ }
+
+ memcpy(con->last_packet, packet, SIZEOF_VLA(packet));
+ con->last_packet_length = SIZEOF_VLA(packet);
+ con->last_packet_sent = len;
+ return 1;
+}
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure (connection must be killed).
+ */
+int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key)
+{
+ uint8_t packet[1 + CRYPTO_PUBLIC_KEY_SIZE];
+ packet[0] = TCP_PACKET_ROUTING_REQUEST;
+ memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ return write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1);
+}
+
+void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id,
+ const uint8_t *public_key), void *object)
+{
+ con->response_callback = response_callback;
+ con->response_callback_object = object;
+}
+
+void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint32_t number,
+ uint8_t connection_id, uint8_t status), void *object)
+{
+ con->status_callback = status_callback;
+ con->status_callback_object = object;
+}
+
+static int tcp_send_ping_response(TCP_Client_Connection *con);
+static int tcp_send_ping_request(TCP_Client_Connection *con);
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure.
+ */
+int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length)
+{
+ if (con_id >= NUM_CLIENT_CONNECTIONS) {
+ return -1;
+ }
+
+ if (con->connections[con_id].status != 2) {
+ return -1;
+ }
+
+ if (tcp_send_ping_response(con) == 0 || tcp_send_ping_request(con) == 0) {
+ return 0;
+ }
+
+ VLA(uint8_t, packet, 1 + length);
+ packet[0] = con_id + NUM_RESERVED_PORTS;
+ memcpy(packet + 1, data, length);
+ return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0);
+}
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure.
+ */
+int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, uint16_t length)
+{
+ if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) {
+ return -1;
+ }
+
+ VLA(uint8_t, packet, 1 + CRYPTO_PUBLIC_KEY_SIZE + length);
+ packet[0] = TCP_PACKET_OOB_SEND;
+ memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length);
+ return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0);
+}
+
+
+/* Set the number that will be used as an argument in the callbacks related to con_id.
+ *
+ * When not set by this function, the number is ~0.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32_t number)
+{
+ if (con_id >= NUM_CLIENT_CONNECTIONS) {
+ return -1;
+ }
+
+ if (con->connections[con_id].status == 0) {
+ return -1;
+ }
+
+ con->connections[con_id].number = number;
+ return 0;
+}
+
+void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number,
+ uint8_t connection_id, const uint8_t *data, uint16_t length, void *userdata), void *object)
+{
+ con->data_callback = data_callback;
+ con->data_callback_object = object;
+}
+
+void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, const uint8_t *public_key,
+ const uint8_t *data, uint16_t length, void *userdata), void *object)
+{
+ con->oob_data_callback = oob_data_callback;
+ con->oob_data_callback_object = object;
+}
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure (connection must be killed).
+ */
+static int client_send_disconnect_notification(TCP_Client_Connection *con, uint8_t id)
+{
+ uint8_t packet[1 + 1];
+ packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION;
+ packet[1] = id;
+ return write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1);
+}
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure (connection must be killed).
+ */
+static int tcp_send_ping_request(TCP_Client_Connection *con)
+{
+ if (!con->ping_request_id) {
+ return 1;
+ }
+
+ uint8_t packet[1 + sizeof(uint64_t)];
+ packet[0] = TCP_PACKET_PING;
+ memcpy(packet + 1, &con->ping_request_id, sizeof(uint64_t));
+ int ret;
+
+ if ((ret = write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1)) == 1) {
+ con->ping_request_id = 0;
+ }
+
+ return ret;
+}
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure (connection must be killed).
+ */
+static int tcp_send_ping_response(TCP_Client_Connection *con)
+{
+ if (!con->ping_response_id) {
+ return 1;
+ }
+
+ uint8_t packet[1 + sizeof(uint64_t)];
+ packet[0] = TCP_PACKET_PONG;
+ memcpy(packet + 1, &con->ping_response_id, sizeof(uint64_t));
+ int ret;
+
+ if ((ret = write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1)) == 1) {
+ con->ping_response_id = 0;
+ }
+
+ return ret;
+}
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure (connection must be killed).
+ */
+int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id)
+{
+ if (con_id >= NUM_CLIENT_CONNECTIONS) {
+ return -1;
+ }
+
+ con->connections[con_id].status = 0;
+ con->connections[con_id].number = 0;
+ return client_send_disconnect_notification(con, con_id + NUM_RESERVED_PORTS);
+}
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure (connection must be killed).
+ */
+int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t length)
+{
+ VLA(uint8_t, packet, 1 + length);
+ packet[0] = TCP_PACKET_ONION_REQUEST;
+ memcpy(packet + 1, data, length);
+ return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0);
+}
+
+void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, const uint8_t *data,
+ uint16_t length, void *userdata), void *object)
+{
+ con->onion_callback = onion_callback;
+ con->onion_callback_object = object;
+}
+
+/* Create new TCP connection to ip_port/public_key
+ */
+TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public_key, const uint8_t *self_public_key,
+ const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info)
+{
+ if (networking_at_startup() != 0) {
+ return NULL;
+ }
+
+ if (ip_port.ip.family != TOX_AF_INET && ip_port.ip.family != TOX_AF_INET6) {
+ return NULL;
+ }
+
+ TCP_Proxy_Info default_proxyinfo;
+
+ if (proxy_info == NULL) {
+ default_proxyinfo.proxy_type = TCP_PROXY_NONE;
+ proxy_info = &default_proxyinfo;
+ }
+
+ uint8_t family = ip_port.ip.family;
+
+ if (proxy_info->proxy_type != TCP_PROXY_NONE) {
+ family = proxy_info->ip_port.ip.family;
+ }
+
+ Socket sock = net_socket(family, TOX_SOCK_STREAM, TOX_PROTO_TCP);
+
+ if (!sock_valid(sock)) {
+ return NULL;
+ }
+
+ if (!set_socket_nosigpipe(sock)) {
+ kill_sock(sock);
+ return 0;
+ }
+
+ if (!(set_socket_nonblock(sock) && connect_sock_to(sock, ip_port, proxy_info))) {
+ kill_sock(sock);
+ return NULL;
+ }
+
+ TCP_Client_Connection *temp = (TCP_Client_Connection *)calloc(sizeof(TCP_Client_Connection), 1);
+
+ if (temp == NULL) {
+ kill_sock(sock);
+ return NULL;
+ }
+
+ temp->sock = sock;
+ memcpy(temp->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(temp->self_public_key, self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ encrypt_precompute(temp->public_key, self_secret_key, temp->shared_key);
+ temp->ip_port = ip_port;
+ temp->proxy_info = *proxy_info;
+
+ switch (proxy_info->proxy_type) {
+ case TCP_PROXY_HTTP:
+ temp->status = TCP_CLIENT_PROXY_HTTP_CONNECTING;
+ proxy_http_generate_connection_request(temp);
+ break;
+
+ case TCP_PROXY_SOCKS5:
+ temp->status = TCP_CLIENT_PROXY_SOCKS5_CONNECTING;
+ proxy_socks5_generate_handshake(temp);
+ break;
+
+ case TCP_PROXY_NONE:
+ temp->status = TCP_CLIENT_CONNECTING;
+
+ if (generate_handshake(temp) == -1) {
+ kill_sock(sock);
+ free(temp);
+ return NULL;
+ }
+
+ break;
+ }
+
+ temp->kill_at = unix_time() + TCP_CONNECTION_TIMEOUT;
+
+ return temp;
+}
+
+/* return 0 on success
+ * return -1 on failure
+ */
+static int handle_TCP_client_packet(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length, void *userdata)
+{
+ if (length <= 1) {
+ return -1;
+ }
+
+ switch (data[0]) {
+ case TCP_PACKET_ROUTING_RESPONSE: {
+ if (length != 1 + 1 + CRYPTO_PUBLIC_KEY_SIZE) {
+ return -1;
+ }
+
+ if (data[1] < NUM_RESERVED_PORTS) {
+ return 0;
+ }
+
+ uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
+
+ if (conn->connections[con_id].status != 0) {
+ return 0;
+ }
+
+ conn->connections[con_id].status = 1;
+ conn->connections[con_id].number = ~0;
+ memcpy(conn->connections[con_id].public_key, data + 2, CRYPTO_PUBLIC_KEY_SIZE);
+
+ if (conn->response_callback) {
+ conn->response_callback(conn->response_callback_object, con_id, conn->connections[con_id].public_key);
+ }
+
+ return 0;
+ }
+
+ case TCP_PACKET_CONNECTION_NOTIFICATION: {
+ if (length != 1 + 1) {
+ return -1;
+ }
+
+ if (data[1] < NUM_RESERVED_PORTS) {
+ return -1;
+ }
+
+ uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
+
+ if (conn->connections[con_id].status != 1) {
+ return 0;
+ }
+
+ conn->connections[con_id].status = 2;
+
+ if (conn->status_callback) {
+ conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id,
+ conn->connections[con_id].status);
+ }
+
+ return 0;
+ }
+
+ case TCP_PACKET_DISCONNECT_NOTIFICATION: {
+ if (length != 1 + 1) {
+ return -1;
+ }
+
+ if (data[1] < NUM_RESERVED_PORTS) {
+ return -1;
+ }
+
+ uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
+
+ if (conn->connections[con_id].status == 0) {
+ return 0;
+ }
+
+ if (conn->connections[con_id].status != 2) {
+ return 0;
+ }
+
+ conn->connections[con_id].status = 1;
+
+ if (conn->status_callback) {
+ conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id,
+ conn->connections[con_id].status);
+ }
+
+ return 0;
+ }
+
+ case TCP_PACKET_PING: {
+ if (length != 1 + sizeof(uint64_t)) {
+ return -1;
+ }
+
+ uint64_t ping_id;
+ memcpy(&ping_id, data + 1, sizeof(uint64_t));
+ conn->ping_response_id = ping_id;
+ tcp_send_ping_response(conn);
+ return 0;
+ }
+
+ case TCP_PACKET_PONG: {
+ if (length != 1 + sizeof(uint64_t)) {
+ return -1;
+ }
+
+ uint64_t ping_id;
+ memcpy(&ping_id, data + 1, sizeof(uint64_t));
+
+ if (ping_id) {
+ if (ping_id == conn->ping_id) {
+ conn->ping_id = 0;
+ }
+
+ return 0;
+ }
+
+ return -1;
+ }
+
+ case TCP_PACKET_OOB_RECV: {
+ if (length <= 1 + CRYPTO_PUBLIC_KEY_SIZE) {
+ return -1;
+ }
+
+ if (conn->oob_data_callback) {
+ conn->oob_data_callback(conn->oob_data_callback_object, data + 1, data + 1 + CRYPTO_PUBLIC_KEY_SIZE,
+ length - (1 + CRYPTO_PUBLIC_KEY_SIZE), userdata);
+ }
+
+ return 0;
+ }
+
+ case TCP_PACKET_ONION_RESPONSE: {
+ conn->onion_callback(conn->onion_callback_object, data + 1, length - 1, userdata);
+ return 0;
+ }
+
+ default: {
+ if (data[0] < NUM_RESERVED_PORTS) {
+ return -1;
+ }
+
+ uint8_t con_id = data[0] - NUM_RESERVED_PORTS;
+
+ if (conn->data_callback) {
+ conn->data_callback(conn->data_callback_object, conn->connections[con_id].number, con_id, data + 1, length - 1,
+ userdata);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata)
+{
+ client_send_pending_data(conn);
+ tcp_send_ping_response(conn);
+ tcp_send_ping_request(conn);
+
+ uint8_t packet[MAX_PACKET_SIZE];
+ int len;
+
+ if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) {
+ uint64_t ping_id = random_64b();
+
+ if (!ping_id) {
+ ++ping_id;
+ }
+
+ conn->ping_request_id = conn->ping_id = ping_id;
+ tcp_send_ping_request(conn);
+ conn->last_pinged = unix_time();
+ }
+
+ if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) {
+ conn->status = TCP_CLIENT_DISCONNECTED;
+ return 0;
+ }
+
+ while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key,
+ conn->recv_nonce, packet, sizeof(packet)))) {
+ if (len == -1) {
+ conn->status = TCP_CLIENT_DISCONNECTED;
+ break;
+ }
+
+ if (handle_TCP_client_packet(conn, packet, len, userdata) == -1) {
+ conn->status = TCP_CLIENT_DISCONNECTED;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/* Run the TCP connection
+ */
+void do_TCP_connection(TCP_Client_Connection *TCP_connection, void *userdata)
+{
+ unix_time_update();
+
+ if (TCP_connection->status == TCP_CLIENT_DISCONNECTED) {
+ return;
+ }
+
+ if (TCP_connection->status == TCP_CLIENT_PROXY_HTTP_CONNECTING) {
+ if (client_send_pending_data(TCP_connection) == 0) {
+ int ret = proxy_http_read_connection_response(TCP_connection);
+
+ if (ret == -1) {
+ TCP_connection->kill_at = 0;
+ TCP_connection->status = TCP_CLIENT_DISCONNECTED;
+ }
+
+ if (ret == 1) {
+ generate_handshake(TCP_connection);
+ TCP_connection->status = TCP_CLIENT_CONNECTING;
+ }
+ }
+ }
+
+ if (TCP_connection->status == TCP_CLIENT_PROXY_SOCKS5_CONNECTING) {
+ if (client_send_pending_data(TCP_connection) == 0) {
+ int ret = socks5_read_handshake_response(TCP_connection);
+
+ if (ret == -1) {
+ TCP_connection->kill_at = 0;
+ TCP_connection->status = TCP_CLIENT_DISCONNECTED;
+ }
+
+ if (ret == 1) {
+ proxy_socks5_generate_connection_request(TCP_connection);
+ TCP_connection->status = TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED;
+ }
+ }
+ }
+
+ if (TCP_connection->status == TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED) {
+ if (client_send_pending_data(TCP_connection) == 0) {
+ int ret = proxy_socks5_read_connection_response(TCP_connection);
+
+ if (ret == -1) {
+ TCP_connection->kill_at = 0;
+ TCP_connection->status = TCP_CLIENT_DISCONNECTED;
+ }
+
+ if (ret == 1) {
+ generate_handshake(TCP_connection);
+ TCP_connection->status = TCP_CLIENT_CONNECTING;
+ }
+ }
+ }
+
+ if (TCP_connection->status == TCP_CLIENT_CONNECTING) {
+ if (client_send_pending_data(TCP_connection) == 0) {
+ TCP_connection->status = TCP_CLIENT_UNCONFIRMED;
+ }
+ }
+
+ if (TCP_connection->status == TCP_CLIENT_UNCONFIRMED) {
+ uint8_t data[TCP_SERVER_HANDSHAKE_SIZE];
+ int len = read_TCP_packet(TCP_connection->sock, data, sizeof(data));
+
+ if (sizeof(data) == len) {
+ if (handle_handshake(TCP_connection, data) == 0) {
+ TCP_connection->kill_at = ~0;
+ TCP_connection->status = TCP_CLIENT_CONFIRMED;
+ } else {
+ TCP_connection->kill_at = 0;
+ TCP_connection->status = TCP_CLIENT_DISCONNECTED;
+ }
+ }
+ }
+
+ if (TCP_connection->status == TCP_CLIENT_CONFIRMED) {
+ do_confirmed_TCP(TCP_connection, userdata);
+ }
+
+ if (TCP_connection->kill_at <= unix_time()) {
+ TCP_connection->status = TCP_CLIENT_DISCONNECTED;
+ }
+}
+
+/* Kill the TCP connection
+ */
+void kill_TCP_connection(TCP_Client_Connection *TCP_connection)
+{
+ if (TCP_connection == NULL) {
+ return;
+ }
+
+ wipe_priority_list(TCP_connection);
+ kill_sock(TCP_connection->sock);
+ crypto_memzero(TCP_connection, sizeof(TCP_Client_Connection));
+ free(TCP_connection);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_client.h b/protocols/Tox/libtox/src/toxcore/TCP_client.h
new file mode 100644
index 0000000000..212543147c
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/TCP_client.h
@@ -0,0 +1,167 @@
+/*
+ * Implementation of the TCP relay client part of Tox.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2014 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TCP_CLIENT_H
+#define TCP_CLIENT_H
+
+#include "TCP_server.h"
+#include "crypto_core.h"
+
+#define TCP_CONNECTION_TIMEOUT 10
+
+typedef enum {
+ TCP_PROXY_NONE,
+ TCP_PROXY_HTTP,
+ TCP_PROXY_SOCKS5
+} TCP_PROXY_TYPE;
+
+typedef struct {
+ IP_Port ip_port;
+ uint8_t proxy_type; // a value from TCP_PROXY_TYPE
+} TCP_Proxy_Info;
+
+enum {
+ TCP_CLIENT_NO_STATUS,
+ TCP_CLIENT_PROXY_HTTP_CONNECTING,
+ TCP_CLIENT_PROXY_SOCKS5_CONNECTING,
+ TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED,
+ TCP_CLIENT_CONNECTING,
+ TCP_CLIENT_UNCONFIRMED,
+ TCP_CLIENT_CONFIRMED,
+ TCP_CLIENT_DISCONNECTED,
+};
+typedef struct {
+ uint8_t status;
+ Socket sock;
+ uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* our public key */
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* public key of the server */
+ IP_Port ip_port; /* The ip and port of the server */
+ TCP_Proxy_Info proxy_info;
+ uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */
+ uint8_t sent_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of sent packets. */
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
+ uint16_t next_packet_length;
+
+ uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE];
+
+ uint8_t last_packet[2 + MAX_PACKET_SIZE];
+ uint16_t last_packet_length;
+ uint16_t last_packet_sent;
+
+ TCP_Priority_List *priority_queue_start, *priority_queue_end;
+
+ uint64_t kill_at;
+
+ uint64_t last_pinged;
+ uint64_t ping_id;
+
+ uint64_t ping_response_id;
+ uint64_t ping_request_id;
+
+ struct {
+ uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint32_t number;
+ } connections[NUM_CLIENT_CONNECTIONS];
+ int (*response_callback)(void *object, uint8_t connection_id, const uint8_t *public_key);
+ void *response_callback_object;
+ int (*status_callback)(void *object, uint32_t number, uint8_t connection_id, uint8_t status);
+ void *status_callback_object;
+ int (*data_callback)(void *object, uint32_t number, uint8_t connection_id, const uint8_t *data, uint16_t length,
+ void *userdata);
+ void *data_callback_object;
+ int (*oob_data_callback)(void *object, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata);
+ void *oob_data_callback_object;
+
+ int (*onion_callback)(void *object, const uint8_t *data, uint16_t length, void *userdata);
+ void *onion_callback_object;
+
+ /* Can be used by user. */
+ void *custom_object;
+ uint32_t custom_uint;
+} TCP_Client_Connection;
+
+/* Create new TCP connection to ip_port/public_key
+ */
+TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public_key, const uint8_t *self_public_key,
+ const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info);
+
+/* Run the TCP connection
+ */
+void do_TCP_connection(TCP_Client_Connection *TCP_connection, void *userdata);
+
+/* Kill the TCP connection
+ */
+void kill_TCP_connection(TCP_Client_Connection *TCP_connection);
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure (connection must be killed).
+ */
+int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t length);
+void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, const uint8_t *data,
+ uint16_t length, void *userdata), void *object);
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure (connection must be killed).
+ */
+int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key);
+void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id,
+ const uint8_t *public_key), void *object);
+void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint32_t number,
+ uint8_t connection_id, uint8_t status), void *object);
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure (connection must be killed).
+ */
+int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id);
+
+/* Set the number that will be used as an argument in the callbacks related to con_id.
+ *
+ * When not set by this function, the number is ~0.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32_t number);
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure.
+ */
+int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length);
+void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number,
+ uint8_t connection_id, const uint8_t *data, uint16_t length, void *userdata), void *object);
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure.
+ */
+int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, uint16_t length);
+void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, const uint8_t *public_key,
+ const uint8_t *data, uint16_t length, void *userdata), void *object);
+
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_connection.c b/protocols/Tox/libtox/src/toxcore/TCP_connection.c
new file mode 100644
index 0000000000..251594912a
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/TCP_connection.c
@@ -0,0 +1,1491 @@
+/*
+ * Handles TCP relay connections between two Tox clients.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2015 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "TCP_connection.h"
+
+#include "util.h"
+
+#include <assert.h>
+
+
+struct TCP_Connections {
+ DHT *dht;
+
+ uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
+
+ TCP_Connection_to *connections;
+ uint32_t connections_length; /* Length of connections array. */
+
+ TCP_con *tcp_connections;
+ uint32_t tcp_connections_length; /* Length of tcp_connections array. */
+
+ int (*tcp_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
+ void *tcp_data_callback_object;
+
+ int (*tcp_oob_callback)(void *object, const uint8_t *public_key, unsigned int tcp_connections_number,
+ const uint8_t *data, uint16_t length, void *userdata);
+ void *tcp_oob_callback_object;
+
+ int (*tcp_onion_callback)(void *object, const uint8_t *data, uint16_t length, void *userdata);
+ void *tcp_onion_callback_object;
+
+ TCP_Proxy_Info proxy_info;
+
+ bool onion_status;
+ uint16_t onion_num_conns;
+};
+
+
+const uint8_t *tcp_connections_public_key(const TCP_Connections *tcp_c)
+{
+ return tcp_c->self_public_key;
+}
+
+
+/* Set the size of the array to num.
+ *
+ * return -1 if realloc fails.
+ * return 0 if it succeeds.
+ */
+#define realloc_tox_array(array, element_type, num, temp_pointer) \
+ (num \
+ ? (temp_pointer = (element_type *)realloc( \
+ array, \
+ (num) * sizeof(element_type)), \
+ temp_pointer ? (array = temp_pointer, 0) : -1) \
+ : (free(array), array = NULL, 0))
+
+
+/* return 1 if the connections_number is not valid.
+ * return 0 if the connections_number is valid.
+ */
+static bool connections_number_not_valid(const TCP_Connections *tcp_c, int connections_number)
+{
+ if ((unsigned int)connections_number >= tcp_c->connections_length) {
+ return 1;
+ }
+
+ if (tcp_c->connections == NULL) {
+ return 1;
+ }
+
+ if (tcp_c->connections[connections_number].status == TCP_CONN_NONE) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/* return 1 if the tcp_connections_number is not valid.
+ * return 0 if the tcp_connections_number is valid.
+ */
+static bool tcp_connections_number_not_valid(const TCP_Connections *tcp_c, int tcp_connections_number)
+{
+ if ((unsigned int)tcp_connections_number >= tcp_c->tcp_connections_length) {
+ return 1;
+ }
+
+ if (tcp_c->tcp_connections == NULL) {
+ return 1;
+ }
+
+ if (tcp_c->tcp_connections[tcp_connections_number].status == TCP_CONN_NONE) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Create a new empty connection.
+ *
+ * return -1 on failure.
+ * return connections_number on success.
+ */
+static int create_connection(TCP_Connections *tcp_c)
+{
+ uint32_t i;
+
+ for (i = 0; i < tcp_c->connections_length; ++i) {
+ if (tcp_c->connections[i].status == TCP_CONN_NONE) {
+ return i;
+ }
+ }
+
+ int id = -1;
+
+ TCP_Connection_to *temp_pointer;
+
+ if (realloc_tox_array(tcp_c->connections, TCP_Connection_to, tcp_c->connections_length + 1,
+ temp_pointer) == 0) {
+ id = tcp_c->connections_length;
+ ++tcp_c->connections_length;
+ memset(&(tcp_c->connections[id]), 0, sizeof(TCP_Connection_to));
+ }
+
+ return id;
+}
+
+/* Create a new empty tcp connection.
+ *
+ * return -1 on failure.
+ * return tcp_connections_number on success.
+ */
+static int create_tcp_connection(TCP_Connections *tcp_c)
+{
+ uint32_t i;
+
+ for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
+ if (tcp_c->tcp_connections[i].status == TCP_CONN_NONE) {
+ return i;
+ }
+ }
+
+ int id = -1;
+
+ TCP_con *temp_pointer;
+
+ if (realloc_tox_array(tcp_c->tcp_connections, TCP_con, tcp_c->tcp_connections_length + 1, temp_pointer) == 0) {
+ id = tcp_c->tcp_connections_length;
+ ++tcp_c->tcp_connections_length;
+ memset(&(tcp_c->tcp_connections[id]), 0, sizeof(TCP_con));
+ }
+
+ return id;
+}
+
+/* Wipe a connection.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int wipe_connection(TCP_Connections *tcp_c, int connections_number)
+{
+ if (connections_number_not_valid(tcp_c, connections_number)) {
+ return -1;
+ }
+
+ uint32_t i;
+ memset(&(tcp_c->connections[connections_number]), 0 , sizeof(TCP_Connection_to));
+
+ for (i = tcp_c->connections_length; i != 0; --i) {
+ if (tcp_c->connections[i - 1].status != TCP_CONN_NONE) {
+ break;
+ }
+ }
+
+ if (tcp_c->connections_length != i) {
+ tcp_c->connections_length = i;
+ TCP_Connection_to *temp_pointer;
+ realloc_tox_array(tcp_c->connections, TCP_Connection_to, tcp_c->connections_length, temp_pointer);
+ }
+
+ return 0;
+}
+
+/* Wipe a connection.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int wipe_tcp_connection(TCP_Connections *tcp_c, int tcp_connections_number)
+{
+ if (tcp_connections_number_not_valid(tcp_c, tcp_connections_number)) {
+ return -1;
+ }
+
+ uint32_t i;
+ memset(&(tcp_c->tcp_connections[tcp_connections_number]), 0 , sizeof(TCP_con));
+
+ for (i = tcp_c->tcp_connections_length; i != 0; --i) {
+ if (tcp_c->tcp_connections[i - 1].status != TCP_CONN_NONE) {
+ break;
+ }
+ }
+
+ if (tcp_c->tcp_connections_length != i) {
+ tcp_c->tcp_connections_length = i;
+ TCP_con *temp_pointer;
+ realloc_tox_array(tcp_c->tcp_connections, TCP_con, tcp_c->tcp_connections_length, temp_pointer);
+ }
+
+ return 0;
+}
+
+static TCP_Connection_to *get_connection(const TCP_Connections *tcp_c, int connections_number)
+{
+ if (connections_number_not_valid(tcp_c, connections_number)) {
+ return 0;
+ }
+
+ return &tcp_c->connections[connections_number];
+}
+
+static TCP_con *get_tcp_connection(const TCP_Connections *tcp_c, int tcp_connections_number)
+{
+ if (tcp_connections_number_not_valid(tcp_c, tcp_connections_number)) {
+ return 0;
+ }
+
+ return &tcp_c->tcp_connections[tcp_connections_number];
+}
+
+/* Send a packet to the TCP connection.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, const uint8_t *packet, uint16_t length)
+{
+ TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
+
+ if (!con_to) {
+ return -1;
+ }
+
+ // TODO(irungentoo): detect and kill bad relays.
+ // TODO(irungentoo): thread safety?
+ unsigned int i;
+ int ret = -1;
+
+ bool limit_reached = 0;
+
+ for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
+ uint32_t tcp_con_num = con_to->connections[i].tcp_connection;
+ uint8_t status = con_to->connections[i].status;
+ uint8_t connection_id = con_to->connections[i].connection_id;
+
+ if (tcp_con_num && status == TCP_CONNECTIONS_STATUS_ONLINE) {
+ tcp_con_num -= 1;
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_con_num);
+
+ if (!tcp_con) {
+ continue;
+ }
+
+ ret = send_data(tcp_con->connection, connection_id, packet, length);
+
+ if (ret == 0) {
+ limit_reached = 1;
+ }
+
+ if (ret == 1) {
+ break;
+ }
+ }
+ }
+
+ if (ret == 1) {
+ return 0;
+ }
+
+ if (!limit_reached) {
+ ret = 0;
+
+ /* Send oob packets to all relays tied to the connection. */
+ for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
+ uint32_t tcp_con_num = con_to->connections[i].tcp_connection;
+ uint8_t status = con_to->connections[i].status;
+
+ if (tcp_con_num && status == TCP_CONNECTIONS_STATUS_REGISTERED) {
+ tcp_con_num -= 1;
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_con_num);
+
+ if (!tcp_con) {
+ continue;
+ }
+
+ if (send_oob_packet(tcp_con->connection, con_to->public_key, packet, length) == 1) {
+ ret += 1;
+ }
+ }
+ }
+
+ if (ret >= 1) {
+ return 0;
+ }
+
+ return -1;
+ }
+
+ return -1;
+}
+
+/* Return a random TCP connection number for use in send_tcp_onion_request.
+ *
+ * TODO(irungentoo): This number is just the index of an array that the elements
+ * can change without warning.
+ *
+ * return TCP connection number on success.
+ * return -1 on failure.
+ */
+int get_random_tcp_onion_conn_number(TCP_Connections *tcp_c)
+{
+ unsigned int i, r = rand();
+
+ for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
+ unsigned int index = ((i + r) % tcp_c->tcp_connections_length);
+
+ if (tcp_c->tcp_connections[index].onion && tcp_c->tcp_connections[index].status == TCP_CONN_CONNECTED) {
+ return index;
+ }
+ }
+
+ return -1;
+}
+
+/* Send an onion packet via the TCP relay corresponding to tcp_connections_number.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int tcp_send_onion_request(TCP_Connections *tcp_c, unsigned int tcp_connections_number, const uint8_t *data,
+ uint16_t length)
+{
+ if (tcp_connections_number >= tcp_c->tcp_connections_length) {
+ return -1;
+ }
+
+ if (tcp_c->tcp_connections[tcp_connections_number].status == TCP_CONN_CONNECTED) {
+ int ret = send_onion_request(tcp_c->tcp_connections[tcp_connections_number].connection, data, length);
+
+ if (ret == 1) {
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/* Send an oob packet via the TCP relay corresponding to tcp_connections_number.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int tcp_send_oob_packet(TCP_Connections *tcp_c, unsigned int tcp_connections_number, const uint8_t *public_key,
+ const uint8_t *packet, uint16_t length)
+{
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
+
+ if (!tcp_con) {
+ return -1;
+ }
+
+ if (tcp_con->status != TCP_CONN_CONNECTED) {
+ return -1;
+ }
+
+ int ret = send_oob_packet(tcp_con->connection, public_key, packet, length);
+
+ if (ret == 1) {
+ return 0;
+ }
+
+ return -1;
+}
+
+/* Set the callback for TCP data packets.
+ */
+void set_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_data_callback)(void *object, int id,
+ const uint8_t *data, uint16_t length, void *userdata), void *object)
+{
+ tcp_c->tcp_data_callback = tcp_data_callback;
+ tcp_c->tcp_data_callback_object = object;
+}
+
+/* Set the callback for TCP onion packets.
+ */
+void set_oob_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_oob_callback)(void *object,
+ const uint8_t *public_key, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length, void *userdata),
+ void *object)
+{
+ tcp_c->tcp_oob_callback = tcp_oob_callback;
+ tcp_c->tcp_oob_callback_object = object;
+}
+
+/* Set the callback for TCP oob data packets.
+ */
+void set_onion_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_onion_callback)(void *object,
+ const uint8_t *data, uint16_t length, void *userdata), void *object)
+{
+ tcp_c->tcp_onion_callback = tcp_onion_callback;
+ tcp_c->tcp_onion_callback_object = object;
+}
+
+
+/* Find the TCP connection with public_key.
+ *
+ * return connections_number on success.
+ * return -1 on failure.
+ */
+static int find_tcp_connection_to(TCP_Connections *tcp_c, const uint8_t *public_key)
+{
+ unsigned int i;
+
+ for (i = 0; i < tcp_c->connections_length; ++i) {
+ TCP_Connection_to *con_to = get_connection(tcp_c, i);
+
+ if (con_to) {
+ if (public_key_cmp(con_to->public_key, public_key) == 0) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+}
+
+/* Find the TCP connection to a relay with relay_pk.
+ *
+ * return connections_number on success.
+ * return -1 on failure.
+ */
+static int find_tcp_connection_relay(TCP_Connections *tcp_c, const uint8_t *relay_pk)
+{
+ unsigned int i;
+
+ for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
+
+ if (tcp_con) {
+ if (tcp_con->status == TCP_CONN_SLEEPING) {
+ if (public_key_cmp(tcp_con->relay_pk, relay_pk) == 0) {
+ return i;
+ }
+ } else {
+ if (public_key_cmp(tcp_con->connection->public_key, relay_pk) == 0) {
+ return i;
+ }
+ }
+ }
+ }
+
+ return -1;
+}
+
+/* Create a new TCP connection to public_key.
+ *
+ * public_key must be the counterpart to the secret key that the other peer used with new_tcp_connections().
+ *
+ * id is the id in the callbacks for that connection.
+ *
+ * return connections_number on success.
+ * return -1 on failure.
+ */
+int new_tcp_connection_to(TCP_Connections *tcp_c, const uint8_t *public_key, int id)
+{
+ if (find_tcp_connection_to(tcp_c, public_key) != -1) {
+ return -1;
+ }
+
+ int connections_number = create_connection(tcp_c);
+
+ if (connections_number == -1) {
+ return -1;
+ }
+
+ TCP_Connection_to *con_to = &tcp_c->connections[connections_number];
+
+ con_to->status = TCP_CONN_VALID;
+ memcpy(con_to->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ con_to->id = id;
+
+ return connections_number;
+}
+
+/* return 0 on success.
+ * return -1 on failure.
+ */
+int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number)
+{
+ TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
+
+ if (!con_to) {
+ return -1;
+ }
+
+ unsigned int i;
+
+ for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
+ if (con_to->connections[i].tcp_connection) {
+ unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
+
+ if (!tcp_con) {
+ continue;
+ }
+
+ if (tcp_con->status == TCP_CONN_CONNECTED) {
+ send_disconnect_request(tcp_con->connection, con_to->connections[i].connection_id);
+ }
+
+ if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) {
+ --tcp_con->lock_count;
+
+ if (con_to->status == TCP_CONN_SLEEPING) {
+ --tcp_con->sleep_count;
+ }
+ }
+ }
+ }
+
+ return wipe_connection(tcp_c, connections_number);
+}
+
+/* Set connection status.
+ *
+ * status of 1 means we are using the connection.
+ * status of 0 means we are not using it.
+ *
+ * Unused tcp connections will be disconnected from but kept in case they are needed.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number, bool status)
+{
+ TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
+
+ if (!con_to) {
+ return -1;
+ }
+
+ if (status) {
+ /* Connection is unsleeping. */
+ if (con_to->status != TCP_CONN_SLEEPING) {
+ return -1;
+ }
+
+ unsigned int i;
+
+ for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
+ if (con_to->connections[i].tcp_connection) {
+ unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
+
+ if (!tcp_con) {
+ continue;
+ }
+
+ if (tcp_con->status == TCP_CONN_SLEEPING) {
+ tcp_con->unsleep = 1;
+ }
+ }
+ }
+
+ con_to->status = TCP_CONN_VALID;
+ return 0;
+ }
+
+ /* Connection is going to sleep. */
+ if (con_to->status != TCP_CONN_VALID) {
+ return -1;
+ }
+
+ unsigned int i;
+
+ for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
+ if (con_to->connections[i].tcp_connection) {
+ unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
+
+ if (!tcp_con) {
+ continue;
+ }
+
+ if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) {
+ ++tcp_con->sleep_count;
+ }
+ }
+ }
+
+ con_to->status = TCP_CONN_SLEEPING;
+ return 0;
+}
+
+static bool tcp_connection_in_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number)
+{
+ unsigned int i;
+
+ for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
+ if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* return index on success.
+ * return -1 on failure.
+ */
+static int add_tcp_connection_to_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number)
+{
+ unsigned int i;
+
+ if (tcp_connection_in_conn(con_to, tcp_connections_number)) {
+ return -1;
+ }
+
+ for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
+ if (con_to->connections[i].tcp_connection == 0) {
+ con_to->connections[i].tcp_connection = tcp_connections_number + 1;
+ con_to->connections[i].status = TCP_CONNECTIONS_STATUS_NONE;
+ con_to->connections[i].connection_id = 0;
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/* return index on success.
+ * return -1 on failure.
+ */
+static int rm_tcp_connection_from_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number)
+{
+ unsigned int i;
+
+ for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
+ if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) {
+ con_to->connections[i].tcp_connection = 0;
+ con_to->connections[i].status = TCP_CONNECTIONS_STATUS_NONE;
+ con_to->connections[i].connection_id = 0;
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/* return number of online connections on success.
+ * return -1 on failure.
+ */
+static unsigned int online_tcp_connection_from_conn(TCP_Connection_to *con_to)
+{
+ unsigned int i, count = 0;
+
+ for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
+ if (con_to->connections[i].tcp_connection) {
+ if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) {
+ ++count;
+ }
+ }
+ }
+
+ return count;
+}
+
+/* return index on success.
+ * return -1 on failure.
+ */
+static int set_tcp_connection_status(TCP_Connection_to *con_to, unsigned int tcp_connections_number,
+ unsigned int status, uint8_t connection_id)
+{
+ unsigned int i;
+
+ for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
+ if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) {
+
+ if (con_to->connections[i].status == status) {
+ return -1;
+ }
+
+ con_to->connections[i].status = status;
+ con_to->connections[i].connection_id = connection_id;
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/* Kill a TCP relay connection.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+static int kill_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
+{
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
+
+ if (!tcp_con) {
+ return -1;
+ }
+
+ unsigned int i;
+
+ for (i = 0; i < tcp_c->connections_length; ++i) {
+ TCP_Connection_to *con_to = get_connection(tcp_c, i);
+
+ if (con_to) {
+ rm_tcp_connection_from_conn(con_to, tcp_connections_number);
+ }
+ }
+
+ if (tcp_con->onion) {
+ --tcp_c->onion_num_conns;
+ }
+
+ kill_TCP_connection(tcp_con->connection);
+
+ return wipe_tcp_connection(tcp_c, tcp_connections_number);
+}
+
+static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
+{
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
+
+ if (!tcp_con) {
+ return -1;
+ }
+
+ if (tcp_con->status == TCP_CONN_SLEEPING) {
+ return -1;
+ }
+
+ IP_Port ip_port = tcp_con->connection->ip_port;
+ uint8_t relay_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ memcpy(relay_pk, tcp_con->connection->public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ kill_TCP_connection(tcp_con->connection);
+ tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key,
+ &tcp_c->proxy_info);
+
+ if (!tcp_con->connection) {
+ kill_tcp_relay_connection(tcp_c, tcp_connections_number);
+ return -1;
+ }
+
+ unsigned int i;
+
+ for (i = 0; i < tcp_c->connections_length; ++i) {
+ TCP_Connection_to *con_to = get_connection(tcp_c, i);
+
+ if (con_to) {
+ set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_NONE, 0);
+ }
+ }
+
+ if (tcp_con->onion) {
+ --tcp_c->onion_num_conns;
+ tcp_con->onion = 0;
+ }
+
+ tcp_con->lock_count = 0;
+ tcp_con->sleep_count = 0;
+ tcp_con->connected_time = 0;
+ tcp_con->status = TCP_CONN_VALID;
+ tcp_con->unsleep = 0;
+
+ return 0;
+}
+
+static int sleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
+{
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
+
+ if (!tcp_con) {
+ return -1;
+ }
+
+ if (tcp_con->status != TCP_CONN_CONNECTED) {
+ return -1;
+ }
+
+ if (tcp_con->lock_count != tcp_con->sleep_count) {
+ return -1;
+ }
+
+ tcp_con->ip_port = tcp_con->connection->ip_port;
+ memcpy(tcp_con->relay_pk, tcp_con->connection->public_key, CRYPTO_PUBLIC_KEY_SIZE);
+
+ kill_TCP_connection(tcp_con->connection);
+ tcp_con->connection = NULL;
+
+ unsigned int i;
+
+ for (i = 0; i < tcp_c->connections_length; ++i) {
+ TCP_Connection_to *con_to = get_connection(tcp_c, i);
+
+ if (con_to) {
+ set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_NONE, 0);
+ }
+ }
+
+ if (tcp_con->onion) {
+ --tcp_c->onion_num_conns;
+ tcp_con->onion = 0;
+ }
+
+ tcp_con->lock_count = 0;
+ tcp_con->sleep_count = 0;
+ tcp_con->connected_time = 0;
+ tcp_con->status = TCP_CONN_SLEEPING;
+ tcp_con->unsleep = 0;
+
+ return 0;
+}
+
+static int unsleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
+{
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
+
+ if (!tcp_con) {
+ return -1;
+ }
+
+ if (tcp_con->status != TCP_CONN_SLEEPING) {
+ return -1;
+ }
+
+ tcp_con->connection = new_TCP_connection(tcp_con->ip_port, tcp_con->relay_pk, tcp_c->self_public_key,
+ tcp_c->self_secret_key, &tcp_c->proxy_info);
+
+ if (!tcp_con->connection) {
+ kill_tcp_relay_connection(tcp_c, tcp_connections_number);
+ return -1;
+ }
+
+ tcp_con->lock_count = 0;
+ tcp_con->sleep_count = 0;
+ tcp_con->connected_time = 0;
+ tcp_con->status = TCP_CONN_VALID;
+ tcp_con->unsleep = 0;
+ return 0;
+}
+
+/* Send a TCP routing request.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+static int send_tcp_relay_routing_request(TCP_Connections *tcp_c, int tcp_connections_number, uint8_t *public_key)
+{
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
+
+ if (!tcp_con) {
+ return -1;
+ }
+
+ if (tcp_con->status == TCP_CONN_SLEEPING) {
+ return -1;
+ }
+
+ if (send_routing_request(tcp_con->connection, public_key) != 1) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int tcp_response_callback(void *object, uint8_t connection_id, const uint8_t *public_key)
+{
+ TCP_Client_Connection *TCP_client_con = (TCP_Client_Connection *)object;
+ TCP_Connections *tcp_c = (TCP_Connections *)TCP_client_con->custom_object;
+
+ unsigned int tcp_connections_number = TCP_client_con->custom_uint;
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
+
+ if (!tcp_con) {
+ return -1;
+ }
+
+ int connections_number = find_tcp_connection_to(tcp_c, public_key);
+
+ if (connections_number == -1) {
+ return -1;
+ }
+
+ TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
+
+ if (con_to == NULL) {
+ return -1;
+ }
+
+ if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1) {
+ return -1;
+ }
+
+ set_tcp_connection_number(tcp_con->connection, connection_id, connections_number);
+
+ return 0;
+}
+
+static int tcp_status_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t status)
+{
+ TCP_Client_Connection *TCP_client_con = (TCP_Client_Connection *)object;
+ TCP_Connections *tcp_c = (TCP_Connections *)TCP_client_con->custom_object;
+
+ unsigned int tcp_connections_number = TCP_client_con->custom_uint;
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
+ TCP_Connection_to *con_to = get_connection(tcp_c, number);
+
+ if (!con_to || !tcp_con) {
+ return -1;
+ }
+
+ if (status == 1) {
+ if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1) {
+ return -1;
+ }
+
+ --tcp_con->lock_count;
+
+ if (con_to->status == TCP_CONN_SLEEPING) {
+ --tcp_con->sleep_count;
+ }
+ } else if (status == 2) {
+ if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_ONLINE, connection_id) == -1) {
+ return -1;
+ }
+
+ ++tcp_con->lock_count;
+
+ if (con_to->status == TCP_CONN_SLEEPING) {
+ ++tcp_con->sleep_count;
+ }
+ }
+
+ return 0;
+}
+
+static int tcp_conn_data_callback(void *object, uint32_t number, uint8_t connection_id, const uint8_t *data,
+ uint16_t length, void *userdata)
+{
+ if (length == 0) {
+ return -1;
+ }
+
+ TCP_Client_Connection *TCP_client_con = (TCP_Client_Connection *)object;
+ TCP_Connections *tcp_c = (TCP_Connections *)TCP_client_con->custom_object;
+
+ unsigned int tcp_connections_number = TCP_client_con->custom_uint;
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
+
+ if (!tcp_con) {
+ return -1;
+ }
+
+ TCP_Connection_to *con_to = get_connection(tcp_c, number);
+
+ if (!con_to) {
+ return -1;
+ }
+
+ if (tcp_c->tcp_data_callback) {
+ tcp_c->tcp_data_callback(tcp_c->tcp_data_callback_object, con_to->id, data, length, userdata);
+ }
+
+ return 0;
+}
+
+static int tcp_conn_oob_callback(void *object, const uint8_t *public_key, const uint8_t *data, uint16_t length,
+ void *userdata)
+{
+ if (length == 0) {
+ return -1;
+ }
+
+ TCP_Client_Connection *TCP_client_con = (TCP_Client_Connection *)object;
+ TCP_Connections *tcp_c = (TCP_Connections *)TCP_client_con->custom_object;
+
+ unsigned int tcp_connections_number = TCP_client_con->custom_uint;
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
+
+ if (!tcp_con) {
+ return -1;
+ }
+
+ /* TODO(irungentoo): optimize */
+ int connections_number = find_tcp_connection_to(tcp_c, public_key);
+
+ TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
+
+ if (con_to && tcp_connection_in_conn(con_to, tcp_connections_number)) {
+ return tcp_conn_data_callback(object, connections_number, 0, data, length, userdata);
+ }
+
+ if (tcp_c->tcp_oob_callback) {
+ tcp_c->tcp_oob_callback(tcp_c->tcp_oob_callback_object, public_key, tcp_connections_number, data, length, userdata);
+ }
+
+ return 0;
+}
+
+static int tcp_onion_callback(void *object, const uint8_t *data, uint16_t length, void *userdata)
+{
+ TCP_Connections *tcp_c = (TCP_Connections *)object;
+
+ if (tcp_c->tcp_onion_callback) {
+ tcp_c->tcp_onion_callback(tcp_c->tcp_onion_callback_object, data, length, userdata);
+ }
+
+ return 0;
+}
+
+/* Set callbacks for the TCP relay connection.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+static int tcp_relay_set_callbacks(TCP_Connections *tcp_c, int tcp_connections_number)
+{
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
+
+ if (!tcp_con) {
+ return -1;
+ }
+
+ TCP_Client_Connection *con = tcp_con->connection;
+
+ con->custom_object = tcp_c;
+ con->custom_uint = tcp_connections_number;
+ onion_response_handler(con, &tcp_onion_callback, tcp_c);
+ routing_response_handler(con, &tcp_response_callback, con);
+ routing_status_handler(con, &tcp_status_callback, con);
+ routing_data_handler(con, &tcp_conn_data_callback, con);
+ oob_data_handler(con, &tcp_conn_oob_callback, con);
+
+ return 0;
+}
+
+static int tcp_relay_on_online(TCP_Connections *tcp_c, int tcp_connections_number)
+{
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
+
+ if (!tcp_con) {
+ return -1;
+ }
+
+ unsigned int i, sent = 0;
+
+ for (i = 0; i < tcp_c->connections_length; ++i) {
+ TCP_Connection_to *con_to = get_connection(tcp_c, i);
+
+ if (con_to) {
+ if (tcp_connection_in_conn(con_to, tcp_connections_number)) {
+ if (send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key) == 0) {
+ ++sent;
+ }
+ }
+ }
+ }
+
+ tcp_relay_set_callbacks(tcp_c, tcp_connections_number);
+ tcp_con->status = TCP_CONN_CONNECTED;
+
+ /* If this connection isn't used by any connection, we don't need to wait for them to come online. */
+ if (sent) {
+ tcp_con->connected_time = unix_time();
+ } else {
+ tcp_con->connected_time = 0;
+ }
+
+ if (tcp_c->onion_status && tcp_c->onion_num_conns < NUM_ONION_TCP_CONNECTIONS) {
+ tcp_con->onion = 1;
+ ++tcp_c->onion_num_conns;
+ }
+
+ return 0;
+}
+
+static int add_tcp_relay_instance(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t *relay_pk)
+{
+ if (ip_port.ip.family == TCP_INET) {
+ ip_port.ip.family = TOX_AF_INET;
+ } else if (ip_port.ip.family == TCP_INET6) {
+ ip_port.ip.family = TOX_AF_INET6;
+ }
+
+ if (ip_port.ip.family != TOX_AF_INET && ip_port.ip.family != TOX_AF_INET6) {
+ return -1;
+ }
+
+ int tcp_connections_number = create_tcp_connection(tcp_c);
+
+ if (tcp_connections_number == -1) {
+ return -1;
+ }
+
+ TCP_con *tcp_con = &tcp_c->tcp_connections[tcp_connections_number];
+
+ tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key,
+ &tcp_c->proxy_info);
+
+ if (!tcp_con->connection) {
+ return -1;
+ }
+
+ tcp_con->status = TCP_CONN_VALID;
+
+ return tcp_connections_number;
+}
+
+/* Add a TCP relay to the TCP_Connections instance.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int add_tcp_relay_global(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t *relay_pk)
+{
+ int tcp_connections_number = find_tcp_connection_relay(tcp_c, relay_pk);
+
+ if (tcp_connections_number != -1) {
+ return -1;
+ }
+
+ if (add_tcp_relay_instance(tcp_c, ip_port, relay_pk) == -1) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Add a TCP relay tied to a connection.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int add_tcp_number_relay_connection(TCP_Connections *tcp_c, int connections_number, unsigned int tcp_connections_number)
+{
+ TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
+
+ if (!con_to) {
+ return -1;
+ }
+
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
+
+ if (!tcp_con) {
+ return -1;
+ }
+
+ if (con_to->status != TCP_CONN_SLEEPING && tcp_con->status == TCP_CONN_SLEEPING) {
+ tcp_con->unsleep = 1;
+ }
+
+ if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) {
+ return -1;
+ }
+
+ if (tcp_con->status == TCP_CONN_CONNECTED) {
+ if (send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key) == 0) {
+ tcp_con->connected_time = unix_time();
+ }
+ }
+
+ return 0;
+}
+
+/* Add a TCP relay tied to a connection.
+ *
+ * This should be called with the same relay by two peers who want to create a TCP connection with each other.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int add_tcp_relay_connection(TCP_Connections *tcp_c, int connections_number, IP_Port ip_port, const uint8_t *relay_pk)
+{
+ TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
+
+ if (!con_to) {
+ return -1;
+ }
+
+ int tcp_connections_number = find_tcp_connection_relay(tcp_c, relay_pk);
+
+ if (tcp_connections_number != -1) {
+ return add_tcp_number_relay_connection(tcp_c, connections_number, tcp_connections_number);
+ }
+
+ if (online_tcp_connection_from_conn(con_to) >= RECOMMENDED_FRIEND_TCP_CONNECTIONS) {
+ return -1;
+ }
+
+ tcp_connections_number = add_tcp_relay_instance(tcp_c, ip_port, relay_pk);
+
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
+
+ if (!tcp_con) {
+ return -1;
+ }
+
+ if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* return number of online tcp relays tied to the connection on success.
+ * return 0 on failure.
+ */
+unsigned int tcp_connection_to_online_tcp_relays(TCP_Connections *tcp_c, int connections_number)
+{
+ TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
+
+ if (!con_to) {
+ return 0;
+ }
+
+ return online_tcp_connection_from_conn(con_to);
+}
+
+/* Copy a maximum of max_num TCP relays we are connected to to tcp_relays.
+ * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.
+ *
+ * return number of relays copied to tcp_relays on success.
+ * return 0 on failure.
+ */
+unsigned int tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num)
+{
+ unsigned int i, copied = 0, r = rand();
+
+ for (i = 0; (i < tcp_c->tcp_connections_length) && (copied < max_num); ++i) {
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, (i + r) % tcp_c->tcp_connections_length);
+
+ if (!tcp_con) {
+ continue;
+ }
+
+ if (tcp_con->status == TCP_CONN_CONNECTED) {
+ memcpy(tcp_relays[copied].public_key, tcp_con->connection->public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ tcp_relays[copied].ip_port = tcp_con->connection->ip_port;
+
+ if (tcp_relays[copied].ip_port.ip.family == TOX_AF_INET) {
+ tcp_relays[copied].ip_port.ip.family = TCP_INET;
+ } else if (tcp_relays[copied].ip_port.ip.family == TOX_AF_INET6) {
+ tcp_relays[copied].ip_port.ip.family = TCP_INET6;
+ }
+
+ ++copied;
+ }
+ }
+
+ return copied;
+}
+
+/* Set if we want TCP_connection to allocate some connection for onion use.
+ *
+ * If status is 1, allocate some connections. if status is 0, don't.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int set_tcp_onion_status(TCP_Connections *tcp_c, bool status)
+{
+ if (tcp_c->onion_status == status) {
+ return -1;
+ }
+
+ if (status) {
+ unsigned int i;
+
+ for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
+
+ if (tcp_con) {
+ if (tcp_con->status == TCP_CONN_CONNECTED && !tcp_con->onion) {
+ ++tcp_c->onion_num_conns;
+ tcp_con->onion = 1;
+ }
+ }
+
+ if (tcp_c->onion_num_conns >= NUM_ONION_TCP_CONNECTIONS) {
+ break;
+ }
+ }
+
+ if (tcp_c->onion_num_conns < NUM_ONION_TCP_CONNECTIONS) {
+ unsigned int wakeup = NUM_ONION_TCP_CONNECTIONS - tcp_c->onion_num_conns;
+
+ for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
+
+ if (tcp_con) {
+ if (tcp_con->status == TCP_CONN_SLEEPING) {
+ tcp_con->unsleep = 1;
+ }
+ }
+
+ if (!wakeup) {
+ break;
+ }
+ }
+ }
+
+ tcp_c->onion_status = 1;
+ } else {
+ unsigned int i;
+
+ for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
+
+ if (tcp_con) {
+ if (tcp_con->onion) {
+ --tcp_c->onion_num_conns;
+ tcp_con->onion = 0;
+ }
+ }
+ }
+
+ tcp_c->onion_status = 0;
+ }
+
+ return 0;
+}
+
+/* Returns a new TCP_Connections object associated with the secret_key.
+ *
+ * In order for others to connect to this instance new_tcp_connection_to() must be called with the
+ * public_key associated with secret_key.
+ *
+ * Returns NULL on failure.
+ */
+TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info)
+{
+ if (secret_key == NULL) {
+ return NULL;
+ }
+
+ TCP_Connections *temp = (TCP_Connections *)calloc(1, sizeof(TCP_Connections));
+
+ if (temp == NULL) {
+ return NULL;
+ }
+
+ memcpy(temp->self_secret_key, secret_key, CRYPTO_SECRET_KEY_SIZE);
+ crypto_derive_public_key(temp->self_public_key, temp->self_secret_key);
+ temp->proxy_info = *proxy_info;
+
+ return temp;
+}
+
+static void do_tcp_conns(TCP_Connections *tcp_c, void *userdata)
+{
+ unsigned int i;
+
+ for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
+
+ if (tcp_con) {
+ if (tcp_con->status != TCP_CONN_SLEEPING) {
+ do_TCP_connection(tcp_con->connection, userdata);
+
+ /* callbacks can change TCP connection address. */
+ tcp_con = get_tcp_connection(tcp_c, i);
+
+ // Make sure the TCP connection wasn't dropped in any of the callbacks.
+ assert(tcp_con != NULL);
+
+ if (tcp_con->connection->status == TCP_CLIENT_DISCONNECTED) {
+ if (tcp_con->status == TCP_CONN_CONNECTED) {
+ reconnect_tcp_relay_connection(tcp_c, i);
+ } else {
+ kill_tcp_relay_connection(tcp_c, i);
+ }
+
+ continue;
+ }
+
+ if (tcp_con->status == TCP_CONN_VALID && tcp_con->connection->status == TCP_CLIENT_CONFIRMED) {
+ tcp_relay_on_online(tcp_c, i);
+ }
+
+ if (tcp_con->status == TCP_CONN_CONNECTED && !tcp_con->onion && tcp_con->lock_count
+ && tcp_con->lock_count == tcp_con->sleep_count
+ && is_timeout(tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) {
+ sleep_tcp_relay_connection(tcp_c, i);
+ }
+ }
+
+ if (tcp_con->status == TCP_CONN_SLEEPING && tcp_con->unsleep) {
+ unsleep_tcp_relay_connection(tcp_c, i);
+ }
+ }
+ }
+}
+
+static void kill_nonused_tcp(TCP_Connections *tcp_c)
+{
+ if (tcp_c->tcp_connections_length == 0) {
+ return;
+ }
+
+ unsigned int i;
+ unsigned int num_online = 0;
+ unsigned int num_kill = 0;
+ VLA(unsigned int, to_kill, tcp_c->tcp_connections_length);
+
+ for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
+ TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
+
+ if (tcp_con) {
+ if (tcp_con->status == TCP_CONN_CONNECTED) {
+ if (!tcp_con->onion && !tcp_con->lock_count && is_timeout(tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) {
+ to_kill[num_kill] = i;
+ ++num_kill;
+ }
+
+ ++num_online;
+ }
+ }
+ }
+
+ if (num_online <= RECOMMENDED_FRIEND_TCP_CONNECTIONS) {
+ return;
+ }
+
+ unsigned int n = num_online - RECOMMENDED_FRIEND_TCP_CONNECTIONS;
+
+ if (n < num_kill) {
+ num_kill = n;
+ }
+
+ for (i = 0; i < num_kill; ++i) {
+ kill_tcp_relay_connection(tcp_c, to_kill[i]);
+ }
+}
+
+void do_tcp_connections(TCP_Connections *tcp_c, void *userdata)
+{
+ do_tcp_conns(tcp_c, userdata);
+ kill_nonused_tcp(tcp_c);
+}
+
+void kill_tcp_connections(TCP_Connections *tcp_c)
+{
+ unsigned int i;
+
+ for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
+ kill_TCP_connection(tcp_c->tcp_connections[i].connection);
+ }
+
+ free(tcp_c->tcp_connections);
+ free(tcp_c->connections);
+ free(tcp_c);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_connection.h b/protocols/Tox/libtox/src/toxcore/TCP_connection.h
new file mode 100644
index 0000000000..a45129a7e8
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/TCP_connection.h
@@ -0,0 +1,223 @@
+/*
+ * Handles TCP relay connections between two Tox clients.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2015 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TCP_CONNECTION_H
+#define TCP_CONNECTION_H
+
+#include "TCP_client.h"
+
+#define TCP_CONN_NONE 0
+#define TCP_CONN_VALID 1
+
+/* NOTE: only used by TCP_con */
+#define TCP_CONN_CONNECTED 2
+
+/* Connection is not connected but can be quickly reconnected in case it is needed. */
+#define TCP_CONN_SLEEPING 3
+
+#define TCP_CONNECTIONS_STATUS_NONE 0
+#define TCP_CONNECTIONS_STATUS_REGISTERED 1
+#define TCP_CONNECTIONS_STATUS_ONLINE 2
+
+#define MAX_FRIEND_TCP_CONNECTIONS 6
+
+/* Time until connection to friend gets killed (if it doesn't get locked within that time) */
+#define TCP_CONNECTION_ANNOUNCE_TIMEOUT (TCP_CONNECTION_TIMEOUT)
+
+/* The amount of recommended connections for each friend
+ NOTE: Must be at most (MAX_FRIEND_TCP_CONNECTIONS / 2) */
+#define RECOMMENDED_FRIEND_TCP_CONNECTIONS (MAX_FRIEND_TCP_CONNECTIONS / 2)
+
+/* Number of TCP connections used for onion purposes. */
+#define NUM_ONION_TCP_CONNECTIONS RECOMMENDED_FRIEND_TCP_CONNECTIONS
+
+typedef struct {
+ uint8_t status;
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The dht public key of the peer */
+
+ struct {
+ uint32_t tcp_connection;
+ unsigned int status;
+ unsigned int connection_id;
+ } connections[MAX_FRIEND_TCP_CONNECTIONS];
+
+ int id; /* id used in callbacks. */
+} TCP_Connection_to;
+
+typedef struct {
+ uint8_t status;
+ TCP_Client_Connection *connection;
+ uint64_t connected_time;
+ uint32_t lock_count;
+ uint32_t sleep_count;
+ bool onion;
+
+ /* Only used when connection is sleeping. */
+ IP_Port ip_port;
+ uint8_t relay_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ bool unsleep; /* set to 1 to unsleep connection. */
+} TCP_con;
+
+typedef struct TCP_Connections TCP_Connections;
+
+const uint8_t *tcp_connections_public_key(const TCP_Connections *tcp_c);
+
+/* Send a packet to the TCP connection.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, const uint8_t *packet, uint16_t length);
+
+/* Return a random TCP connection number for use in send_tcp_onion_request.
+ *
+ * TODO(irungentoo): This number is just the index of an array that the elements
+ * can change without warning.
+ *
+ * return TCP connection number on success.
+ * return -1 on failure.
+ */
+int get_random_tcp_onion_conn_number(TCP_Connections *tcp_c);
+
+/* Send an onion packet via the TCP relay corresponding to tcp_connections_number.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int tcp_send_onion_request(TCP_Connections *tcp_c, unsigned int tcp_connections_number, const uint8_t *data,
+ uint16_t length);
+
+/* Set if we want TCP_connection to allocate some connection for onion use.
+ *
+ * If status is 1, allocate some connections. if status is 0, don't.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int set_tcp_onion_status(TCP_Connections *tcp_c, bool status);
+
+/* Send an oob packet via the TCP relay corresponding to tcp_connections_number.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int tcp_send_oob_packet(TCP_Connections *tcp_c, unsigned int tcp_connections_number, const uint8_t *public_key,
+ const uint8_t *packet, uint16_t length);
+
+/* Set the callback for TCP data packets.
+ */
+void set_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_data_callback)(void *object, int id,
+ const uint8_t *data, uint16_t length, void *userdata), void *object);
+
+/* Set the callback for TCP onion packets.
+ */
+void set_onion_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_onion_callback)(void *object,
+ const uint8_t *data, uint16_t length, void *userdata), void *object);
+
+/* Set the callback for TCP oob data packets.
+ */
+void set_oob_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_oob_callback)(void *object,
+ const uint8_t *public_key, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length, void *userdata),
+ void *object);
+
+/* Create a new TCP connection to public_key.
+ *
+ * public_key must be the counterpart to the secret key that the other peer used with new_tcp_connections().
+ *
+ * id is the id in the callbacks for that connection.
+ *
+ * return connections_number on success.
+ * return -1 on failure.
+ */
+int new_tcp_connection_to(TCP_Connections *tcp_c, const uint8_t *public_key, int id);
+
+/* return 0 on success.
+ * return -1 on failure.
+ */
+int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number);
+
+/* Set connection status.
+ *
+ * status of 1 means we are using the connection.
+ * status of 0 means we are not using it.
+ *
+ * Unused tcp connections will be disconnected from but kept in case they are needed.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number, bool status);
+
+/* return number of online tcp relays tied to the connection on success.
+ * return 0 on failure.
+ */
+unsigned int tcp_connection_to_online_tcp_relays(TCP_Connections *tcp_c, int connections_number);
+
+/* Add a TCP relay tied to a connection.
+ *
+ * NOTE: This can only be used during the tcp_oob_callback.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int add_tcp_number_relay_connection(TCP_Connections *tcp_c, int connections_number,
+ unsigned int tcp_connections_number);
+
+/* Add a TCP relay tied to a connection.
+ *
+ * This should be called with the same relay by two peers who want to create a TCP connection with each other.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int add_tcp_relay_connection(TCP_Connections *tcp_c, int connections_number, IP_Port ip_port, const uint8_t *relay_pk);
+
+/* Add a TCP relay to the instance.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int add_tcp_relay_global(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t *relay_pk);
+
+/* Copy a maximum of max_num TCP relays we are connected to to tcp_relays.
+ * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.
+ *
+ * return number of relays copied to tcp_relays on success.
+ * return 0 on failure.
+ */
+unsigned int tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num);
+
+/* Returns a new TCP_Connections object associated with the secret_key.
+ *
+ * In order for others to connect to this instance new_tcp_connection_to() must be called with the
+ * public_key associated with secret_key.
+ *
+ * Returns NULL on failure.
+ */
+TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info);
+
+void do_tcp_connections(TCP_Connections *tcp_c, void *userdata);
+void kill_tcp_connections(TCP_Connections *tcp_c);
+
+#endif
+
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_server.c b/protocols/Tox/libtox/src/toxcore/TCP_server.c
new file mode 100644
index 0000000000..9b94667aa1
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/TCP_server.c
@@ -0,0 +1,1417 @@
+/*
+ * Implementation of the TCP relay server part of Tox.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2014 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "TCP_server.h"
+
+#include "util.h"
+
+#if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32)
+#include <sys/ioctl.h>
+#endif
+
+struct TCP_Server {
+ Onion *onion;
+
+#ifdef TCP_SERVER_USE_EPOLL
+ int efd;
+ uint64_t last_run_pinged;
+#endif
+ Socket *socks_listening;
+ unsigned int num_listening_socks;
+
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE];
+ TCP_Secure_Connection incoming_connection_queue[MAX_INCOMING_CONNECTIONS];
+ uint16_t incoming_connection_queue_index;
+ TCP_Secure_Connection unconfirmed_connection_queue[MAX_INCOMING_CONNECTIONS];
+ uint16_t unconfirmed_connection_queue_index;
+
+ TCP_Secure_Connection *accepted_connection_array;
+ uint32_t size_accepted_connections;
+ uint32_t num_accepted_connections;
+
+ uint64_t counter;
+
+ BS_LIST accepted_key_list;
+};
+
+const uint8_t *tcp_server_public_key(const TCP_Server *tcp_server)
+{
+ return tcp_server->public_key;
+}
+
+size_t tcp_server_listen_count(const TCP_Server *tcp_server)
+{
+ return tcp_server->num_listening_socks;
+}
+
+/* This is needed to compile on Android below API 21
+ */
+#ifndef EPOLLRDHUP
+#define EPOLLRDHUP 0x2000
+#endif
+
+/* Set the size of the connection list to numfriends.
+ *
+ * return -1 if realloc fails.
+ * return 0 if it succeeds.
+ */
+static int realloc_connection(TCP_Server *TCP_server, uint32_t num)
+{
+ if (num == 0) {
+ free(TCP_server->accepted_connection_array);
+ TCP_server->accepted_connection_array = NULL;
+ TCP_server->size_accepted_connections = 0;
+ return 0;
+ }
+
+ if (num == TCP_server->size_accepted_connections) {
+ return 0;
+ }
+
+ TCP_Secure_Connection *new_connections = (TCP_Secure_Connection *)realloc(
+ TCP_server->accepted_connection_array,
+ num * sizeof(TCP_Secure_Connection));
+
+ if (new_connections == NULL) {
+ return -1;
+ }
+
+ if (num > TCP_server->size_accepted_connections) {
+ uint32_t old_size = TCP_server->size_accepted_connections;
+ uint32_t size_new_entries = (num - old_size) * sizeof(TCP_Secure_Connection);
+ memset(new_connections + old_size, 0, size_new_entries);
+ }
+
+ TCP_server->accepted_connection_array = new_connections;
+ TCP_server->size_accepted_connections = num;
+ return 0;
+}
+
+/* return index corresponding to connection with peer on success
+ * return -1 on failure.
+ */
+static int get_TCP_connection_index(const TCP_Server *TCP_server, const uint8_t *public_key)
+{
+ return bs_list_find(&TCP_server->accepted_key_list, public_key);
+}
+
+
+static int kill_accepted(TCP_Server *TCP_server, int index);
+
+/* Add accepted TCP connection to the list.
+ *
+ * return index on success
+ * return -1 on failure
+ */
+static int add_accepted(TCP_Server *TCP_server, const TCP_Secure_Connection *con)
+{
+ int index = get_TCP_connection_index(TCP_server, con->public_key);
+
+ if (index != -1) { /* If an old connection to the same public key exists, kill it. */
+ kill_accepted(TCP_server, index);
+ index = -1;
+ }
+
+ if (TCP_server->size_accepted_connections == TCP_server->num_accepted_connections) {
+ if (realloc_connection(TCP_server, TCP_server->size_accepted_connections + 4) == -1) {
+ return -1;
+ }
+
+ index = TCP_server->num_accepted_connections;
+ } else {
+ uint32_t i;
+
+ for (i = TCP_server->size_accepted_connections; i != 0; --i) {
+ if (TCP_server->accepted_connection_array[i - 1].status == TCP_STATUS_NO_STATUS) {
+ index = i - 1;
+ break;
+ }
+ }
+ }
+
+ if (index == -1) {
+ fprintf(stderr, "FAIL index is -1\n");
+ return -1;
+ }
+
+ if (!bs_list_add(&TCP_server->accepted_key_list, con->public_key, index)) {
+ return -1;
+ }
+
+ memcpy(&TCP_server->accepted_connection_array[index], con, sizeof(TCP_Secure_Connection));
+ TCP_server->accepted_connection_array[index].status = TCP_STATUS_CONFIRMED;
+ ++TCP_server->num_accepted_connections;
+ TCP_server->accepted_connection_array[index].identifier = ++TCP_server->counter;
+ TCP_server->accepted_connection_array[index].last_pinged = unix_time();
+ TCP_server->accepted_connection_array[index].ping_id = 0;
+
+ return index;
+}
+
+/* Delete accepted connection from list.
+ *
+ * return 0 on success
+ * return -1 on failure
+ */
+static int del_accepted(TCP_Server *TCP_server, int index)
+{
+ if ((uint32_t)index >= TCP_server->size_accepted_connections) {
+ return -1;
+ }
+
+ if (TCP_server->accepted_connection_array[index].status == TCP_STATUS_NO_STATUS) {
+ return -1;
+ }
+
+ if (!bs_list_remove(&TCP_server->accepted_key_list, TCP_server->accepted_connection_array[index].public_key, index)) {
+ return -1;
+ }
+
+ crypto_memzero(&TCP_server->accepted_connection_array[index], sizeof(TCP_Secure_Connection));
+ --TCP_server->num_accepted_connections;
+
+ if (TCP_server->num_accepted_connections == 0) {
+ realloc_connection(TCP_server, 0);
+ }
+
+ return 0;
+}
+
+/* return the amount of data in the tcp recv buffer.
+ * return 0 on failure.
+ */
+unsigned int TCP_socket_data_recv_buffer(Socket sock)
+{
+#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
+ unsigned long count = 0;
+ ioctlsocket(sock, FIONREAD, &count);
+#else
+ int count = 0;
+ ioctl(sock, FIONREAD, &count);
+#endif
+
+ return count;
+}
+
+/* Read the next two bytes in TCP stream then convert them to
+ * length (host byte order).
+ *
+ * return length on success
+ * return 0 if nothing has been read from socket.
+ * return ~0 on failure.
+ */
+uint16_t read_TCP_length(Socket sock)
+{
+ unsigned int count = TCP_socket_data_recv_buffer(sock);
+
+ if (count >= sizeof(uint16_t)) {
+ uint16_t length;
+ int len = recv(sock, (char *)&length, sizeof(uint16_t), MSG_NOSIGNAL);
+
+ if (len != sizeof(uint16_t)) {
+ fprintf(stderr, "FAIL recv packet\n");
+ return 0;
+ }
+
+ length = net_ntohs(length);
+
+ if (length > MAX_PACKET_SIZE) {
+ return ~0;
+ }
+
+ return length;
+ }
+
+ return 0;
+}
+
+/* Read length bytes from socket.
+ *
+ * return length on success
+ * return -1 on failure/no data in buffer.
+ */
+int read_TCP_packet(Socket sock, uint8_t *data, uint16_t length)
+{
+ unsigned int count = TCP_socket_data_recv_buffer(sock);
+
+ if (count >= length) {
+ int len = recv(sock, (char *)data, length, MSG_NOSIGNAL);
+
+ if (len != length) {
+ fprintf(stderr, "FAIL recv packet\n");
+ return -1;
+ }
+
+ return len;
+ }
+
+ return -1;
+}
+
+/* return length of received packet on success.
+ * return 0 if could not read any packet.
+ * return -1 on failure (connection must be killed).
+ */
+int read_packet_TCP_secure_connection(Socket sock, uint16_t *next_packet_length, const uint8_t *shared_key,
+ uint8_t *recv_nonce, uint8_t *data, uint16_t max_len)
+{
+ if (*next_packet_length == 0) {
+ uint16_t len = read_TCP_length(sock);
+
+ if (len == (uint16_t)~0) {
+ return -1;
+ }
+
+ if (len == 0) {
+ return 0;
+ }
+
+ *next_packet_length = len;
+ }
+
+ if (max_len + CRYPTO_MAC_SIZE < *next_packet_length) {
+ return -1;
+ }
+
+ VLA(uint8_t, data_encrypted, *next_packet_length);
+ int len_packet = read_TCP_packet(sock, data_encrypted, *next_packet_length);
+
+ if (len_packet != *next_packet_length) {
+ return 0;
+ }
+
+ *next_packet_length = 0;
+
+ int len = decrypt_data_symmetric(shared_key, recv_nonce, data_encrypted, len_packet, data);
+
+ if (len + CRYPTO_MAC_SIZE != len_packet) {
+ return -1;
+ }
+
+ increment_nonce(recv_nonce);
+
+ return len;
+}
+
+/* return 0 if pending data was sent completely
+ * return -1 if it wasn't
+ */
+static int send_pending_data_nonpriority(TCP_Secure_Connection *con)
+{
+ if (con->last_packet_length == 0) {
+ return 0;
+ }
+
+ uint16_t left = con->last_packet_length - con->last_packet_sent;
+ int len = send(con->sock, (const char *)(con->last_packet + con->last_packet_sent), left, MSG_NOSIGNAL);
+
+ if (len <= 0) {
+ return -1;
+ }
+
+ if (len == left) {
+ con->last_packet_length = 0;
+ con->last_packet_sent = 0;
+ return 0;
+ }
+
+ con->last_packet_sent += len;
+ return -1;
+}
+
+/* return 0 if pending data was sent completely
+ * return -1 if it wasn't
+ */
+static int send_pending_data(TCP_Secure_Connection *con)
+{
+ /* finish sending current non-priority packet */
+ if (send_pending_data_nonpriority(con) == -1) {
+ return -1;
+ }
+
+ TCP_Priority_List *p = con->priority_queue_start;
+
+ while (p) {
+ uint16_t left = p->size - p->sent;
+ int len = send(con->sock, (const char *)(p->data + p->sent), left, MSG_NOSIGNAL);
+
+ if (len != left) {
+ if (len > 0) {
+ p->sent += len;
+ }
+
+ break;
+ }
+
+ TCP_Priority_List *pp = p;
+ p = p->next;
+ free(pp);
+ }
+
+ con->priority_queue_start = p;
+
+ if (!p) {
+ con->priority_queue_end = NULL;
+ return 0;
+ }
+
+ return -1;
+}
+
+/* return 0 on failure (only if malloc fails)
+ * return 1 on success
+ */
+static bool add_priority(TCP_Secure_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent)
+{
+ TCP_Priority_List *p = con->priority_queue_end;
+ TCP_Priority_List *new_list = (TCP_Priority_List *)malloc(sizeof(TCP_Priority_List) + size);
+
+ if (!new_list) {
+ return 0;
+ }
+
+ new_list->next = NULL;
+ new_list->size = size;
+ new_list->sent = sent;
+ memcpy(new_list->data, packet, size);
+
+ if (p) {
+ p->next = new_list;
+ } else {
+ con->priority_queue_start = new_list;
+ }
+
+ con->priority_queue_end = new_list;
+ return 1;
+}
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure (connection must be killed).
+ */
+static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length,
+ bool priority)
+{
+ if (length + CRYPTO_MAC_SIZE > MAX_PACKET_SIZE) {
+ return -1;
+ }
+
+ bool sendpriority = 1;
+
+ if (send_pending_data(con) == -1) {
+ if (priority) {
+ sendpriority = 0;
+ } else {
+ return 0;
+ }
+ }
+
+ VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE);
+
+ uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE);
+ memcpy(packet, &c_length, sizeof(uint16_t));
+ int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));
+
+ if ((unsigned int)len != (SIZEOF_VLA(packet) - sizeof(uint16_t))) {
+ return -1;
+ }
+
+ if (priority) {
+ len = sendpriority ? send(con->sock, (const char *)packet, SIZEOF_VLA(packet), MSG_NOSIGNAL) : 0;
+
+ if (len <= 0) {
+ len = 0;
+ }
+
+ increment_nonce(con->sent_nonce);
+
+ if ((unsigned int)len == SIZEOF_VLA(packet)) {
+ return 1;
+ }
+
+ return add_priority(con, packet, SIZEOF_VLA(packet), len);
+ }
+
+ len = send(con->sock, (const char *)packet, SIZEOF_VLA(packet), MSG_NOSIGNAL);
+
+ if (len <= 0) {
+ return 0;
+ }
+
+ increment_nonce(con->sent_nonce);
+
+ if ((unsigned int)len == SIZEOF_VLA(packet)) {
+ return 1;
+ }
+
+ memcpy(con->last_packet, packet, SIZEOF_VLA(packet));
+ con->last_packet_length = SIZEOF_VLA(packet);
+ con->last_packet_sent = len;
+ return 1;
+}
+
+/* Kill a TCP_Secure_Connection
+ */
+static void kill_TCP_secure_connection(TCP_Secure_Connection *con)
+{
+ kill_sock(con->sock);
+ crypto_memzero(con, sizeof(TCP_Secure_Connection));
+}
+
+static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number);
+
+/* Kill an accepted TCP_Secure_Connection
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int kill_accepted(TCP_Server *TCP_server, int index)
+{
+ if ((uint32_t)index >= TCP_server->size_accepted_connections) {
+ return -1;
+ }
+
+ uint32_t i;
+
+ for (i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) {
+ rm_connection_index(TCP_server, &TCP_server->accepted_connection_array[index], i);
+ }
+
+ Socket sock = TCP_server->accepted_connection_array[index].sock;
+
+ if (del_accepted(TCP_server, index) != 0) {
+ return -1;
+ }
+
+ kill_sock(sock);
+ return 0;
+}
+
+/* return 1 if everything went well.
+ * return -1 if the connection must be killed.
+ */
+static int handle_TCP_handshake(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length,
+ const uint8_t *self_secret_key)
+{
+ if (length != TCP_CLIENT_HANDSHAKE_SIZE) {
+ return -1;
+ }
+
+ if (con->status != TCP_STATUS_CONNECTED) {
+ return -1;
+ }
+
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
+ encrypt_precompute(data, self_secret_key, shared_key);
+ uint8_t plain[TCP_HANDSHAKE_PLAIN_SIZE];
+ int len = decrypt_data_symmetric(shared_key, data + CRYPTO_PUBLIC_KEY_SIZE,
+ data + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE, plain);
+
+ if (len != TCP_HANDSHAKE_PLAIN_SIZE) {
+ return -1;
+ }
+
+ memcpy(con->public_key, data, CRYPTO_PUBLIC_KEY_SIZE);
+ uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE];
+ uint8_t resp_plain[TCP_HANDSHAKE_PLAIN_SIZE];
+ crypto_new_keypair(resp_plain, temp_secret_key);
+ random_nonce(con->sent_nonce);
+ memcpy(resp_plain + CRYPTO_PUBLIC_KEY_SIZE, con->sent_nonce, CRYPTO_NONCE_SIZE);
+ memcpy(con->recv_nonce, plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_NONCE_SIZE);
+
+ uint8_t response[TCP_SERVER_HANDSHAKE_SIZE];
+ random_nonce(response);
+
+ len = encrypt_data_symmetric(shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE,
+ response + CRYPTO_NONCE_SIZE);
+
+ if (len != TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE) {
+ return -1;
+ }
+
+ if (TCP_SERVER_HANDSHAKE_SIZE != send(con->sock, (const char *)response, TCP_SERVER_HANDSHAKE_SIZE, MSG_NOSIGNAL)) {
+ return -1;
+ }
+
+ encrypt_precompute(plain, temp_secret_key, con->shared_key);
+ con->status = TCP_STATUS_UNCONFIRMED;
+ return 1;
+}
+
+/* return 1 if connection handshake was handled correctly.
+ * return 0 if we didn't get it yet.
+ * return -1 if the connection must be killed.
+ */
+static int read_connection_handshake(TCP_Secure_Connection *con, const uint8_t *self_secret_key)
+{
+ uint8_t data[TCP_CLIENT_HANDSHAKE_SIZE];
+ int len = 0;
+
+ if ((len = read_TCP_packet(con->sock, data, TCP_CLIENT_HANDSHAKE_SIZE)) != -1) {
+ return handle_TCP_handshake(con, data, len, self_secret_key);
+ }
+
+ return 0;
+}
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure (connection must be killed).
+ */
+static int send_routing_response(TCP_Secure_Connection *con, uint8_t rpid, const uint8_t *public_key)
+{
+ uint8_t data[1 + 1 + CRYPTO_PUBLIC_KEY_SIZE];
+ data[0] = TCP_PACKET_ROUTING_RESPONSE;
+ data[1] = rpid;
+ memcpy(data + 2, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+
+ return write_packet_TCP_secure_connection(con, data, sizeof(data), 1);
+}
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure (connection must be killed).
+ */
+static int send_connect_notification(TCP_Secure_Connection *con, uint8_t id)
+{
+ uint8_t data[2] = {TCP_PACKET_CONNECTION_NOTIFICATION, (uint8_t)(id + NUM_RESERVED_PORTS)};
+ return write_packet_TCP_secure_connection(con, data, sizeof(data), 1);
+}
+
+/* return 1 on success.
+ * return 0 if could not send packet.
+ * return -1 on failure (connection must be killed).
+ */
+static int send_disconnect_notification(TCP_Secure_Connection *con, uint8_t id)
+{
+ uint8_t data[2] = {TCP_PACKET_DISCONNECT_NOTIFICATION, (uint8_t)(id + NUM_RESERVED_PORTS)};
+ return write_packet_TCP_secure_connection(con, data, sizeof(data), 1);
+}
+
+/* return 0 on success.
+ * return -1 on failure (connection must be killed).
+ */
+static int handle_TCP_routing_req(TCP_Server *TCP_server, uint32_t con_id, const uint8_t *public_key)
+{
+ uint32_t i;
+ uint32_t index = ~0;
+ TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[con_id];
+
+ /* If person tries to cennect to himself we deny the request*/
+ if (public_key_cmp(con->public_key, public_key) == 0) {
+ if (send_routing_response(con, 0, public_key) == -1) {
+ return -1;
+ }
+
+ return 0;
+ }
+
+ for (i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) {
+ if (con->connections[i].status != 0) {
+ if (public_key_cmp(public_key, con->connections[i].public_key) == 0) {
+ if (send_routing_response(con, i + NUM_RESERVED_PORTS, public_key) == -1) {
+ return -1;
+ }
+
+ return 0;
+ }
+ } else if (index == (uint32_t)~0) {
+ index = i;
+ }
+ }
+
+ if (index == (uint32_t)~0) {
+ if (send_routing_response(con, 0, public_key) == -1) {
+ return -1;
+ }
+
+ return 0;
+ }
+
+ int ret = send_routing_response(con, index + NUM_RESERVED_PORTS, public_key);
+
+ if (ret == 0) {
+ return 0;
+ }
+
+ if (ret == -1) {
+ return -1;
+ }
+
+ con->connections[index].status = 1;
+ memcpy(con->connections[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ int other_index = get_TCP_connection_index(TCP_server, public_key);
+
+ if (other_index != -1) {
+ uint32_t other_id = ~0;
+ TCP_Secure_Connection *other_conn = &TCP_server->accepted_connection_array[other_index];
+
+ for (i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) {
+ if (other_conn->connections[i].status == 1
+ && public_key_cmp(other_conn->connections[i].public_key, con->public_key) == 0) {
+ other_id = i;
+ break;
+ }
+ }
+
+ if (other_id != (uint32_t)~0) {
+ con->connections[index].status = 2;
+ con->connections[index].index = other_index;
+ con->connections[index].other_id = other_id;
+ other_conn->connections[other_id].status = 2;
+ other_conn->connections[other_id].index = con_id;
+ other_conn->connections[other_id].other_id = index;
+ // TODO(irungentoo): return values?
+ send_connect_notification(con, index);
+ send_connect_notification(other_conn, other_id);
+ }
+ }
+
+ return 0;
+}
+
+/* return 0 on success.
+ * return -1 on failure (connection must be killed).
+ */
+static int handle_TCP_oob_send(TCP_Server *TCP_server, uint32_t con_id, const uint8_t *public_key, const uint8_t *data,
+ uint16_t length)
+{
+ if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) {
+ return -1;
+ }
+
+ TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[con_id];
+
+ int other_index = get_TCP_connection_index(TCP_server, public_key);
+
+ if (other_index != -1) {
+ VLA(uint8_t, resp_packet, 1 + CRYPTO_PUBLIC_KEY_SIZE + length);
+ resp_packet[0] = TCP_PACKET_OOB_RECV;
+ memcpy(resp_packet + 1, con->public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(resp_packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length);
+ write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[other_index], resp_packet,
+ SIZEOF_VLA(resp_packet), 0);
+ }
+
+ return 0;
+}
+
+/* Remove connection with con_number from the connections array of con.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number)
+{
+ if (con_number >= NUM_CLIENT_CONNECTIONS) {
+ return -1;
+ }
+
+ if (con->connections[con_number].status) {
+ uint32_t index = con->connections[con_number].index;
+ uint8_t other_id = con->connections[con_number].other_id;
+
+ if (con->connections[con_number].status == 2) {
+
+ if (index >= TCP_server->size_accepted_connections) {
+ return -1;
+ }
+
+ TCP_server->accepted_connection_array[index].connections[other_id].other_id = 0;
+ TCP_server->accepted_connection_array[index].connections[other_id].index = 0;
+ TCP_server->accepted_connection_array[index].connections[other_id].status = 1;
+ // TODO(irungentoo): return values?
+ send_disconnect_notification(&TCP_server->accepted_connection_array[index], other_id);
+ }
+
+ con->connections[con_number].index = 0;
+ con->connections[con_number].other_id = 0;
+ con->connections[con_number].status = 0;
+ return 0;
+ }
+
+ return -1;
+}
+
+static int handle_onion_recv_1(void *object, IP_Port dest, const uint8_t *data, uint16_t length)
+{
+ TCP_Server *TCP_server = (TCP_Server *)object;
+ uint32_t index = dest.ip.ip6.uint32[0];
+
+ if (index >= TCP_server->size_accepted_connections) {
+ return 1;
+ }
+
+ TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[index];
+
+ if (con->identifier != dest.ip.ip6.uint64[1]) {
+ return 1;
+ }
+
+ VLA(uint8_t, packet, 1 + length);
+ memcpy(packet + 1, data, length);
+ packet[0] = TCP_PACKET_ONION_RESPONSE;
+
+ if (write_packet_TCP_secure_connection(con, packet, SIZEOF_VLA(packet), 0) != 1) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/* return 0 on success
+ * return -1 on failure
+ */
+static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, const uint8_t *data, uint16_t length)
+{
+ if (length == 0) {
+ return -1;
+ }
+
+ TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[con_id];
+
+ switch (data[0]) {
+ case TCP_PACKET_ROUTING_REQUEST: {
+ if (length != 1 + CRYPTO_PUBLIC_KEY_SIZE) {
+ return -1;
+ }
+
+ return handle_TCP_routing_req(TCP_server, con_id, data + 1);
+ }
+
+ case TCP_PACKET_CONNECTION_NOTIFICATION: {
+ if (length != 2) {
+ return -1;
+ }
+
+ break;
+ }
+
+ case TCP_PACKET_DISCONNECT_NOTIFICATION: {
+ if (length != 2) {
+ return -1;
+ }
+
+ return rm_connection_index(TCP_server, con, data[1] - NUM_RESERVED_PORTS);
+ }
+
+ case TCP_PACKET_PING: {
+ if (length != 1 + sizeof(uint64_t)) {
+ return -1;
+ }
+
+ uint8_t response[1 + sizeof(uint64_t)];
+ response[0] = TCP_PACKET_PONG;
+ memcpy(response + 1, data + 1, sizeof(uint64_t));
+ write_packet_TCP_secure_connection(con, response, sizeof(response), 1);
+ return 0;
+ }
+
+ case TCP_PACKET_PONG: {
+ if (length != 1 + sizeof(uint64_t)) {
+ return -1;
+ }
+
+ uint64_t ping_id;
+ memcpy(&ping_id, data + 1, sizeof(uint64_t));
+
+ if (ping_id) {
+ if (ping_id == con->ping_id) {
+ con->ping_id = 0;
+ }
+
+ return 0;
+ }
+
+ return -1;
+ }
+
+ case TCP_PACKET_OOB_SEND: {
+ if (length <= 1 + CRYPTO_PUBLIC_KEY_SIZE) {
+ return -1;
+ }
+
+ return handle_TCP_oob_send(TCP_server, con_id, data + 1, data + 1 + CRYPTO_PUBLIC_KEY_SIZE,
+ length - (1 + CRYPTO_PUBLIC_KEY_SIZE));
+ }
+
+ case TCP_PACKET_ONION_REQUEST: {
+ if (TCP_server->onion) {
+ if (length <= 1 + CRYPTO_NONCE_SIZE + ONION_SEND_BASE * 2) {
+ return -1;
+ }
+
+ IP_Port source;
+ source.port = 0; // dummy initialise
+ source.ip.family = TCP_ONION_FAMILY;
+ source.ip.ip6.uint32[0] = con_id;
+ source.ip.ip6.uint32[1] = 0;
+ source.ip.ip6.uint64[1] = con->identifier;
+ onion_send_1(TCP_server->onion, data + 1 + CRYPTO_NONCE_SIZE, length - (1 + CRYPTO_NONCE_SIZE), source,
+ data + 1);
+ }
+
+ return 0;
+ }
+
+ case TCP_PACKET_ONION_RESPONSE: {
+ return -1;
+ }
+
+ default: {
+ if (data[0] < NUM_RESERVED_PORTS) {
+ return -1;
+ }
+
+ uint8_t c_id = data[0] - NUM_RESERVED_PORTS;
+
+ if (c_id >= NUM_CLIENT_CONNECTIONS) {
+ return -1;
+ }
+
+ if (con->connections[c_id].status == 0) {
+ return -1;
+ }
+
+ if (con->connections[c_id].status != 2) {
+ return 0;
+ }
+
+ uint32_t index = con->connections[c_id].index;
+ uint8_t other_c_id = con->connections[c_id].other_id + NUM_RESERVED_PORTS;
+ VLA(uint8_t, new_data, length);
+ memcpy(new_data, data, length);
+ new_data[0] = other_c_id;
+ int ret = write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[index], new_data, length, 0);
+
+ if (ret == -1) {
+ return -1;
+ }
+
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+
+static int confirm_TCP_connection(TCP_Server *TCP_server, TCP_Secure_Connection *con, const uint8_t *data,
+ uint16_t length)
+{
+ int index = add_accepted(TCP_server, con);
+
+ if (index == -1) {
+ kill_TCP_secure_connection(con);
+ return -1;
+ }
+
+ crypto_memzero(con, sizeof(TCP_Secure_Connection));
+
+ if (handle_TCP_packet(TCP_server, index, data, length) == -1) {
+ kill_accepted(TCP_server, index);
+ return -1;
+ }
+
+ return index;
+}
+
+/* return index on success
+ * return -1 on failure
+ */
+static int accept_connection(TCP_Server *TCP_server, Socket sock)
+{
+ if (!sock_valid(sock)) {
+ return -1;
+ }
+
+ if (!set_socket_nonblock(sock)) {
+ kill_sock(sock);
+ return -1;
+ }
+
+ if (!set_socket_nosigpipe(sock)) {
+ kill_sock(sock);
+ return -1;
+ }
+
+ uint16_t index = TCP_server->incoming_connection_queue_index % MAX_INCOMING_CONNECTIONS;
+
+ TCP_Secure_Connection *conn = &TCP_server->incoming_connection_queue[index];
+
+ if (conn->status != TCP_STATUS_NO_STATUS) {
+ kill_TCP_secure_connection(conn);
+ }
+
+ conn->status = TCP_STATUS_CONNECTED;
+ conn->sock = sock;
+ conn->next_packet_length = 0;
+
+ ++TCP_server->incoming_connection_queue_index;
+ return index;
+}
+
+static Socket new_listening_TCP_socket(int family, uint16_t port)
+{
+ Socket sock = net_socket(family, TOX_SOCK_STREAM, TOX_PROTO_TCP);
+
+ if (!sock_valid(sock)) {
+ return ~0;
+ }
+
+ int ok = set_socket_nonblock(sock);
+
+ if (ok && family == TOX_AF_INET6) {
+ ok = set_socket_dualstack(sock);
+ }
+
+ if (ok) {
+ ok = set_socket_reuseaddr(sock);
+ }
+
+ ok = ok && bind_to_port(sock, family, port) && (listen(sock, TCP_MAX_BACKLOG) == 0);
+
+ if (!ok) {
+ kill_sock(sock);
+ return ~0;
+ }
+
+ return sock;
+}
+
+TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uint16_t *ports, const uint8_t *secret_key,
+ Onion *onion)
+{
+ if (num_sockets == 0 || ports == NULL) {
+ return NULL;
+ }
+
+ if (networking_at_startup() != 0) {
+ return NULL;
+ }
+
+ TCP_Server *temp = (TCP_Server *)calloc(1, sizeof(TCP_Server));
+
+ if (temp == NULL) {
+ return NULL;
+ }
+
+ temp->socks_listening = (Socket *)calloc(num_sockets, sizeof(Socket));
+
+ if (temp->socks_listening == NULL) {
+ free(temp);
+ return NULL;
+ }
+
+#ifdef TCP_SERVER_USE_EPOLL
+ temp->efd = epoll_create(8);
+
+ if (temp->efd == -1) {
+ free(temp->socks_listening);
+ free(temp);
+ return NULL;
+ }
+
+#endif
+
+ uint8_t family;
+
+ if (ipv6_enabled) {
+ family = TOX_AF_INET6;
+ } else {
+ family = TOX_AF_INET;
+ }
+
+ uint32_t i;
+#ifdef TCP_SERVER_USE_EPOLL
+ struct epoll_event ev;
+#endif
+
+ for (i = 0; i < num_sockets; ++i) {
+ Socket sock = new_listening_TCP_socket(family, ports[i]);
+
+ if (sock_valid(sock)) {
+#ifdef TCP_SERVER_USE_EPOLL
+ ev.events = EPOLLIN | EPOLLET;
+ ev.data.u64 = sock | ((uint64_t)TCP_SOCKET_LISTENING << 32);
+
+ if (epoll_ctl(temp->efd, EPOLL_CTL_ADD, sock, &ev) == -1) {
+ continue;
+ }
+
+#endif
+
+ temp->socks_listening[temp->num_listening_socks] = sock;
+ ++temp->num_listening_socks;
+ }
+ }
+
+ if (temp->num_listening_socks == 0) {
+ free(temp->socks_listening);
+ free(temp);
+ return NULL;
+ }
+
+ if (onion) {
+ temp->onion = onion;
+ set_callback_handle_recv_1(onion, &handle_onion_recv_1, temp);
+ }
+
+ memcpy(temp->secret_key, secret_key, CRYPTO_SECRET_KEY_SIZE);
+ crypto_derive_public_key(temp->public_key, temp->secret_key);
+
+ bs_list_init(&temp->accepted_key_list, CRYPTO_PUBLIC_KEY_SIZE, 8);
+
+ return temp;
+}
+
+static void do_TCP_accept_new(TCP_Server *TCP_server)
+{
+ uint32_t i;
+
+ for (i = 0; i < TCP_server->num_listening_socks; ++i) {
+ struct sockaddr_storage addr;
+ socklen_t addrlen = sizeof(addr);
+ Socket sock;
+
+ do {
+ sock = accept(TCP_server->socks_listening[i], (struct sockaddr *)&addr, &addrlen);
+ } while (accept_connection(TCP_server, sock) != -1);
+ }
+}
+
+static int do_incoming(TCP_Server *TCP_server, uint32_t i)
+{
+ if (TCP_server->incoming_connection_queue[i].status != TCP_STATUS_CONNECTED) {
+ return -1;
+ }
+
+ int ret = read_connection_handshake(&TCP_server->incoming_connection_queue[i], TCP_server->secret_key);
+
+ if (ret == -1) {
+ kill_TCP_secure_connection(&TCP_server->incoming_connection_queue[i]);
+ } else if (ret == 1) {
+ int index_new = TCP_server->unconfirmed_connection_queue_index % MAX_INCOMING_CONNECTIONS;
+ TCP_Secure_Connection *conn_old = &TCP_server->incoming_connection_queue[i];
+ TCP_Secure_Connection *conn_new = &TCP_server->unconfirmed_connection_queue[index_new];
+
+ if (conn_new->status != TCP_STATUS_NO_STATUS) {
+ kill_TCP_secure_connection(conn_new);
+ }
+
+ memcpy(conn_new, conn_old, sizeof(TCP_Secure_Connection));
+ crypto_memzero(conn_old, sizeof(TCP_Secure_Connection));
+ ++TCP_server->unconfirmed_connection_queue_index;
+
+ return index_new;
+ }
+
+ return -1;
+}
+
+static int do_unconfirmed(TCP_Server *TCP_server, uint32_t i)
+{
+ TCP_Secure_Connection *conn = &TCP_server->unconfirmed_connection_queue[i];
+
+ if (conn->status != TCP_STATUS_UNCONFIRMED) {
+ return -1;
+ }
+
+ uint8_t packet[MAX_PACKET_SIZE];
+ int len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, conn->recv_nonce,
+ packet, sizeof(packet));
+
+ if (len == 0) {
+ return -1;
+ }
+
+ if (len == -1) {
+ kill_TCP_secure_connection(conn);
+ return -1;
+ }
+
+ return confirm_TCP_connection(TCP_server, conn, packet, len);
+}
+
+static void do_confirmed_recv(TCP_Server *TCP_server, uint32_t i)
+{
+ TCP_Secure_Connection *conn = &TCP_server->accepted_connection_array[i];
+
+ uint8_t packet[MAX_PACKET_SIZE];
+ int len;
+
+ while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key,
+ conn->recv_nonce, packet, sizeof(packet)))) {
+ if (len == -1) {
+ kill_accepted(TCP_server, i);
+ break;
+ }
+
+ if (handle_TCP_packet(TCP_server, i, packet, len) == -1) {
+ kill_accepted(TCP_server, i);
+ break;
+ }
+ }
+}
+
+static void do_TCP_incoming(TCP_Server *TCP_server)
+{
+ uint32_t i;
+
+ for (i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) {
+ do_incoming(TCP_server, i);
+ }
+}
+
+static void do_TCP_unconfirmed(TCP_Server *TCP_server)
+{
+ uint32_t i;
+
+ for (i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) {
+ do_unconfirmed(TCP_server, i);
+ }
+}
+
+static void do_TCP_confirmed(TCP_Server *TCP_server)
+{
+#ifdef TCP_SERVER_USE_EPOLL
+
+ if (TCP_server->last_run_pinged == unix_time()) {
+ return;
+ }
+
+ TCP_server->last_run_pinged = unix_time();
+#endif
+ uint32_t i;
+
+ for (i = 0; i < TCP_server->size_accepted_connections; ++i) {
+ TCP_Secure_Connection *conn = &TCP_server->accepted_connection_array[i];
+
+ if (conn->status != TCP_STATUS_CONFIRMED) {
+ continue;
+ }
+
+ if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) {
+ uint8_t ping[1 + sizeof(uint64_t)];
+ ping[0] = TCP_PACKET_PING;
+ uint64_t ping_id = random_64b();
+
+ if (!ping_id) {
+ ++ping_id;
+ }
+
+ memcpy(ping + 1, &ping_id, sizeof(uint64_t));
+ int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping), 1);
+
+ if (ret == 1) {
+ conn->last_pinged = unix_time();
+ conn->ping_id = ping_id;
+ } else {
+ if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY + TCP_PING_TIMEOUT)) {
+ kill_accepted(TCP_server, i);
+ continue;
+ }
+ }
+ }
+
+ if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) {
+ kill_accepted(TCP_server, i);
+ continue;
+ }
+
+ send_pending_data(conn);
+
+#ifndef TCP_SERVER_USE_EPOLL
+
+ do_confirmed_recv(TCP_server, i);
+
+#endif
+ }
+}
+
+#ifdef TCP_SERVER_USE_EPOLL
+static void do_TCP_epoll(TCP_Server *TCP_server)
+{
+#define MAX_EVENTS 16
+ struct epoll_event events[MAX_EVENTS];
+ int nfds;
+
+ while ((nfds = epoll_wait(TCP_server->efd, events, MAX_EVENTS, 0)) > 0) {
+ int n;
+
+ for (n = 0; n < nfds; ++n) {
+ Socket sock = events[n].data.u64 & 0xFFFFFFFF;
+ int status = (events[n].data.u64 >> 32) & 0xFF, index = (events[n].data.u64 >> 40);
+
+ if ((events[n].events & EPOLLERR) || (events[n].events & EPOLLHUP) || (events[n].events & EPOLLRDHUP)) {
+ switch (status) {
+ case TCP_SOCKET_LISTENING: {
+ //should never happen
+ break;
+ }
+
+ case TCP_SOCKET_INCOMING: {
+ kill_TCP_secure_connection(&TCP_server->incoming_connection_queue[index]);
+ break;
+ }
+
+ case TCP_SOCKET_UNCONFIRMED: {
+ kill_TCP_secure_connection(&TCP_server->unconfirmed_connection_queue[index]);
+ break;
+ }
+
+ case TCP_SOCKET_CONFIRMED: {
+ kill_accepted(TCP_server, index);
+ break;
+ }
+ }
+
+ continue;
+ }
+
+
+ if (!(events[n].events & EPOLLIN)) {
+ continue;
+ }
+
+ switch (status) {
+ case TCP_SOCKET_LISTENING: {
+ //socket is from socks_listening, accept connection
+ struct sockaddr_storage addr;
+ socklen_t addrlen = sizeof(addr);
+
+ while (1) {
+ Socket sock_new = accept(sock, (struct sockaddr *)&addr, &addrlen);
+
+ if (!sock_valid(sock_new)) {
+ break;
+ }
+
+ int index_new = accept_connection(TCP_server, sock_new);
+
+ if (index_new == -1) {
+ continue;
+ }
+
+ struct epoll_event ev = {
+ .events = EPOLLIN | EPOLLET | EPOLLRDHUP,
+ .data.u64 = sock_new | ((uint64_t)TCP_SOCKET_INCOMING << 32) | ((uint64_t)index_new << 40)
+ };
+
+ if (epoll_ctl(TCP_server->efd, EPOLL_CTL_ADD, sock_new, &ev) == -1) {
+ kill_TCP_secure_connection(&TCP_server->incoming_connection_queue[index_new]);
+ continue;
+ }
+ }
+
+ break;
+ }
+
+ case TCP_SOCKET_INCOMING: {
+ int index_new;
+
+ if ((index_new = do_incoming(TCP_server, index)) != -1) {
+ events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP;
+ events[n].data.u64 = sock | ((uint64_t)TCP_SOCKET_UNCONFIRMED << 32) | ((uint64_t)index_new << 40);
+
+ if (epoll_ctl(TCP_server->efd, EPOLL_CTL_MOD, sock, &events[n]) == -1) {
+ kill_TCP_secure_connection(&TCP_server->unconfirmed_connection_queue[index_new]);
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case TCP_SOCKET_UNCONFIRMED: {
+ int index_new;
+
+ if ((index_new = do_unconfirmed(TCP_server, index)) != -1) {
+ events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP;
+ events[n].data.u64 = sock | ((uint64_t)TCP_SOCKET_CONFIRMED << 32) | ((uint64_t)index_new << 40);
+
+ if (epoll_ctl(TCP_server->efd, EPOLL_CTL_MOD, sock, &events[n]) == -1) {
+ //remove from confirmed connections
+ kill_accepted(TCP_server, index_new);
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case TCP_SOCKET_CONFIRMED: {
+ do_confirmed_recv(TCP_server, index);
+ break;
+ }
+ }
+ }
+ }
+
+#undef MAX_EVENTS
+}
+#endif
+
+void do_TCP_server(TCP_Server *TCP_server)
+{
+ unix_time_update();
+
+#ifdef TCP_SERVER_USE_EPOLL
+ do_TCP_epoll(TCP_server);
+
+#else
+ do_TCP_accept_new(TCP_server);
+ do_TCP_incoming(TCP_server);
+ do_TCP_unconfirmed(TCP_server);
+#endif
+
+ do_TCP_confirmed(TCP_server);
+}
+
+void kill_TCP_server(TCP_Server *TCP_server)
+{
+ uint32_t i;
+
+ for (i = 0; i < TCP_server->num_listening_socks; ++i) {
+ kill_sock(TCP_server->socks_listening[i]);
+ }
+
+ if (TCP_server->onion) {
+ set_callback_handle_recv_1(TCP_server->onion, NULL, NULL);
+ }
+
+ bs_list_free(&TCP_server->accepted_key_list);
+
+#ifdef TCP_SERVER_USE_EPOLL
+ close(TCP_server->efd);
+#endif
+
+ free(TCP_server->socks_listening);
+ free(TCP_server->accepted_connection_array);
+ free(TCP_server);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_server.h b/protocols/Tox/libtox/src/toxcore/TCP_server.h
new file mode 100644
index 0000000000..f213c078e6
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/TCP_server.h
@@ -0,0 +1,167 @@
+/*
+ * Implementation of the TCP relay server part of Tox.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2014 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TCP_SERVER_H
+#define TCP_SERVER_H
+
+#include "crypto_core.h"
+#include "list.h"
+#include "onion.h"
+
+#ifdef TCP_SERVER_USE_EPOLL
+#include <sys/epoll.h>
+#endif
+
+// Disable MSG_NOSIGNAL on systems not supporting it, e.g. Windows, FreeBSD
+#if !defined(MSG_NOSIGNAL)
+#define MSG_NOSIGNAL 0
+#endif
+
+#define MAX_INCOMING_CONNECTIONS 256
+
+#define TCP_MAX_BACKLOG MAX_INCOMING_CONNECTIONS
+
+#define MAX_PACKET_SIZE 2048
+
+#define TCP_HANDSHAKE_PLAIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE)
+#define TCP_SERVER_HANDSHAKE_SIZE (CRYPTO_NONCE_SIZE + TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE)
+#define TCP_CLIENT_HANDSHAKE_SIZE (CRYPTO_PUBLIC_KEY_SIZE + TCP_SERVER_HANDSHAKE_SIZE)
+#define TCP_MAX_OOB_DATA_LENGTH 1024
+
+#define NUM_RESERVED_PORTS 16
+#define NUM_CLIENT_CONNECTIONS (256 - NUM_RESERVED_PORTS)
+
+#define TCP_PACKET_ROUTING_REQUEST 0
+#define TCP_PACKET_ROUTING_RESPONSE 1
+#define TCP_PACKET_CONNECTION_NOTIFICATION 2
+#define TCP_PACKET_DISCONNECT_NOTIFICATION 3
+#define TCP_PACKET_PING 4
+#define TCP_PACKET_PONG 5
+#define TCP_PACKET_OOB_SEND 6
+#define TCP_PACKET_OOB_RECV 7
+#define TCP_PACKET_ONION_REQUEST 8
+#define TCP_PACKET_ONION_RESPONSE 9
+
+#define ARRAY_ENTRY_SIZE 6
+
+/* frequency to ping connected nodes and timeout in seconds */
+#define TCP_PING_FREQUENCY 30
+#define TCP_PING_TIMEOUT 10
+
+#ifdef TCP_SERVER_USE_EPOLL
+#define TCP_SOCKET_LISTENING 0
+#define TCP_SOCKET_INCOMING 1
+#define TCP_SOCKET_UNCONFIRMED 2
+#define TCP_SOCKET_CONFIRMED 3
+#endif
+
+enum {
+ TCP_STATUS_NO_STATUS,
+ TCP_STATUS_CONNECTED,
+ TCP_STATUS_UNCONFIRMED,
+ TCP_STATUS_CONFIRMED,
+};
+
+typedef struct TCP_Priority_List TCP_Priority_List;
+
+struct TCP_Priority_List {
+ TCP_Priority_List *next;
+ uint16_t size, sent;
+ uint8_t data[];
+};
+
+typedef struct TCP_Secure_Connection {
+ Socket sock;
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */
+ uint8_t sent_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of sent packets. */
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
+ uint16_t next_packet_length;
+ struct {
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint32_t index;
+ uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */
+ uint8_t other_id;
+ } connections[NUM_CLIENT_CONNECTIONS];
+ uint8_t last_packet[2 + MAX_PACKET_SIZE];
+ uint8_t status;
+ uint16_t last_packet_length;
+ uint16_t last_packet_sent;
+
+ TCP_Priority_List *priority_queue_start, *priority_queue_end;
+
+ uint64_t identifier;
+
+ uint64_t last_pinged;
+ uint64_t ping_id;
+} TCP_Secure_Connection;
+
+
+typedef struct TCP_Server TCP_Server;
+
+const uint8_t *tcp_server_public_key(const TCP_Server *tcp_server);
+size_t tcp_server_listen_count(const TCP_Server *tcp_server);
+
+/* Create new TCP server instance.
+ */
+TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uint16_t *ports, const uint8_t *secret_key,
+ Onion *onion);
+
+/* Run the TCP_server
+ */
+void do_TCP_server(TCP_Server *TCP_server);
+
+/* Kill the TCP server
+ */
+void kill_TCP_server(TCP_Server *TCP_server);
+
+/* return the amount of data in the tcp recv buffer.
+ * return 0 on failure.
+ */
+unsigned int TCP_socket_data_recv_buffer(Socket sock);
+
+/* Read the next two bytes in TCP stream then convert them to
+ * length (host byte order).
+ *
+ * return length on success
+ * return 0 if nothing has been read from socket.
+ * return ~0 on failure.
+ */
+uint16_t read_TCP_length(Socket sock);
+
+/* Read length bytes from socket.
+ *
+ * return length on success
+ * return -1 on failure/no data in buffer.
+ */
+int read_TCP_packet(Socket sock, uint8_t *data, uint16_t length);
+
+/* return length of received packet on success.
+ * return 0 if could not read any packet.
+ * return -1 on failure (connection must be killed).
+ */
+int read_packet_TCP_secure_connection(Socket sock, uint16_t *next_packet_length, const uint8_t *shared_key,
+ uint8_t *recv_nonce, uint8_t *data, uint16_t max_len);
+
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxcore/ccompat.h b/protocols/Tox/libtox/src/toxcore/ccompat.h
new file mode 100644
index 0000000000..e72e66ae58
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/ccompat.h
@@ -0,0 +1,43 @@
+/*
+ * C language compatibility macros for varying compiler support.
+ */
+#ifndef CCOMPAT_H
+#define CCOMPAT_H
+
+// Marking GNU extensions to avoid warnings.
+#if defined(__GNUC__)
+#define GNU_EXTENSION __extension__
+#else
+#define GNU_EXTENSION
+#endif
+
+// Variable length arrays.
+// VLA(type, name, size) allocates a variable length array with automatic
+// storage duration. VLA_SIZE(name) evaluates to the runtime size of that array
+// in bytes.
+//
+// If C99 VLAs are not available, an emulation using alloca (stack allocation
+// "function") is used. Note the semantic difference: alloca'd memory does not
+// get freed at the end of the declaration's scope. Do not use VLA() in loops or
+// you may run out of stack space.
+#if !defined(_MSC_VER) && __STDC_VERSION__ >= 199901L
+// C99 VLAs.
+#define VLA(type, name, size) type name[size]
+#define SIZEOF_VLA sizeof
+#else
+
+// Emulation using alloca.
+#ifdef _WIN32
+#include <malloc.h>
+#else
+#include <alloca.h>
+#endif
+
+#define VLA(type, name, size) \
+ const size_t name##_size = (size) * sizeof(type); \
+ type *const name = (type *)alloca(name##_size)
+#define SIZEOF_VLA(name) name##_size
+
+#endif
+
+#endif /* CCOMPAT_H */
diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core.api.h b/protocols/Tox/libtox/src/toxcore/crypto_core.api.h
new file mode 100644
index 0000000000..cef1a52c14
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/crypto_core.api.h
@@ -0,0 +1,246 @@
+%{
+/*
+ * Functions for the core crypto.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef CRYPTO_CORE_H
+#define CRYPTO_CORE_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+%}
+
+/**
+ * The number of bytes in a Tox public key.
+ */
+const CRYPTO_PUBLIC_KEY_SIZE = 32;
+
+/**
+ * The number of bytes in a Tox secret key.
+ */
+const CRYPTO_SECRET_KEY_SIZE = 32;
+
+/**
+ * The number of bytes in a shared key computed from public and secret keys.
+ */
+const CRYPTO_SHARED_KEY_SIZE = 32;
+
+/**
+ * The number of bytes in a symmetric key.
+ */
+const CRYPTO_SYMMETRIC_KEY_SIZE = CRYPTO_SHARED_KEY_SIZE;
+
+/**
+ * The number of bytes needed for the MAC (message authentication code) in an
+ * encrypted message.
+ */
+const CRYPTO_MAC_SIZE = 16;
+
+/**
+ * The number of bytes in a nonce used for encryption/decryption.
+ */
+const CRYPTO_NONCE_SIZE = 24;
+
+/**
+ * The number of bytes in a SHA256 hash.
+ */
+const CRYPTO_SHA256_SIZE = 32;
+
+/**
+ * The number of bytes in a SHA512 hash.
+ */
+const CRYPTO_SHA512_SIZE = 64;
+
+/**
+ * A `memcmp`-like function whose running time does not depend on the input
+ * bytes, only on the input length. Useful to compare sensitive data where
+ * timing attacks could reveal that data.
+ *
+ * This means for instance that comparing "aaaa" and "aaaa" takes 4 time, and
+ * "aaaa" and "baaa" also takes 4 time. With a regular `memcmp`, the latter may
+ * take 1 time, because it immediately knows that the two strings are not equal.
+ */
+static int32_t crypto_memcmp(const void *p1, const void *p2, size_t length);
+
+/**
+ * A `bzero`-like function which won't be optimised away by the compiler. Some
+ * compilers will inline `bzero` or `memset` if they can prove that there will
+ * be no reads to the written data. Use this function if you want to be sure the
+ * memory is indeed zeroed.
+ */
+static void crypto_memzero(void *data, size_t length);
+
+/**
+ * Compute a SHA256 hash (32 bytes).
+ */
+static void crypto_sha256(uint8_t[CRYPTO_SHA256_SIZE] hash, const uint8_t[length] data);
+
+/**
+ * Compute a SHA512 hash (64 bytes).
+ */
+static void crypto_sha512(uint8_t[CRYPTO_SHA512_SIZE] hash, const uint8_t[length] data);
+
+/**
+ * Compare 2 public keys of length CRYPTO_PUBLIC_KEY_SIZE, not vulnerable to
+ * timing attacks.
+ *
+ * @return 0 if both mem locations of length are equal, -1 if they are not.
+ */
+static int32_t public_key_cmp(
+ const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] pk1,
+ const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] pk2);
+
+/**
+ * Return a random 32 bit integer.
+ */
+static uint32_t random_int();
+
+/**
+ * Return a random 64 bit integer.
+ */
+static uint64_t random_64b();
+
+/**
+ * Check if a Tox public key CRYPTO_PUBLIC_KEY_SIZE is valid or not. This
+ * should only be used for input validation.
+ *
+ * @return false if it isn't, true if it is.
+ */
+static bool public_key_valid(const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key);
+
+/**
+ * Generate a new random keypair. Every call to this function is likely to
+ * generate a different keypair.
+ */
+static int32_t crypto_new_keypair(
+ uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
+ uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key);
+
+/**
+ * Derive the public key from a given secret key.
+ */
+static void crypto_derive_public_key(
+ uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
+ const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key);
+
+/**
+ * Encrypt plain text of the given length to encrypted of length +
+ * $CRYPTO_MAC_SIZE using the public key ($CRYPTO_PUBLIC_KEY_SIZE bytes) of the
+ * receiver and the secret key of the sender and a $CRYPTO_NONCE_SIZE byte
+ * nonce.
+ *
+ * @return -1 if there was a problem, length of encrypted data if everything
+ * was fine.
+ */
+static int32_t encrypt_data(
+ const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
+ const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key,
+ const uint8_t[CRYPTO_NONCE_SIZE] nonce,
+ const uint8_t[length] plain,
+ uint8_t *encrypted);
+
+
+/**
+ * Decrypt encrypted text of the given length to plain text of the given length
+ * - $CRYPTO_MAC_SIZE using the public key ($CRYPTO_PUBLIC_KEY_SIZE bytes) of
+ * the sender, the secret key of the receiver and a $CRYPTO_NONCE_SIZE byte
+ * nonce.
+ *
+ * @return -1 if there was a problem (decryption failed), length of plain text
+ * data if everything was fine.
+ */
+static int32_t decrypt_data(
+ const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
+ const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key,
+ const uint8_t[CRYPTO_NONCE_SIZE] nonce,
+ const uint8_t[length] encrypted,
+ uint8_t *plain);
+
+/**
+ * Fast encrypt/decrypt operations. Use if this is not a one-time communication.
+ * $encrypt_precompute does the shared-key generation once so it does not have
+ * to be preformed on every encrypt/decrypt.
+ */
+static int32_t encrypt_precompute(
+ const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
+ const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key,
+ uint8_t[CRYPTO_SHARED_KEY_SIZE] shared_key);
+
+/**
+ * Encrypts plain of length length to encrypted of length + $CRYPTO_MAC_SIZE
+ * using a shared key $CRYPTO_SYMMETRIC_KEY_SIZE big and a $CRYPTO_NONCE_SIZE
+ * byte nonce.
+ *
+ * @return -1 if there was a problem, length of encrypted data if everything
+ * was fine.
+ */
+static int32_t encrypt_data_symmetric(
+ const uint8_t[CRYPTO_SHARED_KEY_SIZE] shared_key,
+ const uint8_t[CRYPTO_NONCE_SIZE] nonce,
+ const uint8_t[length] plain,
+ uint8_t *encrypted);
+
+/**
+ * Decrypts encrypted of length length to plain of length length -
+ * $CRYPTO_MAC_SIZE using a shared key CRYPTO_SHARED_KEY_SIZE big and a
+ * $CRYPTO_NONCE_SIZE byte nonce.
+ *
+ * @return -1 if there was a problem (decryption failed), length of plain data
+ * if everything was fine.
+ */
+static int32_t decrypt_data_symmetric(
+ const uint8_t[CRYPTO_SHARED_KEY_SIZE] shared_key,
+ const uint8_t[CRYPTO_NONCE_SIZE] nonce,
+ const uint8_t[length] encrypted,
+ uint8_t *plain);
+
+/**
+ * Increment the given nonce by 1 in big endian (rightmost byte incremented
+ * first).
+ */
+static void increment_nonce(uint8_t[CRYPTO_NONCE_SIZE] nonce);
+
+/**
+ * Increment the given nonce by a given number. The number should be in host
+ * byte order.
+ */
+static void increment_nonce_number(uint8_t[CRYPTO_NONCE_SIZE] nonce, uint32_t host_order_num);
+
+/**
+ * Fill the given nonce with random bytes.
+ */
+static void random_nonce(uint8_t[CRYPTO_NONCE_SIZE] nonce);
+
+/**
+ * Fill a key CRYPTO_SYMMETRIC_KEY_SIZE big with random bytes.
+ */
+static void new_symmetric_key(uint8_t[CRYPTO_SYMMETRIC_KEY_SIZE] key);
+
+/**
+ * Fill an array of bytes with random values.
+ */
+static void random_bytes(uint8_t[length] bytes);
+
+%{
+#endif /* CRYPTO_CORE_H */
+%}
diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core.c b/protocols/Tox/libtox/src/toxcore/crypto_core.c
new file mode 100644
index 0000000000..8e34b5876a
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/crypto_core.c
@@ -0,0 +1,287 @@
+/*
+ * Functions for the core crypto.
+ *
+ * NOTE: This code has to be perfect. We don't mess around with encryption.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ccompat.h"
+#include "crypto_core.h"
+
+#include <string.h>
+
+#ifndef VANILLA_NACL
+/* We use libsodium by default. */
+#include <sodium.h>
+#else
+#include <crypto_box.h>
+#include <crypto_hash_sha256.h>
+#include <crypto_hash_sha512.h>
+#include <crypto_scalarmult_curve25519.h>
+#include <crypto_verify_16.h>
+#include <crypto_verify_32.h>
+#include <randombytes.h>
+#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
+#endif
+
+#if CRYPTO_PUBLIC_KEY_SIZE != crypto_box_PUBLICKEYBYTES
+#error CRYPTO_PUBLIC_KEY_SIZE should be equal to crypto_box_PUBLICKEYBYTES
+#endif
+
+#if CRYPTO_SECRET_KEY_SIZE != crypto_box_SECRETKEYBYTES
+#error CRYPTO_SECRET_KEY_SIZE should be equal to crypto_box_SECRETKEYBYTES
+#endif
+
+#if CRYPTO_SHARED_KEY_SIZE != crypto_box_BEFORENMBYTES
+#error CRYPTO_SHARED_KEY_SIZE should be equal to crypto_box_BEFORENMBYTES
+#endif
+
+#if CRYPTO_SYMMETRIC_KEY_SIZE != crypto_box_BEFORENMBYTES
+#error CRYPTO_SYMMETRIC_KEY_SIZE should be equal to crypto_box_BEFORENMBYTES
+#endif
+
+#if CRYPTO_MAC_SIZE != crypto_box_MACBYTES
+#error CRYPTO_MAC_SIZE should be equal to crypto_box_MACBYTES
+#endif
+
+#if CRYPTO_NONCE_SIZE != crypto_box_NONCEBYTES
+#error CRYPTO_NONCE_SIZE should be equal to crypto_box_NONCEBYTES
+#endif
+
+#if CRYPTO_SHA256_SIZE != crypto_hash_sha256_BYTES
+#error CRYPTO_SHA256_SIZE should be equal to crypto_hash_sha256_BYTES
+#endif
+
+#if CRYPTO_SHA512_SIZE != crypto_hash_sha512_BYTES
+#error CRYPTO_SHA512_SIZE should be equal to crypto_hash_sha512_BYTES
+#endif
+
+int32_t public_key_cmp(const uint8_t *pk1, const uint8_t *pk2)
+{
+#if CRYPTO_PUBLIC_KEY_SIZE != 32
+#error CRYPTO_PUBLIC_KEY_SIZE is required to be 32 bytes for public_key_cmp to work,
+#endif
+ return crypto_verify_32(pk1, pk2);
+}
+
+uint32_t random_int(void)
+{
+ uint32_t randnum;
+ randombytes((uint8_t *)&randnum , sizeof(randnum));
+ return randnum;
+}
+
+uint64_t random_64b(void)
+{
+ uint64_t randnum;
+ randombytes((uint8_t *)&randnum, sizeof(randnum));
+ return randnum;
+}
+
+bool public_key_valid(const uint8_t *public_key)
+{
+ if (public_key[31] >= 128) { /* Last bit of key is always zero. */
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Precomputes the shared key from their public_key and our secret_key.
+ * This way we can avoid an expensive elliptic curve scalar multiply for each
+ * encrypt/decrypt operation.
+ * shared_key has to be crypto_box_BEFORENMBYTES bytes long.
+ */
+int32_t encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, uint8_t *shared_key)
+{
+ return crypto_box_beforenm(shared_key, public_key, secret_key);
+}
+
+int32_t encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain, size_t length,
+ uint8_t *encrypted)
+{
+ if (length == 0 || !secret_key || !nonce || !plain || !encrypted) {
+ return -1;
+ }
+
+ VLA(uint8_t, temp_plain, length + crypto_box_ZEROBYTES);
+ VLA(uint8_t, temp_encrypted, length + crypto_box_MACBYTES + crypto_box_BOXZEROBYTES);
+
+ memset(temp_plain, 0, crypto_box_ZEROBYTES);
+ memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); // Pad the message with 32 0 bytes.
+
+ if (crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, secret_key) != 0) {
+ return -1;
+ }
+
+ /* Unpad the encrypted message. */
+ memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES);
+ return length + crypto_box_MACBYTES;
+}
+
+int32_t decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *encrypted, size_t length,
+ uint8_t *plain)
+{
+ if (length <= crypto_box_BOXZEROBYTES || !secret_key || !nonce || !encrypted || !plain) {
+ return -1;
+ }
+
+ VLA(uint8_t, temp_plain, length + crypto_box_ZEROBYTES);
+ VLA(uint8_t, temp_encrypted, length + crypto_box_BOXZEROBYTES);
+
+ memset(temp_encrypted, 0, crypto_box_BOXZEROBYTES);
+ memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); // Pad the message with 16 0 bytes.
+
+ if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, secret_key) != 0) {
+ return -1;
+ }
+
+ memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES);
+ return length - crypto_box_MACBYTES;
+}
+
+int32_t encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
+ const uint8_t *plain, size_t length, uint8_t *encrypted)
+{
+ if (!public_key || !secret_key) {
+ return -1;
+ }
+
+ uint8_t k[crypto_box_BEFORENMBYTES];
+ encrypt_precompute(public_key, secret_key, k);
+ int ret = encrypt_data_symmetric(k, nonce, plain, length, encrypted);
+ crypto_memzero(k, sizeof k);
+ return ret;
+}
+
+int32_t decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
+ const uint8_t *encrypted, size_t length, uint8_t *plain)
+{
+ if (!public_key || !secret_key) {
+ return -1;
+ }
+
+ uint8_t k[crypto_box_BEFORENMBYTES];
+ encrypt_precompute(public_key, secret_key, k);
+ int ret = decrypt_data_symmetric(k, nonce, encrypted, length, plain);
+ crypto_memzero(k, sizeof k);
+ return ret;
+}
+
+
+/* Increment the given nonce by 1. */
+void increment_nonce(uint8_t *nonce)
+{
+ /* TODO(irungentoo): use increment_nonce_number(nonce, 1) or sodium_increment (change to little endian)
+ * NOTE don't use breaks inside this loop
+ * In particular, make sure, as far as possible,
+ * that loop bounds and their potential underflow or overflow
+ * are independent of user-controlled input (you may have heard of the Heartbleed bug).
+ */
+ uint32_t i = crypto_box_NONCEBYTES;
+ uint_fast16_t carry = 1U;
+
+ for (; i != 0; --i) {
+ carry += (uint_fast16_t) nonce[i - 1];
+ nonce[i - 1] = (uint8_t) carry;
+ carry >>= 8;
+ }
+}
+
+static uint32_t host_to_network(uint32_t x)
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ return
+ ((x >> 24) & 0x000000FF) | // move byte 3 to byte 0
+ ((x >> 8) & 0x0000FF00) | // move byte 2 to byte 1
+ ((x << 8) & 0x00FF0000) | // move byte 1 to byte 2
+ ((x << 24) & 0xFF000000); // move byte 0 to byte 3
+#else
+ return x;
+#endif
+}
+
+/* increment the given nonce by num */
+void increment_nonce_number(uint8_t *nonce, uint32_t host_order_num)
+{
+ /* NOTE don't use breaks inside this loop
+ * In particular, make sure, as far as possible,
+ * that loop bounds and their potential underflow or overflow
+ * are independent of user-controlled input (you may have heard of the Heartbleed bug).
+ */
+ const uint32_t big_endian_num = host_to_network(host_order_num);
+ const uint8_t *const num_vec = (const uint8_t *) &big_endian_num;
+ uint8_t num_as_nonce[crypto_box_NONCEBYTES] = {0};
+ num_as_nonce[crypto_box_NONCEBYTES - 4] = num_vec[0];
+ num_as_nonce[crypto_box_NONCEBYTES - 3] = num_vec[1];
+ num_as_nonce[crypto_box_NONCEBYTES - 2] = num_vec[2];
+ num_as_nonce[crypto_box_NONCEBYTES - 1] = num_vec[3];
+
+ uint32_t i = crypto_box_NONCEBYTES;
+ uint_fast16_t carry = 0U;
+
+ for (; i != 0; --i) {
+ carry += (uint_fast16_t) nonce[i - 1] + (uint_fast16_t) num_as_nonce[i - 1];
+ nonce[i - 1] = (unsigned char) carry;
+ carry >>= 8;
+ }
+}
+
+/* Fill the given nonce with random bytes. */
+void random_nonce(uint8_t *nonce)
+{
+ randombytes(nonce, crypto_box_NONCEBYTES);
+}
+
+/* Fill a key CRYPTO_SYMMETRIC_KEY_SIZE big with random bytes */
+void new_symmetric_key(uint8_t *key)
+{
+ randombytes(key, CRYPTO_SYMMETRIC_KEY_SIZE);
+}
+
+int32_t crypto_new_keypair(uint8_t *public_key, uint8_t *secret_key)
+{
+ return crypto_box_keypair(public_key, secret_key);
+}
+
+void crypto_derive_public_key(uint8_t *public_key, const uint8_t *secret_key)
+{
+ crypto_scalarmult_curve25519_base(public_key, secret_key);
+}
+
+void crypto_sha256(uint8_t *hash, const uint8_t *data, size_t length)
+{
+ crypto_hash_sha256(hash, data, length);
+}
+
+void crypto_sha512(uint8_t *hash, const uint8_t *data, size_t length)
+{
+ crypto_hash_sha512(hash, data, length);
+}
+
+void random_bytes(uint8_t *data, size_t length)
+{
+ randombytes(data, length);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core.h b/protocols/Tox/libtox/src/toxcore/crypto_core.h
new file mode 100644
index 0000000000..fc5756c1d2
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/crypto_core.h
@@ -0,0 +1,234 @@
+/*
+ * Functions for the core crypto.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef CRYPTO_CORE_H
+#define CRYPTO_CORE_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/**
+ * The number of bytes in a Tox public key.
+ */
+#define CRYPTO_PUBLIC_KEY_SIZE 32
+
+uint32_t crypto_public_key_size(void);
+
+/**
+ * The number of bytes in a Tox secret key.
+ */
+#define CRYPTO_SECRET_KEY_SIZE 32
+
+uint32_t crypto_secret_key_size(void);
+
+/**
+ * The number of bytes in a shared key computed from public and secret keys.
+ */
+#define CRYPTO_SHARED_KEY_SIZE 32
+
+uint32_t crypto_shared_key_size(void);
+
+/**
+ * The number of bytes in a symmetric key.
+ */
+#define CRYPTO_SYMMETRIC_KEY_SIZE CRYPTO_SHARED_KEY_SIZE
+
+uint32_t crypto_symmetric_key_size(void);
+
+/**
+ * The number of bytes needed for the MAC (message authentication code) in an
+ * encrypted message.
+ */
+#define CRYPTO_MAC_SIZE 16
+
+uint32_t crypto_mac_size(void);
+
+/**
+ * The number of bytes in a nonce used for encryption/decryption.
+ */
+#define CRYPTO_NONCE_SIZE 24
+
+uint32_t crypto_nonce_size(void);
+
+/**
+ * The number of bytes in a SHA256 hash.
+ */
+#define CRYPTO_SHA256_SIZE 32
+
+uint32_t crypto_sha256_size(void);
+
+/**
+ * The number of bytes in a SHA512 hash.
+ */
+#define CRYPTO_SHA512_SIZE 64
+
+uint32_t crypto_sha512_size(void);
+
+/**
+ * A `memcmp`-like function whose running time does not depend on the input
+ * bytes, only on the input length. Useful to compare sensitive data where
+ * timing attacks could reveal that data.
+ *
+ * This means for instance that comparing "aaaa" and "aaaa" takes 4 time, and
+ * "aaaa" and "baaa" also takes 4 time. With a regular `memcmp`, the latter may
+ * take 1 time, because it immediately knows that the two strings are not equal.
+ */
+int32_t crypto_memcmp(const void *p1, const void *p2, size_t length);
+
+/**
+ * A `bzero`-like function which won't be optimised away by the compiler. Some
+ * compilers will inline `bzero` or `memset` if they can prove that there will
+ * be no reads to the written data. Use this function if you want to be sure the
+ * memory is indeed zeroed.
+ */
+void crypto_memzero(void *data, size_t length);
+
+/**
+ * Compute a SHA256 hash (32 bytes).
+ */
+void crypto_sha256(uint8_t *hash, const uint8_t *data, size_t length);
+
+/**
+ * Compute a SHA512 hash (64 bytes).
+ */
+void crypto_sha512(uint8_t *hash, const uint8_t *data, size_t length);
+
+/**
+ * Compare 2 public keys of length CRYPTO_PUBLIC_KEY_SIZE, not vulnerable to
+ * timing attacks.
+ *
+ * @return 0 if both mem locations of length are equal, -1 if they are not.
+ */
+int32_t public_key_cmp(const uint8_t *pk1, const uint8_t *pk2);
+
+/**
+ * Return a random 32 bit integer.
+ */
+uint32_t random_int(void);
+
+/**
+ * Return a random 64 bit integer.
+ */
+uint64_t random_64b(void);
+
+/**
+ * Check if a Tox public key CRYPTO_PUBLIC_KEY_SIZE is valid or not. This
+ * should only be used for input validation.
+ *
+ * @return false if it isn't, true if it is.
+ */
+bool public_key_valid(const uint8_t *public_key);
+
+/**
+ * Generate a new random keypair. Every call to this function is likely to
+ * generate a different keypair.
+ */
+int32_t crypto_new_keypair(uint8_t *public_key, uint8_t *secret_key);
+
+/**
+ * Derive the public key from a given secret key.
+ */
+void crypto_derive_public_key(uint8_t *public_key, const uint8_t *secret_key);
+
+/**
+ * Encrypt plain text of the given length to encrypted of length +
+ * CRYPTO_MAC_SIZE using the public key (CRYPTO_PUBLIC_KEY_SIZE bytes) of the
+ * receiver and the secret key of the sender and a CRYPTO_NONCE_SIZE byte
+ * nonce.
+ *
+ * @return -1 if there was a problem, length of encrypted data if everything
+ * was fine.
+ */
+int32_t encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain,
+ size_t length, uint8_t *encrypted);
+
+/**
+ * Decrypt encrypted text of the given length to plain text of the given length
+ * - CRYPTO_MAC_SIZE using the public key (CRYPTO_PUBLIC_KEY_SIZE bytes) of
+ * the sender, the secret key of the receiver and a CRYPTO_NONCE_SIZE byte
+ * nonce.
+ *
+ * @return -1 if there was a problem (decryption failed), length of plain text
+ * data if everything was fine.
+ */
+int32_t decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
+ const uint8_t *encrypted, size_t length, uint8_t *plain);
+
+/**
+ * Fast encrypt/decrypt operations. Use if this is not a one-time communication.
+ * encrypt_precompute does the shared-key generation once so it does not have
+ * to be preformed on every encrypt/decrypt.
+ */
+int32_t encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, uint8_t *shared_key);
+
+/**
+ * Encrypts plain of length length to encrypted of length + CRYPTO_MAC_SIZE
+ * using a shared key CRYPTO_SYMMETRIC_KEY_SIZE big and a CRYPTO_NONCE_SIZE
+ * byte nonce.
+ *
+ * @return -1 if there was a problem, length of encrypted data if everything
+ * was fine.
+ */
+int32_t encrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce, const uint8_t *plain, size_t length,
+ uint8_t *encrypted);
+
+/**
+ * Decrypts encrypted of length length to plain of length length -
+ * CRYPTO_MAC_SIZE using a shared key CRYPTO_SHARED_KEY_SIZE big and a
+ * CRYPTO_NONCE_SIZE byte nonce.
+ *
+ * @return -1 if there was a problem (decryption failed), length of plain data
+ * if everything was fine.
+ */
+int32_t decrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce, const uint8_t *encrypted, size_t length,
+ uint8_t *plain);
+
+/**
+ * Increment the given nonce by 1 in big endian (rightmost byte incremented
+ * first).
+ */
+void increment_nonce(uint8_t *nonce);
+
+/**
+ * Increment the given nonce by a given number. The number should be in host
+ * byte order.
+ */
+void increment_nonce_number(uint8_t *nonce, uint32_t host_order_num);
+
+/**
+ * Fill the given nonce with random bytes.
+ */
+void random_nonce(uint8_t *nonce);
+
+/**
+ * Fill a key CRYPTO_SYMMETRIC_KEY_SIZE big with random bytes.
+ */
+void new_symmetric_key(uint8_t *key);
+
+/**
+ * Fill an array of bytes with random values.
+ */
+void random_bytes(uint8_t *bytes, size_t length);
+
+#endif /* CRYPTO_CORE_H */
diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core_mem.c b/protocols/Tox/libtox/src/toxcore/crypto_core_mem.c
new file mode 100644
index 0000000000..b8f4223e65
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/crypto_core_mem.c
@@ -0,0 +1,87 @@
+/*
+ * ISC License
+ *
+ * Copyright (c) 2013-2016
+ * Frank Denis <j at pureftpd dot org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "crypto_core.h"
+
+#ifndef VANILLA_NACL
+/* We use libsodium by default. */
+#include <sodium.h>
+#else
+#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+#include <windows.h>
+#include <wincrypt.h>
+#endif
+#endif
+
+
+void crypto_memzero(void *data, size_t length)
+{
+#ifndef VANILLA_NACL
+ sodium_memzero(data, length);
+#else
+#ifdef _WIN32
+ SecureZeroMemory(data, length);
+#elif defined(HAVE_MEMSET_S)
+
+ if (length > 0U) {
+ errno_t code = memset_s(data, (rsize_t) length, 0, (rsize_t) length);
+
+ if (code != 0) {
+ abort(); /* LCOV_EXCL_LINE */
+ }
+ }
+
+#elif defined(HAVE_EXPLICIT_BZERO)
+ explicit_bzero(data, length);
+#else
+ volatile unsigned char *volatile pnt =
+ (volatile unsigned char *volatile) data;
+ size_t i = (size_t) 0U;
+
+ while (i < length) {
+ pnt[i++] = 0U;
+ }
+
+#endif
+#endif
+}
+
+int32_t crypto_memcmp(const void *p1, const void *p2, size_t length)
+{
+#ifndef VANILLA_NACL
+ return sodium_memcmp(p1, p2, length);
+#else
+ const volatile unsigned char *volatile b1 =
+ (const volatile unsigned char *volatile) p1;
+ const volatile unsigned char *volatile b2 =
+ (const volatile unsigned char *volatile) p2;
+
+ size_t i;
+ unsigned char d = (unsigned char) 0U;
+
+ for (i = 0U; i < length; i++) {
+ d |= b1[i] ^ b2[i];
+ }
+
+ return (1 & ((d - 1) >> 8)) - 1;
+#endif
+}
diff --git a/protocols/Tox/libtox/src/toxcore/friend_connection.c b/protocols/Tox/libtox/src/toxcore/friend_connection.c
new file mode 100644
index 0000000000..9f0677b109
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/friend_connection.c
@@ -0,0 +1,937 @@
+/*
+ * Connection to friends.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2014 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "friend_connection.h"
+
+#include "util.h"
+
+#define PORTS_PER_DISCOVERY 10
+
+/* return 1 if the friendcon_id is not valid.
+ * return 0 if the friendcon_id is valid.
+ */
+static uint8_t friendconn_id_not_valid(const Friend_Connections *fr_c, int friendcon_id)
+{
+ if ((unsigned int)friendcon_id >= fr_c->num_cons) {
+ return 1;
+ }
+
+ if (fr_c->conns == NULL) {
+ return 1;
+ }
+
+ if (fr_c->conns[friendcon_id].status == FRIENDCONN_STATUS_NONE) {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* Set the size of the friend connections list to num.
+ *
+ * return -1 if realloc fails.
+ * return 0 if it succeeds.
+ */
+static int realloc_friendconns(Friend_Connections *fr_c, uint32_t num)
+{
+ if (num == 0) {
+ free(fr_c->conns);
+ fr_c->conns = NULL;
+ return 0;
+ }
+
+ Friend_Conn *newgroup_cons = (Friend_Conn *)realloc(fr_c->conns, num * sizeof(Friend_Conn));
+
+ if (newgroup_cons == NULL) {
+ return -1;
+ }
+
+ fr_c->conns = newgroup_cons;
+ return 0;
+}
+
+/* Create a new empty friend connection.
+ *
+ * return -1 on failure.
+ * return friendcon_id on success.
+ */
+static int create_friend_conn(Friend_Connections *fr_c)
+{
+ uint32_t i;
+
+ for (i = 0; i < fr_c->num_cons; ++i) {
+ if (fr_c->conns[i].status == FRIENDCONN_STATUS_NONE) {
+ return i;
+ }
+ }
+
+ int id = -1;
+
+ if (realloc_friendconns(fr_c, fr_c->num_cons + 1) == 0) {
+ id = fr_c->num_cons;
+ ++fr_c->num_cons;
+ memset(&(fr_c->conns[id]), 0, sizeof(Friend_Conn));
+ }
+
+ return id;
+}
+
+/* Wipe a friend connection.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int wipe_friend_conn(Friend_Connections *fr_c, int friendcon_id)
+{
+ if (friendconn_id_not_valid(fr_c, friendcon_id)) {
+ return -1;
+ }
+
+ uint32_t i;
+ memset(&(fr_c->conns[friendcon_id]), 0 , sizeof(Friend_Conn));
+
+ for (i = fr_c->num_cons; i != 0; --i) {
+ if (fr_c->conns[i - 1].status != FRIENDCONN_STATUS_NONE) {
+ break;
+ }
+ }
+
+ if (fr_c->num_cons != i) {
+ fr_c->num_cons = i;
+ realloc_friendconns(fr_c, fr_c->num_cons);
+ }
+
+ return 0;
+}
+
+static Friend_Conn *get_conn(const Friend_Connections *fr_c, int friendcon_id)
+{
+ if (friendconn_id_not_valid(fr_c, friendcon_id)) {
+ return 0;
+ }
+
+ return &fr_c->conns[friendcon_id];
+}
+
+/* return friendcon_id corresponding to the real public key on success.
+ * return -1 on failure.
+ */
+int getfriend_conn_id_pk(Friend_Connections *fr_c, const uint8_t *real_pk)
+{
+ uint32_t i;
+
+ for (i = 0; i < fr_c->num_cons; ++i) {
+ Friend_Conn *friend_con = get_conn(fr_c, i);
+
+ if (friend_con) {
+ if (public_key_cmp(friend_con->real_public_key, real_pk) == 0) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+}
+
+/* Add a TCP relay associated to the friend.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_port, const uint8_t *public_key)
+{
+ Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
+
+ if (!friend_con) {
+ return -1;
+ }
+
+ /* Local ip and same pk means that they are hosting a TCP relay. */
+ if (Local_ip(ip_port.ip) && public_key_cmp(friend_con->dht_temp_pk, public_key) == 0) {
+ if (friend_con->dht_ip_port.ip.family != 0) {
+ ip_port.ip = friend_con->dht_ip_port.ip;
+ } else {
+ friend_con->hosting_tcp_relay = 0;
+ }
+ }
+
+ unsigned int i;
+
+ uint16_t index = friend_con->tcp_relay_counter % FRIEND_MAX_STORED_TCP_RELAYS;
+
+ for (i = 0; i < FRIEND_MAX_STORED_TCP_RELAYS; ++i) {
+ if (friend_con->tcp_relays[i].ip_port.ip.family != 0
+ && public_key_cmp(friend_con->tcp_relays[i].public_key, public_key) == 0) {
+ memset(&friend_con->tcp_relays[i], 0, sizeof(Node_format));
+ }
+ }
+
+ friend_con->tcp_relays[index].ip_port = ip_port;
+ memcpy(friend_con->tcp_relays[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ ++friend_con->tcp_relay_counter;
+
+ return add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, public_key);
+}
+
+/* Connect to number saved relays for friend. */
+static void connect_to_saved_tcp_relays(Friend_Connections *fr_c, int friendcon_id, unsigned int number)
+{
+ Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
+
+ if (!friend_con) {
+ return;
+ }
+
+ unsigned int i;
+
+ for (i = 0; (i < FRIEND_MAX_STORED_TCP_RELAYS) && (number != 0); ++i) {
+ uint16_t index = (friend_con->tcp_relay_counter - (i + 1)) % FRIEND_MAX_STORED_TCP_RELAYS;
+
+ if (friend_con->tcp_relays[index].ip_port.ip.family) {
+ if (add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->tcp_relays[index].ip_port,
+ friend_con->tcp_relays[index].public_key) == 0) {
+ --number;
+ }
+ }
+ }
+}
+
+static unsigned int send_relays(Friend_Connections *fr_c, int friendcon_id)
+{
+ Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
+
+ if (!friend_con) {
+ return 0;
+ }
+
+ Node_format nodes[MAX_SHARED_RELAYS];
+ uint8_t data[1024];
+ int n, length;
+
+ n = copy_connected_tcp_relays(fr_c->net_crypto, nodes, MAX_SHARED_RELAYS);
+
+ int i;
+
+ for (i = 0; i < n; ++i) {
+ /* Associated the relays being sent with this connection.
+ On receiving the peer will do the same which will establish the connection. */
+ friend_add_tcp_relay(fr_c, friendcon_id, nodes[i].ip_port, nodes[i].public_key);
+ }
+
+ length = pack_nodes(data + 1, sizeof(data) - 1, nodes, n);
+
+ if (length <= 0) {
+ return 0;
+ }
+
+ data[0] = PACKET_ID_SHARE_RELAYS;
+ ++length;
+
+ if (write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, data, length, 0) != -1) {
+ friend_con->share_relays_lastsent = unix_time();
+ return 1;
+ }
+
+ return 0;
+}
+
+/* callback for recv TCP relay nodes. */
+static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key)
+{
+ Friend_Connections *fr_c = (Friend_Connections *)object;
+ Friend_Conn *friend_con = get_conn(fr_c, number);
+
+ if (!friend_con) {
+ return -1;
+ }
+
+ if (friend_con->crypt_connection_id != -1) {
+ return friend_add_tcp_relay(fr_c, number, ip_port, public_key);
+ }
+
+ return add_tcp_relay(fr_c->net_crypto, ip_port, public_key);
+}
+
+static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id);
+/* Callback for DHT ip_port changes. */
+static void dht_ip_callback(void *object, int32_t number, IP_Port ip_port)
+{
+ Friend_Connections *fr_c = (Friend_Connections *)object;
+ Friend_Conn *friend_con = get_conn(fr_c, number);
+
+ if (!friend_con) {
+ return;
+ }
+
+ if (friend_con->crypt_connection_id == -1) {
+ friend_new_connection(fr_c, number);
+ }
+
+ set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, 1);
+ friend_con->dht_ip_port = ip_port;
+ friend_con->dht_ip_port_lastrecv = unix_time();
+
+ if (friend_con->hosting_tcp_relay) {
+ friend_add_tcp_relay(fr_c, number, ip_port, friend_con->dht_temp_pk);
+ friend_con->hosting_tcp_relay = 0;
+ }
+}
+
+static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_public_key)
+{
+ Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
+
+ if (!friend_con) {
+ return;
+ }
+
+ friend_con->dht_pk_lastrecv = unix_time();
+
+ if (friend_con->dht_lock) {
+ if (DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock) != 0) {
+ printf("a. Could not delete dht peer. Please report this.\n");
+ return;
+ }
+
+ friend_con->dht_lock = 0;
+ }
+
+ DHT_addfriend(fr_c->dht, dht_public_key, dht_ip_callback, fr_c, friendcon_id, &friend_con->dht_lock);
+ memcpy(friend_con->dht_temp_pk, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+}
+
+static int handle_status(void *object, int number, uint8_t status, void *userdata)
+{
+ Friend_Connections *fr_c = (Friend_Connections *)object;
+ Friend_Conn *friend_con = get_conn(fr_c, number);
+
+ if (!friend_con) {
+ return -1;
+ }
+
+ bool call_cb = 0;
+
+ if (status) { /* Went online. */
+ call_cb = 1;
+ friend_con->status = FRIENDCONN_STATUS_CONNECTED;
+ friend_con->ping_lastrecv = unix_time();
+ friend_con->share_relays_lastsent = 0;
+ onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status);
+ } else { /* Went offline. */
+ if (friend_con->status != FRIENDCONN_STATUS_CONNECTING) {
+ call_cb = 1;
+ friend_con->dht_pk_lastrecv = unix_time();
+ onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status);
+ }
+
+ friend_con->status = FRIENDCONN_STATUS_CONNECTING;
+ friend_con->crypt_connection_id = -1;
+ friend_con->hosting_tcp_relay = 0;
+ }
+
+ if (call_cb) {
+ unsigned int i;
+
+ for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) {
+ if (friend_con->callbacks[i].status_callback) {
+ friend_con->callbacks[i].status_callback(
+ friend_con->callbacks[i].callback_object,
+ friend_con->callbacks[i].callback_id, status, userdata);
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* Callback for dht public key changes. */
+static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key, void *userdata)
+{
+ Friend_Connections *fr_c = (Friend_Connections *)object;
+ Friend_Conn *friend_con = get_conn(fr_c, number);
+
+ if (!friend_con) {
+ return;
+ }
+
+ if (public_key_cmp(friend_con->dht_temp_pk, dht_public_key) == 0) {
+ return;
+ }
+
+ change_dht_pk(fr_c, number, dht_public_key);
+
+ /* if pk changed, create a new connection.*/
+ if (friend_con->crypt_connection_id != -1) {
+ crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
+ friend_con->crypt_connection_id = -1;
+ handle_status(object, number, 0, userdata); /* Going offline. */
+ }
+
+ friend_new_connection(fr_c, number);
+ onion_set_friend_DHT_pubkey(fr_c->onion_c, friend_con->onion_friendnum, dht_public_key);
+}
+
+static int handle_packet(void *object, int number, const uint8_t *data, uint16_t length, void *userdata)
+{
+ if (length == 0) {
+ return -1;
+ }
+
+ Friend_Connections *fr_c = (Friend_Connections *)object;
+ Friend_Conn *friend_con = get_conn(fr_c, number);
+
+ if (!friend_con) {
+ return -1;
+ }
+
+ if (data[0] == PACKET_ID_FRIEND_REQUESTS) {
+ if (fr_c->fr_request_callback) {
+ fr_c->fr_request_callback(fr_c->fr_request_object, friend_con->real_public_key, data, length, userdata);
+ }
+
+ return 0;
+ }
+
+ if (data[0] == PACKET_ID_ALIVE) {
+ friend_con->ping_lastrecv = unix_time();
+ return 0;
+ }
+
+ if (data[0] == PACKET_ID_SHARE_RELAYS) {
+ Node_format nodes[MAX_SHARED_RELAYS];
+ int n;
+
+ if ((n = unpack_nodes(nodes, MAX_SHARED_RELAYS, NULL, data + 1, length - 1, 1)) == -1) {
+ return -1;
+ }
+
+ int j;
+
+ for (j = 0; j < n; j++) {
+ friend_add_tcp_relay(fr_c, number, nodes[j].ip_port, nodes[j].public_key);
+ }
+
+ return 0;
+ }
+
+ unsigned int i;
+
+ for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) {
+ if (friend_con->callbacks[i].data_callback) {
+ friend_con->callbacks[i].data_callback(
+ friend_con->callbacks[i].callback_object,
+ friend_con->callbacks[i].callback_id, data, length, userdata);
+ }
+
+ friend_con = get_conn(fr_c, number);
+
+ if (!friend_con) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int handle_lossy_packet(void *object, int number, const uint8_t *data, uint16_t length, void *userdata)
+{
+ if (length == 0) {
+ return -1;
+ }
+
+ Friend_Connections *fr_c = (Friend_Connections *)object;
+ Friend_Conn *friend_con = get_conn(fr_c, number);
+
+ if (!friend_con) {
+ return -1;
+ }
+
+ unsigned int i;
+
+ for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) {
+ if (friend_con->callbacks[i].lossy_data_callback) {
+ friend_con->callbacks[i].lossy_data_callback(
+ friend_con->callbacks[i].callback_object,
+ friend_con->callbacks[i].callback_id, data, length, userdata);
+ }
+
+ friend_con = get_conn(fr_c, number);
+
+ if (!friend_con) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int handle_new_connections(void *object, New_Connection *n_c)
+{
+ Friend_Connections *fr_c = (Friend_Connections *)object;
+ int friendcon_id = getfriend_conn_id_pk(fr_c, n_c->public_key);
+ Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
+
+ if (friend_con) {
+
+ if (friend_con->crypt_connection_id != -1) {
+ return -1;
+ }
+
+ int id = accept_crypto_connection(fr_c->net_crypto, n_c);
+
+ if (id == -1) {
+ return -1;
+ }
+
+ connection_status_handler(fr_c->net_crypto, id, &handle_status, fr_c, friendcon_id);
+ connection_data_handler(fr_c->net_crypto, id, &handle_packet, fr_c, friendcon_id);
+ connection_lossy_data_handler(fr_c->net_crypto, id, &handle_lossy_packet, fr_c, friendcon_id);
+ friend_con->crypt_connection_id = id;
+
+ if (n_c->source.ip.family != TOX_AF_INET && n_c->source.ip.family != TOX_AF_INET6) {
+ set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0);
+ } else {
+ friend_con->dht_ip_port = n_c->source;
+ friend_con->dht_ip_port_lastrecv = unix_time();
+ }
+
+ if (public_key_cmp(friend_con->dht_temp_pk, n_c->dht_public_key) != 0) {
+ change_dht_pk(fr_c, friendcon_id, n_c->dht_public_key);
+ }
+
+ nc_dht_pk_callback(fr_c->net_crypto, id, &dht_pk_callback, fr_c, friendcon_id);
+ return 0;
+ }
+
+ return -1;
+}
+
+static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id)
+{
+ Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
+
+ if (!friend_con) {
+ return -1;
+ }
+
+ if (friend_con->crypt_connection_id != -1) {
+ return -1;
+ }
+
+ /* If dht_temp_pk does not contains a pk. */
+ if (!friend_con->dht_lock) {
+ return -1;
+ }
+
+ int id = new_crypto_connection(fr_c->net_crypto, friend_con->real_public_key, friend_con->dht_temp_pk);
+
+ if (id == -1) {
+ return -1;
+ }
+
+ friend_con->crypt_connection_id = id;
+ connection_status_handler(fr_c->net_crypto, id, &handle_status, fr_c, friendcon_id);
+ connection_data_handler(fr_c->net_crypto, id, &handle_packet, fr_c, friendcon_id);
+ connection_lossy_data_handler(fr_c->net_crypto, id, &handle_lossy_packet, fr_c, friendcon_id);
+ nc_dht_pk_callback(fr_c->net_crypto, id, &dht_pk_callback, fr_c, friendcon_id);
+
+ return 0;
+}
+
+static int send_ping(const Friend_Connections *fr_c, int friendcon_id)
+{
+ Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
+
+ if (!friend_con) {
+ return -1;
+ }
+
+ uint8_t ping = PACKET_ID_ALIVE;
+ int64_t ret = write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, &ping, sizeof(ping), 0);
+
+ if (ret != -1) {
+ friend_con->ping_lastsent = unix_time();
+ return 0;
+ }
+
+ return -1;
+}
+
+/* Increases lock_count for the connection with friendcon_id by 1.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int friend_connection_lock(Friend_Connections *fr_c, int friendcon_id)
+{
+ Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
+
+ if (!friend_con) {
+ return -1;
+ }
+
+ ++friend_con->lock_count;
+ return 0;
+}
+
+/* return FRIENDCONN_STATUS_CONNECTED if the friend is connected.
+ * return FRIENDCONN_STATUS_CONNECTING if the friend isn't connected.
+ * return FRIENDCONN_STATUS_NONE on failure.
+ */
+unsigned int friend_con_connected(Friend_Connections *fr_c, int friendcon_id)
+{
+ Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
+
+ if (!friend_con) {
+ return 0;
+ }
+
+ return friend_con->status;
+}
+
+/* Copy public keys associated to friendcon_id.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int get_friendcon_public_keys(uint8_t *real_pk, uint8_t *dht_temp_pk, Friend_Connections *fr_c, int friendcon_id)
+{
+ Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
+
+ if (!friend_con) {
+ return -1;
+ }
+
+ if (real_pk) {
+ memcpy(real_pk, friend_con->real_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ }
+
+ if (dht_temp_pk) {
+ memcpy(dht_temp_pk, friend_con->dht_temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
+ }
+
+ return 0;
+}
+
+/* Set temp dht key for connection.
+ */
+void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_temp_pk, void *userdata)
+{
+ dht_pk_callback(fr_c, friendcon_id, dht_temp_pk, userdata);
+}
+
+/* Set the callbacks for the friend connection.
+ * index is the index (0 to (MAX_FRIEND_CONNECTION_CALLBACKS - 1)) we want the callback to set in the array.
+ *
+ * return 0 on success.
+ * return -1 on failure
+ */
+int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsigned int index,
+ int (*status_callback)(void *object, int id, uint8_t status, void *userdata),
+ int (*data_callback)(void *object, int id, const uint8_t *data, uint16_t len, void *userdata),
+ int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata),
+ void *object, int number)
+{
+ Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
+
+ if (!friend_con) {
+ return -1;
+ }
+
+ if (index >= MAX_FRIEND_CONNECTION_CALLBACKS) {
+ return -1;
+ }
+
+ friend_con->callbacks[index].status_callback = status_callback;
+ friend_con->callbacks[index].data_callback = data_callback;
+ friend_con->callbacks[index].lossy_data_callback = lossy_data_callback;
+
+ friend_con->callbacks[index].callback_object = object;
+ friend_con->callbacks[index].callback_id = number;
+
+ return 0;
+}
+
+/* return the crypt_connection_id for the connection.
+ *
+ * return crypt_connection_id on success.
+ * return -1 on failure.
+ */
+int friend_connection_crypt_connection_id(Friend_Connections *fr_c, int friendcon_id)
+{
+ Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
+
+ if (!friend_con) {
+ return -1;
+ }
+
+ return friend_con->crypt_connection_id;
+}
+
+/* Create a new friend connection.
+ * If one to that real public key already exists, increase lock count and return it.
+ *
+ * return -1 on failure.
+ * return connection id on success.
+ */
+int new_friend_connection(Friend_Connections *fr_c, const uint8_t *real_public_key)
+{
+ int friendcon_id = getfriend_conn_id_pk(fr_c, real_public_key);
+
+ if (friendcon_id != -1) {
+ ++fr_c->conns[friendcon_id].lock_count;
+ return friendcon_id;
+ }
+
+ friendcon_id = create_friend_conn(fr_c);
+
+ if (friendcon_id == -1) {
+ return -1;
+ }
+
+ int32_t onion_friendnum = onion_addfriend(fr_c->onion_c, real_public_key);
+
+ if (onion_friendnum == -1) {
+ return -1;
+ }
+
+ Friend_Conn *friend_con = &fr_c->conns[friendcon_id];
+
+ friend_con->crypt_connection_id = -1;
+ friend_con->status = FRIENDCONN_STATUS_CONNECTING;
+ memcpy(friend_con->real_public_key, real_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ friend_con->onion_friendnum = onion_friendnum;
+
+ recv_tcp_relay_handler(fr_c->onion_c, onion_friendnum, &tcp_relay_node_callback, fr_c, friendcon_id);
+ onion_dht_pk_callback(fr_c->onion_c, onion_friendnum, &dht_pk_callback, fr_c, friendcon_id);
+
+ return friendcon_id;
+}
+
+/* Kill a friend connection.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int kill_friend_connection(Friend_Connections *fr_c, int friendcon_id)
+{
+ Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
+
+ if (!friend_con) {
+ return -1;
+ }
+
+ if (friend_con->lock_count) {
+ --friend_con->lock_count;
+ return 0;
+ }
+
+ onion_delfriend(fr_c->onion_c, friend_con->onion_friendnum);
+ crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
+
+ if (friend_con->dht_lock) {
+ DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock);
+ }
+
+ return wipe_friend_conn(fr_c, friendcon_id);
+}
+
+
+/* Set friend request callback.
+ *
+ * This function will be called every time a friend request packet is received.
+ */
+void set_friend_request_callback(Friend_Connections *fr_c, int (*fr_request_callback)(void *, const uint8_t *,
+ const uint8_t *, uint16_t, void *), void *object)
+{
+ fr_c->fr_request_callback = fr_request_callback;
+ fr_c->fr_request_object = object;
+ oniondata_registerhandler(fr_c->onion_c, CRYPTO_PACKET_FRIEND_REQ, fr_request_callback, object);
+}
+
+/* Send a Friend request packet.
+ *
+ * return -1 if failure.
+ * return 0 if it sent the friend request directly to the friend.
+ * return the number of peers it was routed through if it did not send it directly.
+ */
+int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint32_t nospam_num, const uint8_t *data,
+ uint16_t length)
+{
+ if (1 + sizeof(nospam_num) + length > ONION_CLIENT_MAX_DATA_SIZE || length == 0) {
+ return -1;
+ }
+
+ Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
+
+ if (!friend_con) {
+ return -1;
+ }
+
+ VLA(uint8_t, packet, 1 + sizeof(nospam_num) + length);
+ memcpy(packet + 1, &nospam_num, sizeof(nospam_num));
+ memcpy(packet + 1 + sizeof(nospam_num), data, length);
+
+ if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) {
+ packet[0] = PACKET_ID_FRIEND_REQUESTS;
+ return write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, packet, SIZEOF_VLA(packet), 0) != -1;
+ }
+
+ packet[0] = CRYPTO_PACKET_FRIEND_REQ;
+ int num = send_onion_data(fr_c->onion_c, friend_con->onion_friendnum, packet, SIZEOF_VLA(packet));
+
+ if (num <= 0) {
+ return -1;
+ }
+
+ return num;
+}
+
+/* Create new friend_connections instance. */
+Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_discovery_enabled)
+{
+ if (!onion_c) {
+ return NULL;
+ }
+
+ Friend_Connections *temp = (Friend_Connections *)calloc(1, sizeof(Friend_Connections));
+
+ if (temp == NULL) {
+ return NULL;
+ }
+
+ temp->dht = onion_c->dht;
+ temp->net_crypto = onion_c->c;
+ temp->onion_c = onion_c;
+ temp->local_discovery_enabled = local_discovery_enabled;
+ // Don't include default port in port range
+ temp->next_LANport = TOX_PORTRANGE_FROM + 1;
+
+ new_connection_handler(temp->net_crypto, &handle_new_connections, temp);
+
+ if (temp->local_discovery_enabled) {
+ LANdiscovery_init(temp->dht);
+ }
+
+ return temp;
+}
+
+/* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */
+static void LANdiscovery(Friend_Connections *fr_c)
+{
+ if (fr_c->last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) {
+ const uint16_t first = fr_c->next_LANport;
+ uint16_t last = first + PORTS_PER_DISCOVERY;
+ last = last > TOX_PORTRANGE_TO ? TOX_PORTRANGE_TO : last;
+
+ // Always send to default port
+ send_LANdiscovery(net_htons(TOX_PORT_DEFAULT), fr_c->dht);
+
+ // And check some extra ports
+ for (uint16_t port = first; port < last; port++) {
+ send_LANdiscovery(net_htons(port), fr_c->dht);
+ }
+
+ // Don't include default port in port range
+ fr_c->next_LANport = last != TOX_PORTRANGE_TO ? last : TOX_PORTRANGE_FROM + 1;
+ fr_c->last_LANdiscovery = unix_time();
+ }
+}
+
+/* main friend_connections loop. */
+void do_friend_connections(Friend_Connections *fr_c, void *userdata)
+{
+ uint32_t i;
+ uint64_t temp_time = unix_time();
+
+ for (i = 0; i < fr_c->num_cons; ++i) {
+ Friend_Conn *friend_con = get_conn(fr_c, i);
+
+ if (friend_con) {
+ if (friend_con->status == FRIENDCONN_STATUS_CONNECTING) {
+ if (friend_con->dht_pk_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
+ if (friend_con->dht_lock) {
+ DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock);
+ friend_con->dht_lock = 0;
+ memset(friend_con->dht_temp_pk, 0, CRYPTO_PUBLIC_KEY_SIZE);
+ }
+ }
+
+ if (friend_con->dht_ip_port_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
+ friend_con->dht_ip_port.ip.family = 0;
+ }
+
+ if (friend_con->dht_lock) {
+ if (friend_new_connection(fr_c, i) == 0) {
+ set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0);
+ connect_to_saved_tcp_relays(fr_c, i, (MAX_FRIEND_TCP_CONNECTIONS / 2)); /* Only fill it half up. */
+ }
+ }
+ } else if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) {
+ if (friend_con->ping_lastsent + FRIEND_PING_INTERVAL < temp_time) {
+ send_ping(fr_c, i);
+ }
+
+ if (friend_con->share_relays_lastsent + SHARE_RELAYS_INTERVAL < temp_time) {
+ send_relays(fr_c, i);
+ }
+
+ if (friend_con->ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) {
+ /* If we stopped receiving ping packets, kill it. */
+ crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
+ friend_con->crypt_connection_id = -1;
+ handle_status(fr_c, i, 0, userdata); /* Going offline. */
+ }
+ }
+ }
+ }
+
+ if (fr_c->local_discovery_enabled) {
+ LANdiscovery(fr_c);
+ }
+}
+
+/* Free everything related with friend_connections. */
+void kill_friend_connections(Friend_Connections *fr_c)
+{
+ if (!fr_c) {
+ return;
+ }
+
+ uint32_t i;
+
+ for (i = 0; i < fr_c->num_cons; ++i) {
+ kill_friend_connection(fr_c, i);
+ }
+
+ if (fr_c->local_discovery_enabled) {
+ LANdiscovery_kill(fr_c->dht);
+ }
+
+ free(fr_c);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/friend_connection.h b/protocols/Tox/libtox/src/toxcore/friend_connection.h
new file mode 100644
index 0000000000..e993a103d3
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/friend_connection.h
@@ -0,0 +1,210 @@
+/*
+ * Connection to friends.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2014 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef FRIEND_CONNECTION_H
+#define FRIEND_CONNECTION_H
+
+#include "DHT.h"
+#include "LAN_discovery.h"
+#include "net_crypto.h"
+#include "onion_client.h"
+
+#define MAX_FRIEND_CONNECTION_CALLBACKS 2
+#define MESSENGER_CALLBACK_INDEX 0
+#define GROUPCHAT_CALLBACK_INDEX 1
+
+#define PACKET_ID_ALIVE 16
+#define PACKET_ID_SHARE_RELAYS 17
+#define PACKET_ID_FRIEND_REQUESTS 18
+
+/* Interval between the sending of ping packets. */
+#define FRIEND_PING_INTERVAL 8
+
+/* If no packets are received from friend in this time interval, kill the connection. */
+#define FRIEND_CONNECTION_TIMEOUT (FRIEND_PING_INTERVAL * 4)
+
+/* Time before friend is removed from the DHT after last hearing about him. */
+#define FRIEND_DHT_TIMEOUT BAD_NODE_TIMEOUT
+
+#define FRIEND_MAX_STORED_TCP_RELAYS (MAX_FRIEND_TCP_CONNECTIONS * 4)
+
+/* Max number of tcp relays sent to friends */
+#define MAX_SHARED_RELAYS (RECOMMENDED_FRIEND_TCP_CONNECTIONS)
+
+/* Interval between the sending of tcp relay information */
+#define SHARE_RELAYS_INTERVAL (5 * 60)
+
+
+enum {
+ FRIENDCONN_STATUS_NONE,
+ FRIENDCONN_STATUS_CONNECTING,
+ FRIENDCONN_STATUS_CONNECTED
+};
+
+typedef struct {
+ uint8_t status;
+
+ uint8_t real_public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t dht_temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ uint16_t dht_lock;
+ IP_Port dht_ip_port;
+ uint64_t dht_pk_lastrecv, dht_ip_port_lastrecv;
+
+ int onion_friendnum;
+ int crypt_connection_id;
+
+ uint64_t ping_lastrecv, ping_lastsent;
+ uint64_t share_relays_lastsent;
+
+ struct {
+ int (*status_callback)(void *object, int id, uint8_t status, void *userdata);
+ int (*data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
+ int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
+
+ void *callback_object;
+ int callback_id;
+ } callbacks[MAX_FRIEND_CONNECTION_CALLBACKS];
+
+ uint16_t lock_count;
+
+ Node_format tcp_relays[FRIEND_MAX_STORED_TCP_RELAYS];
+ uint16_t tcp_relay_counter;
+
+ bool hosting_tcp_relay;
+} Friend_Conn;
+
+
+typedef struct {
+ Net_Crypto *net_crypto;
+ DHT *dht;
+ Onion_Client *onion_c;
+
+ Friend_Conn *conns;
+ uint32_t num_cons;
+
+ int (*fr_request_callback)(void *object, const uint8_t *source_pubkey, const uint8_t *data, uint16_t len,
+ void *userdata);
+ void *fr_request_object;
+
+ uint64_t last_LANdiscovery;
+ uint16_t next_LANport;
+
+ bool local_discovery_enabled;
+} Friend_Connections;
+
+/* return friendcon_id corresponding to the real public key on success.
+ * return -1 on failure.
+ */
+int getfriend_conn_id_pk(Friend_Connections *fr_c, const uint8_t *real_pk);
+
+/* Increases lock_count for the connection with friendcon_id by 1.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int friend_connection_lock(Friend_Connections *fr_c, int friendcon_id);
+
+/* return FRIENDCONN_STATUS_CONNECTED if the friend is connected.
+ * return FRIENDCONN_STATUS_CONNECTING if the friend isn't connected.
+ * return FRIENDCONN_STATUS_NONE on failure.
+ */
+unsigned int friend_con_connected(Friend_Connections *fr_c, int friendcon_id);
+
+/* Copy public keys associated to friendcon_id.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int get_friendcon_public_keys(uint8_t *real_pk, uint8_t *dht_temp_pk, Friend_Connections *fr_c, int friendcon_id);
+
+/* Set temp dht key for connection.
+ */
+void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_temp_pk, void *userdata);
+
+/* Add a TCP relay associated to the friend.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_port, const uint8_t *public_key);
+
+/* Set the callbacks for the friend connection.
+ * index is the index (0 to (MAX_FRIEND_CONNECTION_CALLBACKS - 1)) we want the callback to set in the array.
+ *
+ * return 0 on success.
+ * return -1 on failure
+ */
+int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsigned int index,
+ int (*status_callback)(void *object, int id, uint8_t status, void *userdata),
+ int (*data_callback)(void *object, int id, const uint8_t *data, uint16_t len, void *userdata),
+ int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata),
+ void *object, int number);
+
+/* return the crypt_connection_id for the connection.
+ *
+ * return crypt_connection_id on success.
+ * return -1 on failure.
+ */
+int friend_connection_crypt_connection_id(Friend_Connections *fr_c, int friendcon_id);
+
+/* Create a new friend connection.
+ * If one to that real public key already exists, increase lock count and return it.
+ *
+ * return -1 on failure.
+ * return connection id on success.
+ */
+int new_friend_connection(Friend_Connections *fr_c, const uint8_t *real_public_key);
+
+/* Kill a friend connection.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int kill_friend_connection(Friend_Connections *fr_c, int friendcon_id);
+
+/* Send a Friend request packet.
+ *
+ * return -1 if failure.
+ * return 0 if it sent the friend request directly to the friend.
+ * return the number of peers it was routed through if it did not send it directly.
+ */
+int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint32_t nospam_num, const uint8_t *data,
+ uint16_t length);
+
+/* Set friend request callback.
+ *
+ * This function will be called every time a friend request is received.
+ */
+void set_friend_request_callback(Friend_Connections *fr_c, int (*fr_request_callback)(void *, const uint8_t *,
+ const uint8_t *, uint16_t, void *), void *object);
+
+/* Create new friend_connections instance. */
+Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_discovery_enabled);
+
+/* main friend_connections loop. */
+void do_friend_connections(Friend_Connections *fr_c, void *userdata);
+
+/* Free everything related with friend_connections. */
+void kill_friend_connections(Friend_Connections *fr_c);
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxcore/friend_requests.c b/protocols/Tox/libtox/src/toxcore/friend_requests.c
new file mode 100644
index 0000000000..ba782e2b01
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/friend_requests.c
@@ -0,0 +1,152 @@
+/*
+ * Handle friend requests.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "friend_requests.h"
+
+#include "util.h"
+
+/* Set and get the nospam variable used to prevent one type of friend request spam. */
+void set_nospam(Friend_Requests *fr, uint32_t num)
+{
+ fr->nospam = num;
+}
+
+uint32_t get_nospam(const Friend_Requests *fr)
+{
+ return fr->nospam;
+}
+
+
+/* Set the function that will be executed when a friend request is received. */
+void callback_friendrequest(Friend_Requests *fr, void (*function)(void *, const uint8_t *, const uint8_t *, size_t,
+ void *), void *object)
+{
+ fr->handle_friendrequest = function;
+ fr->handle_friendrequest_isset = 1;
+ fr->handle_friendrequest_object = object;
+}
+/* Set the function used to check if a friend request should be displayed to the user or not. */
+void set_filter_function(Friend_Requests *fr, int (*function)(const uint8_t *, void *), void *userdata)
+{
+ fr->filter_function = function;
+ fr->filter_function_userdata = userdata;
+}
+
+/* Add to list of received friend requests. */
+static void addto_receivedlist(Friend_Requests *fr, const uint8_t *real_pk)
+{
+ if (fr->received_requests_index >= MAX_RECEIVED_STORED) {
+ fr->received_requests_index = 0;
+ }
+
+ id_copy(fr->received_requests[fr->received_requests_index], real_pk);
+ ++fr->received_requests_index;
+}
+
+/* Check if a friend request was already received.
+ *
+ * return 0 if it did not.
+ * return 1 if it did.
+ */
+static int request_received(Friend_Requests *fr, const uint8_t *real_pk)
+{
+ uint32_t i;
+
+ for (i = 0; i < MAX_RECEIVED_STORED; ++i) {
+ if (id_equal(fr->received_requests[i], real_pk)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* Remove real pk from received_requests list.
+ *
+ * return 0 if it removed it successfully.
+ * return -1 if it didn't find it.
+ */
+int remove_request_received(Friend_Requests *fr, const uint8_t *real_pk)
+{
+ uint32_t i;
+
+ for (i = 0; i < MAX_RECEIVED_STORED; ++i) {
+ if (id_equal(fr->received_requests[i], real_pk)) {
+ crypto_memzero(fr->received_requests[i], CRYPTO_PUBLIC_KEY_SIZE);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+
+static int friendreq_handlepacket(void *object, const uint8_t *source_pubkey, const uint8_t *packet, uint16_t length,
+ void *userdata)
+{
+ Friend_Requests *fr = (Friend_Requests *)object;
+
+ if (length <= 1 + sizeof(fr->nospam) || length > ONION_CLIENT_MAX_DATA_SIZE) {
+ return 1;
+ }
+
+ ++packet;
+ --length;
+
+ if (fr->handle_friendrequest_isset == 0) {
+ return 1;
+ }
+
+ if (request_received(fr, source_pubkey)) {
+ return 1;
+ }
+
+ if (memcmp(packet, &fr->nospam, sizeof(fr->nospam)) != 0) {
+ return 1;
+ }
+
+ if (fr->filter_function) {
+ if ((*fr->filter_function)(source_pubkey, fr->filter_function_userdata) != 0) {
+ return 1;
+ }
+ }
+
+ addto_receivedlist(fr, source_pubkey);
+
+ uint32_t message_len = length - sizeof(fr->nospam);
+ VLA(uint8_t, message, message_len + 1);
+ memcpy(message, packet + sizeof(fr->nospam), message_len);
+ message[SIZEOF_VLA(message) - 1] = 0; /* Be sure the message is null terminated. */
+
+ (*fr->handle_friendrequest)(fr->handle_friendrequest_object, source_pubkey, message, message_len, userdata);
+ return 0;
+}
+
+void friendreq_init(Friend_Requests *fr, Friend_Connections *fr_c)
+{
+ set_friend_request_callback(fr_c, &friendreq_handlepacket, fr);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/friend_requests.h b/protocols/Tox/libtox/src/toxcore/friend_requests.h
new file mode 100644
index 0000000000..316e1c671f
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/friend_requests.h
@@ -0,0 +1,76 @@
+/*
+ * Handle friend requests.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2014 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef FRIEND_REQUESTS_H
+#define FRIEND_REQUESTS_H
+
+#include "friend_connection.h"
+
+#define MAX_FRIEND_REQUEST_DATA_SIZE (ONION_CLIENT_MAX_DATA_SIZE - (1 + sizeof(uint32_t)))
+
+typedef struct {
+ uint32_t nospam;
+ void (*handle_friendrequest)(void *, const uint8_t *, const uint8_t *, size_t, void *);
+ uint8_t handle_friendrequest_isset;
+ void *handle_friendrequest_object;
+
+ int (*filter_function)(const uint8_t *, void *);
+ void *filter_function_userdata;
+ /* NOTE: The following is just a temporary fix for the multiple friend requests received at the same time problem.
+ * TODO(irungentoo): Make this better (This will most likely tie in with the way we will handle spam.)
+ */
+
+#define MAX_RECEIVED_STORED 32
+
+ uint8_t received_requests[MAX_RECEIVED_STORED][CRYPTO_PUBLIC_KEY_SIZE];
+ uint16_t received_requests_index;
+} Friend_Requests;
+
+/* Set and get the nospam variable used to prevent one type of friend request spam. */
+void set_nospam(Friend_Requests *fr, uint32_t num);
+uint32_t get_nospam(const Friend_Requests *fr);
+
+/* Remove real_pk from received_requests list.
+ *
+ * return 0 if it removed it successfully.
+ * return -1 if it didn't find it.
+ */
+int remove_request_received(Friend_Requests *fr, const uint8_t *real_pk);
+
+/* Set the function that will be executed when a friend request for us is received.
+ * Function format is function(uint8_t * public_key, uint8_t * data, size_t length, void * userdata)
+ */
+void callback_friendrequest(Friend_Requests *fr, void (*function)(void *, const uint8_t *, const uint8_t *, size_t,
+ void *), void *object);
+
+/* Set the function used to check if a friend request should be displayed to the user or not.
+ * Function format is int function(uint8_t * public_key, void * userdata)
+ * It must return 0 if the request is ok (anything else if it is bad.)
+ */
+void set_filter_function(Friend_Requests *fr, int (*function)(const uint8_t *, void *), void *userdata);
+
+/* Sets up friendreq packet handlers. */
+void friendreq_init(Friend_Requests *fr, Friend_Connections *fr_c);
+
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxcore/group.c b/protocols/Tox/libtox/src/toxcore/group.c
new file mode 100644
index 0000000000..d3f068dfce
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/group.c
@@ -0,0 +1,2544 @@
+/*
+ * Slightly better groupchats implementation.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2014 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "group.h"
+
+#include "util.h"
+
+/* return 1 if the groupnumber is not valid.
+ * return 0 if the groupnumber is valid.
+ */
+static uint8_t groupnumber_not_valid(const Group_Chats *g_c, int groupnumber)
+{
+ if ((unsigned int)groupnumber >= g_c->num_chats) {
+ return 1;
+ }
+
+ if (g_c->chats == NULL) {
+ return 1;
+ }
+
+ if (g_c->chats[groupnumber].status == GROUPCHAT_STATUS_NONE) {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* Set the size of the groupchat list to num.
+ *
+ * return -1 if realloc fails.
+ * return 0 if it succeeds.
+ */
+static int realloc_groupchats(Group_Chats *g_c, uint32_t num)
+{
+ if (num == 0) {
+ free(g_c->chats);
+ g_c->chats = NULL;
+ return 0;
+ }
+
+ Group_c *newgroup_chats = (Group_c *)realloc(g_c->chats, num * sizeof(Group_c));
+
+ if (newgroup_chats == NULL) {
+ return -1;
+ }
+
+ g_c->chats = newgroup_chats;
+ return 0;
+}
+
+
+/* Create a new empty groupchat connection.
+ *
+ * return -1 on failure.
+ * return groupnumber on success.
+ */
+static int create_group_chat(Group_Chats *g_c)
+{
+ uint32_t i;
+
+ for (i = 0; i < g_c->num_chats; ++i) {
+ if (g_c->chats[i].status == GROUPCHAT_STATUS_NONE) {
+ return i;
+ }
+ }
+
+ int id = -1;
+
+ if (realloc_groupchats(g_c, g_c->num_chats + 1) == 0) {
+ id = g_c->num_chats;
+ ++g_c->num_chats;
+ memset(&(g_c->chats[id]), 0, sizeof(Group_c));
+ }
+
+ return id;
+}
+
+
+/* Wipe a groupchat.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int wipe_group_chat(Group_Chats *g_c, int groupnumber)
+{
+ if (groupnumber_not_valid(g_c, groupnumber)) {
+ return -1;
+ }
+
+ uint32_t i;
+ crypto_memzero(&(g_c->chats[groupnumber]), sizeof(Group_c));
+
+ for (i = g_c->num_chats; i != 0; --i) {
+ if (g_c->chats[i - 1].status != GROUPCHAT_STATUS_NONE) {
+ break;
+ }
+ }
+
+ if (g_c->num_chats != i) {
+ g_c->num_chats = i;
+ realloc_groupchats(g_c, g_c->num_chats);
+ }
+
+ return 0;
+}
+
+static Group_c *get_group_c(const Group_Chats *g_c, int groupnumber)
+{
+ if (groupnumber_not_valid(g_c, groupnumber)) {
+ return 0;
+ }
+
+ return &g_c->chats[groupnumber];
+}
+
+/*
+ * check if peer with real_pk is in peer array.
+ *
+ * return peer index if peer is in chat.
+ * return -1 if peer is not in chat.
+ *
+ * TODO(irungentoo): make this more efficient.
+ */
+
+static int peer_in_chat(const Group_c *chat, const uint8_t *real_pk)
+{
+ uint32_t i;
+
+ for (i = 0; i < chat->numpeers; ++i) {
+ if (id_equal(chat->group[i].real_pk, real_pk)) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/*
+ * check if group with identifier is in group array.
+ *
+ * return group number if peer is in list.
+ * return -1 if group is not in list.
+ *
+ * TODO(irungentoo): make this more efficient and maybe use constant time comparisons?
+ */
+static int get_group_num(const Group_Chats *g_c, const uint8_t *identifier)
+{
+ uint32_t i;
+
+ for (i = 0; i < g_c->num_chats; ++i) {
+ if (crypto_memcmp(g_c->chats[i].identifier, identifier, GROUP_IDENTIFIER_LENGTH) == 0) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/*
+ * check if peer with peer_number is in peer array.
+ *
+ * return peer number if peer is in chat.
+ * return -1 if peer is not in chat.
+ *
+ * TODO(irungentoo): make this more efficient.
+ */
+static int get_peer_index(Group_c *g, uint16_t peer_number)
+{
+ uint32_t i;
+
+ for (i = 0; i < g->numpeers; ++i) {
+ if (g->group[i].peer_number == peer_number) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+
+static uint64_t calculate_comp_value(const uint8_t *pk1, const uint8_t *pk2)
+{
+ uint64_t cmp1 = 0, cmp2 = 0;
+
+ unsigned int i;
+
+ for (i = 0; i < sizeof(uint64_t); ++i) {
+ cmp1 = (cmp1 << 8) + (uint64_t)pk1[i];
+ cmp2 = (cmp2 << 8) + (uint64_t)pk2[i];
+ }
+
+ return (cmp1 - cmp2);
+}
+
+enum {
+ GROUPCHAT_CLOSEST_NONE,
+ GROUPCHAT_CLOSEST_ADDED,
+ GROUPCHAT_CLOSEST_REMOVED
+};
+
+static int friend_in_close(Group_c *g, int friendcon_id);
+static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnumber, uint8_t closest, uint8_t lock);
+
+static int add_to_closest(Group_Chats *g_c, int groupnumber, const uint8_t *real_pk, const uint8_t *temp_pk)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ if (public_key_cmp(g->real_pk, real_pk) == 0) {
+ return -1;
+ }
+
+ unsigned int i;
+ unsigned int index = DESIRED_CLOSE_CONNECTIONS;
+
+ for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) {
+ if (g->closest_peers[i].entry && public_key_cmp(real_pk, g->closest_peers[i].real_pk) == 0) {
+ return 0;
+ }
+ }
+
+ for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) {
+ if (g->closest_peers[i].entry == 0) {
+ index = i;
+ break;
+ }
+ }
+
+ if (index == DESIRED_CLOSE_CONNECTIONS) {
+ uint64_t comp_val = calculate_comp_value(g->real_pk, real_pk);
+ uint64_t comp_d = 0;
+
+ for (i = 0; i < (DESIRED_CLOSE_CONNECTIONS / 2); ++i) {
+ uint64_t comp;
+ comp = calculate_comp_value(g->real_pk, g->closest_peers[i].real_pk);
+
+ if (comp > comp_val && comp > comp_d) {
+ index = i;
+ comp_d = comp;
+ }
+ }
+
+ comp_val = calculate_comp_value(real_pk, g->real_pk);
+
+ for (i = (DESIRED_CLOSE_CONNECTIONS / 2); i < DESIRED_CLOSE_CONNECTIONS; ++i) {
+ uint64_t comp = calculate_comp_value(g->closest_peers[i].real_pk, g->real_pk);
+
+ if (comp > comp_val && comp > comp_d) {
+ index = i;
+ comp_d = comp;
+ }
+ }
+ }
+
+ if (index == DESIRED_CLOSE_CONNECTIONS) {
+ return -1;
+ }
+
+ uint8_t old_real_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t old_temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t old = 0;
+
+ if (g->closest_peers[index].entry) {
+ memcpy(old_real_pk, g->closest_peers[index].real_pk, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(old_temp_pk, g->closest_peers[index].temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
+ old = 1;
+ }
+
+ g->closest_peers[index].entry = 1;
+ memcpy(g->closest_peers[index].real_pk, real_pk, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(g->closest_peers[index].temp_pk, temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
+
+ if (old) {
+ add_to_closest(g_c, groupnumber, old_real_pk, old_temp_pk);
+ }
+
+ if (!g->changed) {
+ g->changed = GROUPCHAT_CLOSEST_ADDED;
+ }
+
+ return 0;
+}
+
+static unsigned int pk_in_closest_peers(Group_c *g, uint8_t *real_pk)
+{
+ unsigned int i;
+
+ for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) {
+ if (!g->closest_peers[i].entry) {
+ continue;
+ }
+
+ if (public_key_cmp(g->closest_peers[i].real_pk, real_pk) == 0) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t *identifier);
+
+static int connect_to_closest(Group_Chats *g_c, int groupnumber, void *userdata)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ if (!g->changed) {
+ return 0;
+ }
+
+ unsigned int i;
+
+ if (g->changed == GROUPCHAT_CLOSEST_REMOVED) {
+ for (i = 0; i < g->numpeers; ++i) {
+ add_to_closest(g_c, groupnumber, g->group[i].real_pk, g->group[i].temp_pk);
+ }
+ }
+
+ for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
+ if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
+ continue;
+ }
+
+ if (!g->close[i].closest) {
+ continue;
+ }
+
+ uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t dht_temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[i].number);
+
+ if (!pk_in_closest_peers(g, real_pk)) {
+ g->close[i].type = GROUPCHAT_CLOSE_NONE;
+ kill_friend_connection(g_c->fr_c, g->close[i].number);
+ }
+ }
+
+ for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) {
+ if (!g->closest_peers[i].entry) {
+ continue;
+ }
+
+ int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->closest_peers[i].real_pk);
+
+ uint8_t lock = 1;
+
+ if (friendcon_id == -1) {
+ friendcon_id = new_friend_connection(g_c->fr_c, g->closest_peers[i].real_pk);
+ lock = 0;
+
+ if (friendcon_id == -1) {
+ continue;
+ }
+
+ set_dht_temp_pk(g_c->fr_c, friendcon_id, g->closest_peers[i].temp_pk, userdata);
+ }
+
+ add_conn_to_groupchat(g_c, friendcon_id, groupnumber, 1, lock);
+
+ if (friend_con_connected(g_c->fr_c, friendcon_id) == FRIENDCONN_STATUS_CONNECTED) {
+ send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->identifier);
+ }
+ }
+
+ g->changed = GROUPCHAT_CLOSEST_NONE;
+
+ return 0;
+}
+
+/* Add a peer to the group chat.
+ *
+ * do_gc_callback indicates whether we want to trigger callbacks set by the client
+ * via the public API. This should be set to false if this function is called
+ * from outside of the tox_iterate() loop.
+ *
+ * return peer_index if success or peer already in chat.
+ * return -1 if error.
+ */
+static int addpeer(Group_Chats *g_c, int groupnumber, const uint8_t *real_pk, const uint8_t *temp_pk,
+ uint16_t peer_number, void *userdata, bool do_gc_callback)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ // TODO(irungentoo):
+ int peer_index = peer_in_chat(g, real_pk);
+
+ if (peer_index != -1) {
+ id_copy(g->group[peer_index].temp_pk, temp_pk);
+
+ if (g->group[peer_index].peer_number != peer_number) {
+ return -1;
+ }
+
+ return peer_index;
+ }
+
+ peer_index = get_peer_index(g, peer_number);
+
+ if (peer_index != -1) {
+ return -1;
+ }
+
+ Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers + 1));
+
+ if (temp == NULL) {
+ return -1;
+ }
+
+ memset(&(temp[g->numpeers]), 0, sizeof(Group_Peer));
+ g->group = temp;
+
+ id_copy(g->group[g->numpeers].real_pk, real_pk);
+ id_copy(g->group[g->numpeers].temp_pk, temp_pk);
+ g->group[g->numpeers].peer_number = peer_number;
+
+ g->group[g->numpeers].last_recv = unix_time();
+ ++g->numpeers;
+
+ add_to_closest(g_c, groupnumber, real_pk, temp_pk);
+
+ if (do_gc_callback && g_c->group_namelistchange) {
+ g_c->group_namelistchange(g_c->m, groupnumber, g->numpeers - 1, CHAT_CHANGE_PEER_ADD, userdata);
+ }
+
+ if (g->peer_on_join) {
+ g->peer_on_join(g->object, groupnumber, g->numpeers - 1);
+ }
+
+ return (g->numpeers - 1);
+}
+
+static int remove_close_conn(Group_Chats *g_c, int groupnumber, int friendcon_id)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ uint32_t i;
+
+ for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
+ if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
+ continue;
+ }
+
+ if (g->close[i].number == (unsigned int)friendcon_id) {
+ g->close[i].type = GROUPCHAT_CLOSE_NONE;
+ kill_friend_connection(g_c->fr_c, friendcon_id);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+
+/*
+ * Delete a peer from the group chat.
+ *
+ * return 0 if success
+ * return -1 if error.
+ */
+static int delpeer(Group_Chats *g_c, int groupnumber, int peer_index, void *userdata)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ uint32_t i;
+
+ for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { /* If peer is in closest_peers list, remove it. */
+ if (g->closest_peers[i].entry && id_equal(g->closest_peers[i].real_pk, g->group[peer_index].real_pk)) {
+ g->closest_peers[i].entry = 0;
+ g->changed = GROUPCHAT_CLOSEST_REMOVED;
+ break;
+ }
+ }
+
+ int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->group[peer_index].real_pk);
+
+ if (friendcon_id != -1) {
+ remove_close_conn(g_c, groupnumber, friendcon_id);
+ }
+
+ --g->numpeers;
+
+ void *peer_object = g->group[peer_index].object;
+
+ if (g->numpeers == 0) {
+ free(g->group);
+ g->group = NULL;
+ } else {
+ if (g->numpeers != (uint32_t)peer_index) {
+ memcpy(&g->group[peer_index], &g->group[g->numpeers], sizeof(Group_Peer));
+ }
+
+ Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers));
+
+ if (temp == NULL) {
+ return -1;
+ }
+
+ g->group = temp;
+ }
+
+ if (g_c->group_namelistchange) {
+ g_c->group_namelistchange(g_c->m, groupnumber, peer_index, CHAT_CHANGE_PEER_DEL, userdata);
+ }
+
+ if (g->peer_on_leave) {
+ g->peer_on_leave(g->object, groupnumber, peer_index, peer_object);
+ }
+
+ return 0;
+}
+
+/* Set the nick for a peer.
+ *
+ * do_gc_callback indicates whether we want to trigger callbacks set by the client
+ * via the public API. This should be set to false if this function is called
+ * from outside of the tox_iterate() loop.
+ *
+ * return 0 on success.
+ * return -1 if error.
+ */
+static int setnick(Group_Chats *g_c, int groupnumber, int peer_index, const uint8_t *nick, uint16_t nick_len,
+ void *userdata, bool do_gc_callback)
+{
+ if (nick_len > MAX_NAME_LENGTH) {
+ return -1;
+ }
+
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ /* same name as already stored? */
+ if (g->group[peer_index].nick_len == nick_len) {
+ if (nick_len == 0 || !memcmp(g->group[peer_index].nick, nick, nick_len)) {
+ return 0;
+ }
+ }
+
+ if (nick_len) {
+ memcpy(g->group[peer_index].nick, nick, nick_len);
+ }
+
+ g->group[peer_index].nick_len = nick_len;
+
+ if (do_gc_callback && g_c->group_namelistchange) {
+ g_c->group_namelistchange(g_c->m, groupnumber, peer_index, CHAT_CHANGE_PEER_NAME, userdata);
+ }
+
+ return 0;
+}
+
+static int settitle(Group_Chats *g_c, int groupnumber, int peer_index, const uint8_t *title, uint8_t title_len,
+ void *userdata)
+{
+ if (title_len > MAX_NAME_LENGTH || title_len == 0) {
+ return -1;
+ }
+
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ /* same as already set? */
+ if (g->title_len == title_len && !memcmp(g->title, title, title_len)) {
+ return 0;
+ }
+
+ memcpy(g->title, title, title_len);
+ g->title_len = title_len;
+
+ if (g_c->title_callback) {
+ g_c->title_callback(g_c->m, groupnumber, peer_index, title, title_len, userdata);
+ }
+
+ return 0;
+}
+
+static void set_conns_type_close(Group_Chats *g_c, int groupnumber, int friendcon_id, uint8_t type)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return;
+ }
+
+ uint32_t i;
+
+ for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
+ if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
+ continue;
+ }
+
+ if (g->close[i].number != (unsigned int)friendcon_id) {
+ continue;
+ }
+
+ if (type == GROUPCHAT_CLOSE_ONLINE) {
+ send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->identifier);
+ } else {
+ g->close[i].type = type;
+ }
+ }
+}
+/* Set the type for all close connections with friendcon_id */
+static void set_conns_status_groups(Group_Chats *g_c, int friendcon_id, uint8_t type)
+{
+ uint32_t i;
+
+ for (i = 0; i < g_c->num_chats; ++i) {
+ set_conns_type_close(g_c, i, friendcon_id, type);
+ }
+}
+
+static int g_handle_status(void *object, int friendcon_id, uint8_t status, void *userdata)
+{
+ Group_Chats *g_c = (Group_Chats *)object;
+
+ if (status) { /* Went online */
+ set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_ONLINE);
+ } else { /* Went offline */
+ set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_CONNECTION);
+ // TODO(irungentoo): remove timedout connections?
+ }
+
+ return 0;
+}
+
+static int g_handle_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata);
+static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata);
+
+/* Add friend to group chat.
+ *
+ * return close index on success
+ * return -1 on failure.
+ */
+static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnumber, uint8_t closest, uint8_t lock)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ uint16_t i, ind = MAX_GROUP_CONNECTIONS;
+
+ for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
+ if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
+ ind = i;
+ continue;
+ }
+
+ if (g->close[i].number == (uint32_t)friendcon_id) {
+ g->close[i].closest = closest;
+ return i; /* Already in list. */
+ }
+ }
+
+ if (ind == MAX_GROUP_CONNECTIONS) {
+ return -1;
+ }
+
+ if (lock) {
+ friend_connection_lock(g_c->fr_c, friendcon_id);
+ }
+
+ g->close[ind].type = GROUPCHAT_CLOSE_CONNECTION;
+ g->close[ind].number = friendcon_id;
+ g->close[ind].closest = closest;
+ // TODO(irungentoo):
+ friend_connection_callbacks(g_c->m->fr_c, friendcon_id, GROUPCHAT_CALLBACK_INDEX, &g_handle_status, &g_handle_packet,
+ &handle_lossy, g_c, friendcon_id);
+
+ return ind;
+}
+
+/* Creates a new groupchat and puts it in the chats array.
+ *
+ * type is one of GROUPCHAT_TYPE_*
+ *
+ * return group number on success.
+ * return -1 on failure.
+ */
+int add_groupchat(Group_Chats *g_c, uint8_t type)
+{
+ int groupnumber = create_group_chat(g_c);
+
+ if (groupnumber == -1) {
+ return -1;
+ }
+
+ Group_c *g = &g_c->chats[groupnumber];
+
+ g->status = GROUPCHAT_STATUS_CONNECTED;
+ g->number_joined = -1;
+ new_symmetric_key(g->identifier + 1);
+ g->identifier[0] = type;
+ g->peer_number = 0; /* Founder is peer 0. */
+ memcpy(g->real_pk, g_c->m->net_crypto->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ int peer_index = addpeer(g_c, groupnumber, g->real_pk, g_c->m->dht->self_public_key, 0, NULL, false);
+
+ if (peer_index == -1) {
+ return -1;
+ }
+
+ setnick(g_c, groupnumber, peer_index, g_c->m->name, g_c->m->name_length, NULL, false);
+
+ return groupnumber;
+}
+
+static int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num);
+/* Delete a groupchat from the chats array.
+ *
+ * return 0 on success.
+ * return -1 if groupnumber is invalid.
+ */
+int del_groupchat(Group_Chats *g_c, int groupnumber)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ group_kill_peer_send(g_c, groupnumber, g->peer_number);
+
+ unsigned int i;
+
+ for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
+ if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
+ continue;
+ }
+
+ g->close[i].type = GROUPCHAT_CLOSE_NONE;
+ kill_friend_connection(g_c->fr_c, g->close[i].number);
+ }
+
+ for (i = 0; i < g->numpeers; ++i) {
+ if (g->peer_on_leave) {
+ g->peer_on_leave(g->object, groupnumber, i, g->group[i].object);
+ }
+ }
+
+ free(g->group);
+
+ if (g->group_on_delete) {
+ g->group_on_delete(g->object, groupnumber);
+ }
+
+ return wipe_group_chat(g_c, groupnumber);
+}
+
+/* Copy the public key of peernumber who is in groupnumber to pk.
+ * pk must be CRYPTO_PUBLIC_KEY_SIZE long.
+ *
+ * return 0 on success
+ * return -1 if groupnumber is invalid.
+ * return -2 if peernumber is invalid.
+ */
+int group_peer_pubkey(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *pk)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ if ((uint32_t)peernumber >= g->numpeers) {
+ return -2;
+ }
+
+ memcpy(pk, g->group[peernumber].real_pk, CRYPTO_PUBLIC_KEY_SIZE);
+ return 0;
+}
+
+/*
+ * Return the size of peernumber's name.
+ *
+ * return -1 if groupnumber is invalid.
+ * return -2 if peernumber is invalid.
+ */
+int group_peername_size(const Group_Chats *g_c, int groupnumber, int peernumber)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ if ((uint32_t)peernumber >= g->numpeers) {
+ return -2;
+ }
+
+ if (g->group[peernumber].nick_len == 0) {
+ return 8;
+ }
+
+ return g->group[peernumber].nick_len;
+}
+
+/* Copy the name of peernumber who is in groupnumber to name.
+ * name must be at least MAX_NAME_LENGTH long.
+ *
+ * return length of name if success
+ * return -1 if groupnumber is invalid.
+ * return -2 if peernumber is invalid.
+ */
+int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *name)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ if ((uint32_t)peernumber >= g->numpeers) {
+ return -2;
+ }
+
+ if (g->group[peernumber].nick_len == 0) {
+ memcpy(name, "Tox User", 8);
+ return 8;
+ }
+
+ memcpy(name, g->group[peernumber].nick, g->group[peernumber].nick_len);
+ return g->group[peernumber].nick_len;
+}
+
+/* List all the peers in the group chat.
+ *
+ * Copies the names of the peers to the name[length][MAX_NAME_LENGTH] array.
+ *
+ * Copies the lengths of the names to lengths[length]
+ *
+ * returns the number of peers on success.
+ *
+ * return -1 on failure.
+ */
+int group_names(const Group_Chats *g_c, int groupnumber, uint8_t names[][MAX_NAME_LENGTH], uint16_t lengths[],
+ uint16_t length)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ unsigned int i;
+
+ for (i = 0; i < g->numpeers && i < length; ++i) {
+ lengths[i] = group_peername(g_c, groupnumber, i, names[i]);
+ }
+
+ return i;
+}
+
+/* Return the number of peers in the group chat on success.
+ * return -1 if groupnumber is invalid.
+ */
+int group_number_peers(const Group_Chats *g_c, int groupnumber)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ return g->numpeers;
+}
+
+/* return 1 if the peernumber corresponds to ours.
+ * return 0 if the peernumber is not ours.
+ * return -1 if groupnumber is invalid.
+ * return -2 if peernumber is invalid.
+ * return -3 if we are not connected to the group chat.
+ */
+int group_peernumber_is_ours(const Group_Chats *g_c, int groupnumber, int peernumber)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ if ((uint32_t)peernumber >= g->numpeers) {
+ return -2;
+ }
+
+ if (g->status != GROUPCHAT_STATUS_CONNECTED) {
+ return -3;
+ }
+
+ return g->peer_number == g->group[peernumber].peer_number;
+}
+
+/* return the type of groupchat (GROUPCHAT_TYPE_) that groupnumber is.
+ *
+ * return -1 on failure.
+ * return type on success.
+ */
+int group_get_type(const Group_Chats *g_c, int groupnumber)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ return g->identifier[0];
+}
+
+/* Send a group packet to friendcon_id.
+ *
+ * return 1 on success
+ * return 0 on failure
+ */
+static unsigned int send_packet_group_peer(Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id,
+ uint16_t group_num, const uint8_t *data, uint16_t length)
+{
+ if (1 + sizeof(uint16_t) + length > MAX_CRYPTO_DATA_SIZE) {
+ return 0;
+ }
+
+ group_num = net_htons(group_num);
+ VLA(uint8_t, packet, 1 + sizeof(uint16_t) + length);
+ packet[0] = packet_id;
+ memcpy(packet + 1, &group_num, sizeof(uint16_t));
+ memcpy(packet + 1 + sizeof(uint16_t), data, length);
+ return write_cryptpacket(fr_c->net_crypto, friend_connection_crypt_connection_id(fr_c, friendcon_id), packet,
+ SIZEOF_VLA(packet), 0) != -1;
+}
+
+/* Send a group lossy packet to friendcon_id.
+ *
+ * return 1 on success
+ * return 0 on failure
+ */
+static unsigned int send_lossy_group_peer(Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id,
+ uint16_t group_num, const uint8_t *data, uint16_t length)
+{
+ if (1 + sizeof(uint16_t) + length > MAX_CRYPTO_DATA_SIZE) {
+ return 0;
+ }
+
+ group_num = net_htons(group_num);
+ VLA(uint8_t, packet, 1 + sizeof(uint16_t) + length);
+ packet[0] = packet_id;
+ memcpy(packet + 1, &group_num, sizeof(uint16_t));
+ memcpy(packet + 1 + sizeof(uint16_t), data, length);
+ return send_lossy_cryptpacket(fr_c->net_crypto, friend_connection_crypt_connection_id(fr_c, friendcon_id), packet,
+ SIZEOF_VLA(packet)) != -1;
+}
+
+#define INVITE_PACKET_SIZE (1 + sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH)
+#define INVITE_ID 0
+
+#define INVITE_RESPONSE_PACKET_SIZE (1 + sizeof(uint16_t) * 2 + GROUP_IDENTIFIER_LENGTH)
+#define INVITE_RESPONSE_ID 1
+
+/* invite friendnumber to groupnumber.
+ *
+ * return 0 on success.
+ * return -1 if groupnumber is invalid.
+ * return -2 if invite packet failed to send.
+ */
+int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ uint8_t invite[INVITE_PACKET_SIZE];
+ invite[0] = INVITE_ID;
+ uint16_t groupchat_num = net_htons((uint16_t)groupnumber);
+ memcpy(invite + 1, &groupchat_num, sizeof(groupchat_num));
+ memcpy(invite + 1 + sizeof(groupchat_num), g->identifier, GROUP_IDENTIFIER_LENGTH);
+
+ if (send_conference_invite_packet(g_c->m, friendnumber, invite, sizeof(invite))) {
+ return 0;
+ }
+
+ wipe_group_chat(g_c, groupnumber);
+ return -2;
+}
+
+static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num);
+
+/* Join a group (you need to have been invited first.)
+ *
+ * expected_type is the groupchat type we expect the chat we are joining is.
+ *
+ * return group number on success.
+ * return -1 if data length is invalid.
+ * return -2 if group is not the expected type.
+ * return -3 if friendnumber is invalid.
+ * return -4 if client is already in this group.
+ * return -5 if group instance failed to initialize.
+ * return -6 if join packet fails to send.
+ */
+int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type, const uint8_t *data, uint16_t length)
+{
+ if (length != sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH) {
+ return -1;
+ }
+
+ if (data[sizeof(uint16_t)] != expected_type) {
+ return -2;
+ }
+
+ int friendcon_id = getfriendcon_id(g_c->m, friendnumber);
+
+ if (friendcon_id == -1) {
+ return -3;
+ }
+
+ if (get_group_num(g_c, data + sizeof(uint16_t)) != -1) {
+ return -4;
+ }
+
+ int groupnumber = create_group_chat(g_c);
+
+ if (groupnumber == -1) {
+ return -5;
+ }
+
+ Group_c *g = &g_c->chats[groupnumber];
+
+ uint16_t group_num = net_htons(groupnumber);
+ g->status = GROUPCHAT_STATUS_VALID;
+ g->number_joined = -1;
+ memcpy(g->real_pk, g_c->m->net_crypto->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+
+ uint8_t response[INVITE_RESPONSE_PACKET_SIZE];
+ response[0] = INVITE_RESPONSE_ID;
+ memcpy(response + 1, &group_num, sizeof(uint16_t));
+ memcpy(response + 1 + sizeof(uint16_t), data, sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH);
+
+ if (send_conference_invite_packet(g_c->m, friendnumber, response, sizeof(response))) {
+ uint16_t other_groupnum;
+ memcpy(&other_groupnum, data, sizeof(other_groupnum));
+ other_groupnum = net_ntohs(other_groupnum);
+ memcpy(g->identifier, data + sizeof(uint16_t), GROUP_IDENTIFIER_LENGTH);
+ int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnumber, 0, 1);
+
+ if (close_index != -1) {
+ g->close[close_index].group_number = other_groupnum;
+ g->close[close_index].type = GROUPCHAT_CLOSE_ONLINE;
+ g->number_joined = friendcon_id;
+ }
+
+ send_peer_query(g_c, friendcon_id, other_groupnum);
+ return groupnumber;
+ }
+
+ g->status = GROUPCHAT_STATUS_NONE;
+ return -6;
+}
+
+/* Set handlers for custom lossy packets.
+ *
+ * NOTE: Handler must return 0 if packet is to be relayed, -1 if the packet should not be relayed.
+ *
+ * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber, void *group peer object (set with group_peer_set_object), const uint8_t *packet, uint16_t length)
+ */
+void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, int (*function)(void *, int, int, void *,
+ const uint8_t *, uint16_t))
+{
+ g_c->lossy_packethandlers[byte].function = function;
+}
+
+/* Set the callback for group invites.
+ *
+ * Function(Group_Chats *g_c, int32_t friendnumber, uint8_t type, uint8_t *data, uint16_t length, void *userdata)
+ *
+ * data of length is what needs to be passed to join_groupchat().
+ */
+void g_callback_group_invite(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, int, const uint8_t *,
+ size_t, void *))
+{
+ g_c->invite_callback = function;
+}
+
+/* Set the callback for group messages.
+ *
+ * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata)
+ */
+void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, int, const uint8_t *,
+ size_t, void *))
+{
+ g_c->message_callback = function;
+}
+
+/* Set callback function for peer name list changes.
+ *
+ * It gets called every time the name list changes(new peer/name, deleted peer)
+ * Function(Group_Chats *g_c, int groupnumber, int peernumber, TOX_CHAT_CHANGE change, void *userdata)
+ */
+void g_callback_group_namelistchange(Group_Chats *g_c, void (*function)(Messenger *m, int, int, uint8_t, void *))
+{
+ g_c->group_namelistchange = function;
+}
+
+/* Set callback function for title changes.
+ *
+ * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * title, uint8_t length, void *userdata)
+ * if friendgroupnumber == -1, then author is unknown (e.g. initial joining the group)
+ */
+void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, const uint8_t *,
+ size_t, void *))
+{
+ g_c->title_callback = function;
+}
+
+/* Set a function to be called when a new peer joins a group chat.
+ *
+ * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber)
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int callback_groupchat_peer_new(const Group_Chats *g_c, int groupnumber, void (*function)(void *, int, int))
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ g->peer_on_join = function;
+ return 0;
+}
+
+/* Set a function to be called when a peer leaves a group chat.
+ *
+ * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber, void *group peer object (set with group_peer_set_object))
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int callback_groupchat_peer_delete(Group_Chats *g_c, int groupnumber, void (*function)(void *, int, int, void *))
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ g->peer_on_leave = function;
+ return 0;
+}
+
+/* Set a function to be called when the group chat is deleted.
+ *
+ * Function(void *group object (set with group_set_object), int groupnumber)
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int callback_groupchat_delete(Group_Chats *g_c, int groupnumber, void (*function)(void *, int))
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ g->group_on_delete = function;
+ return 0;
+}
+
+static int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data,
+ uint16_t len);
+
+#define GROUP_MESSAGE_PING_ID 0
+static int group_ping_send(const Group_Chats *g_c, int groupnumber)
+{
+ if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_PING_ID, 0, 0) > 0) {
+ return 0;
+ }
+
+ return -1;
+}
+
+#define GROUP_MESSAGE_NEW_PEER_ID 16
+#define GROUP_MESSAGE_NEW_PEER_LENGTH (sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE * 2)
+/* send a new_peer message
+ * return 0 on success
+ * return -1 on failure
+ */
+static int group_new_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num, const uint8_t *real_pk,
+ uint8_t *temp_pk)
+{
+ uint8_t packet[GROUP_MESSAGE_NEW_PEER_LENGTH];
+
+ peer_num = net_htons(peer_num);
+ memcpy(packet, &peer_num, sizeof(uint16_t));
+ memcpy(packet + sizeof(uint16_t), real_pk, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(packet + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE, temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
+
+ if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_NEW_PEER_ID, packet, sizeof(packet)) > 0) {
+ return 0;
+ }
+
+ return -1;
+}
+
+#define GROUP_MESSAGE_KILL_PEER_ID 17
+#define GROUP_MESSAGE_KILL_PEER_LENGTH (sizeof(uint16_t))
+
+/* send a kill_peer message
+ * return 0 on success
+ * return -1 on failure
+ */
+static int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num)
+{
+ uint8_t packet[GROUP_MESSAGE_KILL_PEER_LENGTH];
+
+ peer_num = net_htons(peer_num);
+ memcpy(packet, &peer_num, sizeof(uint16_t));
+
+ if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_KILL_PEER_ID, packet, sizeof(packet)) > 0) {
+ return 0;
+ }
+
+ return -1;
+}
+
+#define GROUP_MESSAGE_NAME_ID 48
+
+/* send a name message
+ * return 0 on success
+ * return -1 on failure
+ */
+static int group_name_send(const Group_Chats *g_c, int groupnumber, const uint8_t *nick, uint16_t nick_len)
+{
+ if (nick_len > MAX_NAME_LENGTH) {
+ return -1;
+ }
+
+ if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_NAME_ID, nick, nick_len) > 0) {
+ return 0;
+ }
+
+ return -1;
+}
+
+#define GROUP_MESSAGE_TITLE_ID 49
+
+/* set the group's title, limited to MAX_NAME_LENGTH
+ * return 0 on success
+ * return -1 if groupnumber is invalid.
+ * return -2 if title is too long or empty.
+ * return -3 if packet fails to send.
+ */
+int group_title_send(const Group_Chats *g_c, int groupnumber, const uint8_t *title, uint8_t title_len)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ if (title_len > MAX_NAME_LENGTH || title_len == 0) {
+ return -2;
+ }
+
+ /* same as already set? */
+ if (g->title_len == title_len && !memcmp(g->title, title, title_len)) {
+ return 0;
+ }
+
+ memcpy(g->title, title, title_len);
+ g->title_len = title_len;
+
+ if (g->numpeers == 1) {
+ return 0;
+ }
+
+ if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_TITLE_ID, title, title_len) > 0) {
+ return 0;
+ }
+
+ return -3;
+}
+
+/* return the group's title size.
+ * return -1 of groupnumber is invalid.
+ * return -2 if title is too long or empty.
+ */
+int group_title_get_size(const Group_Chats *g_c, int groupnumber)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ if (g->title_len == 0 || g->title_len > MAX_NAME_LENGTH) {
+ return -2;
+ }
+
+ return g->title_len;
+}
+
+/* Get group title from groupnumber and put it in title.
+ * Title needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
+ *
+ * return length of copied title if success.
+ * return -1 if groupnumber is invalid.
+ * return -2 if title is too long or empty.
+ */
+int group_title_get(const Group_Chats *g_c, int groupnumber, uint8_t *title)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ if (g->title_len == 0 || g->title_len > MAX_NAME_LENGTH) {
+ return -2;
+ }
+
+ memcpy(title, g->title, g->title_len);
+ return g->title_len;
+}
+
+static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length,
+ void *userdata)
+{
+ Group_Chats *g_c = (Group_Chats *)m->conferences_object;
+
+ if (length <= 1) {
+ return;
+ }
+
+ const uint8_t *invite_data = data + 1;
+ uint16_t invite_length = length - 1;
+
+ switch (data[0]) {
+ case INVITE_ID: {
+ if (length != INVITE_PACKET_SIZE) {
+ return;
+ }
+
+ int groupnumber = get_group_num(g_c, data + 1 + sizeof(uint16_t));
+
+ if (groupnumber == -1) {
+ if (g_c->invite_callback) {
+ g_c->invite_callback(m, friendnumber, *(invite_data + sizeof(uint16_t)), invite_data, invite_length, userdata);
+ }
+
+ return;
+ }
+
+ break;
+ }
+
+ case INVITE_RESPONSE_ID: {
+ if (length != INVITE_RESPONSE_PACKET_SIZE) {
+ return;
+ }
+
+ uint16_t other_groupnum, groupnum;
+ memcpy(&groupnum, data + 1 + sizeof(uint16_t), sizeof(uint16_t));
+ groupnum = net_ntohs(groupnum);
+
+ Group_c *g = get_group_c(g_c, groupnum);
+
+ if (!g) {
+ return;
+ }
+
+ if (crypto_memcmp(data + 1 + sizeof(uint16_t) * 2, g->identifier, GROUP_IDENTIFIER_LENGTH) != 0) {
+ return;
+ }
+
+ /* TODO(irungentoo): what if two people enter the group at the same time and
+ are given the same peer_number by different nodes? */
+ uint16_t peer_number = rand();
+
+ unsigned int tries = 0;
+
+ while (get_peer_index(g, peer_number) != -1) {
+ peer_number = rand();
+ ++tries;
+
+ if (tries > 32) {
+ return;
+ }
+ }
+
+ memcpy(&other_groupnum, data + 1, sizeof(uint16_t));
+ other_groupnum = net_ntohs(other_groupnum);
+
+ int friendcon_id = getfriendcon_id(m, friendnumber);
+ uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE], temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ get_friendcon_public_keys(real_pk, temp_pk, g_c->fr_c, friendcon_id);
+
+ addpeer(g_c, groupnum, real_pk, temp_pk, peer_number, userdata, true);
+ int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnum, 0, 1);
+
+ if (close_index != -1) {
+ g->close[close_index].group_number = other_groupnum;
+ g->close[close_index].type = GROUPCHAT_CLOSE_ONLINE;
+ }
+
+ group_new_peer_send(g_c, groupnum, peer_number, real_pk, temp_pk);
+ break;
+ }
+
+ default:
+ return;
+ }
+}
+
+/* Find index of friend in the close list;
+ *
+ * returns index on success
+ * returns -1 on failure.
+ */
+static int friend_in_close(Group_c *g, int friendcon_id)
+{
+ unsigned int i;
+
+ for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
+ if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
+ continue;
+ }
+
+ if (g->close[i].number != (uint32_t)friendcon_id) {
+ continue;
+ }
+
+ return i;
+ }
+
+ return -1;
+}
+
+/* return number of connected close connections.
+ */
+static unsigned int count_close_connected(Group_c *g)
+{
+ unsigned int i, count = 0;
+
+ for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
+ if (g->close[i].type == GROUPCHAT_CLOSE_ONLINE) {
+ ++count;
+ }
+ }
+
+ return count;
+}
+
+#define ONLINE_PACKET_DATA_SIZE (sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH)
+
+static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t *identifier)
+{
+ uint8_t packet[1 + ONLINE_PACKET_DATA_SIZE];
+ group_num = net_htons(group_num);
+ packet[0] = PACKET_ID_ONLINE_PACKET;
+ memcpy(packet + 1, &group_num, sizeof(uint16_t));
+ memcpy(packet + 1 + sizeof(uint16_t), identifier, GROUP_IDENTIFIER_LENGTH);
+ return write_cryptpacket(fr_c->net_crypto, friend_connection_crypt_connection_id(fr_c, friendcon_id), packet,
+ sizeof(packet), 0) != -1;
+}
+
+static unsigned int send_peer_kill(Group_Chats *g_c, int friendcon_id, uint16_t group_num);
+
+static int handle_packet_online(Group_Chats *g_c, int friendcon_id, const uint8_t *data, uint16_t length)
+{
+ if (length != ONLINE_PACKET_DATA_SIZE) {
+ return -1;
+ }
+
+ int groupnumber = get_group_num(g_c, data + sizeof(uint16_t));
+ uint16_t other_groupnum;
+ memcpy(&other_groupnum, data, sizeof(uint16_t));
+ other_groupnum = net_ntohs(other_groupnum);
+
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ int index = friend_in_close(g, friendcon_id);
+
+ if (index == -1) {
+ return -1;
+ }
+
+ if (g->close[index].type == GROUPCHAT_CLOSE_ONLINE) {
+ return -1;
+ }
+
+ if (count_close_connected(g) == 0) {
+ send_peer_query(g_c, friendcon_id, other_groupnum);
+ }
+
+ g->close[index].group_number = other_groupnum;
+ g->close[index].type = GROUPCHAT_CLOSE_ONLINE;
+ send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->identifier);
+
+ if (g->number_joined != -1 && count_close_connected(g) >= DESIRED_CLOSE_CONNECTIONS) {
+ int fr_close_index = friend_in_close(g, g->number_joined);
+
+ if (fr_close_index == -1) {
+ return -1;
+ }
+
+ if (!g->close[fr_close_index].closest) {
+ g->close[fr_close_index].type = GROUPCHAT_CLOSE_NONE;
+ send_peer_kill(g_c, g->close[fr_close_index].number, g->close[fr_close_index].group_number);
+ kill_friend_connection(g_c->fr_c, g->close[fr_close_index].number);
+ g->number_joined = -1;
+ }
+ }
+
+ return 0;
+}
+
+#define PEER_KILL_ID 1
+#define PEER_QUERY_ID 8
+#define PEER_RESPONSE_ID 9
+#define PEER_TITLE_ID 10
+// we could send title with invite, but then if it changes between sending and accepting inv, joinee won't see it
+
+/* return 1 on success.
+ * return 0 on failure
+ */
+static unsigned int send_peer_kill(Group_Chats *g_c, int friendcon_id, uint16_t group_num)
+{
+ uint8_t packet[1];
+ packet[0] = PEER_KILL_ID;
+ return send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, packet, sizeof(packet));
+}
+
+
+/* return 1 on success.
+ * return 0 on failure
+ */
+static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num)
+{
+ uint8_t packet[1];
+ packet[0] = PEER_QUERY_ID;
+ return send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, packet, sizeof(packet));
+}
+
+/* return number of peers sent on success.
+ * return 0 on failure.
+ */
+static unsigned int send_peers(Group_Chats *g_c, int groupnumber, int friendcon_id, uint16_t group_num)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ uint8_t packet[MAX_CRYPTO_DATA_SIZE - (1 + sizeof(uint16_t))];
+ packet[0] = PEER_RESPONSE_ID;
+ uint8_t *p = packet + 1;
+
+ uint16_t sent = 0;
+ unsigned int i;
+
+ for (i = 0; i < g->numpeers; ++i) {
+ if ((p - packet) + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE * 2 + 1 + g->group[i].nick_len > sizeof(packet)) {
+ if (send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, packet, (p - packet))) {
+ sent = i;
+ } else {
+ return sent;
+ }
+
+ p = packet + 1;
+ }
+
+ uint16_t peer_num = net_htons(g->group[i].peer_number);
+ memcpy(p, &peer_num, sizeof(peer_num));
+ p += sizeof(peer_num);
+ memcpy(p, g->group[i].real_pk, CRYPTO_PUBLIC_KEY_SIZE);
+ p += CRYPTO_PUBLIC_KEY_SIZE;
+ memcpy(p, g->group[i].temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
+ p += CRYPTO_PUBLIC_KEY_SIZE;
+ *p = g->group[i].nick_len;
+ p += 1;
+ memcpy(p, g->group[i].nick, g->group[i].nick_len);
+ p += g->group[i].nick_len;
+ }
+
+ if (sent != i) {
+ if (send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, packet, (p - packet))) {
+ sent = i;
+ }
+ }
+
+ if (g->title_len) {
+ VLA(uint8_t, Packet, 1 + g->title_len);
+ Packet[0] = PEER_TITLE_ID;
+ memcpy(Packet + 1, g->title, g->title_len);
+ send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, Packet, SIZEOF_VLA(Packet));
+ }
+
+ return sent;
+}
+
+static int handle_send_peers(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length, void *userdata)
+{
+ if (length == 0) {
+ return -1;
+ }
+
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ const uint8_t *d = data;
+
+ while ((unsigned int)(length - (d - data)) >= sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE * 2 + 1) {
+ uint16_t peer_num;
+ memcpy(&peer_num, d, sizeof(peer_num));
+ peer_num = net_ntohs(peer_num);
+ d += sizeof(uint16_t);
+ int peer_index = addpeer(g_c, groupnumber, d, d + CRYPTO_PUBLIC_KEY_SIZE, peer_num, userdata, true);
+
+ if (peer_index == -1) {
+ return -1;
+ }
+
+ if (g->status == GROUPCHAT_STATUS_VALID
+ && public_key_cmp(d, g_c->m->net_crypto->self_public_key) == 0) {
+ g->peer_number = peer_num;
+ g->status = GROUPCHAT_STATUS_CONNECTED;
+ group_name_send(g_c, groupnumber, g_c->m->name, g_c->m->name_length);
+ }
+
+ d += CRYPTO_PUBLIC_KEY_SIZE * 2;
+ uint8_t name_length = *d;
+ d += 1;
+
+ if (name_length > (length - (d - data)) || name_length > MAX_NAME_LENGTH) {
+ return -1;
+ }
+
+ setnick(g_c, groupnumber, peer_index, d, name_length, userdata, true);
+ d += name_length;
+ }
+
+ return 0;
+}
+
+static void handle_direct_packet(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length,
+ int close_index, void *userdata)
+{
+ if (length == 0) {
+ return;
+ }
+
+ switch (data[0]) {
+ case PEER_KILL_ID: {
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return;
+ }
+
+ if (!g->close[close_index].closest) {
+ g->close[close_index].type = GROUPCHAT_CLOSE_NONE;
+ kill_friend_connection(g_c->fr_c, g->close[close_index].number);
+ }
+ }
+
+ break;
+
+ case PEER_QUERY_ID: {
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return;
+ }
+
+ send_peers(g_c, groupnumber, g->close[close_index].number, g->close[close_index].group_number);
+ }
+
+ break;
+
+ case PEER_RESPONSE_ID: {
+ handle_send_peers(g_c, groupnumber, data + 1, length - 1, userdata);
+ }
+
+ break;
+
+ case PEER_TITLE_ID: {
+ settitle(g_c, groupnumber, -1, data + 1, length - 1, userdata);
+ }
+
+ break;
+ }
+}
+
+#define MIN_MESSAGE_PACKET_LEN (sizeof(uint16_t) * 2 + sizeof(uint32_t) + 1)
+
+/* Send message to all close except receiver (if receiver isn't -1)
+ * NOTE: this function appends the group chat number to the data passed to it.
+ *
+ * return number of messages sent.
+ */
+static unsigned int send_message_all_close(const Group_Chats *g_c, int groupnumber, const uint8_t *data,
+ uint16_t length, int receiver)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return 0;
+ }
+
+ uint16_t i, sent = 0;
+
+ for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
+ if (g->close[i].type != GROUPCHAT_CLOSE_ONLINE) {
+ continue;
+ }
+
+ if ((int)i == receiver) {
+ continue;
+ }
+
+ if (send_packet_group_peer(g_c->fr_c, g->close[i].number, PACKET_ID_MESSAGE_CONFERENCE, g->close[i].group_number, data,
+ length)) {
+ ++sent;
+ }
+ }
+
+ return sent;
+}
+
+/* Send lossy message to all close except receiver (if receiver isn't -1)
+ * NOTE: this function appends the group chat number to the data passed to it.
+ *
+ * return number of messages sent.
+ */
+static unsigned int send_lossy_all_close(const Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length,
+ int receiver)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return 0;
+ }
+
+ unsigned int i, sent = 0, num_connected_closest = 0, connected_closest[DESIRED_CLOSE_CONNECTIONS];
+
+ for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
+ if (g->close[i].type != GROUPCHAT_CLOSE_ONLINE) {
+ continue;
+ }
+
+ if ((int)i == receiver) {
+ continue;
+ }
+
+ if (g->close[i].closest) {
+ connected_closest[num_connected_closest] = i;
+ ++num_connected_closest;
+ continue;
+ }
+
+ if (send_lossy_group_peer(g_c->fr_c, g->close[i].number, PACKET_ID_LOSSY_CONFERENCE, g->close[i].group_number, data,
+ length)) {
+ ++sent;
+ }
+ }
+
+ if (!num_connected_closest) {
+ return sent;
+ }
+
+ unsigned int to_send = 0;
+ uint64_t comp_val_old = ~0;
+
+ for (i = 0; i < num_connected_closest; ++i) {
+ uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t dht_temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[connected_closest[i]].number);
+ uint64_t comp_val = calculate_comp_value(g->real_pk, real_pk);
+
+ if (comp_val < comp_val_old) {
+ to_send = connected_closest[i];
+ comp_val_old = comp_val;
+ }
+ }
+
+ if (send_lossy_group_peer(g_c->fr_c, g->close[to_send].number, PACKET_ID_LOSSY_CONFERENCE,
+ g->close[to_send].group_number, data, length)) {
+ ++sent;
+ }
+
+ unsigned int to_send_other = 0;
+ comp_val_old = ~0;
+
+ for (i = 0; i < num_connected_closest; ++i) {
+ uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t dht_temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[connected_closest[i]].number);
+ uint64_t comp_val = calculate_comp_value(real_pk, g->real_pk);
+
+ if (comp_val < comp_val_old) {
+ to_send_other = connected_closest[i];
+ comp_val_old = comp_val;
+ }
+ }
+
+ if (to_send_other == to_send) {
+ return sent;
+ }
+
+ if (send_lossy_group_peer(g_c->fr_c, g->close[to_send_other].number, PACKET_ID_LOSSY_CONFERENCE,
+ g->close[to_send_other].group_number, data, length)) {
+ ++sent;
+ }
+
+ return sent;
+}
+
+#define MAX_GROUP_MESSAGE_DATA_LEN (MAX_CRYPTO_DATA_SIZE - (1 + MIN_MESSAGE_PACKET_LEN))
+
+/* Send data of len with message_id to groupnumber.
+ *
+ * return number of peers it was sent to on success.
+ * return -1 if groupnumber is invalid.
+ * return -2 if message is too long.
+ * return -3 if we are not connected to the group.
+ * reutrn -4 if message failed to send.
+ */
+static int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data,
+ uint16_t len)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ if (len > MAX_GROUP_MESSAGE_DATA_LEN) {
+ return -2;
+ }
+
+ if (g->status != GROUPCHAT_STATUS_CONNECTED) {
+ return -3;
+ }
+
+ VLA(uint8_t, packet, sizeof(uint16_t) + sizeof(uint32_t) + 1 + len);
+ uint16_t peer_num = net_htons(g->peer_number);
+ memcpy(packet, &peer_num, sizeof(peer_num));
+
+ ++g->message_number;
+
+ if (!g->message_number) {
+ ++g->message_number;
+ }
+
+ uint32_t message_num = net_htonl(g->message_number);
+ memcpy(packet + sizeof(uint16_t), &message_num, sizeof(message_num));
+
+ packet[sizeof(uint16_t) + sizeof(uint32_t)] = message_id;
+
+ if (len) {
+ memcpy(packet + sizeof(uint16_t) + sizeof(uint32_t) + 1, data, len);
+ }
+
+ unsigned int ret = send_message_all_close(g_c, groupnumber, packet, SIZEOF_VLA(packet), -1);
+
+ return (ret == 0) ? -4 : ret;
+}
+
+/* send a group message
+ * return 0 on success
+ * see: send_message_group() for error codes.
+ */
+int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint16_t length)
+{
+ int ret = send_message_group(g_c, groupnumber, PACKET_ID_MESSAGE, message, length);
+
+ if (ret > 0) {
+ return 0;
+ }
+
+ return ret;
+}
+
+/* send a group action
+ * return 0 on success
+ * see: send_message_group() for error codes.
+ */
+int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint16_t length)
+{
+ int ret = send_message_group(g_c, groupnumber, PACKET_ID_ACTION, action, length);
+
+ if (ret > 0) {
+ return 0;
+ }
+
+ return ret;
+}
+
+/* High level function to send custom lossy packets.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int send_group_lossy_packet(const Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length)
+{
+ // TODO(irungentoo): length check here?
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ VLA(uint8_t, packet, sizeof(uint16_t) * 2 + length);
+ uint16_t peer_number = net_htons(g->peer_number);
+ memcpy(packet, &peer_number, sizeof(uint16_t));
+ uint16_t message_num = net_htons(g->lossy_message_number);
+ memcpy(packet + sizeof(uint16_t), &message_num, sizeof(uint16_t));
+ memcpy(packet + sizeof(uint16_t) * 2, data, length);
+
+ if (send_lossy_all_close(g_c, groupnumber, packet, SIZEOF_VLA(packet), -1) == 0) {
+ return -1;
+ }
+
+ ++g->lossy_message_number;
+ return 0;
+}
+
+static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length,
+ int close_index, void *userdata)
+{
+ if (length < sizeof(uint16_t) + sizeof(uint32_t) + 1) {
+ return;
+ }
+
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return;
+ }
+
+ uint16_t peer_number;
+ memcpy(&peer_number, data, sizeof(uint16_t));
+ peer_number = net_ntohs(peer_number);
+
+ int index = get_peer_index(g, peer_number);
+
+ if (index == -1) {
+ /* We don't know the peer this packet came from so we query the list of peers from that peer.
+ (They would not have relayed it if they didn't know the peer.) */
+ send_peer_query(g_c, g->close[close_index].number, g->close[close_index].group_number);
+ return;
+ }
+
+ uint32_t message_number;
+ memcpy(&message_number, data + sizeof(uint16_t), sizeof(message_number));
+ message_number = net_ntohl(message_number);
+
+ if (g->group[index].last_message_number == 0) {
+ g->group[index].last_message_number = message_number;
+ } else if (message_number - g->group[index].last_message_number > 64 ||
+ message_number == g->group[index].last_message_number) {
+ return;
+ }
+
+ g->group[index].last_message_number = message_number;
+
+ uint8_t message_id = data[sizeof(uint16_t) + sizeof(message_number)];
+ const uint8_t *msg_data = data + sizeof(uint16_t) + sizeof(message_number) + 1;
+ uint16_t msg_data_len = length - (sizeof(uint16_t) + sizeof(message_number) + 1);
+
+ switch (message_id) {
+ case GROUP_MESSAGE_PING_ID: {
+ if (msg_data_len != 0) {
+ return;
+ }
+
+ g->group[index].last_recv = unix_time();
+ }
+ break;
+
+ case GROUP_MESSAGE_NEW_PEER_ID: {
+ if (msg_data_len != GROUP_MESSAGE_NEW_PEER_LENGTH) {
+ return;
+ }
+
+ uint16_t new_peer_number;
+ memcpy(&new_peer_number, msg_data, sizeof(uint16_t));
+ new_peer_number = net_ntohs(new_peer_number);
+ addpeer(g_c, groupnumber, msg_data + sizeof(uint16_t), msg_data + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE,
+ new_peer_number, userdata, true);
+ }
+ break;
+
+ case GROUP_MESSAGE_KILL_PEER_ID: {
+ if (msg_data_len != GROUP_MESSAGE_KILL_PEER_LENGTH) {
+ return;
+ }
+
+ uint16_t kill_peer_number;
+ memcpy(&kill_peer_number, msg_data, sizeof(uint16_t));
+ kill_peer_number = net_ntohs(kill_peer_number);
+
+ if (peer_number == kill_peer_number) {
+ delpeer(g_c, groupnumber, index, userdata);
+ } else {
+ return;
+ // TODO(irungentoo):
+ }
+ }
+ break;
+
+ case GROUP_MESSAGE_NAME_ID: {
+ if (setnick(g_c, groupnumber, index, msg_data, msg_data_len, userdata, true) == -1) {
+ return;
+ }
+ }
+ break;
+
+ case GROUP_MESSAGE_TITLE_ID: {
+ if (settitle(g_c, groupnumber, index, msg_data, msg_data_len, userdata) == -1) {
+ return;
+ }
+ }
+ break;
+
+ case PACKET_ID_MESSAGE: {
+ if (msg_data_len == 0) {
+ return;
+ }
+
+ VLA(uint8_t, newmsg, msg_data_len + 1);
+ memcpy(newmsg, msg_data, msg_data_len);
+ newmsg[msg_data_len] = 0;
+
+ // TODO(irungentoo):
+ if (g_c->message_callback) {
+ g_c->message_callback(g_c->m, groupnumber, index, 0, newmsg, msg_data_len, userdata);
+ }
+
+ break;
+ }
+
+ case PACKET_ID_ACTION: {
+ if (msg_data_len == 0) {
+ return;
+ }
+
+ VLA(uint8_t, newmsg, msg_data_len + 1);
+ memcpy(newmsg, msg_data, msg_data_len);
+ newmsg[msg_data_len] = 0;
+
+ // TODO(irungentoo):
+ if (g_c->message_callback) {
+ g_c->message_callback(g_c->m, groupnumber, index, 1, newmsg, msg_data_len, userdata);
+ }
+
+ break;
+ }
+
+ default:
+ return;
+ }
+
+ send_message_all_close(g_c, groupnumber, data, length, -1/* TODO(irungentoo) close_index */);
+}
+
+static int g_handle_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata)
+{
+ Group_Chats *g_c = (Group_Chats *)object;
+
+ if (length < 1 + sizeof(uint16_t) + 1) {
+ return -1;
+ }
+
+ if (data[0] == PACKET_ID_ONLINE_PACKET) {
+ return handle_packet_online(g_c, friendcon_id, data + 1, length - 1);
+ }
+
+ if (data[0] != PACKET_ID_DIRECT_CONFERENCE && data[0] != PACKET_ID_MESSAGE_CONFERENCE) {
+ return -1;
+ }
+
+ uint16_t groupnumber;
+ memcpy(&groupnumber, data + 1, sizeof(uint16_t));
+ groupnumber = net_ntohs(groupnumber);
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ int index = friend_in_close(g, friendcon_id);
+
+ if (index == -1) {
+ return -1;
+ }
+
+ switch (data[0]) {
+ case PACKET_ID_DIRECT_CONFERENCE: {
+ handle_direct_packet(g_c, groupnumber, data + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), index, userdata);
+ break;
+ }
+
+ case PACKET_ID_MESSAGE_CONFERENCE: {
+ handle_message_packet_group(g_c, groupnumber, data + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), index,
+ userdata);
+ break;
+ }
+
+ default: {
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+/* Did we already receive the lossy packet or not.
+ *
+ * return -1 on failure.
+ * return 0 if packet was not received.
+ * return 1 if packet was received.
+ *
+ * TODO(irungentoo): test this
+ */
+static unsigned int lossy_packet_not_received(Group_c *g, int peer_index, uint16_t message_number)
+{
+ if (peer_index == -1) {
+ return -1;
+ }
+
+ if (g->group[peer_index].bottom_lossy_number == g->group[peer_index].top_lossy_number) {
+ g->group[peer_index].top_lossy_number = message_number;
+ g->group[peer_index].bottom_lossy_number = (message_number - MAX_LOSSY_COUNT) + 1;
+ g->group[peer_index].recv_lossy[message_number % MAX_LOSSY_COUNT] = 1;
+ return 0;
+ }
+
+ if ((uint16_t)(message_number - g->group[peer_index].bottom_lossy_number) < MAX_LOSSY_COUNT) {
+ if (g->group[peer_index].recv_lossy[message_number % MAX_LOSSY_COUNT]) {
+ return 1;
+ }
+
+ g->group[peer_index].recv_lossy[message_number % MAX_LOSSY_COUNT] = 1;
+ return 0;
+ }
+
+ if ((uint16_t)(message_number - g->group[peer_index].bottom_lossy_number) > (1 << 15)) {
+ return -1;
+ }
+
+ uint16_t top_distance = message_number - g->group[peer_index].top_lossy_number;
+
+ if (top_distance >= MAX_LOSSY_COUNT) {
+ crypto_memzero(g->group[peer_index].recv_lossy, sizeof(g->group[peer_index].recv_lossy));
+ g->group[peer_index].top_lossy_number = message_number;
+ g->group[peer_index].bottom_lossy_number = (message_number - MAX_LOSSY_COUNT) + 1;
+ g->group[peer_index].recv_lossy[message_number % MAX_LOSSY_COUNT] = 1;
+ return 0;
+ }
+
+ if (top_distance < MAX_LOSSY_COUNT) {
+ unsigned int i;
+
+ for (i = g->group[peer_index].bottom_lossy_number; i != (g->group[peer_index].bottom_lossy_number + top_distance);
+ ++i) {
+ g->group[peer_index].recv_lossy[i % MAX_LOSSY_COUNT] = 0;
+ }
+
+ g->group[peer_index].top_lossy_number = message_number;
+ g->group[peer_index].bottom_lossy_number = (message_number - MAX_LOSSY_COUNT) + 1;
+ g->group[peer_index].recv_lossy[message_number % MAX_LOSSY_COUNT] = 1;
+ return 0;
+ }
+
+ return -1;
+}
+
+static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata)
+{
+ Group_Chats *g_c = (Group_Chats *)object;
+
+ if (length < 1 + sizeof(uint16_t) * 3 + 1) {
+ return -1;
+ }
+
+ if (data[0] != PACKET_ID_LOSSY_CONFERENCE) {
+ return -1;
+ }
+
+ uint16_t groupnumber, peer_number, message_number;
+ memcpy(&groupnumber, data + 1, sizeof(uint16_t));
+ memcpy(&peer_number, data + 1 + sizeof(uint16_t), sizeof(uint16_t));
+ memcpy(&message_number, data + 1 + sizeof(uint16_t) * 2, sizeof(uint16_t));
+ groupnumber = net_ntohs(groupnumber);
+ peer_number = net_ntohs(peer_number);
+ message_number = net_ntohs(message_number);
+
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ int index = friend_in_close(g, friendcon_id);
+
+ if (index == -1) {
+ return -1;
+ }
+
+ if (peer_number == g->peer_number) {
+ return -1;
+ }
+
+ int peer_index = get_peer_index(g, peer_number);
+
+ if (peer_index == -1) {
+ return -1;
+ }
+
+ if (lossy_packet_not_received(g, peer_index, message_number)) {
+ return -1;
+ }
+
+ const uint8_t *lossy_data = data + 1 + sizeof(uint16_t) * 3;
+ uint16_t lossy_length = length - (1 + sizeof(uint16_t) * 3);
+ uint8_t message_id = lossy_data[0];
+ ++lossy_data;
+ --lossy_length;
+
+ if (g_c->lossy_packethandlers[message_id].function) {
+ if (g_c->lossy_packethandlers[message_id].function(g->object, groupnumber, peer_index, g->group[peer_index].object,
+ lossy_data, lossy_length) == -1) {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+
+ send_lossy_all_close(g_c, groupnumber, data + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), index);
+ return 0;
+}
+
+/* Set the object that is tied to the group chat.
+ *
+ * return 0 on success.
+ * return -1 on failure
+ */
+int group_set_object(const Group_Chats *g_c, int groupnumber, void *object)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ g->object = object;
+ return 0;
+}
+
+/* Set the object that is tied to the group peer.
+ *
+ * return 0 on success.
+ * return -1 on failure
+ */
+int group_peer_set_object(const Group_Chats *g_c, int groupnumber, int peernumber, void *object)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ if ((uint32_t)peernumber >= g->numpeers) {
+ return -1;
+ }
+
+ g->group[peernumber].object = object;
+ return 0;
+}
+
+/* Return the object tide to the group chat previously set by group_set_object.
+ *
+ * return NULL on failure.
+ * return object on success.
+ */
+void *group_get_object(const Group_Chats *g_c, int groupnumber)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return NULL;
+ }
+
+ return g->object;
+}
+
+/* Return the object tide to the group chat peer previously set by group_peer_set_object.
+ *
+ * return NULL on failure.
+ * return object on success.
+ */
+void *group_peer_get_object(const Group_Chats *g_c, int groupnumber, int peernumber)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return NULL;
+ }
+
+ if ((uint32_t)peernumber >= g->numpeers) {
+ return NULL;
+ }
+
+ return g->group[peernumber].object;
+}
+
+/* Interval in seconds to send ping messages */
+#define GROUP_PING_INTERVAL 20
+
+static int ping_groupchat(Group_Chats *g_c, int groupnumber)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ if (is_timeout(g->last_sent_ping, GROUP_PING_INTERVAL)) {
+ if (group_ping_send(g_c, groupnumber) != -1) { /* Ping */
+ g->last_sent_ping = unix_time();
+ }
+ }
+
+ return 0;
+}
+
+static int groupchat_clear_timedout(Group_Chats *g_c, int groupnumber, void *userdata)
+{
+ Group_c *g = get_group_c(g_c, groupnumber);
+
+ if (!g) {
+ return -1;
+ }
+
+ uint32_t i;
+
+ for (i = 0; i < g->numpeers; ++i) {
+ if (g->peer_number != g->group[i].peer_number && is_timeout(g->group[i].last_recv, GROUP_PING_INTERVAL * 3)) {
+ delpeer(g_c, groupnumber, i, userdata);
+ }
+
+ if (g->group == NULL || i >= g->numpeers) {
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/* Send current name (set in messenger) to all online groups.
+ */
+void send_name_all_groups(Group_Chats *g_c)
+{
+ unsigned int i;
+
+ for (i = 0; i < g_c->num_chats; ++i) {
+ Group_c *g = get_group_c(g_c, i);
+
+ if (!g) {
+ continue;
+ }
+
+ if (g->status == GROUPCHAT_STATUS_CONNECTED) {
+ group_name_send(g_c, i, g_c->m->name, g_c->m->name_length);
+ }
+ }
+}
+
+/* Create new groupchat instance. */
+Group_Chats *new_groupchats(Messenger *m)
+{
+ if (!m) {
+ return NULL;
+ }
+
+ Group_Chats *temp = (Group_Chats *)calloc(1, sizeof(Group_Chats));
+
+ if (temp == NULL) {
+ return NULL;
+ }
+
+ temp->m = m;
+ temp->fr_c = m->fr_c;
+ m->conferences_object = temp;
+ m_callback_conference_invite(m, &handle_friend_invite_packet);
+
+ return temp;
+}
+
+/* main groupchats loop. */
+void do_groupchats(Group_Chats *g_c, void *userdata)
+{
+ unsigned int i;
+
+ for (i = 0; i < g_c->num_chats; ++i) {
+ Group_c *g = get_group_c(g_c, i);
+
+ if (!g) {
+ continue;
+ }
+
+ if (g->status == GROUPCHAT_STATUS_CONNECTED) {
+ connect_to_closest(g_c, i, userdata);
+ ping_groupchat(g_c, i);
+ groupchat_clear_timedout(g_c, i, userdata);
+ }
+ }
+
+ // TODO(irungentoo):
+}
+
+/* Free everything related with group chats. */
+void kill_groupchats(Group_Chats *g_c)
+{
+ unsigned int i;
+
+ for (i = 0; i < g_c->num_chats; ++i) {
+ del_groupchat(g_c, i);
+ }
+
+ m_callback_conference_invite(g_c->m, NULL);
+ g_c->m->conferences_object = NULL;
+ free(g_c);
+}
+
+/* Return the number of chats in the instance m.
+ * You should use this to determine how much memory to allocate
+ * for copy_chatlist.
+ */
+uint32_t count_chatlist(Group_Chats *g_c)
+{
+ uint32_t ret = 0;
+ uint32_t i;
+
+ for (i = 0; i < g_c->num_chats; i++) {
+ if (g_c->chats[i].status != GROUPCHAT_STATUS_NONE) {
+ ret++;
+ }
+ }
+
+ return ret;
+}
+
+/* Copy a list of valid chat IDs into the array out_list.
+ * If out_list is NULL, returns 0.
+ * Otherwise, returns the number of elements copied.
+ * If the array was too small, the contents
+ * of out_list will be truncated to list_size. */
+uint32_t copy_chatlist(Group_Chats *g_c, uint32_t *out_list, uint32_t list_size)
+{
+ if (!out_list) {
+ return 0;
+ }
+
+ if (g_c->num_chats == 0) {
+ return 0;
+ }
+
+ uint32_t i, ret = 0;
+
+ for (i = 0; i < g_c->num_chats; ++i) {
+ if (ret >= list_size) {
+ break; /* Abandon ship */
+ }
+
+ if (g_c->chats[i].status > GROUPCHAT_STATUS_NONE) {
+ out_list[ret] = i;
+ ret++;
+ }
+ }
+
+ return ret;
+}
diff --git a/protocols/Tox/libtox/src/toxcore/group.h b/protocols/Tox/libtox/src/toxcore/group.h
new file mode 100644
index 0000000000..2e014da36d
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/group.h
@@ -0,0 +1,395 @@
+/*
+ * Slightly better groupchats implementation.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2014 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef GROUP_H
+#define GROUP_H
+
+#include "Messenger.h"
+
+enum {
+ GROUPCHAT_STATUS_NONE,
+ GROUPCHAT_STATUS_VALID,
+ GROUPCHAT_STATUS_CONNECTED
+};
+
+enum {
+ GROUPCHAT_TYPE_TEXT,
+ GROUPCHAT_TYPE_AV
+};
+
+#define MAX_LOSSY_COUNT 256
+
+typedef struct {
+ uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
+
+ uint64_t last_recv;
+ uint32_t last_message_number;
+
+ uint8_t nick[MAX_NAME_LENGTH];
+ uint8_t nick_len;
+
+ uint16_t peer_number;
+
+ uint8_t recv_lossy[MAX_LOSSY_COUNT];
+ uint16_t bottom_lossy_number, top_lossy_number;
+
+ void *object;
+} Group_Peer;
+
+#define DESIRED_CLOSE_CONNECTIONS 4
+#define MAX_GROUP_CONNECTIONS 16
+#define GROUP_IDENTIFIER_LENGTH (1 + CRYPTO_SYMMETRIC_KEY_SIZE) /* type + CRYPTO_SYMMETRIC_KEY_SIZE so we can use new_symmetric_key(...) to fill it */
+
+enum {
+ GROUPCHAT_CLOSE_NONE,
+ GROUPCHAT_CLOSE_CONNECTION,
+ GROUPCHAT_CLOSE_ONLINE
+};
+
+typedef struct {
+ uint8_t status;
+
+ Group_Peer *group;
+ uint32_t numpeers;
+
+ struct {
+ uint8_t type; /* GROUPCHAT_CLOSE_* */
+ uint8_t closest;
+ uint32_t number;
+ uint16_t group_number;
+ } close[MAX_GROUP_CONNECTIONS];
+
+ uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ struct {
+ uint8_t entry;
+ uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ } closest_peers[DESIRED_CLOSE_CONNECTIONS];
+ uint8_t changed;
+
+ uint8_t identifier[GROUP_IDENTIFIER_LENGTH];
+
+ uint8_t title[MAX_NAME_LENGTH];
+ uint8_t title_len;
+
+ uint32_t message_number;
+ uint16_t lossy_message_number;
+ uint16_t peer_number;
+
+ uint64_t last_sent_ping;
+
+ int number_joined; /* friendcon_id of person that invited us to the chat. (-1 means none) */
+
+ void *object;
+
+ void (*peer_on_join)(void *, int, int);
+ void (*peer_on_leave)(void *, int, int, void *);
+ void (*group_on_delete)(void *, int);
+} Group_c;
+
+typedef struct {
+ Messenger *m;
+ Friend_Connections *fr_c;
+
+ Group_c *chats;
+ uint32_t num_chats;
+
+ void (*invite_callback)(Messenger *m, uint32_t, int, const uint8_t *, size_t, void *);
+ void (*message_callback)(Messenger *m, uint32_t, uint32_t, int, const uint8_t *, size_t, void *);
+ void (*group_namelistchange)(Messenger *m, int, int, uint8_t, void *);
+ void (*title_callback)(Messenger *m, uint32_t, uint32_t, const uint8_t *, size_t, void *);
+
+ struct {
+ int (*function)(void *, int, int, void *, const uint8_t *, uint16_t);
+ } lossy_packethandlers[256];
+} Group_Chats;
+
+/* Set the callback for group invites.
+ *
+ * Function(Group_Chats *g_c, int32_t friendnumber, uint8_t type, uint8_t *data, uint16_t length, void *userdata)
+ *
+ * data of length is what needs to be passed to join_groupchat().
+ */
+void g_callback_group_invite(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, int, const uint8_t *,
+ size_t, void *));
+
+/* Set the callback for group messages.
+ *
+ * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata)
+ */
+void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, int, const uint8_t *,
+ size_t, void *));
+
+
+/* Set callback function for title changes.
+ *
+ * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * title, uint8_t length, void *userdata)
+ * if friendgroupnumber == -1, then author is unknown (e.g. initial joining the group)
+ */
+void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, const uint8_t *,
+ size_t, void *));
+
+/* Set callback function for peer name list changes.
+ *
+ * It gets called every time the name list changes(new peer/name, deleted peer)
+ * Function(Group_Chats *g_c, int groupnumber, int peernumber, TOX_CHAT_CHANGE change, void *userdata)
+ */
+enum {
+ CHAT_CHANGE_PEER_ADD,
+ CHAT_CHANGE_PEER_DEL,
+ CHAT_CHANGE_PEER_NAME,
+};
+void g_callback_group_namelistchange(Group_Chats *g_c, void (*function)(Messenger *m, int, int, uint8_t, void *));
+
+/* Creates a new groupchat and puts it in the chats array.
+ *
+ * type is one of GROUPCHAT_TYPE_*
+ *
+ * return group number on success.
+ * return -1 on failure.
+ */
+int add_groupchat(Group_Chats *g_c, uint8_t type);
+
+/* Delete a groupchat from the chats array.
+ *
+ * return 0 on success.
+ * return -1 if groupnumber is invalid.
+ */
+int del_groupchat(Group_Chats *g_c, int groupnumber);
+
+/* Copy the public key of peernumber who is in groupnumber to pk.
+ * pk must be CRYPTO_PUBLIC_KEY_SIZE long.
+ *
+ * return 0 on success
+ * return -1 if groupnumber is invalid.
+ * return -2 if peernumber is invalid.
+ */
+int group_peer_pubkey(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *pk);
+
+/*
+ * Return the size of peernumber's name.
+ *
+ * return -1 if groupnumber is invalid.
+ * return -2 if peernumber is invalid.
+ */
+int group_peername_size(const Group_Chats *g_c, int groupnumber, int peernumber);
+
+/* Copy the name of peernumber who is in groupnumber to name.
+ * name must be at least MAX_NAME_LENGTH long.
+ *
+ * return length of name if success
+ * return -1 if groupnumber is invalid.
+ * return -2 if peernumber is invalid.
+ */
+int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *name);
+
+/* invite friendnumber to groupnumber
+ *
+ * return 0 on success.
+ * return -1 if groupnumber is invalid.
+ * return -2 if invite packet failed to send.
+ */
+int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber);
+
+/* Join a group (you need to have been invited first.)
+ *
+ * expected_type is the groupchat type we expect the chat we are joining is.
+ *
+ * return group number on success.
+ * return -1 if data length is invalid.
+ * return -2 if group is not the expected type.
+ * return -3 if friendnumber is invalid.
+ * return -4 if client is already in this group.
+ * return -5 if group instance failed to initialize.
+ * return -6 if join packet fails to send.
+ */
+int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type, const uint8_t *data, uint16_t length);
+
+/* send a group message
+ * return 0 on success
+ * see: send_message_group() for error codes.
+ */
+int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint16_t length);
+
+/* send a group action
+ * return 0 on success
+ * see: send_message_group() for error codes.
+ */
+int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint16_t length);
+
+/* set the group's title, limited to MAX_NAME_LENGTH
+ * return 0 on success
+ * return -1 if groupnumber is invalid.
+ * return -2 if title is too long or empty.
+ * return -3 if packet fails to send.
+ */
+int group_title_send(const Group_Chats *g_c, int groupnumber, const uint8_t *title, uint8_t title_len);
+
+
+/* return the group's title size.
+ * return -1 of groupnumber is invalid.
+ * return -2 if title is too long or empty.
+ */
+int group_title_get_size(const Group_Chats *g_c, int groupnumber);
+
+/* Get group title from groupnumber and put it in title.
+ * Title needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
+ *
+ * return length of copied title if success.
+ * return -1 if groupnumber is invalid.
+ * return -2 if title is too long or empty.
+ */
+int group_title_get(const Group_Chats *g_c, int groupnumber, uint8_t *title);
+
+/* Return the number of peers in the group chat on success.
+ * return -1 if groupnumber is invalid.
+ */
+int group_number_peers(const Group_Chats *g_c, int groupnumber);
+
+/* return 1 if the peernumber corresponds to ours.
+ * return 0 if the peernumber is not ours.
+ * return -1 if groupnumber is invalid.
+ * return -2 if peernumber is invalid.
+ * return -3 if we are not connected to the group chat.
+ */
+int group_peernumber_is_ours(const Group_Chats *g_c, int groupnumber, int peernumber);
+
+/* List all the peers in the group chat.
+ *
+ * Copies the names of the peers to the name[length][MAX_NAME_LENGTH] array.
+ *
+ * Copies the lengths of the names to lengths[length]
+ *
+ * returns the number of peers on success.
+ *
+ * return -1 on failure.
+ */
+int group_names(const Group_Chats *g_c, int groupnumber, uint8_t names[][MAX_NAME_LENGTH], uint16_t lengths[],
+ uint16_t length);
+
+/* Set handlers for custom lossy packets.
+ *
+ * NOTE: Handler must return 0 if packet is to be relayed, -1 if the packet should not be relayed.
+ *
+ * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber, void *group peer object (set with group_peer_set_object), const uint8_t *packet, uint16_t length)
+ */
+void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, int (*function)(void *, int, int, void *,
+ const uint8_t *, uint16_t));
+
+/* High level function to send custom lossy packets.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int send_group_lossy_packet(const Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length);
+
+/* Return the number of chats in the instance m.
+ * You should use this to determine how much memory to allocate
+ * for copy_chatlist.
+ */
+uint32_t count_chatlist(Group_Chats *g_c);
+
+/* Copy a list of valid chat IDs into the array out_list.
+ * If out_list is NULL, returns 0.
+ * Otherwise, returns the number of elements copied.
+ * If the array was too small, the contents
+ * of out_list will be truncated to list_size. */
+uint32_t copy_chatlist(Group_Chats *g_c, uint32_t *out_list, uint32_t list_size);
+
+/* return the type of groupchat (GROUPCHAT_TYPE_) that groupnumber is.
+ *
+ * return -1 on failure.
+ * return type on success.
+ */
+int group_get_type(const Group_Chats *g_c, int groupnumber);
+
+/* Send current name (set in messenger) to all online groups.
+ */
+void send_name_all_groups(Group_Chats *g_c);
+
+/* Set the object that is tied to the group chat.
+ *
+ * return 0 on success.
+ * return -1 on failure
+ */
+int group_set_object(const Group_Chats *g_c, int groupnumber, void *object);
+
+/* Set the object that is tied to the group peer.
+ *
+ * return 0 on success.
+ * return -1 on failure
+ */
+int group_peer_set_object(const Group_Chats *g_c, int groupnumber, int peernumber, void *object);
+
+/* Return the object tide to the group chat previously set by group_set_object.
+ *
+ * return NULL on failure.
+ * return object on success.
+ */
+void *group_get_object(const Group_Chats *g_c, int groupnumber);
+
+/* Return the object tide to the group chat peer previously set by group_peer_set_object.
+ *
+ * return NULL on failure.
+ * return object on success.
+ */
+void *group_peer_get_object(const Group_Chats *g_c, int groupnumber, int peernumber);
+
+/* Set a function to be called when a new peer joins a group chat.
+ *
+ * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber)
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int callback_groupchat_peer_new(const Group_Chats *g_c, int groupnumber, void (*function)(void *, int, int));
+
+/* Set a function to be called when a peer leaves a group chat.
+ *
+ * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber, void *group peer object (set with group_peer_set_object))
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int callback_groupchat_peer_delete(Group_Chats *g_c, int groupnumber, void (*function)(void *, int, int, void *));
+
+/* Set a function to be called when the group chat is deleted.
+ *
+ * Function(void *group object (set with group_set_object), int groupnumber)
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int callback_groupchat_delete(Group_Chats *g_c, int groupnumber, void (*function)(void *, int));
+
+/* Create new groupchat instance. */
+Group_Chats *new_groupchats(Messenger *m);
+
+/* main groupchats loop. */
+void do_groupchats(Group_Chats *g_c, void *userdata);
+
+/* Free everything related with group chats. */
+void kill_groupchats(Group_Chats *g_c);
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxcore/list.c b/protocols/Tox/libtox/src/toxcore/list.c
new file mode 100644
index 0000000000..36d609fbd1
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/list.c
@@ -0,0 +1,266 @@
+/*
+ * Simple struct with functions to create a list which associates ids with data
+ * -Allows for finding ids associated with data such as IPs or public keys in a short time
+ * -Should only be used if there are relatively few add/remove calls to the list
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2014 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "list.h"
+
+/* Basically, the elements in the list are placed in order so that they can be searched for easily
+ * -each element is seen as a big-endian integer when ordering them
+ * -the ids array is maintained so that each id always matches
+ * -the search algorithm cuts down the time to find the id associated with a piece of data
+ * at the cost of slow add/remove functions for large lists
+ * -Starts at 1/2 of the array, compares the element in the array with the data,
+ * then moves +/- 1/4 of the array depending on whether the value is greater or lower,
+ * then +- 1/8, etc, until the value is matched or its position where it should be in the array is found
+ * -some considerations since the array size is never perfect
+ */
+
+#define INDEX(i) (~i)
+
+/* Find data in list
+ *
+ * return value:
+ * >= 0 : index of data in array
+ * < 0 : no match, returns index (return value is INDEX(index)) where
+ * the data should be inserted
+ */
+static int find(const BS_LIST *list, const uint8_t *data)
+{
+ //should work well, but could be improved
+ if (list->n == 0) {
+ return INDEX(0);
+ }
+
+ uint32_t i = list->n / 2; //current position in the array
+ uint32_t delta = i / 2; //how much we move in the array
+
+ if (!delta) {
+ delta = 1;
+ }
+
+ int d = -1; //used to determine if closest match is found
+ //closest match is found if we move back to where we have already been
+
+ while (1) {
+ int r = memcmp(data, list->data + list->element_size * i, list->element_size);
+
+ if (r == 0) {
+ return i;
+ }
+
+ if (r > 0) {
+ //data is greater
+ //move down
+ i += delta;
+
+ if (d == 0 || i == list->n) {
+ //reached bottom of list, or closest match
+ return INDEX(i);
+ }
+
+ delta = (delta) / 2;
+
+ if (delta == 0) {
+ delta = 1;
+ d = 1;
+ }
+ } else {
+ //data is smaller
+ if (d == 1 || i == 0) {
+ //reached top or list or closest match
+ return INDEX(i);
+ }
+
+ //move up
+ i -= delta;
+
+ delta = (delta) / 2;
+
+ if (delta == 0) {
+ delta = 1;
+ d = 0;
+ }
+ }
+ }
+}
+
+/* Resized the list list
+ *
+ * return value:
+ * 1 : success
+ * 0 : failure
+ */
+static int resize(BS_LIST *list, uint32_t new_size)
+{
+ if (new_size == 0) {
+ bs_list_free(list);
+ return 1;
+ }
+
+ uint8_t *data = (uint8_t *)realloc(list->data, list->element_size * new_size);
+
+ if (!data) {
+ return 0;
+ }
+
+ list->data = data;
+
+ int *ids = (int *)realloc(list->ids, sizeof(int) * new_size);
+
+ if (!ids) {
+ return 0;
+ }
+
+ list->ids = ids;
+
+ return 1;
+}
+
+
+int bs_list_init(BS_LIST *list, uint32_t element_size, uint32_t initial_capacity)
+{
+ //set initial values
+ list->n = 0;
+ list->element_size = element_size;
+ list->capacity = 0;
+ list->data = NULL;
+ list->ids = NULL;
+
+ if (initial_capacity != 0) {
+ if (!resize(list, initial_capacity)) {
+ return 0;
+ }
+ }
+
+ list->capacity = initial_capacity;
+
+ return 1;
+}
+
+void bs_list_free(BS_LIST *list)
+{
+ //free both arrays
+ free(list->data);
+ list->data = NULL;
+
+ free(list->ids);
+ list->ids = NULL;
+}
+
+int bs_list_find(const BS_LIST *list, const uint8_t *data)
+{
+ int r = find(list, data);
+
+ //return only -1 and positive values
+ if (r < 0) {
+ return -1;
+ }
+
+ return list->ids[r];
+}
+
+int bs_list_add(BS_LIST *list, const uint8_t *data, int id)
+{
+ //find where the new element should be inserted
+ //see: return value of find()
+ int i = find(list, data);
+
+ if (i >= 0) {
+ //already in list
+ return 0;
+ }
+
+ i = ~i;
+
+ //increase the size of the arrays if needed
+ if (list->n == list->capacity) {
+ // 1.5 * n + 1
+ const uint32_t new_capacity = list->n + list->n / 2 + 1;
+
+ if (!resize(list, new_capacity)) {
+ return 0;
+ }
+
+ list->capacity = new_capacity;
+ }
+
+ //insert data to element array
+ memmove(list->data + (i + 1) * list->element_size, list->data + i * list->element_size,
+ (list->n - i) * list->element_size);
+ memcpy(list->data + i * list->element_size, data, list->element_size);
+
+ //insert id to id array
+ memmove(&list->ids[i + 1], &list->ids[i], (list->n - i) * sizeof(int));
+ list->ids[i] = id;
+
+ //increase n
+ list->n++;
+
+ return 1;
+}
+
+int bs_list_remove(BS_LIST *list, const uint8_t *data, int id)
+{
+ int i = find(list, data);
+
+ if (i < 0) {
+ return 0;
+ }
+
+ if (list->ids[i] != id) {
+ //this should never happen
+ return 0;
+ }
+
+ //decrease the size of the arrays if needed
+ if (list->n < list->capacity / 2) {
+ const uint32_t new_capacity = list->capacity / 2;
+
+ if (resize(list, new_capacity)) {
+ list->capacity = new_capacity;
+ }
+ }
+
+ list->n--;
+
+ memmove(list->data + i * list->element_size, list->data + (i + 1) * list->element_size,
+ (list->n - i) * list->element_size);
+ memmove(&list->ids[i], &list->ids[i + 1], (list->n - i) * sizeof(int));
+
+ return 1;
+}
+
+int bs_list_trim(BS_LIST *list)
+{
+ if (!resize(list, list->n)) {
+ return 0;
+ }
+
+ list->capacity = list->n;
+ return 1;
+}
diff --git a/protocols/Tox/libtox/src/toxcore/list.h b/protocols/Tox/libtox/src/toxcore/list.h
new file mode 100644
index 0000000000..cb3b328c5a
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/list.h
@@ -0,0 +1,85 @@
+/*
+ * Simple struct with functions to create a list which associates ids with data
+ * -Allows for finding ids associated with data such as IPs or public keys in a short time
+ * -Should only be used if there are relatively few add/remove calls to the list
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2014 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef LIST_H
+#define LIST_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct {
+ uint32_t n; //number of elements
+ uint32_t capacity; //number of elements memory is allocated for
+ uint32_t element_size; //size of the elements
+ uint8_t *data; //array of elements
+ int *ids; //array of element ids
+} BS_LIST;
+
+/* Initialize a list, element_size is the size of the elements in the list and
+ * initial_capacity is the number of elements the memory will be initially allocated for
+ *
+ * return value:
+ * 1 : success
+ * 0 : failure
+ */
+int bs_list_init(BS_LIST *list, uint32_t element_size, uint32_t initial_capacity);
+
+/* Free a list initiated with list_init */
+void bs_list_free(BS_LIST *list);
+
+/* Retrieve the id of an element in the list
+ *
+ * return value:
+ * >= 0 : id associated with data
+ * -1 : failure
+ */
+int bs_list_find(const BS_LIST *list, const uint8_t *data);
+
+/* Add an element with associated id to the list
+ *
+ * return value:
+ * 1 : success
+ * 0 : failure (data already in list)
+ */
+int bs_list_add(BS_LIST *list, const uint8_t *data, int id);
+
+/* Remove element from the list
+ *
+ * return value:
+ * 1 : success
+ * 0 : failure (element not found or id does not match)
+ */
+int bs_list_remove(BS_LIST *list, const uint8_t *data, int id);
+
+/* Removes the memory overhead
+ *
+ * return value:
+ * 1 : success
+ * 0 : failure
+ */
+int bs_list_trim(BS_LIST *list);
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxcore/logger.c b/protocols/Tox/libtox/src/toxcore/logger.c
new file mode 100644
index 0000000000..18b765a385
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/logger.c
@@ -0,0 +1,77 @@
+/*
+ * Text logging abstraction.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013,2015 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "logger.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+struct Logger {
+ logger_cb *callback;
+ void *context;
+ void *userdata;
+};
+
+
+/**
+ * Public Functions
+ */
+Logger *logger_new(void)
+{
+ return (Logger *)calloc(1, sizeof(Logger));
+}
+
+void logger_kill(Logger *log)
+{
+ free(log);
+}
+
+void logger_callback_log(Logger *log, logger_cb *function, void *context, void *userdata)
+{
+ log->callback = function;
+ log->context = context;
+ log->userdata = userdata;
+}
+
+void logger_write(Logger *log, LOGGER_LEVEL level, const char *file, int line, const char *func, const char *format,
+ ...)
+{
+ if (!log || !log->callback) {
+ return;
+ }
+
+ /* Format message */
+ char msg[1024];
+ va_list args;
+ va_start(args, format);
+ vsnprintf(msg, sizeof msg, format, args);
+ va_end(args);
+
+ log->callback(log->context, level, file, line, func, msg, log->userdata);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/logger.h b/protocols/Tox/libtox/src/toxcore/logger.h
new file mode 100644
index 0000000000..8c8a639bec
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/logger.h
@@ -0,0 +1,80 @@
+/*
+ * Logger abstraction backed by callbacks for writing.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TOXLOGGER_H
+#define TOXLOGGER_H
+
+#include <stdint.h>
+
+#ifndef MIN_LOGGER_LEVEL
+#define MIN_LOGGER_LEVEL LOG_INFO
+#endif
+
+typedef enum {
+ LOG_TRACE,
+ LOG_DEBUG,
+ LOG_INFO,
+ LOG_WARNING,
+ LOG_ERROR
+} LOGGER_LEVEL;
+
+typedef struct Logger Logger;
+
+typedef void logger_cb(void *context, LOGGER_LEVEL level, const char *file, int line,
+ const char *func, const char *message, void *userdata);
+
+/**
+ * Creates a new logger with logging disabled (callback is NULL) by default.
+ */
+Logger *logger_new(void);
+
+void logger_kill(Logger *log);
+
+/**
+ * Sets the logger callback. Disables logging if set to NULL.
+ * The context parameter is passed to the callback as first argument.
+ */
+void logger_callback_log(Logger *log, logger_cb *function, void *context, void *userdata);
+
+/**
+ * Main write function. If logging disabled does nothing.
+ */
+void logger_write(Logger *log, LOGGER_LEVEL level, const char *file, int line, const char *func, const char *format,
+ ...);
+
+
+#define LOGGER_WRITE(log, level, ...) \
+ do { \
+ if (level >= MIN_LOGGER_LEVEL) { \
+ logger_write(log, level, __FILE__, __LINE__, __func__, __VA_ARGS__); \
+ } \
+ } while (0)
+
+/* To log with an logger */
+#define LOGGER_TRACE(log, ...) LOGGER_WRITE(log, LOG_TRACE , __VA_ARGS__)
+#define LOGGER_DEBUG(log, ...) LOGGER_WRITE(log, LOG_DEBUG , __VA_ARGS__)
+#define LOGGER_INFO(log, ...) LOGGER_WRITE(log, LOG_INFO , __VA_ARGS__)
+#define LOGGER_WARNING(log, ...) LOGGER_WRITE(log, LOG_WARNING, __VA_ARGS__)
+#define LOGGER_ERROR(log, ...) LOGGER_WRITE(log, LOG_ERROR , __VA_ARGS__)
+
+#endif /* TOXLOGGER_H */
diff --git a/protocols/Tox/libtox/src/toxcore/net_crypto.c b/protocols/Tox/libtox/src/toxcore/net_crypto.c
new file mode 100644
index 0000000000..440db94abd
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/net_crypto.c
@@ -0,0 +1,2908 @@
+/*
+ * Functions for the core network crypto.
+ *
+ * NOTE: This code has to be perfect. We don't mess around with encryption.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "net_crypto.h"
+
+#include "util.h"
+
+#include <math.h>
+
+
+static uint8_t crypt_connection_id_not_valid(const Net_Crypto *c, int crypt_connection_id)
+{
+ if ((uint32_t)crypt_connection_id >= c->crypto_connections_length) {
+ return 1;
+ }
+
+ if (c->crypto_connections == NULL) {
+ return 1;
+ }
+
+ if (c->crypto_connections[crypt_connection_id].status == CRYPTO_CONN_NO_CONNECTION) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/* cookie timeout in seconds */
+#define COOKIE_TIMEOUT 15
+#define COOKIE_DATA_LENGTH (CRYPTO_PUBLIC_KEY_SIZE * 2)
+#define COOKIE_CONTENTS_LENGTH (sizeof(uint64_t) + COOKIE_DATA_LENGTH)
+#define COOKIE_LENGTH (CRYPTO_NONCE_SIZE + COOKIE_CONTENTS_LENGTH + CRYPTO_MAC_SIZE)
+
+#define COOKIE_REQUEST_PLAIN_LENGTH (COOKIE_DATA_LENGTH + sizeof(uint64_t))
+#define COOKIE_REQUEST_LENGTH (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE)
+#define COOKIE_RESPONSE_LENGTH (1 + CRYPTO_NONCE_SIZE + COOKIE_LENGTH + sizeof(uint64_t) + CRYPTO_MAC_SIZE)
+
+/* Create a cookie request packet and put it in packet.
+ * dht_public_key is the dht public key of the other
+ *
+ * packet must be of size COOKIE_REQUEST_LENGTH or bigger.
+ *
+ * return -1 on failure.
+ * return COOKIE_REQUEST_LENGTH on success.
+ */
+static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, uint8_t *dht_public_key, uint64_t number,
+ uint8_t *shared_key)
+{
+ uint8_t plain[COOKIE_REQUEST_PLAIN_LENGTH];
+ uint8_t padding[CRYPTO_PUBLIC_KEY_SIZE] = {0};
+
+ memcpy(plain, c->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, padding, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(plain + (CRYPTO_PUBLIC_KEY_SIZE * 2), &number, sizeof(uint64_t));
+
+ DHT_get_shared_key_sent(c->dht, shared_key, dht_public_key);
+ uint8_t nonce[CRYPTO_NONCE_SIZE];
+ random_nonce(nonce);
+ packet[0] = NET_PACKET_COOKIE_REQUEST;
+ memcpy(packet + 1, c->dht->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
+ int len = encrypt_data_symmetric(shared_key, nonce, plain, sizeof(plain),
+ packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
+
+ if (len != COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE) {
+ return -1;
+ }
+
+ return (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + len);
+}
+
+/* Create cookie of length COOKIE_LENGTH from bytes of length COOKIE_DATA_LENGTH using encryption_key
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int create_cookie(uint8_t *cookie, const uint8_t *bytes, const uint8_t *encryption_key)
+{
+ uint8_t contents[COOKIE_CONTENTS_LENGTH];
+ uint64_t temp_time = unix_time();
+ memcpy(contents, &temp_time, sizeof(temp_time));
+ memcpy(contents + sizeof(temp_time), bytes, COOKIE_DATA_LENGTH);
+ random_nonce(cookie);
+ int len = encrypt_data_symmetric(encryption_key, cookie, contents, sizeof(contents), cookie + CRYPTO_NONCE_SIZE);
+
+ if (len != COOKIE_LENGTH - CRYPTO_NONCE_SIZE) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Open cookie of length COOKIE_LENGTH to bytes of length COOKIE_DATA_LENGTH using encryption_key
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int open_cookie(uint8_t *bytes, const uint8_t *cookie, const uint8_t *encryption_key)
+{
+ uint8_t contents[COOKIE_CONTENTS_LENGTH];
+ int len = decrypt_data_symmetric(encryption_key, cookie, cookie + CRYPTO_NONCE_SIZE,
+ COOKIE_LENGTH - CRYPTO_NONCE_SIZE, contents);
+
+ if (len != sizeof(contents)) {
+ return -1;
+ }
+
+ uint64_t cookie_time;
+ memcpy(&cookie_time, contents, sizeof(cookie_time));
+ uint64_t temp_time = unix_time();
+
+ if (cookie_time + COOKIE_TIMEOUT < temp_time || temp_time < cookie_time) {
+ return -1;
+ }
+
+ memcpy(bytes, contents + sizeof(cookie_time), COOKIE_DATA_LENGTH);
+ return 0;
+}
+
+
+/* Create a cookie response packet and put it in packet.
+ * request_plain must be COOKIE_REQUEST_PLAIN_LENGTH bytes.
+ * packet must be of size COOKIE_RESPONSE_LENGTH or bigger.
+ *
+ * return -1 on failure.
+ * return COOKIE_RESPONSE_LENGTH on success.
+ */
+static int create_cookie_response(const Net_Crypto *c, uint8_t *packet, const uint8_t *request_plain,
+ const uint8_t *shared_key, const uint8_t *dht_public_key)
+{
+ uint8_t cookie_plain[COOKIE_DATA_LENGTH];
+ memcpy(cookie_plain, request_plain, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)];
+
+ if (create_cookie(plain, cookie_plain, c->secret_symmetric_key) != 0) {
+ return -1;
+ }
+
+ memcpy(plain + COOKIE_LENGTH, request_plain + COOKIE_DATA_LENGTH, sizeof(uint64_t));
+ packet[0] = NET_PACKET_COOKIE_RESPONSE;
+ random_nonce(packet + 1);
+ int len = encrypt_data_symmetric(shared_key, packet + 1, plain, sizeof(plain), packet + 1 + CRYPTO_NONCE_SIZE);
+
+ if (len != COOKIE_RESPONSE_LENGTH - (1 + CRYPTO_NONCE_SIZE)) {
+ return -1;
+ }
+
+ return COOKIE_RESPONSE_LENGTH;
+}
+
+/* Handle the cookie request packet of length length.
+ * Put what was in the request in request_plain (must be of size COOKIE_REQUEST_PLAIN_LENGTH)
+ * Put the key used to decrypt the request into shared_key (of size CRYPTO_SHARED_KEY_SIZE) for use in the response.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int handle_cookie_request(const Net_Crypto *c, uint8_t *request_plain, uint8_t *shared_key,
+ uint8_t *dht_public_key, const uint8_t *packet, uint16_t length)
+{
+ if (length != COOKIE_REQUEST_LENGTH) {
+ return -1;
+ }
+
+ memcpy(dht_public_key, packet + 1, CRYPTO_PUBLIC_KEY_SIZE);
+ DHT_get_shared_key_sent(c->dht, shared_key, dht_public_key);
+ int len = decrypt_data_symmetric(shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
+ packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE,
+ request_plain);
+
+ if (len != COOKIE_REQUEST_PLAIN_LENGTH) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Handle the cookie request packet (for raw UDP)
+ */
+static int udp_handle_cookie_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length,
+ void *userdata)
+{
+ Net_Crypto *c = (Net_Crypto *)object;
+ uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH];
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
+ uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
+
+ if (handle_cookie_request(c, request_plain, shared_key, dht_public_key, packet, length) != 0) {
+ return 1;
+ }
+
+ uint8_t data[COOKIE_RESPONSE_LENGTH];
+
+ if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) {
+ return 1;
+ }
+
+ if ((uint32_t)sendpacket(c->dht->net, source, data, sizeof(data)) != sizeof(data)) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Handle the cookie request packet (for TCP)
+ */
+static int tcp_handle_cookie_request(Net_Crypto *c, int connections_number, const uint8_t *packet, uint16_t length)
+{
+ uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH];
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
+ uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
+
+ if (handle_cookie_request(c, request_plain, shared_key, dht_public_key, packet, length) != 0) {
+ return -1;
+ }
+
+ uint8_t data[COOKIE_RESPONSE_LENGTH];
+
+ if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) {
+ return -1;
+ }
+
+ int ret = send_packet_tcp_connection(c->tcp_c, connections_number, data, sizeof(data));
+ return ret;
+}
+
+/* Handle the cookie request packet (for TCP oob packets)
+ */
+static int tcp_oob_handle_cookie_request(const Net_Crypto *c, unsigned int tcp_connections_number,
+ const uint8_t *dht_public_key, const uint8_t *packet, uint16_t length)
+{
+ uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH];
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
+ uint8_t dht_public_key_temp[CRYPTO_PUBLIC_KEY_SIZE];
+
+ if (handle_cookie_request(c, request_plain, shared_key, dht_public_key_temp, packet, length) != 0) {
+ return -1;
+ }
+
+ if (public_key_cmp(dht_public_key, dht_public_key_temp) != 0) {
+ return -1;
+ }
+
+ uint8_t data[COOKIE_RESPONSE_LENGTH];
+
+ if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) {
+ return -1;
+ }
+
+ int ret = tcp_send_oob_packet(c->tcp_c, tcp_connections_number, dht_public_key, data, sizeof(data));
+ return ret;
+}
+
+/* Handle a cookie response packet of length encrypted with shared_key.
+ * put the cookie in the response in cookie
+ *
+ * cookie must be of length COOKIE_LENGTH.
+ *
+ * return -1 on failure.
+ * return COOKIE_LENGTH on success.
+ */
+static int handle_cookie_response(uint8_t *cookie, uint64_t *number, const uint8_t *packet, uint16_t length,
+ const uint8_t *shared_key)
+{
+ if (length != COOKIE_RESPONSE_LENGTH) {
+ return -1;
+ }
+
+ uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)];
+ int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
+ length - (1 + CRYPTO_NONCE_SIZE), plain);
+
+ if (len != sizeof(plain)) {
+ return -1;
+ }
+
+ memcpy(cookie, plain, COOKIE_LENGTH);
+ memcpy(number, plain + COOKIE_LENGTH, sizeof(uint64_t));
+ return COOKIE_LENGTH;
+}
+
+#define HANDSHAKE_PACKET_LENGTH (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE)
+
+/* Create a handshake packet and put it in packet.
+ * cookie must be COOKIE_LENGTH bytes.
+ * packet must be of size HANDSHAKE_PACKET_LENGTH or bigger.
+ *
+ * return -1 on failure.
+ * return HANDSHAKE_PACKET_LENGTH on success.
+ */
+static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const uint8_t *cookie, const uint8_t *nonce,
+ const uint8_t *session_pk, const uint8_t *peer_real_pk, const uint8_t *peer_dht_pubkey)
+{
+ uint8_t plain[CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH];
+ memcpy(plain, nonce, CRYPTO_NONCE_SIZE);
+ memcpy(plain + CRYPTO_NONCE_SIZE, session_pk, CRYPTO_PUBLIC_KEY_SIZE);
+ crypto_sha512(plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, cookie, COOKIE_LENGTH);
+ uint8_t cookie_plain[COOKIE_DATA_LENGTH];
+ memcpy(cookie_plain, peer_real_pk, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, peer_dht_pubkey, CRYPTO_PUBLIC_KEY_SIZE);
+
+ if (create_cookie(plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, cookie_plain,
+ c->secret_symmetric_key) != 0) {
+ return -1;
+ }
+
+ random_nonce(packet + 1 + COOKIE_LENGTH);
+ int len = encrypt_data(peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, plain, sizeof(plain),
+ packet + 1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE);
+
+ if (len != HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE)) {
+ return -1;
+ }
+
+ packet[0] = NET_PACKET_CRYPTO_HS;
+ memcpy(packet + 1, cookie, COOKIE_LENGTH);
+
+ return HANDSHAKE_PACKET_LENGTH;
+}
+
+/* Handle a crypto handshake packet of length.
+ * put the nonce contained in the packet in nonce,
+ * the session public key in session_pk
+ * the real public key of the peer in peer_real_pk
+ * the dht public key of the peer in dht_public_key and
+ * the cookie inside the encrypted part of the packet in cookie.
+ *
+ * if expected_real_pk isn't NULL it denotes the real public key
+ * the packet should be from.
+ *
+ * nonce must be at least CRYPTO_NONCE_SIZE
+ * session_pk must be at least CRYPTO_PUBLIC_KEY_SIZE
+ * peer_real_pk must be at least CRYPTO_PUBLIC_KEY_SIZE
+ * cookie must be at least COOKIE_LENGTH
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t *session_pk, uint8_t *peer_real_pk,
+ uint8_t *dht_public_key, uint8_t *cookie, const uint8_t *packet, uint16_t length, const uint8_t *expected_real_pk)
+{
+ if (length != HANDSHAKE_PACKET_LENGTH) {
+ return -1;
+ }
+
+ uint8_t cookie_plain[COOKIE_DATA_LENGTH];
+
+ if (open_cookie(cookie_plain, packet + 1, c->secret_symmetric_key) != 0) {
+ return -1;
+ }
+
+ if (expected_real_pk) {
+ if (public_key_cmp(cookie_plain, expected_real_pk) != 0) {
+ return -1;
+ }
+ }
+
+ uint8_t cookie_hash[CRYPTO_SHA512_SIZE];
+ crypto_sha512(cookie_hash, packet + 1, COOKIE_LENGTH);
+
+ uint8_t plain[CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH];
+ int len = decrypt_data(cookie_plain, c->self_secret_key, packet + 1 + COOKIE_LENGTH,
+ packet + 1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE,
+ HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE), plain);
+
+ if (len != sizeof(plain)) {
+ return -1;
+ }
+
+ if (crypto_memcmp(cookie_hash, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
+ CRYPTO_SHA512_SIZE) != 0) {
+ return -1;
+ }
+
+ memcpy(nonce, plain, CRYPTO_NONCE_SIZE);
+ memcpy(session_pk, plain + CRYPTO_NONCE_SIZE, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(cookie, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, COOKIE_LENGTH);
+ memcpy(peer_real_pk, cookie_plain, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(dht_public_key, cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE);
+ return 0;
+}
+
+
+static Crypto_Connection *get_crypto_connection(const Net_Crypto *c, int crypt_connection_id)
+{
+ if (crypt_connection_id_not_valid(c, crypt_connection_id)) {
+ return 0;
+ }
+
+ return &c->crypto_connections[crypt_connection_id];
+}
+
+
+/* Associate an ip_port to a connection.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int add_ip_port_connection(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ if (ip_port.ip.family == TOX_AF_INET) {
+ if (!ipport_equal(&ip_port, &conn->ip_portv4) && LAN_ip(conn->ip_portv4.ip) != 0) {
+ if (!bs_list_add(&c->ip_port_list, (uint8_t *)&ip_port, crypt_connection_id)) {
+ return -1;
+ }
+
+ bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv4, crypt_connection_id);
+ conn->ip_portv4 = ip_port;
+ return 0;
+ }
+ } else if (ip_port.ip.family == TOX_AF_INET6) {
+ if (!ipport_equal(&ip_port, &conn->ip_portv6)) {
+ if (!bs_list_add(&c->ip_port_list, (uint8_t *)&ip_port, crypt_connection_id)) {
+ return -1;
+ }
+
+ bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv6, crypt_connection_id);
+ conn->ip_portv6 = ip_port;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/* Return the IP_Port that should be used to send packets to the other peer.
+ *
+ * return IP_Port with family 0 on failure.
+ * return IP_Port on success.
+ */
+static IP_Port return_ip_port_connection(Net_Crypto *c, int crypt_connection_id)
+{
+ const IP_Port empty = {{0}};
+
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return empty;
+ }
+
+ uint64_t current_time = unix_time();
+ bool v6 = 0, v4 = 0;
+
+ if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) {
+ v4 = 1;
+ }
+
+ if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev6) > current_time) {
+ v6 = 1;
+ }
+
+ if (v4 && LAN_ip(conn->ip_portv4.ip) == 0) {
+ return conn->ip_portv4;
+ }
+
+ if (v6 && conn->ip_portv6.ip.family == TOX_AF_INET6) {
+ return conn->ip_portv6;
+ }
+
+ if (conn->ip_portv4.ip.family == TOX_AF_INET) {
+ return conn->ip_portv4;
+ }
+
+ return empty;
+}
+
+/* Sends a packet to the peer using the fastest route.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length)
+{
+// TODO(irungentoo): TCP, etc...
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ int direct_send_attempt = 0;
+
+ pthread_mutex_lock(&conn->mutex);
+ IP_Port ip_port = return_ip_port_connection(c, crypt_connection_id);
+
+ // TODO(irungentoo): on bad networks, direct connections might not last indefinitely.
+ if (ip_port.ip.family != 0) {
+ bool direct_connected = 0;
+ crypto_connection_status(c, crypt_connection_id, &direct_connected, NULL);
+
+ if (direct_connected) {
+ if ((uint32_t)sendpacket(c->dht->net, ip_port, data, length) == length) {
+ pthread_mutex_unlock(&conn->mutex);
+ return 0;
+ }
+
+ pthread_mutex_unlock(&conn->mutex);
+ return -1;
+ }
+
+ // TODO(irungentoo): a better way of sending packets directly to confirm the others ip.
+ uint64_t current_time = unix_time();
+
+ if ((((UDP_DIRECT_TIMEOUT / 2) + conn->direct_send_attempt_time) > current_time && length < 96)
+ || data[0] == NET_PACKET_COOKIE_REQUEST || data[0] == NET_PACKET_CRYPTO_HS) {
+ if ((uint32_t)sendpacket(c->dht->net, ip_port, data, length) == length) {
+ direct_send_attempt = 1;
+ conn->direct_send_attempt_time = unix_time();
+ }
+ }
+ }
+
+ pthread_mutex_unlock(&conn->mutex);
+ pthread_mutex_lock(&c->tcp_mutex);
+ int ret = send_packet_tcp_connection(c->tcp_c, conn->connection_number_tcp, data, length);
+ pthread_mutex_unlock(&c->tcp_mutex);
+
+ pthread_mutex_lock(&conn->mutex);
+
+ if (ret == 0) {
+ conn->last_tcp_sent = current_time_monotonic();
+ }
+
+ pthread_mutex_unlock(&conn->mutex);
+
+ if (ret == 0 || direct_send_attempt) {
+ return 0;
+ }
+
+ return -1;
+}
+
+/** START: Array Related functions **/
+
+
+/* Return number of packets in array
+ * Note that holes are counted too.
+ */
+static uint32_t num_packets_array(const Packets_Array *array)
+{
+ return array->buffer_end - array->buffer_start;
+}
+
+/* Add data with packet number to array.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int add_data_to_buffer(Packets_Array *array, uint32_t number, const Packet_Data *data)
+{
+ if (number - array->buffer_start > CRYPTO_PACKET_BUFFER_SIZE) {
+ return -1;
+ }
+
+ uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE;
+
+ if (array->buffer[num]) {
+ return -1;
+ }
+
+ Packet_Data *new_d = (Packet_Data *)malloc(sizeof(Packet_Data));
+
+ if (new_d == NULL) {
+ return -1;
+ }
+
+ memcpy(new_d, data, sizeof(Packet_Data));
+ array->buffer[num] = new_d;
+
+ if ((number - array->buffer_start) >= (array->buffer_end - array->buffer_start)) {
+ array->buffer_end = number + 1;
+ }
+
+ return 0;
+}
+
+/* Get pointer of data with packet number.
+ *
+ * return -1 on failure.
+ * return 0 if data at number is empty.
+ * return 1 if data pointer was put in data.
+ */
+static int get_data_pointer(const Packets_Array *array, Packet_Data **data, uint32_t number)
+{
+ uint32_t num_spots = array->buffer_end - array->buffer_start;
+
+ if (array->buffer_end - number > num_spots || number - array->buffer_start >= num_spots) {
+ return -1;
+ }
+
+ uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE;
+
+ if (!array->buffer[num]) {
+ return 0;
+ }
+
+ *data = array->buffer[num];
+ return 1;
+}
+
+/* Add data to end of array.
+ *
+ * return -1 on failure.
+ * return packet number on success.
+ */
+static int64_t add_data_end_of_buffer(Packets_Array *array, const Packet_Data *data)
+{
+ if (num_packets_array(array) >= CRYPTO_PACKET_BUFFER_SIZE) {
+ return -1;
+ }
+
+ Packet_Data *new_d = (Packet_Data *)malloc(sizeof(Packet_Data));
+
+ if (new_d == NULL) {
+ return -1;
+ }
+
+ memcpy(new_d, data, sizeof(Packet_Data));
+ uint32_t id = array->buffer_end;
+ array->buffer[id % CRYPTO_PACKET_BUFFER_SIZE] = new_d;
+ ++array->buffer_end;
+ return id;
+}
+
+/* Read data from begginning of array.
+ *
+ * return -1 on failure.
+ * return packet number on success.
+ */
+static int64_t read_data_beg_buffer(Packets_Array *array, Packet_Data *data)
+{
+ if (array->buffer_end == array->buffer_start) {
+ return -1;
+ }
+
+ uint32_t num = array->buffer_start % CRYPTO_PACKET_BUFFER_SIZE;
+
+ if (!array->buffer[num]) {
+ return -1;
+ }
+
+ memcpy(data, array->buffer[num], sizeof(Packet_Data));
+ uint32_t id = array->buffer_start;
+ ++array->buffer_start;
+ free(array->buffer[num]);
+ array->buffer[num] = NULL;
+ return id;
+}
+
+/* Delete all packets in array before number (but not number)
+ *
+ * return -1 on failure.
+ * return 0 on success
+ */
+static int clear_buffer_until(Packets_Array *array, uint32_t number)
+{
+ uint32_t num_spots = array->buffer_end - array->buffer_start;
+
+ if (array->buffer_end - number >= num_spots || number - array->buffer_start > num_spots) {
+ return -1;
+ }
+
+ uint32_t i;
+
+ for (i = array->buffer_start; i != number; ++i) {
+ uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE;
+
+ if (array->buffer[num]) {
+ free(array->buffer[num]);
+ array->buffer[num] = NULL;
+ }
+ }
+
+ array->buffer_start = i;
+ return 0;
+}
+
+static int clear_buffer(Packets_Array *array)
+{
+ uint32_t i;
+
+ for (i = array->buffer_start; i != array->buffer_end; ++i) {
+ uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE;
+
+ if (array->buffer[num]) {
+ free(array->buffer[num]);
+ array->buffer[num] = NULL;
+ }
+ }
+
+ array->buffer_start = i;
+ return 0;
+}
+
+/* Set array buffer end to number.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int set_buffer_end(Packets_Array *array, uint32_t number)
+{
+ if ((number - array->buffer_start) > CRYPTO_PACKET_BUFFER_SIZE) {
+ return -1;
+ }
+
+ if ((number - array->buffer_end) > CRYPTO_PACKET_BUFFER_SIZE) {
+ return -1;
+ }
+
+ array->buffer_end = number;
+ return 0;
+}
+
+/* Create a packet request packet from recv_array and send_buffer_end into
+ * data of length.
+ *
+ * return -1 on failure.
+ * return length of packet on success.
+ */
+static int generate_request_packet(uint8_t *data, uint16_t length, const Packets_Array *recv_array)
+{
+ if (length == 0) {
+ return -1;
+ }
+
+ data[0] = PACKET_ID_REQUEST;
+
+ uint16_t cur_len = 1;
+
+ if (recv_array->buffer_start == recv_array->buffer_end) {
+ return cur_len;
+ }
+
+ if (length <= cur_len) {
+ return cur_len;
+ }
+
+ uint32_t i, n = 1;
+
+ for (i = recv_array->buffer_start; i != recv_array->buffer_end; ++i) {
+ uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE;
+
+ if (!recv_array->buffer[num]) {
+ data[cur_len] = n;
+ n = 0;
+ ++cur_len;
+
+ if (length <= cur_len) {
+ return cur_len;
+ }
+ } else if (n == 255) {
+ data[cur_len] = 0;
+ n = 0;
+ ++cur_len;
+
+ if (length <= cur_len) {
+ return cur_len;
+ }
+ }
+
+ ++n;
+ }
+
+ return cur_len;
+}
+
+/* Handle a request data packet.
+ * Remove all the packets the other received from the array.
+ *
+ * return -1 on failure.
+ * return number of requested packets on success.
+ */
+static int handle_request_packet(Packets_Array *send_array, const uint8_t *data, uint16_t length,
+ uint64_t *latest_send_time, uint64_t rtt_time)
+{
+ if (length < 1) {
+ return -1;
+ }
+
+ if (data[0] != PACKET_ID_REQUEST) {
+ return -1;
+ }
+
+ if (length == 1) {
+ return 0;
+ }
+
+ ++data;
+ --length;
+
+ uint32_t i, n = 1;
+ uint32_t requested = 0;
+
+ uint64_t temp_time = current_time_monotonic();
+ uint64_t l_sent_time = ~0;
+
+ for (i = send_array->buffer_start; i != send_array->buffer_end; ++i) {
+ if (length == 0) {
+ break;
+ }
+
+ uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE;
+
+ if (n == data[0]) {
+ if (send_array->buffer[num]) {
+ uint64_t sent_time = send_array->buffer[num]->sent_time;
+
+ if ((sent_time + rtt_time) < temp_time) {
+ send_array->buffer[num]->sent_time = 0;
+ }
+ }
+
+ ++data;
+ --length;
+ n = 0;
+ ++requested;
+ } else {
+ if (send_array->buffer[num]) {
+ uint64_t sent_time = send_array->buffer[num]->sent_time;
+
+ if (l_sent_time < sent_time) {
+ l_sent_time = sent_time;
+ }
+
+ free(send_array->buffer[num]);
+ send_array->buffer[num] = NULL;
+ }
+ }
+
+ if (n == 255) {
+ n = 1;
+
+ if (data[0] != 0) {
+ return -1;
+ }
+
+ ++data;
+ --length;
+ } else {
+ ++n;
+ }
+ }
+
+ if (*latest_send_time < l_sent_time) {
+ *latest_send_time = l_sent_time;
+ }
+
+ return requested;
+}
+
+/** END: Array Related functions **/
+
+#define MAX_DATA_DATA_PACKET_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE))
+
+/* Creates and sends a data packet to the peer using the fastest route.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length)
+{
+ if (length == 0 || length + (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE) > MAX_CRYPTO_PACKET_SIZE) {
+ return -1;
+ }
+
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ pthread_mutex_lock(&conn->mutex);
+ VLA(uint8_t, packet, 1 + sizeof(uint16_t) + length + CRYPTO_MAC_SIZE);
+ packet[0] = NET_PACKET_CRYPTO_DATA;
+ memcpy(packet + 1, conn->sent_nonce + (CRYPTO_NONCE_SIZE - sizeof(uint16_t)), sizeof(uint16_t));
+ int len = encrypt_data_symmetric(conn->shared_key, conn->sent_nonce, data, length, packet + 1 + sizeof(uint16_t));
+
+ if (len + 1 + sizeof(uint16_t) != SIZEOF_VLA(packet)) {
+ pthread_mutex_unlock(&conn->mutex);
+ return -1;
+ }
+
+ increment_nonce(conn->sent_nonce);
+ pthread_mutex_unlock(&conn->mutex);
+
+ return send_packet_to(c, crypt_connection_id, packet, SIZEOF_VLA(packet));
+}
+
+/* Creates and sends a data packet with buffer_start and num to the peer using the fastest route.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint32_t buffer_start, uint32_t num,
+ const uint8_t *data, uint16_t length)
+{
+ if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
+ return -1;
+ }
+
+ num = net_htonl(num);
+ buffer_start = net_htonl(buffer_start);
+ uint16_t padding_length = (MAX_CRYPTO_DATA_SIZE - length) % CRYPTO_MAX_PADDING;
+ VLA(uint8_t, packet, sizeof(uint32_t) + sizeof(uint32_t) + padding_length + length);
+ memcpy(packet, &buffer_start, sizeof(uint32_t));
+ memcpy(packet + sizeof(uint32_t), &num, sizeof(uint32_t));
+ memset(packet + (sizeof(uint32_t) * 2), PACKET_ID_PADDING, padding_length);
+ memcpy(packet + (sizeof(uint32_t) * 2) + padding_length, data, length);
+
+ return send_data_packet(c, crypt_connection_id, packet, SIZEOF_VLA(packet));
+}
+
+static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ /* If last packet send failed, try to send packet again.
+ If sending it fails we won't be able to send the new packet. */
+ if (conn->maximum_speed_reached) {
+ Packet_Data *dt = NULL;
+ uint32_t packet_num = conn->send_array.buffer_end - 1;
+ int ret = get_data_pointer(&conn->send_array, &dt, packet_num);
+
+ uint8_t send_failed = 0;
+
+ if (ret == 1) {
+ if (!dt->sent_time) {
+ if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, dt->data,
+ dt->length) != 0) {
+ send_failed = 1;
+ } else {
+ dt->sent_time = current_time_monotonic();
+ }
+ }
+ }
+
+ if (!send_failed) {
+ conn->maximum_speed_reached = 0;
+ } else {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/* return -1 if data could not be put in packet queue.
+ * return positive packet number if data was put into the queue.
+ */
+static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length,
+ uint8_t congestion_control)
+{
+ if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
+ return -1;
+ }
+
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ /* If last packet send failed, try to send packet again.
+ If sending it fails we won't be able to send the new packet. */
+ reset_max_speed_reached(c, crypt_connection_id);
+
+ if (conn->maximum_speed_reached && congestion_control) {
+ return -1;
+ }
+
+ Packet_Data dt;
+ dt.sent_time = 0;
+ dt.length = length;
+ memcpy(dt.data, data, length);
+ pthread_mutex_lock(&conn->mutex);
+ int64_t packet_num = add_data_end_of_buffer(&conn->send_array, &dt);
+ pthread_mutex_unlock(&conn->mutex);
+
+ if (packet_num == -1) {
+ return -1;
+ }
+
+ if (!congestion_control && conn->maximum_speed_reached) {
+ return packet_num;
+ }
+
+ if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, data, length) == 0) {
+ Packet_Data *dt1 = NULL;
+
+ if (get_data_pointer(&conn->send_array, &dt1, packet_num) == 1) {
+ dt1->sent_time = current_time_monotonic();
+ }
+ } else {
+ conn->maximum_speed_reached = 1;
+ LOGGER_ERROR(c->log, "send_data_packet failed\n");
+ }
+
+ return packet_num;
+}
+
+/* Get the lowest 2 bytes from the nonce and convert
+ * them to host byte format before returning them.
+ */
+static uint16_t get_nonce_uint16(const uint8_t *nonce)
+{
+ uint16_t num;
+ memcpy(&num, nonce + (CRYPTO_NONCE_SIZE - sizeof(uint16_t)), sizeof(uint16_t));
+ return net_ntohs(num);
+}
+
+#define DATA_NUM_THRESHOLD 21845
+
+/* Handle a data packet.
+ * Decrypt packet of length and put it into data.
+ * data must be at least MAX_DATA_DATA_PACKET_SIZE big.
+ *
+ * return -1 on failure.
+ * return length of data on success.
+ */
+static int handle_data_packet(const Net_Crypto *c, int crypt_connection_id, uint8_t *data, const uint8_t *packet,
+ uint16_t length)
+{
+ if (length <= (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE) || length > MAX_CRYPTO_PACKET_SIZE) {
+ return -1;
+ }
+
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ uint8_t nonce[CRYPTO_NONCE_SIZE];
+ memcpy(nonce, conn->recv_nonce, CRYPTO_NONCE_SIZE);
+ uint16_t num_cur_nonce = get_nonce_uint16(nonce);
+ uint16_t num;
+ memcpy(&num, packet + 1, sizeof(uint16_t));
+ num = net_ntohs(num);
+ uint16_t diff = num - num_cur_nonce;
+ increment_nonce_number(nonce, diff);
+ int len = decrypt_data_symmetric(conn->shared_key, nonce, packet + 1 + sizeof(uint16_t),
+ length - (1 + sizeof(uint16_t)), data);
+
+ if ((unsigned int)len != length - (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE)) {
+ return -1;
+ }
+
+ if (diff > DATA_NUM_THRESHOLD * 2) {
+ increment_nonce_number(conn->recv_nonce, DATA_NUM_THRESHOLD);
+ }
+
+ return len;
+}
+
+/* Send a request packet.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int send_request_packet(Net_Crypto *c, int crypt_connection_id)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ uint8_t data[MAX_CRYPTO_DATA_SIZE];
+ int len = generate_request_packet(data, sizeof(data), &conn->recv_array);
+
+ if (len == -1) {
+ return -1;
+ }
+
+ return send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, conn->send_array.buffer_end, data,
+ len);
+}
+
+/* Send up to max num previously requested data packets.
+ *
+ * return -1 on failure.
+ * return number of packets sent on success.
+ */
+static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32_t max_num)
+{
+ if (max_num == 0) {
+ return -1;
+ }
+
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ uint64_t temp_time = current_time_monotonic();
+ uint32_t i, num_sent = 0, array_size = num_packets_array(&conn->send_array);
+
+ for (i = 0; i < array_size; ++i) {
+ Packet_Data *dt;
+ uint32_t packet_num = (i + conn->send_array.buffer_start);
+ int ret = get_data_pointer(&conn->send_array, &dt, packet_num);
+
+ if (ret == -1) {
+ return -1;
+ }
+
+ if (ret == 0) {
+ continue;
+ }
+
+ if (dt->sent_time) {
+ continue;
+ }
+
+ if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, dt->data,
+ dt->length) == 0) {
+ dt->sent_time = temp_time;
+ ++num_sent;
+ }
+
+ if (num_sent >= max_num) {
+ break;
+ }
+ }
+
+ return num_sent;
+}
+
+
+/* Add a new temp packet to send repeatedly.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int new_temp_packet(const Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length)
+{
+ if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) {
+ return -1;
+ }
+
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ uint8_t *temp_packet = (uint8_t *)malloc(length);
+
+ if (temp_packet == 0) {
+ return -1;
+ }
+
+ if (conn->temp_packet) {
+ free(conn->temp_packet);
+ }
+
+ memcpy(temp_packet, packet, length);
+ conn->temp_packet = temp_packet;
+ conn->temp_packet_length = length;
+ conn->temp_packet_sent_time = 0;
+ conn->temp_packet_num_sent = 0;
+ return 0;
+}
+
+/* Clear the temp packet.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int clear_temp_packet(const Net_Crypto *c, int crypt_connection_id)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ if (conn->temp_packet) {
+ free(conn->temp_packet);
+ }
+
+ conn->temp_packet = 0;
+ conn->temp_packet_length = 0;
+ conn->temp_packet_sent_time = 0;
+ conn->temp_packet_num_sent = 0;
+ return 0;
+}
+
+
+/* Send the temp packet.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int send_temp_packet(Net_Crypto *c, int crypt_connection_id)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ if (!conn->temp_packet) {
+ return -1;
+ }
+
+ if (send_packet_to(c, crypt_connection_id, conn->temp_packet, conn->temp_packet_length) != 0) {
+ return -1;
+ }
+
+ conn->temp_packet_sent_time = current_time_monotonic();
+ ++conn->temp_packet_num_sent;
+ return 0;
+}
+
+/* Create a handshake packet and set it as a temp packet.
+ * cookie must be COOKIE_LENGTH.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, const uint8_t *cookie,
+ const uint8_t *dht_public_key)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ uint8_t handshake_packet[HANDSHAKE_PACKET_LENGTH];
+
+ if (create_crypto_handshake(c, handshake_packet, cookie, conn->sent_nonce, conn->sessionpublic_key,
+ conn->public_key, dht_public_key) != sizeof(handshake_packet)) {
+ return -1;
+ }
+
+ if (new_temp_packet(c, crypt_connection_id, handshake_packet, sizeof(handshake_packet)) != 0) {
+ return -1;
+ }
+
+ send_temp_packet(c, crypt_connection_id);
+ return 0;
+}
+
+/* Send a kill packet.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int send_kill_packet(Net_Crypto *c, int crypt_connection_id)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ uint8_t kill_packet = PACKET_ID_KILL;
+ return send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, conn->send_array.buffer_end,
+ &kill_packet, sizeof(kill_packet));
+}
+
+static void connection_kill(Net_Crypto *c, int crypt_connection_id, void *userdata)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return;
+ }
+
+ if (conn->connection_status_callback) {
+ conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 0,
+ userdata);
+ }
+
+ crypto_kill(c, crypt_connection_id);
+}
+
+/* Handle a received data packet.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length,
+ bool udp, void *userdata)
+{
+ if (length > MAX_CRYPTO_PACKET_SIZE || length <= CRYPTO_DATA_PACKET_MIN_SIZE) {
+ return -1;
+ }
+
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ uint8_t data[MAX_DATA_DATA_PACKET_SIZE];
+ int len = handle_data_packet(c, crypt_connection_id, data, packet, length);
+
+ if (len <= (int)(sizeof(uint32_t) * 2)) {
+ return -1;
+ }
+
+ uint32_t buffer_start, num;
+ memcpy(&buffer_start, data, sizeof(uint32_t));
+ memcpy(&num, data + sizeof(uint32_t), sizeof(uint32_t));
+ buffer_start = net_ntohl(buffer_start);
+ num = net_ntohl(num);
+
+ uint64_t rtt_calc_time = 0;
+
+ if (buffer_start != conn->send_array.buffer_start) {
+ Packet_Data *packet_time;
+
+ if (get_data_pointer(&conn->send_array, &packet_time, conn->send_array.buffer_start) == 1) {
+ rtt_calc_time = packet_time->sent_time;
+ }
+
+ if (clear_buffer_until(&conn->send_array, buffer_start) != 0) {
+ return -1;
+ }
+ }
+
+ uint8_t *real_data = data + (sizeof(uint32_t) * 2);
+ uint16_t real_length = len - (sizeof(uint32_t) * 2);
+
+ while (real_data[0] == PACKET_ID_PADDING) { /* Remove Padding */
+ ++real_data;
+ --real_length;
+
+ if (real_length == 0) {
+ return -1;
+ }
+ }
+
+ if (real_data[0] == PACKET_ID_KILL) {
+ connection_kill(c, crypt_connection_id, userdata);
+ return 0;
+ }
+
+ if (conn->status == CRYPTO_CONN_NOT_CONFIRMED) {
+ clear_temp_packet(c, crypt_connection_id);
+ conn->status = CRYPTO_CONN_ESTABLISHED;
+
+ if (conn->connection_status_callback) {
+ conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 1,
+ userdata);
+ }
+ }
+
+ if (real_data[0] == PACKET_ID_REQUEST) {
+ uint64_t rtt_time;
+
+ if (udp) {
+ rtt_time = conn->rtt_time;
+ } else {
+ rtt_time = DEFAULT_TCP_PING_CONNECTION;
+ }
+
+ int requested = handle_request_packet(&conn->send_array, real_data, real_length, &rtt_calc_time, rtt_time);
+
+ if (requested == -1) {
+ return -1;
+ }
+
+ // else { /* TODO(irungentoo): ? */ }
+
+ set_buffer_end(&conn->recv_array, num);
+ } else if (real_data[0] >= CRYPTO_RESERVED_PACKETS && real_data[0] < PACKET_ID_LOSSY_RANGE_START) {
+ Packet_Data dt;
+ dt.length = real_length;
+ memcpy(dt.data, real_data, real_length);
+
+ if (add_data_to_buffer(&conn->recv_array, num, &dt) != 0) {
+ return -1;
+ }
+
+ while (1) {
+ pthread_mutex_lock(&conn->mutex);
+ int ret = read_data_beg_buffer(&conn->recv_array, &dt);
+ pthread_mutex_unlock(&conn->mutex);
+
+ if (ret == -1) {
+ break;
+ }
+
+ if (conn->connection_data_callback) {
+ conn->connection_data_callback(conn->connection_data_callback_object, conn->connection_data_callback_id, dt.data,
+ dt.length, userdata);
+ }
+
+ /* conn might get killed in callback. */
+ conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+ }
+
+ /* Packet counter. */
+ ++conn->packet_counter;
+ } else if (real_data[0] >= PACKET_ID_LOSSY_RANGE_START &&
+ real_data[0] < (PACKET_ID_LOSSY_RANGE_START + PACKET_ID_LOSSY_RANGE_SIZE)) {
+
+ set_buffer_end(&conn->recv_array, num);
+
+ if (conn->connection_lossy_data_callback) {
+ conn->connection_lossy_data_callback(conn->connection_lossy_data_callback_object,
+ conn->connection_lossy_data_callback_id, real_data, real_length, userdata);
+ }
+ } else {
+ return -1;
+ }
+
+ if (rtt_calc_time != 0) {
+ uint64_t rtt_time = current_time_monotonic() - rtt_calc_time;
+
+ if (rtt_time < conn->rtt_time) {
+ conn->rtt_time = rtt_time;
+ }
+ }
+
+ return 0;
+}
+
+/* Handle a packet that was received for the connection.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length,
+ bool udp, void *userdata)
+{
+ if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) {
+ return -1;
+ }
+
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ switch (packet[0]) {
+ case NET_PACKET_COOKIE_RESPONSE: {
+ if (conn->status != CRYPTO_CONN_COOKIE_REQUESTING) {
+ return -1;
+ }
+
+ uint8_t cookie[COOKIE_LENGTH];
+ uint64_t number;
+
+ if (handle_cookie_response(cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) {
+ return -1;
+ }
+
+ if (number != conn->cookie_request_number) {
+ return -1;
+ }
+
+ if (create_send_handshake(c, crypt_connection_id, cookie, conn->dht_public_key) != 0) {
+ return -1;
+ }
+
+ conn->status = CRYPTO_CONN_HANDSHAKE_SENT;
+ return 0;
+ }
+
+ case NET_PACKET_CRYPTO_HS: {
+ if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT
+ || conn->status == CRYPTO_CONN_NOT_CONFIRMED) {
+ uint8_t peer_real_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t cookie[COOKIE_LENGTH];
+
+ if (handle_crypto_handshake(c, conn->recv_nonce, conn->peersessionpublic_key, peer_real_pk, dht_public_key, cookie,
+ packet, length, conn->public_key) != 0) {
+ return -1;
+ }
+
+ if (public_key_cmp(dht_public_key, conn->dht_public_key) == 0) {
+ encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key);
+
+ if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING) {
+ if (create_send_handshake(c, crypt_connection_id, cookie, dht_public_key) != 0) {
+ return -1;
+ }
+ }
+
+ conn->status = CRYPTO_CONN_NOT_CONFIRMED;
+ } else {
+ if (conn->dht_pk_callback) {
+ conn->dht_pk_callback(conn->dht_pk_callback_object, conn->dht_pk_callback_number, dht_public_key, userdata);
+ }
+ }
+ } else {
+ return -1;
+ }
+
+ return 0;
+ }
+
+ case NET_PACKET_CRYPTO_DATA: {
+ if (conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) {
+ return handle_data_packet_core(c, crypt_connection_id, packet, length, udp, userdata);
+ }
+
+ return -1;
+ }
+
+ default: {
+ return -1;
+ }
+ }
+}
+
+/* Set the size of the friend list to numfriends.
+ *
+ * return -1 if realloc fails.
+ * return 0 if it succeeds.
+ */
+static int realloc_cryptoconnection(Net_Crypto *c, uint32_t num)
+{
+ if (num == 0) {
+ free(c->crypto_connections);
+ c->crypto_connections = NULL;
+ return 0;
+ }
+
+ Crypto_Connection *newcrypto_connections = (Crypto_Connection *)realloc(c->crypto_connections,
+ num * sizeof(Crypto_Connection));
+
+ if (newcrypto_connections == NULL) {
+ return -1;
+ }
+
+ c->crypto_connections = newcrypto_connections;
+ return 0;
+}
+
+
+/* Create a new empty crypto connection.
+ *
+ * return -1 on failure.
+ * return connection id on success.
+ */
+static int create_crypto_connection(Net_Crypto *c)
+{
+ uint32_t i;
+
+ for (i = 0; i < c->crypto_connections_length; ++i) {
+ if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) {
+ return i;
+ }
+ }
+
+ while (1) { /* TODO(irungentoo): is this really the best way to do this? */
+ pthread_mutex_lock(&c->connections_mutex);
+
+ if (!c->connection_use_counter) {
+ break;
+ }
+
+ pthread_mutex_unlock(&c->connections_mutex);
+ }
+
+ int id = -1;
+
+ if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == 0) {
+ id = c->crypto_connections_length;
+ ++c->crypto_connections_length;
+ memset(&(c->crypto_connections[id]), 0, sizeof(Crypto_Connection));
+ // Memsetting float/double to 0 is non-portable, so we explicitly set them to 0
+ c->crypto_connections[id].packet_recv_rate = 0;
+ c->crypto_connections[id].packet_send_rate = 0;
+ c->crypto_connections[id].last_packets_left_rem = 0;
+ c->crypto_connections[id].packet_send_rate_requested = 0;
+ c->crypto_connections[id].last_packets_left_requested_rem = 0;
+
+ if (pthread_mutex_init(&c->crypto_connections[id].mutex, NULL) != 0) {
+ pthread_mutex_unlock(&c->connections_mutex);
+ return -1;
+ }
+ }
+
+ pthread_mutex_unlock(&c->connections_mutex);
+ return id;
+}
+
+/* Wipe a crypto connection.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int wipe_crypto_connection(Net_Crypto *c, int crypt_connection_id)
+{
+ if (crypt_connection_id_not_valid(c, crypt_connection_id)) {
+ return -1;
+ }
+
+ uint32_t i;
+
+ /* Keep mutex, only destroy it when connection is realloced out. */
+ pthread_mutex_t mutex = c->crypto_connections[crypt_connection_id].mutex;
+ crypto_memzero(&(c->crypto_connections[crypt_connection_id]), sizeof(Crypto_Connection));
+ c->crypto_connections[crypt_connection_id].mutex = mutex;
+
+ for (i = c->crypto_connections_length; i != 0; --i) {
+ if (c->crypto_connections[i - 1].status == CRYPTO_CONN_NO_CONNECTION) {
+ pthread_mutex_destroy(&c->crypto_connections[i - 1].mutex);
+ } else {
+ break;
+ }
+ }
+
+ if (c->crypto_connections_length != i) {
+ c->crypto_connections_length = i;
+ realloc_cryptoconnection(c, c->crypto_connections_length);
+ }
+
+ return 0;
+}
+
+/* Get crypto connection id from public key of peer.
+ *
+ * return -1 if there are no connections like we are looking for.
+ * return id if it found it.
+ */
+static int getcryptconnection_id(const Net_Crypto *c, const uint8_t *public_key)
+{
+ uint32_t i;
+
+ for (i = 0; i < c->crypto_connections_length; ++i) {
+ if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION) {
+ if (public_key_cmp(public_key, c->crypto_connections[i].public_key) == 0) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+}
+
+/* Add a source to the crypto connection.
+ * This is to be used only when we have received a packet from that source.
+ *
+ * return -1 on failure.
+ * return positive number on success.
+ * 0 if source was a direct UDP connection.
+ */
+static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id, IP_Port source)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ if (source.ip.family == TOX_AF_INET || source.ip.family == TOX_AF_INET6) {
+ if (add_ip_port_connection(c, crypt_connection_id, source) != 0) {
+ return -1;
+ }
+
+ if (source.ip.family == TOX_AF_INET) {
+ conn->direct_lastrecv_timev4 = unix_time();
+ } else {
+ conn->direct_lastrecv_timev6 = unix_time();
+ }
+
+ return 0;
+ }
+
+ if (source.ip.family == TCP_FAMILY) {
+ if (add_tcp_number_relay_connection(c->tcp_c, conn->connection_number_tcp, source.ip.ip6.uint32[0]) == 0) {
+ return 1;
+ }
+ }
+
+ return -1;
+}
+
+
+/* Set function to be called when someone requests a new connection to us.
+ *
+ * The set function should return -1 on failure and 0 on success.
+ *
+ * n_c is only valid for the duration of the function call.
+ */
+void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c),
+ void *object)
+{
+ c->new_connection_callback = new_connection_callback;
+ c->new_connection_callback_object = object;
+}
+
+/* Handle a handshake packet by someone who wants to initiate a new connection with us.
+ * This calls the callback set by new_connection_handler() if the handshake is ok.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, const uint8_t *data, uint16_t length,
+ void *userdata)
+{
+ New_Connection n_c;
+ n_c.cookie = (uint8_t *)malloc(COOKIE_LENGTH);
+
+ if (n_c.cookie == NULL) {
+ return -1;
+ }
+
+ n_c.source = source;
+ n_c.cookie_length = COOKIE_LENGTH;
+
+ if (handle_crypto_handshake(c, n_c.recv_nonce, n_c.peersessionpublic_key, n_c.public_key, n_c.dht_public_key,
+ n_c.cookie, data, length, 0) != 0) {
+ free(n_c.cookie);
+ return -1;
+ }
+
+ int crypt_connection_id = getcryptconnection_id(c, n_c.public_key);
+
+ if (crypt_connection_id != -1) {
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (public_key_cmp(n_c.dht_public_key, conn->dht_public_key) != 0) {
+ connection_kill(c, crypt_connection_id, userdata);
+ } else {
+ int ret = -1;
+
+ if (conn && (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT)) {
+ memcpy(conn->recv_nonce, n_c.recv_nonce, CRYPTO_NONCE_SIZE);
+ memcpy(conn->peersessionpublic_key, n_c.peersessionpublic_key, CRYPTO_PUBLIC_KEY_SIZE);
+ encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key);
+
+ crypto_connection_add_source(c, crypt_connection_id, source);
+
+ if (create_send_handshake(c, crypt_connection_id, n_c.cookie, n_c.dht_public_key) == 0) {
+ conn->status = CRYPTO_CONN_NOT_CONFIRMED;
+ ret = 0;
+ }
+ }
+
+ free(n_c.cookie);
+ return ret;
+ }
+ }
+
+ int ret = c->new_connection_callback(c->new_connection_callback_object, &n_c);
+ free(n_c.cookie);
+ return ret;
+}
+
+/* Accept a crypto connection.
+ *
+ * return -1 on failure.
+ * return connection id on success.
+ */
+int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c)
+{
+ if (getcryptconnection_id(c, n_c->public_key) != -1) {
+ return -1;
+ }
+
+ int crypt_connection_id = create_crypto_connection(c);
+
+ if (crypt_connection_id == -1) {
+ return -1;
+ }
+
+ Crypto_Connection *conn = &c->crypto_connections[crypt_connection_id];
+
+ if (n_c->cookie_length != COOKIE_LENGTH) {
+ return -1;
+ }
+
+ pthread_mutex_lock(&c->tcp_mutex);
+ int connection_number_tcp = new_tcp_connection_to(c->tcp_c, n_c->dht_public_key, crypt_connection_id);
+ pthread_mutex_unlock(&c->tcp_mutex);
+
+ if (connection_number_tcp == -1) {
+ return -1;
+ }
+
+ conn->connection_number_tcp = connection_number_tcp;
+ memcpy(conn->public_key, n_c->public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(conn->recv_nonce, n_c->recv_nonce, CRYPTO_NONCE_SIZE);
+ memcpy(conn->peersessionpublic_key, n_c->peersessionpublic_key, CRYPTO_PUBLIC_KEY_SIZE);
+ random_nonce(conn->sent_nonce);
+ crypto_new_keypair(conn->sessionpublic_key, conn->sessionsecret_key);
+ encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key);
+ conn->status = CRYPTO_CONN_NOT_CONFIRMED;
+
+ if (create_send_handshake(c, crypt_connection_id, n_c->cookie, n_c->dht_public_key) != 0) {
+ pthread_mutex_lock(&c->tcp_mutex);
+ kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp);
+ pthread_mutex_unlock(&c->tcp_mutex);
+ conn->status = CRYPTO_CONN_NO_CONNECTION;
+ return -1;
+ }
+
+ memcpy(conn->dht_public_key, n_c->dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE;
+ conn->packet_send_rate_requested = CRYPTO_PACKET_MIN_RATE;
+ conn->packets_left = CRYPTO_MIN_QUEUE_LENGTH;
+ conn->rtt_time = DEFAULT_PING_CONNECTION;
+ crypto_connection_add_source(c, crypt_connection_id, n_c->source);
+ return crypt_connection_id;
+}
+
+/* Create a crypto connection.
+ * If one to that real public key already exists, return it.
+ *
+ * return -1 on failure.
+ * return connection id on success.
+ */
+int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const uint8_t *dht_public_key)
+{
+ int crypt_connection_id = getcryptconnection_id(c, real_public_key);
+
+ if (crypt_connection_id != -1) {
+ return crypt_connection_id;
+ }
+
+ crypt_connection_id = create_crypto_connection(c);
+
+ if (crypt_connection_id == -1) {
+ return -1;
+ }
+
+ Crypto_Connection *conn = &c->crypto_connections[crypt_connection_id];
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ pthread_mutex_lock(&c->tcp_mutex);
+ int connection_number_tcp = new_tcp_connection_to(c->tcp_c, dht_public_key, crypt_connection_id);
+ pthread_mutex_unlock(&c->tcp_mutex);
+
+ if (connection_number_tcp == -1) {
+ return -1;
+ }
+
+ conn->connection_number_tcp = connection_number_tcp;
+ memcpy(conn->public_key, real_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ random_nonce(conn->sent_nonce);
+ crypto_new_keypair(conn->sessionpublic_key, conn->sessionsecret_key);
+ conn->status = CRYPTO_CONN_COOKIE_REQUESTING;
+ conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE;
+ conn->packet_send_rate_requested = CRYPTO_PACKET_MIN_RATE;
+ conn->packets_left = CRYPTO_MIN_QUEUE_LENGTH;
+ conn->rtt_time = DEFAULT_PING_CONNECTION;
+ memcpy(conn->dht_public_key, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+
+ conn->cookie_request_number = random_64b();
+ uint8_t cookie_request[COOKIE_REQUEST_LENGTH];
+
+ if (create_cookie_request(c, cookie_request, conn->dht_public_key, conn->cookie_request_number,
+ conn->shared_key) != sizeof(cookie_request)
+ || new_temp_packet(c, crypt_connection_id, cookie_request, sizeof(cookie_request)) != 0) {
+ pthread_mutex_lock(&c->tcp_mutex);
+ kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp);
+ pthread_mutex_unlock(&c->tcp_mutex);
+ conn->status = CRYPTO_CONN_NO_CONNECTION;
+ return -1;
+ }
+
+ return crypt_connection_id;
+}
+
+/* Set the direct ip of the crypto connection.
+ *
+ * Connected is 0 if we are not sure we are connected to that person, 1 if we are sure.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, bool connected)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ if (add_ip_port_connection(c, crypt_connection_id, ip_port) == 0) {
+ if (connected) {
+ if (ip_port.ip.family == TOX_AF_INET) {
+ conn->direct_lastrecv_timev4 = unix_time();
+ } else {
+ conn->direct_lastrecv_timev6 = unix_time();
+ }
+ } else {
+ if (ip_port.ip.family == TOX_AF_INET) {
+ conn->direct_lastrecv_timev4 = 0;
+ } else {
+ conn->direct_lastrecv_timev6 = 0;
+ }
+ }
+
+ return 0;
+ }
+
+ return -1;
+}
+
+
+static int tcp_data_callback(void *object, int id, const uint8_t *data, uint16_t length, void *userdata)
+{
+ if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) {
+ return -1;
+ }
+
+ Net_Crypto *c = (Net_Crypto *)object;
+
+ Crypto_Connection *conn = get_crypto_connection(c, id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ if (data[0] == NET_PACKET_COOKIE_REQUEST) {
+ return tcp_handle_cookie_request(c, conn->connection_number_tcp, data, length);
+ }
+
+ // This unlocks the mutex that at this point is locked by do_tcp before
+ // calling do_tcp_connections.
+ pthread_mutex_unlock(&c->tcp_mutex);
+ int ret = handle_packet_connection(c, id, data, length, 0, userdata);
+ pthread_mutex_lock(&c->tcp_mutex);
+
+ if (ret != 0) {
+ return -1;
+ }
+
+ // TODO(irungentoo): detect and kill bad TCP connections.
+ return 0;
+}
+
+static int tcp_oob_callback(void *object, const uint8_t *public_key, unsigned int tcp_connections_number,
+ const uint8_t *data, uint16_t length, void *userdata)
+{
+ if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) {
+ return -1;
+ }
+
+ Net_Crypto *c = (Net_Crypto *)object;
+
+ if (data[0] == NET_PACKET_COOKIE_REQUEST) {
+ return tcp_oob_handle_cookie_request(c, tcp_connections_number, public_key, data, length);
+ }
+
+ if (data[0] == NET_PACKET_CRYPTO_HS) {
+ IP_Port source;
+ source.port = 0;
+ source.ip.family = TCP_FAMILY;
+ source.ip.ip6.uint32[0] = tcp_connections_number;
+
+ if (handle_new_connection_handshake(c, source, data, length, userdata) != 0) {
+ return -1;
+ }
+
+ return 0;
+ }
+
+ return -1;
+}
+
+/* Add a tcp relay, associating it to a crypt_connection_id.
+ *
+ * return 0 if it was added.
+ * return -1 if it wasn't.
+ */
+int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, const uint8_t *public_key)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ pthread_mutex_lock(&c->tcp_mutex);
+ int ret = add_tcp_relay_connection(c->tcp_c, conn->connection_number_tcp, ip_port, public_key);
+ pthread_mutex_unlock(&c->tcp_mutex);
+ return ret;
+}
+
+/* Add a tcp relay to the array.
+ *
+ * return 0 if it was added.
+ * return -1 if it wasn't.
+ */
+int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, const uint8_t *public_key)
+{
+ pthread_mutex_lock(&c->tcp_mutex);
+ int ret = add_tcp_relay_global(c->tcp_c, ip_port, public_key);
+ pthread_mutex_unlock(&c->tcp_mutex);
+ return ret;
+}
+
+/* Return a random TCP connection number for use in send_tcp_onion_request.
+ *
+ * TODO(irungentoo): This number is just the index of an array that the elements can
+ * change without warning.
+ *
+ * return TCP connection number on success.
+ * return -1 on failure.
+ */
+int get_random_tcp_con_number(Net_Crypto *c)
+{
+ pthread_mutex_lock(&c->tcp_mutex);
+ int ret = get_random_tcp_onion_conn_number(c->tcp_c);
+ pthread_mutex_unlock(&c->tcp_mutex);
+
+ return ret;
+}
+
+/* Send an onion packet via the TCP relay corresponding to tcp_connections_number.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int send_tcp_onion_request(Net_Crypto *c, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length)
+{
+ pthread_mutex_lock(&c->tcp_mutex);
+ int ret = tcp_send_onion_request(c->tcp_c, tcp_connections_number, data, length);
+ pthread_mutex_unlock(&c->tcp_mutex);
+
+ return ret;
+}
+
+/* Copy a maximum of num TCP relays we are connected to to tcp_relays.
+ * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.
+ *
+ * return number of relays copied to tcp_relays on success.
+ * return 0 on failure.
+ */
+unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num)
+{
+ if (num == 0) {
+ return 0;
+ }
+
+ pthread_mutex_lock(&c->tcp_mutex);
+ unsigned int ret = tcp_copy_connected_relays(c->tcp_c, tcp_relays, num);
+ pthread_mutex_unlock(&c->tcp_mutex);
+
+ return ret;
+}
+
+static void do_tcp(Net_Crypto *c, void *userdata)
+{
+ pthread_mutex_lock(&c->tcp_mutex);
+ do_tcp_connections(c->tcp_c, userdata);
+ pthread_mutex_unlock(&c->tcp_mutex);
+
+ uint32_t i;
+
+ for (i = 0; i < c->crypto_connections_length; ++i) {
+ Crypto_Connection *conn = get_crypto_connection(c, i);
+
+ if (conn == 0) {
+ return;
+ }
+
+ if (conn->status == CRYPTO_CONN_ESTABLISHED) {
+ bool direct_connected = 0;
+ crypto_connection_status(c, i, &direct_connected, NULL);
+
+ if (direct_connected) {
+ pthread_mutex_lock(&c->tcp_mutex);
+ set_tcp_connection_to_status(c->tcp_c, conn->connection_number_tcp, 0);
+ pthread_mutex_unlock(&c->tcp_mutex);
+ } else {
+ pthread_mutex_lock(&c->tcp_mutex);
+ set_tcp_connection_to_status(c->tcp_c, conn->connection_number_tcp, 1);
+ pthread_mutex_unlock(&c->tcp_mutex);
+ }
+ }
+ }
+}
+
+/* Set function to be called when connection with crypt_connection_id goes connects/disconnects.
+ *
+ * The set function should return -1 on failure and 0 on success.
+ * Note that if this function is set, the connection will clear itself on disconnect.
+ * Object and id will be passed to this function untouched.
+ * status is 1 if the connection is going online, 0 if it is going offline.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int connection_status_handler(const Net_Crypto *c, int crypt_connection_id,
+ int (*connection_status_callback)(void *object, int id, uint8_t status, void *userdata), void *object, int id)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ conn->connection_status_callback = connection_status_callback;
+ conn->connection_status_callback_object = object;
+ conn->connection_status_callback_id = id;
+ return 0;
+}
+
+/* Set function to be called when connection with crypt_connection_id receives a data packet of length.
+ *
+ * The set function should return -1 on failure and 0 on success.
+ * Object and id will be passed to this function untouched.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int connection_data_handler(const Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object,
+ int id, const uint8_t *data, uint16_t length, void *userdata), void *object, int id)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ conn->connection_data_callback = connection_data_callback;
+ conn->connection_data_callback_object = object;
+ conn->connection_data_callback_id = id;
+ return 0;
+}
+
+/* Set function to be called when connection with crypt_connection_id receives a lossy data packet of length.
+ *
+ * The set function should return -1 on failure and 0 on success.
+ * Object and id will be passed to this function untouched.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id,
+ int (*connection_lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata),
+ void *object, int id)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ conn->connection_lossy_data_callback = connection_lossy_data_callback;
+ conn->connection_lossy_data_callback_object = object;
+ conn->connection_lossy_data_callback_id = id;
+ return 0;
+}
+
+
+/* Set the function for this friend that will be callbacked with object and number if
+ * the friend sends us a different dht public key than we have associated to him.
+ *
+ * If this function is called, the connection should be recreated with the new public key.
+ *
+ * object and number will be passed as argument to this function.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, void (*function)(void *data, int32_t number,
+ const uint8_t *dht_public_key, void *userdata), void *object, uint32_t number)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ conn->dht_pk_callback = function;
+ conn->dht_pk_callback_object = object;
+ conn->dht_pk_callback_number = number;
+ return 0;
+}
+
+/* Get the crypto connection id from the ip_port.
+ *
+ * return -1 on failure.
+ * return connection id on success.
+ */
+static int crypto_id_ip_port(const Net_Crypto *c, IP_Port ip_port)
+{
+ return bs_list_find(&c->ip_port_list, (uint8_t *)&ip_port);
+}
+
+#define CRYPTO_MIN_PACKET_SIZE (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE)
+
+/* Handle raw UDP packets coming directly from the socket.
+ *
+ * Handles:
+ * Cookie response packets.
+ * Crypto handshake packets.
+ * Crypto data packets.
+ *
+ */
+static int udp_handle_packet(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
+{
+ if (length <= CRYPTO_MIN_PACKET_SIZE || length > MAX_CRYPTO_PACKET_SIZE) {
+ return 1;
+ }
+
+ Net_Crypto *c = (Net_Crypto *)object;
+ int crypt_connection_id = crypto_id_ip_port(c, source);
+
+ if (crypt_connection_id == -1) {
+ if (packet[0] != NET_PACKET_CRYPTO_HS) {
+ return 1;
+ }
+
+ if (handle_new_connection_handshake(c, source, packet, length, userdata) != 0) {
+ return 1;
+ }
+
+ return 0;
+ }
+
+ if (handle_packet_connection(c, crypt_connection_id, packet, length, 1, userdata) != 0) {
+ return 1;
+ }
+
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ pthread_mutex_lock(&conn->mutex);
+
+ if (source.ip.family == TOX_AF_INET) {
+ conn->direct_lastrecv_timev4 = unix_time();
+ } else {
+ conn->direct_lastrecv_timev6 = unix_time();
+ }
+
+ pthread_mutex_unlock(&conn->mutex);
+ return 0;
+}
+
+/* The dT for the average packet receiving rate calculations.
+ Also used as the */
+#define PACKET_COUNTER_AVERAGE_INTERVAL 50
+
+/* Ratio of recv queue size / recv packet rate (in seconds) times
+ * the number of ms between request packets to send at that ratio
+ */
+#define REQUEST_PACKETS_COMPARE_CONSTANT (0.125 * 100.0)
+
+/* Timeout for increasing speed after congestion event (in ms). */
+#define CONGESTION_EVENT_TIMEOUT 1000
+
+/* If the send queue is SEND_QUEUE_RATIO times larger than the
+ * calculated link speed the packet send speed will be reduced
+ * by a value depending on this number.
+ */
+#define SEND_QUEUE_RATIO 2.0
+
+static void send_crypto_packets(Net_Crypto *c)
+{
+ uint32_t i;
+ uint64_t temp_time = current_time_monotonic();
+ double total_send_rate = 0;
+ uint32_t peak_request_packet_interval = ~0;
+
+ for (i = 0; i < c->crypto_connections_length; ++i) {
+ Crypto_Connection *conn = get_crypto_connection(c, i);
+
+ if (conn == 0) {
+ return;
+ }
+
+ if (CRYPTO_SEND_PACKET_INTERVAL + conn->temp_packet_sent_time < temp_time) {
+ send_temp_packet(c, i);
+ }
+
+ if ((conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED)
+ && ((CRYPTO_SEND_PACKET_INTERVAL) + conn->last_request_packet_sent) < temp_time) {
+ if (send_request_packet(c, i) == 0) {
+ conn->last_request_packet_sent = temp_time;
+ }
+ }
+
+ if (conn->status == CRYPTO_CONN_ESTABLISHED) {
+ if (conn->packet_recv_rate > CRYPTO_PACKET_MIN_RATE) {
+ double request_packet_interval = (REQUEST_PACKETS_COMPARE_CONSTANT / ((num_packets_array(
+ &conn->recv_array) + 1.0) / (conn->packet_recv_rate + 1.0)));
+
+ double request_packet_interval2 = ((CRYPTO_PACKET_MIN_RATE / conn->packet_recv_rate) *
+ (double)CRYPTO_SEND_PACKET_INTERVAL) + (double)PACKET_COUNTER_AVERAGE_INTERVAL;
+
+ if (request_packet_interval2 < request_packet_interval) {
+ request_packet_interval = request_packet_interval2;
+ }
+
+ if (request_packet_interval < PACKET_COUNTER_AVERAGE_INTERVAL) {
+ request_packet_interval = PACKET_COUNTER_AVERAGE_INTERVAL;
+ }
+
+ if (request_packet_interval > CRYPTO_SEND_PACKET_INTERVAL) {
+ request_packet_interval = CRYPTO_SEND_PACKET_INTERVAL;
+ }
+
+ if (temp_time - conn->last_request_packet_sent > (uint64_t)request_packet_interval) {
+ if (send_request_packet(c, i) == 0) {
+ conn->last_request_packet_sent = temp_time;
+ }
+ }
+
+ if (request_packet_interval < peak_request_packet_interval) {
+ peak_request_packet_interval = request_packet_interval;
+ }
+ }
+
+ if ((PACKET_COUNTER_AVERAGE_INTERVAL + conn->packet_counter_set) < temp_time) {
+
+ double dt = temp_time - conn->packet_counter_set;
+
+ conn->packet_recv_rate = (double)conn->packet_counter / (dt / 1000.0);
+ conn->packet_counter = 0;
+ conn->packet_counter_set = temp_time;
+
+ uint32_t packets_sent = conn->packets_sent;
+ conn->packets_sent = 0;
+
+ uint32_t packets_resent = conn->packets_resent;
+ conn->packets_resent = 0;
+
+ /* conjestion control
+ calculate a new value of conn->packet_send_rate based on some data
+ */
+
+ unsigned int pos = conn->last_sendqueue_counter % CONGESTION_QUEUE_ARRAY_SIZE;
+ conn->last_sendqueue_size[pos] = num_packets_array(&conn->send_array);
+ ++conn->last_sendqueue_counter;
+
+ unsigned int j;
+ long signed int sum = 0;
+ sum = (long signed int)conn->last_sendqueue_size[(pos) % CONGESTION_QUEUE_ARRAY_SIZE] -
+ (long signed int)conn->last_sendqueue_size[(pos - (CONGESTION_QUEUE_ARRAY_SIZE - 1)) % CONGESTION_QUEUE_ARRAY_SIZE];
+
+ unsigned int n_p_pos = conn->last_sendqueue_counter % CONGESTION_LAST_SENT_ARRAY_SIZE;
+ conn->last_num_packets_sent[n_p_pos] = packets_sent;
+ conn->last_num_packets_resent[n_p_pos] = packets_resent;
+
+ bool direct_connected = 0;
+ crypto_connection_status(c, i, &direct_connected, NULL);
+
+ if (direct_connected && conn->last_tcp_sent + CONGESTION_EVENT_TIMEOUT > temp_time) {
+ /* When switching from TCP to UDP, don't change the packet send rate for CONGESTION_EVENT_TIMEOUT ms. */
+ } else {
+ long signed int total_sent = 0, total_resent = 0;
+
+ // TODO(irungentoo): use real delay
+ unsigned int delay = (unsigned int)((conn->rtt_time / PACKET_COUNTER_AVERAGE_INTERVAL) + 0.5);
+ unsigned int packets_set_rem_array = (CONGESTION_LAST_SENT_ARRAY_SIZE - CONGESTION_QUEUE_ARRAY_SIZE);
+
+ if (delay > packets_set_rem_array) {
+ delay = packets_set_rem_array;
+ }
+
+ for (j = 0; j < CONGESTION_QUEUE_ARRAY_SIZE; ++j) {
+ unsigned int ind = (j + (packets_set_rem_array - delay) + n_p_pos) % CONGESTION_LAST_SENT_ARRAY_SIZE;
+ total_sent += conn->last_num_packets_sent[ind];
+ total_resent += conn->last_num_packets_resent[ind];
+ }
+
+ if (sum > 0) {
+ total_sent -= sum;
+ } else {
+ if (total_resent > -sum) {
+ total_resent = -sum;
+ }
+ }
+
+ /* if queue is too big only allow resending packets. */
+ uint32_t npackets = num_packets_array(&conn->send_array);
+ double min_speed = 1000.0 * (((double)(total_sent)) / ((double)(CONGESTION_QUEUE_ARRAY_SIZE) *
+ PACKET_COUNTER_AVERAGE_INTERVAL));
+
+ double min_speed_request = 1000.0 * (((double)(total_sent + total_resent)) / ((double)(
+ CONGESTION_QUEUE_ARRAY_SIZE) * PACKET_COUNTER_AVERAGE_INTERVAL));
+
+ if (min_speed < CRYPTO_PACKET_MIN_RATE) {
+ min_speed = CRYPTO_PACKET_MIN_RATE;
+ }
+
+ double send_array_ratio = (((double)npackets) / min_speed);
+
+ // TODO(irungentoo): Improve formula?
+ if (send_array_ratio > SEND_QUEUE_RATIO && CRYPTO_MIN_QUEUE_LENGTH < npackets) {
+ conn->packet_send_rate = min_speed * (1.0 / (send_array_ratio / SEND_QUEUE_RATIO));
+ } else if (conn->last_congestion_event + CONGESTION_EVENT_TIMEOUT < temp_time) {
+ conn->packet_send_rate = min_speed * 1.2;
+ } else {
+ conn->packet_send_rate = min_speed * 0.9;
+ }
+
+ conn->packet_send_rate_requested = min_speed_request * 1.2;
+
+ if (conn->packet_send_rate < CRYPTO_PACKET_MIN_RATE) {
+ conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE;
+ }
+
+ if (conn->packet_send_rate_requested < conn->packet_send_rate) {
+ conn->packet_send_rate_requested = conn->packet_send_rate;
+ }
+ }
+ }
+
+ if (conn->last_packets_left_set == 0 || conn->last_packets_left_requested_set == 0) {
+ conn->last_packets_left_requested_set = conn->last_packets_left_set = temp_time;
+ conn->packets_left_requested = conn->packets_left = CRYPTO_MIN_QUEUE_LENGTH;
+ } else {
+ if (((uint64_t)((1000.0 / conn->packet_send_rate) + 0.5) + conn->last_packets_left_set) <= temp_time) {
+ double n_packets = conn->packet_send_rate * (((double)(temp_time - conn->last_packets_left_set)) / 1000.0);
+ n_packets += conn->last_packets_left_rem;
+
+ uint32_t num_packets = n_packets;
+ double rem = n_packets - (double)num_packets;
+
+ if (conn->packets_left > num_packets * 4 + CRYPTO_MIN_QUEUE_LENGTH) {
+ conn->packets_left = num_packets * 4 + CRYPTO_MIN_QUEUE_LENGTH;
+ } else {
+ conn->packets_left += num_packets;
+ }
+
+ conn->last_packets_left_set = temp_time;
+ conn->last_packets_left_rem = rem;
+ }
+
+ if (((uint64_t)((1000.0 / conn->packet_send_rate_requested) + 0.5) + conn->last_packets_left_requested_set) <=
+ temp_time) {
+ double n_packets = conn->packet_send_rate_requested * (((double)(temp_time - conn->last_packets_left_requested_set)) /
+ 1000.0);
+ n_packets += conn->last_packets_left_requested_rem;
+
+ uint32_t num_packets = n_packets;
+ double rem = n_packets - (double)num_packets;
+ conn->packets_left_requested = num_packets;
+
+ conn->last_packets_left_requested_set = temp_time;
+ conn->last_packets_left_requested_rem = rem;
+ }
+
+ if (conn->packets_left > conn->packets_left_requested) {
+ conn->packets_left_requested = conn->packets_left;
+ }
+ }
+
+ int ret = send_requested_packets(c, i, conn->packets_left_requested);
+
+ if (ret != -1) {
+ conn->packets_left_requested -= ret;
+ conn->packets_resent += ret;
+
+ if ((unsigned int)ret < conn->packets_left) {
+ conn->packets_left -= ret;
+ } else {
+ conn->last_congestion_event = temp_time;
+ conn->packets_left = 0;
+ }
+ }
+
+ if (conn->packet_send_rate > CRYPTO_PACKET_MIN_RATE * 1.5) {
+ total_send_rate += conn->packet_send_rate;
+ }
+ }
+ }
+
+ c->current_sleep_time = ~0;
+ uint32_t sleep_time = peak_request_packet_interval;
+
+ if (c->current_sleep_time > sleep_time) {
+ c->current_sleep_time = sleep_time;
+ }
+
+ if (total_send_rate > CRYPTO_PACKET_MIN_RATE) {
+ sleep_time = (1000.0 / total_send_rate);
+
+ if (c->current_sleep_time > sleep_time) {
+ c->current_sleep_time = sleep_time + 1;
+ }
+ }
+
+ sleep_time = CRYPTO_SEND_PACKET_INTERVAL;
+
+ if (c->current_sleep_time > sleep_time) {
+ c->current_sleep_time = sleep_time;
+ }
+}
+
+/* Return 1 if max speed was reached for this connection (no more data can be physically through the pipe).
+ * Return 0 if it wasn't reached.
+ */
+bool max_speed_reached(Net_Crypto *c, int crypt_connection_id)
+{
+ return reset_max_speed_reached(c, crypt_connection_id) != 0;
+}
+
+/* returns the number of packet slots left in the sendbuffer.
+ * return 0 if failure.
+ */
+uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connection_id)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return 0;
+ }
+
+ uint32_t max_packets = CRYPTO_PACKET_BUFFER_SIZE - num_packets_array(&conn->send_array);
+
+ if (conn->packets_left < max_packets) {
+ return conn->packets_left;
+ }
+
+ return max_packets;
+}
+
+/* Sends a lossless cryptopacket.
+ *
+ * return -1 if data could not be put in packet queue.
+ * return positive packet number if data was put into the queue.
+ *
+ * congestion_control: should congestion control apply to this packet?
+ */
+int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length,
+ uint8_t congestion_control)
+{
+ if (length == 0) {
+ return -1;
+ }
+
+ if (data[0] < CRYPTO_RESERVED_PACKETS) {
+ return -1;
+ }
+
+ if (data[0] >= PACKET_ID_LOSSY_RANGE_START) {
+ return -1;
+ }
+
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ if (conn->status != CRYPTO_CONN_ESTABLISHED) {
+ return -1;
+ }
+
+ if (congestion_control && conn->packets_left == 0) {
+ return -1;
+ }
+
+ int64_t ret = send_lossless_packet(c, crypt_connection_id, data, length, congestion_control);
+
+ if (ret == -1) {
+ return -1;
+ }
+
+ if (congestion_control) {
+ --conn->packets_left;
+ --conn->packets_left_requested;
+ conn->packets_sent++;
+ }
+
+ return ret;
+}
+
+/* Check if packet_number was received by the other side.
+ *
+ * packet_number must be a valid packet number of a packet sent on this connection.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int cryptpacket_received(Net_Crypto *c, int crypt_connection_id, uint32_t packet_number)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return -1;
+ }
+
+ uint32_t num = conn->send_array.buffer_end - conn->send_array.buffer_start;
+ uint32_t num1 = packet_number - conn->send_array.buffer_start;
+
+ if (num < num1) {
+ return 0;
+ }
+
+ return -1;
+}
+
+/* return -1 on failure.
+ * return 0 on success.
+ *
+ * Sends a lossy cryptopacket. (first byte must in the PACKET_ID_LOSSY_RANGE_*)
+ */
+int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length)
+{
+ if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
+ return -1;
+ }
+
+ if (data[0] < PACKET_ID_LOSSY_RANGE_START) {
+ return -1;
+ }
+
+ if (data[0] >= (PACKET_ID_LOSSY_RANGE_START + PACKET_ID_LOSSY_RANGE_SIZE)) {
+ return -1;
+ }
+
+ pthread_mutex_lock(&c->connections_mutex);
+ ++c->connection_use_counter;
+ pthread_mutex_unlock(&c->connections_mutex);
+
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ int ret = -1;
+
+ if (conn) {
+ pthread_mutex_lock(&conn->mutex);
+ uint32_t buffer_start = conn->recv_array.buffer_start;
+ uint32_t buffer_end = conn->send_array.buffer_end;
+ pthread_mutex_unlock(&conn->mutex);
+ ret = send_data_packet_helper(c, crypt_connection_id, buffer_start, buffer_end, data, length);
+ }
+
+ pthread_mutex_lock(&c->connections_mutex);
+ --c->connection_use_counter;
+ pthread_mutex_unlock(&c->connections_mutex);
+
+ return ret;
+}
+
+/* Kill a crypto connection.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int crypto_kill(Net_Crypto *c, int crypt_connection_id)
+{
+ while (1) { /* TODO(irungentoo): is this really the best way to do this? */
+ pthread_mutex_lock(&c->connections_mutex);
+
+ if (!c->connection_use_counter) {
+ break;
+ }
+
+ pthread_mutex_unlock(&c->connections_mutex);
+ }
+
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ int ret = -1;
+
+ if (conn) {
+ if (conn->status == CRYPTO_CONN_ESTABLISHED) {
+ send_kill_packet(c, crypt_connection_id);
+ }
+
+ pthread_mutex_lock(&c->tcp_mutex);
+ kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp);
+ pthread_mutex_unlock(&c->tcp_mutex);
+
+ bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv4, crypt_connection_id);
+ bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv6, crypt_connection_id);
+ clear_temp_packet(c, crypt_connection_id);
+ clear_buffer(&conn->send_array);
+ clear_buffer(&conn->recv_array);
+ ret = wipe_crypto_connection(c, crypt_connection_id);
+ }
+
+ pthread_mutex_unlock(&c->connections_mutex);
+
+ return ret;
+}
+
+/* return one of CRYPTO_CONN_* values indicating the state of the connection.
+ *
+ * sets direct_connected to 1 if connection connects directly to other, 0 if it isn't.
+ * sets online_tcp_relays to the number of connected tcp relays this connection has.
+ */
+unsigned int crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, bool *direct_connected,
+ unsigned int *online_tcp_relays)
+{
+ Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
+
+ if (conn == 0) {
+ return CRYPTO_CONN_NO_CONNECTION;
+ }
+
+ if (direct_connected) {
+ *direct_connected = 0;
+
+ uint64_t current_time = unix_time();
+
+ if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) {
+ *direct_connected = 1;
+ }
+
+ if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev6) > current_time) {
+ *direct_connected = 1;
+ }
+ }
+
+ if (online_tcp_relays) {
+ *online_tcp_relays = tcp_connection_to_online_tcp_relays(c->tcp_c, conn->connection_number_tcp);
+ }
+
+ return conn->status;
+}
+
+void new_keys(Net_Crypto *c)
+{
+ crypto_new_keypair(c->self_public_key, c->self_secret_key);
+}
+
+/* Save the public and private keys to the keys array.
+ * Length must be CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE.
+ *
+ * TODO(irungentoo): Save only secret key.
+ */
+void save_keys(const Net_Crypto *c, uint8_t *keys)
+{
+ memcpy(keys, c->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(keys + CRYPTO_PUBLIC_KEY_SIZE, c->self_secret_key, CRYPTO_SECRET_KEY_SIZE);
+}
+
+/* Load the secret key.
+ * Length must be CRYPTO_SECRET_KEY_SIZE.
+ */
+void load_secret_key(Net_Crypto *c, const uint8_t *sk)
+{
+ memcpy(c->self_secret_key, sk, CRYPTO_SECRET_KEY_SIZE);
+ crypto_derive_public_key(c->self_public_key, c->self_secret_key);
+}
+
+/* Run this to (re)initialize net_crypto.
+ * Sets all the global connection variables to their default values.
+ */
+Net_Crypto *new_net_crypto(Logger *log, DHT *dht, TCP_Proxy_Info *proxy_info)
+{
+ unix_time_update();
+
+ if (dht == NULL) {
+ return NULL;
+ }
+
+ Net_Crypto *temp = (Net_Crypto *)calloc(1, sizeof(Net_Crypto));
+
+ if (temp == NULL) {
+ return NULL;
+ }
+
+ temp->log = log;
+
+ temp->tcp_c = new_tcp_connections(dht->self_secret_key, proxy_info);
+
+ if (temp->tcp_c == NULL) {
+ free(temp);
+ return NULL;
+ }
+
+ set_packet_tcp_connection_callback(temp->tcp_c, &tcp_data_callback, temp);
+ set_oob_packet_tcp_connection_callback(temp->tcp_c, &tcp_oob_callback, temp);
+
+ if (create_recursive_mutex(&temp->tcp_mutex) != 0 ||
+ pthread_mutex_init(&temp->connections_mutex, NULL) != 0) {
+ kill_tcp_connections(temp->tcp_c);
+ free(temp);
+ return NULL;
+ }
+
+ temp->dht = dht;
+
+ new_keys(temp);
+ new_symmetric_key(temp->secret_symmetric_key);
+
+ temp->current_sleep_time = CRYPTO_SEND_PACKET_INTERVAL;
+
+ networking_registerhandler(dht->net, NET_PACKET_COOKIE_REQUEST, &udp_handle_cookie_request, temp);
+ networking_registerhandler(dht->net, NET_PACKET_COOKIE_RESPONSE, &udp_handle_packet, temp);
+ networking_registerhandler(dht->net, NET_PACKET_CRYPTO_HS, &udp_handle_packet, temp);
+ networking_registerhandler(dht->net, NET_PACKET_CRYPTO_DATA, &udp_handle_packet, temp);
+
+ bs_list_init(&temp->ip_port_list, sizeof(IP_Port), 8);
+
+ return temp;
+}
+
+static void kill_timedout(Net_Crypto *c, void *userdata)
+{
+ uint32_t i;
+ //uint64_t temp_time = current_time_monotonic();
+
+ for (i = 0; i < c->crypto_connections_length; ++i) {
+ Crypto_Connection *conn = get_crypto_connection(c, i);
+
+ if (conn == 0) {
+ return;
+ }
+
+ if (conn->status == CRYPTO_CONN_NO_CONNECTION) {
+ continue;
+ }
+
+ if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT
+ || conn->status == CRYPTO_CONN_NOT_CONFIRMED) {
+ if (conn->temp_packet_num_sent < MAX_NUM_SENDPACKET_TRIES) {
+ continue;
+ }
+
+ connection_kill(c, i, userdata);
+ }
+
+#if 0
+
+ if (conn->status == CRYPTO_CONN_ESTABLISHED) {
+ // TODO(irungentoo): add a timeout here?
+ }
+
+#endif
+ }
+}
+
+/* return the optimal interval in ms for running do_net_crypto.
+ */
+uint32_t crypto_run_interval(const Net_Crypto *c)
+{
+ return c->current_sleep_time;
+}
+
+/* Main loop. */
+void do_net_crypto(Net_Crypto *c, void *userdata)
+{
+ unix_time_update();
+ kill_timedout(c, userdata);
+ do_tcp(c, userdata);
+ send_crypto_packets(c);
+}
+
+void kill_net_crypto(Net_Crypto *c)
+{
+ uint32_t i;
+
+ for (i = 0; i < c->crypto_connections_length; ++i) {
+ crypto_kill(c, i);
+ }
+
+ pthread_mutex_destroy(&c->tcp_mutex);
+ pthread_mutex_destroy(&c->connections_mutex);
+
+ kill_tcp_connections(c->tcp_c);
+ bs_list_free(&c->ip_port_list);
+ networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_REQUEST, NULL, NULL);
+ networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_RESPONSE, NULL, NULL);
+ networking_registerhandler(c->dht->net, NET_PACKET_CRYPTO_HS, NULL, NULL);
+ networking_registerhandler(c->dht->net, NET_PACKET_CRYPTO_DATA, NULL, NULL);
+ crypto_memzero(c, sizeof(Net_Crypto));
+ free(c);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/net_crypto.h b/protocols/Tox/libtox/src/toxcore/net_crypto.h
new file mode 100644
index 0000000000..5ec5ca94fb
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/net_crypto.h
@@ -0,0 +1,428 @@
+/*
+ * Functions for the core network crypto.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef NET_CRYPTO_H
+#define NET_CRYPTO_H
+
+#include "DHT.h"
+#include "LAN_discovery.h"
+#include "TCP_connection.h"
+#include "logger.h"
+
+#include <pthread.h>
+
+#define CRYPTO_CONN_NO_CONNECTION 0
+#define CRYPTO_CONN_COOKIE_REQUESTING 1 //send cookie request packets
+#define CRYPTO_CONN_HANDSHAKE_SENT 2 //send handshake packets
+#define CRYPTO_CONN_NOT_CONFIRMED 3 //send handshake packets, we have received one from the other
+#define CRYPTO_CONN_ESTABLISHED 4
+
+/* Maximum size of receiving and sending packet buffers. */
+#define CRYPTO_PACKET_BUFFER_SIZE 32768 /* Must be a power of 2 */
+
+/* Minimum packet rate per second. */
+#define CRYPTO_PACKET_MIN_RATE 4.0
+
+/* Minimum packet queue max length. */
+#define CRYPTO_MIN_QUEUE_LENGTH 64
+
+/* Maximum total size of packets that net_crypto sends. */
+#define MAX_CRYPTO_PACKET_SIZE 1400
+
+#define CRYPTO_DATA_PACKET_MIN_SIZE (1 + sizeof(uint16_t) + (sizeof(uint32_t) + sizeof(uint32_t)) + CRYPTO_MAC_SIZE)
+
+/* Max size of data in packets */
+#define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - CRYPTO_DATA_PACKET_MIN_SIZE)
+
+/* Interval in ms between sending cookie request/handshake packets. */
+#define CRYPTO_SEND_PACKET_INTERVAL 1000
+
+/* The maximum number of times we try to send the cookie request and handshake
+ before giving up. */
+#define MAX_NUM_SENDPACKET_TRIES 8
+
+/* The timeout of no received UDP packets before the direct UDP connection is considered dead. */
+#define UDP_DIRECT_TIMEOUT ((MAX_NUM_SENDPACKET_TRIES * CRYPTO_SEND_PACKET_INTERVAL) / 1000)
+
+#define PACKET_ID_PADDING 0 /* Denotes padding */
+#define PACKET_ID_REQUEST 1 /* Used to request unreceived packets */
+#define PACKET_ID_KILL 2 /* Used to kill connection */
+
+/* Packet ids 0 to CRYPTO_RESERVED_PACKETS - 1 are reserved for use by net_crypto. */
+#define CRYPTO_RESERVED_PACKETS 16
+
+#define MAX_TCP_CONNECTIONS 64
+#define MAX_TCP_RELAYS_PEER 4
+
+/* All packets starting with a byte in this range are considered lossy packets. */
+#define PACKET_ID_LOSSY_RANGE_START 192
+#define PACKET_ID_LOSSY_RANGE_SIZE 63
+
+#define CRYPTO_MAX_PADDING 8 /* All packets will be padded a number of bytes based on this number. */
+
+/* Base current transfer speed on last CONGESTION_QUEUE_ARRAY_SIZE number of points taken
+ at the dT defined in net_crypto.c */
+#define CONGESTION_QUEUE_ARRAY_SIZE 12
+#define CONGESTION_LAST_SENT_ARRAY_SIZE (CONGESTION_QUEUE_ARRAY_SIZE * 2)
+
+/* Default connection ping in ms. */
+#define DEFAULT_PING_CONNECTION 1000
+#define DEFAULT_TCP_PING_CONNECTION 500
+
+typedef struct {
+ uint64_t sent_time;
+ uint16_t length;
+ uint8_t data[MAX_CRYPTO_DATA_SIZE];
+} Packet_Data;
+
+typedef struct {
+ Packet_Data *buffer[CRYPTO_PACKET_BUFFER_SIZE];
+ uint32_t buffer_start;
+ uint32_t buffer_end; /* packet numbers in array: {buffer_start, buffer_end) */
+} Packets_Array;
+
+typedef struct {
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The real public key of the peer. */
+ uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */
+ uint8_t sent_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of sent packets. */
+ uint8_t sessionpublic_key[CRYPTO_PUBLIC_KEY_SIZE]; /* Our public key for this session. */
+ uint8_t sessionsecret_key[CRYPTO_SECRET_KEY_SIZE]; /* Our private key for this session. */
+ uint8_t peersessionpublic_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The public key of the peer. */
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; /* The precomputed shared key from encrypt_precompute. */
+ uint8_t status; /* 0 if no connection, 1 we are sending cookie request packets,
+ * 2 if we are sending handshake packets
+ * 3 if connection is not confirmed yet (we have received a handshake but no data packets yet),
+ * 4 if the connection is established.
+ */
+ uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */
+ uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The dht public key of the peer */
+
+ uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */
+ uint16_t temp_packet_length;
+ uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */
+ uint32_t temp_packet_num_sent;
+
+ IP_Port ip_portv4; /* The ip and port to contact this guy directly.*/
+ IP_Port ip_portv6;
+ uint64_t direct_lastrecv_timev4; /* The Time at which we last received a direct packet in ms. */
+ uint64_t direct_lastrecv_timev6;
+
+ uint64_t last_tcp_sent; /* Time the last TCP packet was sent. */
+
+ Packets_Array send_array;
+ Packets_Array recv_array;
+
+ int (*connection_status_callback)(void *object, int id, uint8_t status, void *userdata);
+ void *connection_status_callback_object;
+ int connection_status_callback_id;
+
+ int (*connection_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
+ void *connection_data_callback_object;
+ int connection_data_callback_id;
+
+ int (*connection_lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
+ void *connection_lossy_data_callback_object;
+ int connection_lossy_data_callback_id;
+
+ uint64_t last_request_packet_sent;
+ uint64_t direct_send_attempt_time;
+
+ uint32_t packet_counter;
+ double packet_recv_rate;
+ uint64_t packet_counter_set;
+
+ double packet_send_rate;
+ uint32_t packets_left;
+ uint64_t last_packets_left_set;
+ double last_packets_left_rem;
+
+ double packet_send_rate_requested;
+ uint32_t packets_left_requested;
+ uint64_t last_packets_left_requested_set;
+ double last_packets_left_requested_rem;
+
+ uint32_t last_sendqueue_size[CONGESTION_QUEUE_ARRAY_SIZE], last_sendqueue_counter;
+ long signed int last_num_packets_sent[CONGESTION_LAST_SENT_ARRAY_SIZE],
+ last_num_packets_resent[CONGESTION_LAST_SENT_ARRAY_SIZE];
+ uint32_t packets_sent, packets_resent;
+ uint64_t last_congestion_event;
+ uint64_t rtt_time;
+
+ /* TCP_connection connection_number */
+ unsigned int connection_number_tcp;
+
+ uint8_t maximum_speed_reached;
+
+ pthread_mutex_t mutex;
+
+ void (*dht_pk_callback)(void *data, int32_t number, const uint8_t *dht_public_key, void *userdata);
+ void *dht_pk_callback_object;
+ uint32_t dht_pk_callback_number;
+} Crypto_Connection;
+
+typedef struct {
+ IP_Port source;
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The real public key of the peer. */
+ uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The dht public key of the peer. */
+ uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */
+ uint8_t peersessionpublic_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The public key of the peer. */
+ uint8_t *cookie;
+ uint8_t cookie_length;
+} New_Connection;
+
+typedef struct {
+ Logger *log;
+
+ DHT *dht;
+ TCP_Connections *tcp_c;
+
+ Crypto_Connection *crypto_connections;
+ pthread_mutex_t tcp_mutex;
+
+ pthread_mutex_t connections_mutex;
+ unsigned int connection_use_counter;
+
+ uint32_t crypto_connections_length; /* Length of connections array. */
+
+ /* Our public and secret keys. */
+ uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
+
+ /* The secret key used for cookies */
+ uint8_t secret_symmetric_key[CRYPTO_SYMMETRIC_KEY_SIZE];
+
+ int (*new_connection_callback)(void *object, New_Connection *n_c);
+ void *new_connection_callback_object;
+
+ /* The current optimal sleep time */
+ uint32_t current_sleep_time;
+
+ BS_LIST ip_port_list;
+} Net_Crypto;
+
+
+/* Set function to be called when someone requests a new connection to us.
+ *
+ * The set function should return -1 on failure and 0 on success.
+ *
+ * n_c is only valid for the duration of the function call.
+ */
+void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c),
+ void *object);
+
+/* Accept a crypto connection.
+ *
+ * return -1 on failure.
+ * return connection id on success.
+ */
+int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c);
+
+/* Create a crypto connection.
+ * If one to that real public key already exists, return it.
+ *
+ * return -1 on failure.
+ * return connection id on success.
+ */
+int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const uint8_t *dht_public_key);
+
+/* Set the direct ip of the crypto connection.
+ *
+ * Connected is 0 if we are not sure we are connected to that person, 1 if we are sure.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, bool connected);
+
+/* Set function to be called when connection with crypt_connection_id goes connects/disconnects.
+ *
+ * The set function should return -1 on failure and 0 on success.
+ * Note that if this function is set, the connection will clear itself on disconnect.
+ * Object and id will be passed to this function untouched.
+ * status is 1 if the connection is going online, 0 if it is going offline.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int connection_status_handler(const Net_Crypto *c, int crypt_connection_id,
+ int (*connection_status_callback)(void *object, int id, uint8_t status, void *userdata), void *object, int id);
+
+/* Set function to be called when connection with crypt_connection_id receives a lossless data packet of length.
+ *
+ * The set function should return -1 on failure and 0 on success.
+ * Object and id will be passed to this function untouched.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int connection_data_handler(const Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object,
+ int id, const uint8_t *data, uint16_t length, void *userdata), void *object, int id);
+
+
+/* Set function to be called when connection with crypt_connection_id receives a lossy data packet of length.
+ *
+ * The set function should return -1 on failure and 0 on success.
+ * Object and id will be passed to this function untouched.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id,
+ int (*connection_lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata),
+ void *object,
+ int id);
+
+/* Set the function for this friend that will be callbacked with object and number if
+ * the friend sends us a different dht public key than we have associated to him.
+ *
+ * If this function is called, the connection should be recreated with the new public key.
+ *
+ * object and number will be passed as argument to this function.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, void (*function)(void *data, int32_t number,
+ const uint8_t *dht_public_key, void *userdata), void *object, uint32_t number);
+
+/* returns the number of packet slots left in the sendbuffer.
+ * return 0 if failure.
+ */
+uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connection_id);
+
+/* Return 1 if max speed was reached for this connection (no more data can be physically through the pipe).
+ * Return 0 if it wasn't reached.
+ */
+bool max_speed_reached(Net_Crypto *c, int crypt_connection_id);
+
+/* Sends a lossless cryptopacket.
+ *
+ * return -1 if data could not be put in packet queue.
+ * return positive packet number if data was put into the queue.
+ *
+ * The first byte of data must be in the CRYPTO_RESERVED_PACKETS to PACKET_ID_LOSSY_RANGE_START range.
+ *
+ * congestion_control: should congestion control apply to this packet?
+ */
+int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length,
+ uint8_t congestion_control);
+
+/* Check if packet_number was received by the other side.
+ *
+ * packet_number must be a valid packet number of a packet sent on this connection.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int cryptpacket_received(Net_Crypto *c, int crypt_connection_id, uint32_t packet_number);
+
+/* return -1 on failure.
+ * return 0 on success.
+ *
+ * Sends a lossy cryptopacket. (first byte must in the PACKET_ID_LOSSY_RANGE_*)
+ */
+int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length);
+
+/* Add a tcp relay, associating it to a crypt_connection_id.
+ *
+ * return 0 if it was added.
+ * return -1 if it wasn't.
+ */
+int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, const uint8_t *public_key);
+
+/* Add a tcp relay to the array.
+ *
+ * return 0 if it was added.
+ * return -1 if it wasn't.
+ */
+int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, const uint8_t *public_key);
+
+/* Return a random TCP connection number for use in send_tcp_onion_request.
+ *
+ * return TCP connection number on success.
+ * return -1 on failure.
+ */
+int get_random_tcp_con_number(Net_Crypto *c);
+
+/* Send an onion packet via the TCP relay corresponding to TCP_conn_number.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int send_tcp_onion_request(Net_Crypto *c, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length);
+
+/* Copy a maximum of num TCP relays we are connected to to tcp_relays.
+ * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.
+ *
+ * return number of relays copied to tcp_relays on success.
+ * return 0 on failure.
+ */
+unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num);
+
+/* Kill a crypto connection.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int crypto_kill(Net_Crypto *c, int crypt_connection_id);
+
+/* return one of CRYPTO_CONN_* values indicating the state of the connection.
+ *
+ * sets direct_connected to 1 if connection connects directly to other, 0 if it isn't.
+ * sets online_tcp_relays to the number of connected tcp relays this connection has.
+ */
+unsigned int crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, bool *direct_connected,
+ unsigned int *online_tcp_relays);
+
+/* Generate our public and private keys.
+ * Only call this function the first time the program starts.
+ */
+void new_keys(Net_Crypto *c);
+
+/* Save the public and private keys to the keys array.
+ * Length must be CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE.
+ */
+void save_keys(const Net_Crypto *c, uint8_t *keys);
+
+/* Load the secret key.
+ * Length must be CRYPTO_SECRET_KEY_SIZE.
+ */
+void load_secret_key(Net_Crypto *c, const uint8_t *sk);
+
+/* Create new instance of Net_Crypto.
+ * Sets all the global connection variables to their default values.
+ */
+Net_Crypto *new_net_crypto(Logger *log, DHT *dht, TCP_Proxy_Info *proxy_info);
+
+/* return the optimal interval in ms for running do_net_crypto.
+ */
+uint32_t crypto_run_interval(const Net_Crypto *c);
+
+/* Main loop. */
+void do_net_crypto(Net_Crypto *c, void *userdata);
+
+void kill_net_crypto(Net_Crypto *c);
+
+
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxcore/network.c b/protocols/Tox/libtox/src/toxcore/network.c
new file mode 100644
index 0000000000..5c43bf5779
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/network.c
@@ -0,0 +1,1446 @@
+/*
+ * Functions for the core networking.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define _DARWIN_C_SOURCE
+#define _XOPEN_SOURCE 600
+
+#if defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_WINXP
+#define _WIN32_WINNT 0x501
+#endif
+
+#include "network.h"
+
+#include "logger.h"
+#include "util.h"
+
+#include <assert.h>
+#ifdef __APPLE__
+#include <mach/clock.h>
+#include <mach/mach.h>
+#endif
+
+#ifndef IPV6_ADD_MEMBERSHIP
+#ifdef IPV6_JOIN_GROUP
+#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
+#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
+#endif
+#endif
+
+#if !(defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#else
+
+#ifndef IPV6_V6ONLY
+#define IPV6_V6ONLY 27
+#endif
+
+#ifndef EWOULDBLOCK
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#endif
+
+static const char *inet_ntop(Family family, const void *addr, char *buf, size_t bufsize)
+{
+ if (family == TOX_AF_INET) {
+ struct sockaddr_in saddr;
+ memset(&saddr, 0, sizeof(saddr));
+
+ saddr.sin_family = AF_INET;
+ saddr.sin_addr = *(const struct in_addr *)addr;
+
+ DWORD len = bufsize;
+
+ if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), NULL, buf, &len)) {
+ return NULL;
+ }
+
+ return buf;
+ } else if (family == TOX_AF_INET6) {
+ struct sockaddr_in6 saddr;
+ memset(&saddr, 0, sizeof(saddr));
+
+ saddr.sin6_family = AF_INET6;
+ saddr.sin6_addr = *(const struct in6_addr *)addr;
+
+ DWORD len = bufsize;
+
+ if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), NULL, buf, &len)) {
+ return NULL;
+ }
+
+ return buf;
+ }
+
+ return NULL;
+}
+
+static int inet_pton(Family family, const char *addrString, void *addrbuf)
+{
+ if (family == TOX_AF_INET) {
+ struct sockaddr_in saddr;
+ memset(&saddr, 0, sizeof(saddr));
+
+ INT len = sizeof(saddr);
+
+ if (WSAStringToAddress((LPTSTR)addrString, AF_INET, NULL, (LPSOCKADDR)&saddr, &len)) {
+ return 0;
+ }
+
+ *(struct in_addr *)addrbuf = saddr.sin_addr;
+
+ return 1;
+ } else if (family == TOX_AF_INET6) {
+ struct sockaddr_in6 saddr;
+ memset(&saddr, 0, sizeof(saddr));
+
+ INT len = sizeof(saddr);
+
+ if (WSAStringToAddress((LPTSTR)addrString, AF_INET6, NULL, (LPSOCKADDR)&saddr, &len)) {
+ return 0;
+ }
+
+ *(struct in6_addr *)addrbuf = saddr.sin6_addr;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+#endif
+
+#if TOX_INET6_ADDRSTRLEN < INET6_ADDRSTRLEN
+#error TOX_INET6_ADDRSTRLEN should be greater or equal to INET6_ADDRSTRLEN (#INET6_ADDRSTRLEN)
+#endif
+
+#if TOX_INET_ADDRSTRLEN < INET_ADDRSTRLEN
+#error TOX_INET_ADDRSTRLEN should be greater or equal to INET_ADDRSTRLEN (#INET_ADDRSTRLEN)
+#endif
+
+static int make_proto(int proto);
+static int make_socktype(int type);
+static int make_family(int tox_family);
+static int make_tox_family(int family);
+
+static void get_ip4(IP4 *result, const struct in_addr *addr)
+{
+ result->uint32 = addr->s_addr;
+}
+
+static void get_ip6(IP6 *result, const struct in6_addr *addr)
+{
+ assert(sizeof(result->uint8) == sizeof(addr->s6_addr));
+ memcpy(result->uint8, addr->s6_addr, sizeof(result->uint8));
+}
+
+static void fill_addr4(IP4 ip, struct in_addr *addr)
+{
+ addr->s_addr = ip.uint32;
+}
+
+static void fill_addr6(IP6 ip, struct in6_addr *addr)
+{
+ assert(sizeof(ip.uint8) == sizeof(addr->s6_addr));
+ memcpy(addr->s6_addr, ip.uint8, sizeof(ip.uint8));
+}
+
+#if !defined(INADDR_LOOPBACK)
+#define INADDR_LOOPBACK 0x7f000001
+#endif
+
+const IP4 IP4_BROADCAST = { INADDR_BROADCAST };
+const IP6 IP6_BROADCAST = {
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
+};
+
+IP4 get_ip4_loopback()
+{
+ IP4 loopback;
+ loopback.uint32 = htonl(INADDR_LOOPBACK);
+ return loopback;
+}
+
+IP6 get_ip6_loopback()
+{
+ IP6 loopback;
+ get_ip6(&loopback, &in6addr_loopback);
+ return loopback;
+}
+
+/* Check if socket is valid.
+ *
+ * return 1 if valid
+ * return 0 if not valid
+ */
+int sock_valid(Socket sock)
+{
+#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
+
+ if (sock == INVALID_SOCKET) {
+#else
+
+ if (sock < 0) {
+#endif
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Close the socket.
+ */
+void kill_sock(Socket sock)
+{
+#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
+ closesocket(sock);
+#else
+ close(sock);
+#endif
+}
+
+/* Set socket as nonblocking
+ *
+ * return 1 on success
+ * return 0 on failure
+ */
+int set_socket_nonblock(Socket sock)
+{
+#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
+ u_long mode = 1;
+ return (ioctlsocket(sock, FIONBIO, &mode) == 0);
+#else
+ return (fcntl(sock, F_SETFL, O_NONBLOCK, 1) == 0);
+#endif
+}
+
+/* Set socket to not emit SIGPIPE
+ *
+ * return 1 on success
+ * return 0 on failure
+ */
+int set_socket_nosigpipe(Socket sock)
+{
+#if defined(__MACH__)
+ int set = 1;
+ return (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (const char *)&set, sizeof(int)) == 0);
+#else
+ return 1;
+#endif
+}
+
+/* Enable SO_REUSEADDR on socket.
+ *
+ * return 1 on success
+ * return 0 on failure
+ */
+int set_socket_reuseaddr(Socket sock)
+{
+ int set = 1;
+ return (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&set, sizeof(set)) == 0);
+}
+
+/* Set socket to dual (IPv4 + IPv6 socket)
+ *
+ * return 1 on success
+ * return 0 on failure
+ */
+int set_socket_dualstack(Socket sock)
+{
+ int ipv6only = 0;
+ socklen_t optsize = sizeof(ipv6only);
+ int res = getsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, &optsize);
+
+ if ((res == 0) && (ipv6only == 0)) {
+ return 1;
+ }
+
+ ipv6only = 0;
+ return (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&ipv6only, sizeof(ipv6only)) == 0);
+}
+
+
+/* return current UNIX time in microseconds (us). */
+static uint64_t current_time_actual(void)
+{
+ uint64_t time;
+#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
+ /* This probably works fine */
+ FILETIME ft;
+ GetSystemTimeAsFileTime(&ft);
+ time = ft.dwHighDateTime;
+ time <<= 32;
+ time |= ft.dwLowDateTime;
+ time -= 116444736000000000ULL;
+ return time / 10;
+#else
+ struct timeval a;
+ gettimeofday(&a, NULL);
+ time = 1000000ULL * a.tv_sec + a.tv_usec;
+ return time;
+#endif
+}
+
+
+#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
+static uint64_t last_monotime;
+static uint64_t add_monotime;
+#endif
+
+/* return current monotonic time in milliseconds (ms). */
+uint64_t current_time_monotonic(void)
+{
+ uint64_t time;
+#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
+ uint64_t old_add_monotime = add_monotime;
+ time = (uint64_t)GetTickCount() + add_monotime;
+
+ /* Check if time has decreased because of 32 bit wrap from GetTickCount(), while avoiding false positives from race
+ * conditions when multiple threads call this function at once */
+ if (time + 0x10000 < last_monotime) {
+ uint32_t add = ~0;
+ /* use old_add_monotime rather than simply incrementing add_monotime, to handle the case that many threads
+ * simultaneously detect an overflow */
+ add_monotime = old_add_monotime + add;
+ time += add;
+ }
+
+ last_monotime = time;
+#else
+ struct timespec monotime;
+#if defined(__linux__) && defined(CLOCK_MONOTONIC_RAW)
+ clock_gettime(CLOCK_MONOTONIC_RAW, &monotime);
+#elif defined(__APPLE__)
+ clock_serv_t muhclock;
+ mach_timespec_t machtime;
+
+ host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &muhclock);
+ clock_get_time(muhclock, &machtime);
+ mach_port_deallocate(mach_task_self(), muhclock);
+
+ monotime.tv_sec = machtime.tv_sec;
+ monotime.tv_nsec = machtime.tv_nsec;
+#else
+ clock_gettime(CLOCK_MONOTONIC, &monotime);
+#endif
+ time = 1000ULL * monotime.tv_sec + (monotime.tv_nsec / 1000000ULL);
+#endif
+ return time;
+}
+
+static uint32_t data_0(uint16_t buflen, const uint8_t *buffer)
+{
+ return buflen > 4 ? net_ntohl(*(const uint32_t *)&buffer[1]) : 0;
+}
+static uint32_t data_1(uint16_t buflen, const uint8_t *buffer)
+{
+ return buflen > 7 ? net_ntohl(*(const uint32_t *)&buffer[5]) : 0;
+}
+
+static void loglogdata(Logger *log, const char *message, const uint8_t *buffer,
+ uint16_t buflen, IP_Port ip_port, int res)
+{
+ char ip_str[IP_NTOA_LEN];
+
+ if (res < 0) { /* Windows doesn't necessarily know %zu */
+ LOGGER_TRACE(log, "[%2u] %s %3hu%c %s:%hu (%u: %s) | %04x%04x",
+ buffer[0], message, (buflen < 999 ? (uint16_t)buflen : 999), 'E',
+ ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port.port), errno,
+ strerror(errno), data_0(buflen, buffer), data_1(buflen, buffer));
+ } else if ((res > 0) && ((size_t)res <= buflen)) {
+ LOGGER_TRACE(log, "[%2u] %s %3zu%c %s:%hu (%u: %s) | %04x%04x",
+ buffer[0], message, (res < 999 ? (size_t)res : 999), ((size_t)res < buflen ? '<' : '='),
+ ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port.port), 0, "OK",
+ data_0(buflen, buffer), data_1(buflen, buffer));
+ } else { /* empty or overwrite */
+ LOGGER_TRACE(log, "[%2u] %s %zu%c%zu %s:%hu (%u: %s) | %04x%04x",
+ buffer[0], message, (size_t)res, (!res ? '!' : '>'), buflen,
+ ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port.port), 0, "OK",
+ data_0(buflen, buffer), data_1(buflen, buffer));
+ }
+}
+
+/* Basic network functions:
+ * Function to send packet(data) of length length to ip_port.
+ */
+int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint16_t length)
+{
+ if (net->family == 0) { /* Socket not initialized */
+ return -1;
+ }
+
+ /* socket TOX_AF_INET, but target IP NOT: can't send */
+ if ((net->family == TOX_AF_INET) && (ip_port.ip.family != TOX_AF_INET)) {
+ return -1;
+ }
+
+ struct sockaddr_storage addr;
+
+ size_t addrsize = 0;
+
+ if (ip_port.ip.family == TOX_AF_INET) {
+ if (net->family == TOX_AF_INET6) {
+ /* must convert to IPV4-in-IPV6 address */
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
+
+ addrsize = sizeof(struct sockaddr_in6);
+ addr6->sin6_family = AF_INET6;
+ addr6->sin6_port = ip_port.port;
+
+ /* there should be a macro for this in a standards compliant
+ * environment, not found */
+ IP6 ip6;
+
+ ip6.uint32[0] = 0;
+ ip6.uint32[1] = 0;
+ ip6.uint32[2] = net_htonl(0xFFFF);
+ ip6.uint32[3] = ip_port.ip.ip4.uint32;
+ fill_addr6(ip6, &addr6->sin6_addr);
+
+ addr6->sin6_flowinfo = 0;
+ addr6->sin6_scope_id = 0;
+ } else {
+ struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
+
+ addrsize = sizeof(struct sockaddr_in);
+ addr4->sin_family = AF_INET;
+ fill_addr4(ip_port.ip.ip4, &addr4->sin_addr);
+ addr4->sin_port = ip_port.port;
+ }
+ } else if (ip_port.ip.family == TOX_AF_INET6) {
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
+
+ addrsize = sizeof(struct sockaddr_in6);
+ addr6->sin6_family = AF_INET6;
+ addr6->sin6_port = ip_port.port;
+ fill_addr6(ip_port.ip.ip6, &addr6->sin6_addr);
+
+ addr6->sin6_flowinfo = 0;
+ addr6->sin6_scope_id = 0;
+ } else {
+ /* unknown address type*/
+ return -1;
+ }
+
+ int res = sendto(net->sock, (const char *) data, length, 0, (struct sockaddr *)&addr, addrsize);
+
+ loglogdata(net->log, "O=>", data, length, ip_port, res);
+
+ return res;
+}
+
+/* Function to receive data
+ * ip and port of sender is put into ip_port.
+ * Packet data is put into data.
+ * Packet length is put into length.
+ */
+static int receivepacket(Logger *log, Socket sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
+{
+ memset(ip_port, 0, sizeof(IP_Port));
+ struct sockaddr_storage addr;
+#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
+ int addrlen = sizeof(addr);
+#else
+ socklen_t addrlen = sizeof(addr);
+#endif
+ *length = 0;
+ int fail_or_len = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen);
+
+ if (fail_or_len < 0) {
+
+ if (fail_or_len < 0 && errno != EWOULDBLOCK) {
+ LOGGER_ERROR(log, "Unexpected error reading from socket: %u, %s\n", errno, strerror(errno));
+ }
+
+ return -1; /* Nothing received. */
+ }
+
+ *length = (uint32_t)fail_or_len;
+
+ if (addr.ss_family == AF_INET) {
+ struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
+
+ ip_port->ip.family = make_tox_family(addr_in->sin_family);
+ get_ip4(&ip_port->ip.ip4, &addr_in->sin_addr);
+ ip_port->port = addr_in->sin_port;
+ } else if (addr.ss_family == AF_INET6) {
+ struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr;
+ ip_port->ip.family = make_tox_family(addr_in6->sin6_family);
+ get_ip6(&ip_port->ip.ip6, &addr_in6->sin6_addr);
+ ip_port->port = addr_in6->sin6_port;
+
+ if (IPV6_IPV4_IN_V6(ip_port->ip.ip6)) {
+ ip_port->ip.family = TOX_AF_INET;
+ ip_port->ip.ip4.uint32 = ip_port->ip.ip6.uint32[3];
+ }
+ } else {
+ return -1;
+ }
+
+ loglogdata(log, "=>O", data, MAX_UDP_PACKET_SIZE, *ip_port, *length);
+
+ return 0;
+}
+
+void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object)
+{
+ net->packethandlers[byte].function = cb;
+ net->packethandlers[byte].object = object;
+}
+
+void networking_poll(Networking_Core *net, void *userdata)
+{
+ if (net->family == 0) { /* Socket not initialized */
+ return;
+ }
+
+ unix_time_update();
+
+ IP_Port ip_port;
+ uint8_t data[MAX_UDP_PACKET_SIZE];
+ uint32_t length;
+
+ while (receivepacket(net->log, net->sock, &ip_port, data, &length) != -1) {
+ if (length < 1) {
+ continue;
+ }
+
+ if (!(net->packethandlers[data[0]].function)) {
+ LOGGER_WARNING(net->log, "[%02u] -- Packet has no handler", data[0]);
+ continue;
+ }
+
+ net->packethandlers[data[0]].function(net->packethandlers[data[0]].object, ip_port, data, length, userdata);
+ }
+}
+
+#ifndef VANILLA_NACL
+/* Used for sodium_init() */
+#include <sodium.h>
+#endif
+
+static uint8_t at_startup_ran = 0;
+int networking_at_startup(void)
+{
+ if (at_startup_ran != 0) {
+ return 0;
+ }
+
+#ifndef VANILLA_NACL
+
+#ifdef USE_RANDOMBYTES_STIR
+ randombytes_stir();
+#else
+
+ if (sodium_init() == -1) {
+ return -1;
+ }
+
+#endif /*USE_RANDOMBYTES_STIR*/
+
+#endif/*VANILLA_NACL*/
+
+#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
+ WSADATA wsaData;
+
+ if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
+ return -1;
+ }
+
+#endif
+ srand((uint32_t)current_time_actual());
+ at_startup_ran = 1;
+ return 0;
+}
+
+/* TODO(irungentoo): Put this somewhere */
+#if 0
+static void at_shutdown(void)
+{
+#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
+ WSACleanup();
+#endif
+}
+#endif
+
+/* Initialize networking.
+ * Added for reverse compatibility with old new_networking calls.
+ */
+Networking_Core *new_networking(Logger *log, IP ip, uint16_t port)
+{
+ return new_networking_ex(log, ip, port, port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM), 0);
+}
+
+/* Initialize networking.
+ * Bind to ip and port.
+ * ip must be in network order EX: 127.0.0.1 = (7F000001).
+ * port is in host byte order (this means don't worry about it).
+ *
+ * return Networking_Core object if no problems
+ * return NULL if there are problems.
+ *
+ * If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other.
+ */
+Networking_Core *new_networking_ex(Logger *log, IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error)
+{
+ /* If both from and to are 0, use default port range
+ * If one is 0 and the other is non-0, use the non-0 value as only port
+ * If from > to, swap
+ */
+ if (port_from == 0 && port_to == 0) {
+ port_from = TOX_PORTRANGE_FROM;
+ port_to = TOX_PORTRANGE_TO;
+ } else if (port_from == 0 && port_to != 0) {
+ port_from = port_to;
+ } else if (port_from != 0 && port_to == 0) {
+ port_to = port_from;
+ } else if (port_from > port_to) {
+ uint16_t temp = port_from;
+ port_from = port_to;
+ port_to = temp;
+ }
+
+ if (error) {
+ *error = 2;
+ }
+
+ /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */
+ if (ip.family != TOX_AF_INET && ip.family != TOX_AF_INET6) {
+ LOGGER_ERROR(log, "Invalid address family: %u\n", ip.family);
+ return NULL;
+ }
+
+ if (networking_at_startup() != 0) {
+ return NULL;
+ }
+
+ Networking_Core *temp = (Networking_Core *)calloc(1, sizeof(Networking_Core));
+
+ if (temp == NULL) {
+ return NULL;
+ }
+
+ temp->log = log;
+ temp->family = ip.family;
+ temp->port = 0;
+
+ /* Initialize our socket. */
+ /* add log message what we're creating */
+ temp->sock = net_socket(temp->family, TOX_SOCK_DGRAM, TOX_PROTO_UDP);
+
+ /* Check for socket error. */
+ if (!sock_valid(temp->sock)) {
+ LOGGER_ERROR(log, "Failed to get a socket?! %u, %s\n", errno, strerror(errno));
+ free(temp);
+
+ if (error) {
+ *error = 1;
+ }
+
+ return NULL;
+ }
+
+ /* Functions to increase the size of the send and receive UDP buffers.
+ */
+ int n = 1024 * 1024 * 2;
+ setsockopt(temp->sock, SOL_SOCKET, SO_RCVBUF, (const char *)&n, sizeof(n));
+ setsockopt(temp->sock, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof(n));
+
+ /* Enable broadcast on socket */
+ int broadcast = 1;
+ setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(broadcast));
+
+ /* iOS UDP sockets are weird and apparently can SIGPIPE */
+ if (!set_socket_nosigpipe(temp->sock)) {
+ kill_networking(temp);
+
+ if (error) {
+ *error = 1;
+ }
+
+ return NULL;
+ }
+
+ /* Set socket nonblocking. */
+ if (!set_socket_nonblock(temp->sock)) {
+ kill_networking(temp);
+
+ if (error) {
+ *error = 1;
+ }
+
+ return NULL;
+ }
+
+ /* Bind our socket to port PORT and the given IP address (usually 0.0.0.0 or ::) */
+ uint16_t *portptr = NULL;
+ struct sockaddr_storage addr;
+ size_t addrsize;
+
+ memset(&addr, 0, sizeof(struct sockaddr_storage));
+
+ if (temp->family == TOX_AF_INET) {
+ struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
+
+ addrsize = sizeof(struct sockaddr_in);
+ addr4->sin_family = AF_INET;
+ addr4->sin_port = 0;
+ fill_addr4(ip.ip4, &addr4->sin_addr);
+
+ portptr = &addr4->sin_port;
+ } else if (temp->family == TOX_AF_INET6) {
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
+
+ addrsize = sizeof(struct sockaddr_in6);
+ addr6->sin6_family = AF_INET6;
+ addr6->sin6_port = 0;
+ fill_addr6(ip.ip6, &addr6->sin6_addr);
+
+ addr6->sin6_flowinfo = 0;
+ addr6->sin6_scope_id = 0;
+
+ portptr = &addr6->sin6_port;
+ } else {
+ free(temp);
+ return NULL;
+ }
+
+ if (ip.family == TOX_AF_INET6) {
+ int is_dualstack = set_socket_dualstack(temp->sock);
+ LOGGER_DEBUG(log, "Dual-stack socket: %s",
+ is_dualstack ? "enabled" : "Failed to enable, won't be able to receive from/send to IPv4 addresses");
+ /* multicast local nodes */
+ struct ipv6_mreq mreq;
+ memset(&mreq, 0, sizeof(mreq));
+ mreq.ipv6mr_multiaddr.s6_addr[ 0] = 0xFF;
+ mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02;
+ mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01;
+ mreq.ipv6mr_interface = 0;
+ int res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (const char *)&mreq, sizeof(mreq));
+
+ LOGGER_DEBUG(log, res < 0 ? "Failed to activate local multicast membership. (%u, %s)" :
+ "Local multicast group FF02::1 joined successfully", errno, strerror(errno));
+ }
+
+ /* a hanging program or a different user might block the standard port;
+ * as long as it isn't a parameter coming from the commandline,
+ * try a few ports after it, to see if we can find a "free" one
+ *
+ * if we go on without binding, the first sendto() automatically binds to
+ * a free port chosen by the system (i.e. anything from 1024 to 65535)
+ *
+ * returning NULL after bind fails has both advantages and disadvantages:
+ * advantage:
+ * we can rely on getting the port in the range 33445..33450, which
+ * enables us to tell joe user to open their firewall to a small range
+ *
+ * disadvantage:
+ * some clients might not test return of tox_new(), blindly assuming that
+ * it worked ok (which it did previously without a successful bind)
+ */
+ uint16_t port_to_try = port_from;
+ *portptr = net_htons(port_to_try);
+ int tries;
+
+ for (tries = port_from; tries <= port_to; tries++) {
+ int res = bind(temp->sock, (struct sockaddr *)&addr, addrsize);
+
+ if (!res) {
+ temp->port = *portptr;
+
+ char ip_str[IP_NTOA_LEN];
+ LOGGER_DEBUG(log, "Bound successfully to %s:%u", ip_ntoa(&ip, ip_str, sizeof(ip_str)),
+ net_ntohs(temp->port));
+
+ /* errno isn't reset on success, only set on failure, the failed
+ * binds with parallel clients yield a -EPERM to the outside if
+ * errno isn't cleared here */
+ if (tries > 0) {
+ errno = 0;
+ }
+
+ if (error) {
+ *error = 0;
+ }
+
+ return temp;
+ }
+
+ port_to_try++;
+
+ if (port_to_try > port_to) {
+ port_to_try = port_from;
+ }
+
+ *portptr = net_htons(port_to_try);
+ }
+
+ char ip_str[IP_NTOA_LEN];
+ LOGGER_ERROR(log, "Failed to bind socket: %u, %s IP: %s port_from: %u port_to: %u", errno, strerror(errno),
+ ip_ntoa(&ip, ip_str, sizeof(ip_str)), port_from, port_to);
+
+ kill_networking(temp);
+
+ if (error) {
+ *error = 1;
+ }
+
+ return NULL;
+}
+
+/* Function to cleanup networking stuff. */
+void kill_networking(Networking_Core *net)
+{
+ if (!net) {
+ return;
+ }
+
+ if (net->family != 0) { /* Socket not initialized */
+ kill_sock(net->sock);
+ }
+
+ free(net);
+}
+
+
+/* ip_equal
+ * compares two IPAny structures
+ * unset means unequal
+ *
+ * returns 0 when not equal or when uninitialized
+ */
+int ip_equal(const IP *a, const IP *b)
+{
+ if (!a || !b) {
+ return 0;
+ }
+
+ /* same family */
+ if (a->family == b->family) {
+ if (a->family == TOX_AF_INET || a->family == TCP_INET) {
+ struct in_addr addr_a;
+ struct in_addr addr_b;
+ fill_addr4(a->ip4, &addr_a);
+ fill_addr4(b->ip4, &addr_b);
+ return addr_a.s_addr == addr_b.s_addr;
+ }
+
+ if (a->family == TOX_AF_INET6 || a->family == TCP_INET6) {
+ return a->ip6.uint64[0] == b->ip6.uint64[0] &&
+ a->ip6.uint64[1] == b->ip6.uint64[1];
+ }
+
+ return 0;
+ }
+
+ /* different family: check on the IPv6 one if it is the IPv4 one embedded */
+ if ((a->family == TOX_AF_INET) && (b->family == TOX_AF_INET6)) {
+ if (IPV6_IPV4_IN_V6(b->ip6)) {
+ struct in_addr addr_a;
+ fill_addr4(a->ip4, &addr_a);
+ return addr_a.s_addr == b->ip6.uint32[3];
+ }
+ } else if ((a->family == TOX_AF_INET6) && (b->family == TOX_AF_INET)) {
+ if (IPV6_IPV4_IN_V6(a->ip6)) {
+ struct in_addr addr_b;
+ fill_addr4(b->ip4, &addr_b);
+ return a->ip6.uint32[3] == addr_b.s_addr;
+ }
+ }
+
+ return 0;
+}
+
+/* ipport_equal
+ * compares two IPAny_Port structures
+ * unset means unequal
+ *
+ * returns 0 when not equal or when uninitialized
+ */
+int ipport_equal(const IP_Port *a, const IP_Port *b)
+{
+ if (!a || !b) {
+ return 0;
+ }
+
+ if (!a->port || (a->port != b->port)) {
+ return 0;
+ }
+
+ return ip_equal(&a->ip, &b->ip);
+}
+
+/* nulls out ip */
+void ip_reset(IP *ip)
+{
+ if (!ip) {
+ return;
+ }
+
+ memset(ip, 0, sizeof(IP));
+}
+
+/* nulls out ip, sets family according to flag */
+void ip_init(IP *ip, uint8_t ipv6enabled)
+{
+ if (!ip) {
+ return;
+ }
+
+ memset(ip, 0, sizeof(IP));
+ ip->family = ipv6enabled ? TOX_AF_INET6 : TOX_AF_INET;
+}
+
+/* checks if ip is valid */
+int ip_isset(const IP *ip)
+{
+ if (!ip) {
+ return 0;
+ }
+
+ return (ip->family != 0);
+}
+
+/* checks if ip is valid */
+int ipport_isset(const IP_Port *ipport)
+{
+ if (!ipport) {
+ return 0;
+ }
+
+ if (!ipport->port) {
+ return 0;
+ }
+
+ return ip_isset(&ipport->ip);
+}
+
+/* copies an ip structure (careful about direction!) */
+void ip_copy(IP *target, const IP *source)
+{
+ if (!source || !target) {
+ return;
+ }
+
+ memcpy(target, source, sizeof(IP));
+}
+
+/* copies an ip_port structure (careful about direction!) */
+void ipport_copy(IP_Port *target, const IP_Port *source)
+{
+ if (!source || !target) {
+ return;
+ }
+
+ memcpy(target, source, sizeof(IP_Port));
+}
+
+/* ip_ntoa
+ * converts ip into a string
+ * ip_str must be of length at least IP_NTOA_LEN
+ *
+ * IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]"
+ * writes error message into the buffer on error
+ *
+ * returns ip_str
+ */
+const char *ip_ntoa(const IP *ip, char *ip_str, size_t length)
+{
+ if (length < IP_NTOA_LEN) {
+ snprintf(ip_str, length, "Bad buf length");
+ return ip_str;
+ }
+
+ if (ip) {
+ const int family = make_family(ip->family);
+
+ if (ip->family == TOX_AF_INET) {
+ /* returns standard quad-dotted notation */
+ struct in_addr addr;
+ fill_addr4(ip->ip4, &addr);
+
+ ip_str[0] = 0;
+ inet_ntop(family, &addr, ip_str, length);
+ } else if (ip->family == TOX_AF_INET6) {
+ /* returns hex-groups enclosed into square brackets */
+ struct in6_addr addr;
+ fill_addr6(ip->ip6, &addr);
+
+ ip_str[0] = '[';
+ inet_ntop(family, &addr, &ip_str[1], length - 3);
+ size_t len = strlen(ip_str);
+ ip_str[len] = ']';
+ ip_str[len + 1] = 0;
+ } else {
+ snprintf(ip_str, length, "(IP invalid, family %u)", ip->family);
+ }
+ } else {
+ snprintf(ip_str, length, "(IP invalid: NULL)");
+ }
+
+ /* brute force protection against lacking termination */
+ ip_str[length - 1] = 0;
+ return ip_str;
+}
+
+/*
+ * ip_parse_addr
+ * parses IP structure into an address string
+ *
+ * input
+ * ip: ip of TOX_AF_INET or TOX_AF_INET6 families
+ * length: length of the address buffer
+ * Must be at least INET_ADDRSTRLEN for TOX_AF_INET
+ * and INET6_ADDRSTRLEN for TOX_AF_INET6
+ *
+ * output
+ * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
+ *
+ * returns 1 on success, 0 on failure
+ */
+int ip_parse_addr(const IP *ip, char *address, size_t length)
+{
+ if (!address || !ip) {
+ return 0;
+ }
+
+ if (ip->family == TOX_AF_INET) {
+ const struct in_addr *addr = (const struct in_addr *)&ip->ip4;
+ return inet_ntop(ip->family, addr, address, length) != NULL;
+ }
+
+ if (ip->family == TOX_AF_INET6) {
+ const struct in6_addr *addr = (const struct in6_addr *)&ip->ip6;
+ return inet_ntop(ip->family, addr, address, length) != NULL;
+ }
+
+ return 0;
+}
+
+/*
+ * addr_parse_ip
+ * directly parses the input into an IP structure
+ * tries IPv4 first, then IPv6
+ *
+ * input
+ * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
+ *
+ * output
+ * IP: family and the value is set on success
+ *
+ * returns 1 on success, 0 on failure
+ */
+int addr_parse_ip(const char *address, IP *to)
+{
+ if (!address || !to) {
+ return 0;
+ }
+
+ struct in_addr addr4;
+
+ if (inet_pton(AF_INET, address, &addr4) == 1) {
+ to->family = TOX_AF_INET;
+ get_ip4(&to->ip4, &addr4);
+ return 1;
+ }
+
+ struct in6_addr addr6;
+
+ if (inet_pton(AF_INET6, address, &addr6) == 1) {
+ to->family = TOX_AF_INET6;
+ get_ip6(&to->ip6, &addr6);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * addr_resolve():
+ * uses getaddrinfo to resolve an address into an IP address
+ * uses the first IPv4/IPv6 addresses returned by getaddrinfo
+ *
+ * input
+ * address: a hostname (or something parseable to an IP address)
+ * to: to.family MUST be initialized, either set to a specific IP version
+ * (TOX_AF_INET/TOX_AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both
+ * IP versions are acceptable
+ * extra can be NULL and is only set in special circumstances, see returns
+ *
+ * returns in *to a valid IPAny (v4/v6),
+ * prefers v6 if ip.family was AF_UNSPEC and both available
+ * returns in *extra an IPv4 address, if family was AF_UNSPEC and *to is TOX_AF_INET6
+ * returns 0 on failure, TOX_ADDR_RESOLVE_* on success.
+ */
+int addr_resolve(const char *address, IP *to, IP *extra)
+{
+ if (!address || !to) {
+ return 0;
+ }
+
+ Family tox_family = to->family;
+ Family family = make_family(tox_family);
+
+ struct addrinfo *server = NULL;
+ struct addrinfo *walker = NULL;
+ struct addrinfo hints;
+ int rc;
+ int result = 0;
+ int done = 0;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
+
+ if (networking_at_startup() != 0) {
+ return 0;
+ }
+
+ rc = getaddrinfo(address, NULL, &hints, &server);
+
+ // Lookup failed.
+ if (rc != 0) {
+ return 0;
+ }
+
+ IP ip4;
+ ip_init(&ip4, 0); // ipv6enabled = 0
+ IP ip6;
+ ip_init(&ip6, 1); // ipv6enabled = 1
+
+ for (walker = server; (walker != NULL) && !done; walker = walker->ai_next) {
+ switch (walker->ai_family) {
+ case AF_INET:
+ if (walker->ai_family == family) { /* AF_INET requested, done */
+ struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
+ get_ip4(&to->ip4, &addr->sin_addr);
+ result = TOX_ADDR_RESOLVE_INET;
+ done = 1;
+ } else if (!(result & TOX_ADDR_RESOLVE_INET)) { /* AF_UNSPEC requested, store away */
+ struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
+ get_ip4(&ip4.ip4, &addr->sin_addr);
+ result |= TOX_ADDR_RESOLVE_INET;
+ }
+
+ break; /* switch */
+
+ case AF_INET6:
+ if (walker->ai_family == family) { /* AF_INET6 requested, done */
+ if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
+ get_ip6(&to->ip6, &addr->sin6_addr);
+ result = TOX_ADDR_RESOLVE_INET6;
+ done = 1;
+ }
+ } else if (!(result & TOX_ADDR_RESOLVE_INET6)) { /* AF_UNSPEC requested, store away */
+ if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
+ get_ip6(&ip6.ip6, &addr->sin6_addr);
+ result |= TOX_ADDR_RESOLVE_INET6;
+ }
+ }
+
+ break; /* switch */
+ }
+ }
+
+ if (family == AF_UNSPEC) {
+ if (result & TOX_ADDR_RESOLVE_INET6) {
+ ip_copy(to, &ip6);
+
+ if ((result & TOX_ADDR_RESOLVE_INET) && (extra != NULL)) {
+ ip_copy(extra, &ip4);
+ }
+ } else if (result & TOX_ADDR_RESOLVE_INET) {
+ ip_copy(to, &ip4);
+ } else {
+ result = 0;
+ }
+ }
+
+ freeaddrinfo(server);
+ return result;
+}
+
+/*
+ * addr_resolve_or_parse_ip
+ * resolves string into an IP address
+ *
+ * address: a hostname (or something parseable to an IP address)
+ * to: to.family MUST be initialized, either set to a specific IP version
+ * (TOX_AF_INET/TOX_AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both
+ * IP versions are acceptable
+ * extra can be NULL and is only set in special circumstances, see returns
+ *
+ * returns in *tro a matching address (IPv6 or IPv4)
+ * returns in *extra, if not NULL, an IPv4 address, if to->family was AF_UNSPEC
+ * returns 1 on success
+ * returns 0 on failure
+ */
+int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra)
+{
+ if (!addr_resolve(address, to, extra)) {
+ if (!addr_parse_ip(address, to)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int net_connect(Socket sock, IP_Port ip_port)
+{
+ struct sockaddr_storage addr = {0};
+ size_t addrsize;
+
+ if (ip_port.ip.family == TOX_AF_INET) {
+ struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
+
+ addrsize = sizeof(struct sockaddr_in);
+ addr4->sin_family = AF_INET;
+ fill_addr4(ip_port.ip.ip4, &addr4->sin_addr);
+ addr4->sin_port = ip_port.port;
+ } else if (ip_port.ip.family == TOX_AF_INET6) {
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
+
+ addrsize = sizeof(struct sockaddr_in6);
+ addr6->sin6_family = AF_INET6;
+ fill_addr6(ip_port.ip.ip6, &addr6->sin6_addr);
+ addr6->sin6_port = ip_port.port;
+ } else {
+ return 0;
+ }
+
+ return connect(sock, (struct sockaddr *)&addr, addrsize);
+}
+
+int32_t net_getipport(const char *node, IP_Port **res, int tox_type)
+{
+ struct addrinfo *infos;
+ int ret = getaddrinfo(node, NULL, NULL, &infos);
+ *res = NULL;
+
+ if (ret != 0) {
+ return -1;
+ }
+
+ // Used to avoid malloc parameter overflow
+ const size_t MAX_COUNT = MIN(SIZE_MAX, INT32_MAX) / sizeof(IP_Port);
+ int type = make_socktype(tox_type);
+ struct addrinfo *cur;
+ int32_t count = 0;
+
+ for (cur = infos; count < MAX_COUNT && cur != NULL; cur = cur->ai_next) {
+ if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
+ continue;
+ }
+
+ if (cur->ai_family != AF_INET && cur->ai_family != AF_INET6) {
+ continue;
+ }
+
+ count++;
+ }
+
+ assert(count <= MAX_COUNT);
+
+ if (count == 0) {
+ return 0;
+ }
+
+ *res = (IP_Port *)malloc(sizeof(IP_Port) * count);
+
+ if (*res == NULL) {
+ return -1;
+ }
+
+ IP_Port *ip_port = *res;
+
+ for (cur = infos; cur != NULL; cur = cur->ai_next) {
+ if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
+ continue;
+ }
+
+ if (cur->ai_family == AF_INET) {
+ struct sockaddr_in *addr = (struct sockaddr_in *)cur->ai_addr;
+ memcpy(&ip_port->ip.ip4, &addr->sin_addr, sizeof(IP4));
+ } else if (cur->ai_family == AF_INET6) {
+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *)cur->ai_addr;
+ memcpy(&ip_port->ip.ip6, &addr->sin6_addr, sizeof(IP6));
+ } else {
+ continue;
+ }
+
+ ip_port->ip.family = make_tox_family(cur->ai_family);
+
+ ip_port++;
+ }
+
+ freeaddrinfo(infos);
+
+ return count;
+}
+
+void net_freeipport(IP_Port *ip_ports)
+{
+ free(ip_ports);
+}
+
+/* return 1 on success
+ * return 0 on failure
+ */
+int bind_to_port(Socket sock, int family, uint16_t port)
+{
+ struct sockaddr_storage addr = {0};
+ size_t addrsize;
+
+ if (family == TOX_AF_INET) {
+ struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
+
+ addrsize = sizeof(struct sockaddr_in);
+ addr4->sin_family = AF_INET;
+ addr4->sin_port = net_htons(port);
+ } else if (family == TOX_AF_INET6) {
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
+
+ addrsize = sizeof(struct sockaddr_in6);
+ addr6->sin6_family = AF_INET6;
+ addr6->sin6_port = net_htons(port);
+ } else {
+ return 0;
+ }
+
+ return (bind(sock, (struct sockaddr *)&addr, addrsize) == 0);
+}
+
+static int make_tox_family(int family)
+{
+ switch (family) {
+ case AF_INET:
+ return TOX_AF_INET;
+
+ case AF_INET6:
+ return TOX_AF_INET6;
+
+ case AF_UNSPEC:
+ return TOX_AF_UNSPEC;
+
+ default:
+ return family;
+ }
+}
+
+static int make_family(int tox_family)
+{
+ switch (tox_family) {
+ case TOX_AF_INET:
+ return AF_INET;
+
+ case TOX_AF_INET6:
+ return AF_INET6;
+
+ case TOX_AF_UNSPEC:
+ return AF_UNSPEC;
+
+ default:
+ return tox_family;
+ }
+}
+
+static int make_socktype(int type)
+{
+ switch (type) {
+ case TOX_SOCK_STREAM:
+ return SOCK_STREAM;
+
+ case TOX_SOCK_DGRAM:
+ return SOCK_DGRAM;
+
+ default:
+ return type;
+ }
+}
+
+static int make_proto(int proto)
+{
+ switch (proto) {
+ case TOX_PROTO_TCP:
+ return IPPROTO_TCP;
+
+ case TOX_PROTO_UDP:
+ return IPPROTO_UDP;
+
+ default:
+ return proto;
+ }
+}
+
+Socket net_socket(int domain, int type, int protocol)
+{
+ int platform_domain = make_family(domain);
+ int platform_type = make_socktype(type);
+ int platform_prot = make_proto(protocol);
+ return socket(platform_domain, platform_type, platform_prot);
+}
+
+/* TODO: Remove, when tox DNS support will be removed.
+ * Used only by dns3_test.c
+ */
+size_t net_sendto_ip4(Socket sock, const char *buf, size_t n, IP_Port ip_port)
+{
+ struct sockaddr_in target;
+ size_t addrsize = sizeof(target);
+ target.sin_family = make_family(ip_port.ip.family);
+ target.sin_port = net_htons(ip_port.port);
+ fill_addr4(ip_port.ip.ip4, &target.sin_addr);
+
+ return (size_t)sendto(sock, buf, n, 0, (struct sockaddr *)&target, addrsize);
+}
+
+uint32_t net_htonl(uint32_t hostlong)
+{
+ return htonl(hostlong);
+}
+
+uint16_t net_htons(uint16_t hostshort)
+{
+ return htons(hostshort);
+}
+
+uint32_t net_ntohl(uint32_t hostlong)
+{
+ return ntohl(hostlong);
+}
+
+uint16_t net_ntohs(uint16_t hostshort)
+{
+ return ntohs(hostshort);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/network.h b/protocols/Tox/libtox/src/toxcore/network.h
new file mode 100644
index 0000000000..0b9da5a40f
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/network.h
@@ -0,0 +1,424 @@
+/*
+ * Datatypes, functions and includes for the core networking.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef NETWORK_H
+#define NETWORK_H
+
+#ifdef PLAN9
+#include <u.h> // Plan 9 requires this is imported first
+// Comment line here to avoid reordering by source code formatters.
+#include <libc.h>
+#endif
+
+#include "ccompat.h"
+#include "logger.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) /* Put win32 includes here */
+#ifndef WINVER
+//Windows XP
+#define WINVER 0x0501
+#endif
+
+// The mingw32/64 Windows library warns about including winsock2.h after
+// windows.h even though with the above it's a valid thing to do. So, to make
+// mingw32 headers happy, we include winsock2.h first.
+#include <winsock2.h>
+
+#include <windows.h>
+#include <ws2tcpip.h>
+
+#else // UNIX includes
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+
+#endif
+
+typedef short Family;
+
+typedef int Socket;
+Socket net_socket(int domain, int type, int protocol);
+
+#define MAX_UDP_PACKET_SIZE 2048
+
+typedef enum NET_PACKET_TYPE {
+ NET_PACKET_PING_REQUEST = 0x00, /* Ping request packet ID. */
+ NET_PACKET_PING_RESPONSE = 0x01, /* Ping response packet ID. */
+ NET_PACKET_GET_NODES = 0x02, /* Get nodes request packet ID. */
+ NET_PACKET_SEND_NODES_IPV6 = 0x04, /* Send nodes response packet ID for other addresses. */
+ NET_PACKET_COOKIE_REQUEST = 0x18, /* Cookie request packet */
+ NET_PACKET_COOKIE_RESPONSE = 0x19, /* Cookie response packet */
+ NET_PACKET_CRYPTO_HS = 0x1a, /* Crypto handshake packet */
+ NET_PACKET_CRYPTO_DATA = 0x1b, /* Crypto data packet */
+ NET_PACKET_CRYPTO = 0x20, /* Encrypted data packet ID. */
+ NET_PACKET_LAN_DISCOVERY = 0x21, /* LAN discovery packet ID. */
+
+ /* See: docs/Prevent_Tracking.txt and onion.{c,h} */
+ NET_PACKET_ONION_SEND_INITIAL = 0x80,
+ NET_PACKET_ONION_SEND_1 = 0x81,
+ NET_PACKET_ONION_SEND_2 = 0x82,
+
+ NET_PACKET_ANNOUNCE_REQUEST = 0x83,
+ NET_PACKET_ANNOUNCE_RESPONSE = 0x84,
+ NET_PACKET_ONION_DATA_REQUEST = 0x85,
+ NET_PACKET_ONION_DATA_RESPONSE = 0x86,
+
+ NET_PACKET_ONION_RECV_3 = 0x8c,
+ NET_PACKET_ONION_RECV_2 = 0x8d,
+ NET_PACKET_ONION_RECV_1 = 0x8e,
+
+ BOOTSTRAP_INFO_PACKET_ID = 0xf0, /* Only used for bootstrap nodes */
+
+ NET_PACKET_MAX = 0xff, /* This type must remain within a single uint8. */
+} NET_PACKET_TYPE;
+
+
+#define TOX_PORTRANGE_FROM 33445
+#define TOX_PORTRANGE_TO 33545
+#define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM
+
+/* Redefinitions of variables for safe transfer over wire. */
+#define TOX_AF_UNSPEC 0
+#define TOX_AF_INET 2
+#define TOX_AF_INET6 10
+#define TOX_TCP_INET 130
+#define TOX_TCP_INET6 138
+
+#define TOX_SOCK_STREAM 1
+#define TOX_SOCK_DGRAM 2
+
+#define TOX_PROTO_TCP 1
+#define TOX_PROTO_UDP 2
+
+/* TCP related */
+#define TCP_ONION_FAMILY (TOX_AF_INET6 + 1)
+#define TCP_INET (TOX_AF_INET6 + 2)
+#define TCP_INET6 (TOX_AF_INET6 + 3)
+#define TCP_FAMILY (TOX_AF_INET6 + 4)
+
+typedef union {
+ uint32_t uint32;
+ uint16_t uint16[2];
+ uint8_t uint8[4];
+}
+IP4;
+
+IP4 get_ip4_loopback(void);
+extern const IP4 IP4_BROADCAST;
+
+typedef union {
+ uint8_t uint8[16];
+ uint16_t uint16[8];
+ uint32_t uint32[4];
+ uint64_t uint64[2];
+}
+IP6;
+
+IP6 get_ip6_loopback(void);
+extern const IP6 IP6_BROADCAST;
+
+typedef struct {
+ uint8_t family;
+ GNU_EXTENSION union {
+ IP4 ip4;
+ IP6 ip6;
+ };
+}
+IP;
+
+typedef struct {
+ IP ip;
+ uint16_t port;
+}
+IP_Port;
+
+/* Convert values between host and network byte order.
+ */
+uint32_t net_htonl(uint32_t hostlong);
+uint16_t net_htons(uint16_t hostshort);
+uint32_t net_ntohl(uint32_t hostlong);
+uint16_t net_ntohs(uint16_t hostshort);
+
+/* Does the IP6 struct a contain an IPv4 address in an IPv6 one? */
+#define IPV6_IPV4_IN_V6(a) ((a.uint64[0] == 0) && (a.uint32[2] == net_htonl (0xffff)))
+
+#define SIZE_IP4 4
+#define SIZE_IP6 16
+#define SIZE_IP (1 + SIZE_IP6)
+#define SIZE_PORT 2
+#define SIZE_IPPORT (SIZE_IP + SIZE_PORT)
+
+#define TOX_ENABLE_IPV6_DEFAULT 1
+
+/* addr_resolve return values */
+#define TOX_ADDR_RESOLVE_INET 1
+#define TOX_ADDR_RESOLVE_INET6 2
+
+#define TOX_INET6_ADDRSTRLEN 66
+#define TOX_INET_ADDRSTRLEN 22
+
+/* ip_ntoa
+ * converts ip into a string
+ * ip_str must be of length at least IP_NTOA_LEN
+ *
+ * IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]"
+ * writes error message into the buffer on error
+ *
+ * returns ip_str
+ */
+/* this would be TOX_INET6_ADDRSTRLEN, but it might be too short for the error message */
+#define IP_NTOA_LEN 96 // TODO(irungentoo): magic number. Why not INET6_ADDRSTRLEN ?
+const char *ip_ntoa(const IP *ip, char *ip_str, size_t length);
+
+/*
+ * ip_parse_addr
+ * parses IP structure into an address string
+ *
+ * input
+ * ip: ip of TOX_AF_INET or TOX_AF_INET6 families
+ * length: length of the address buffer
+ * Must be at least TOX_INET_ADDRSTRLEN for TOX_AF_INET
+ * and TOX_INET6_ADDRSTRLEN for TOX_AF_INET6
+ *
+ * output
+ * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
+ *
+ * returns 1 on success, 0 on failure
+ */
+int ip_parse_addr(const IP *ip, char *address, size_t length);
+
+/*
+ * addr_parse_ip
+ * directly parses the input into an IP structure
+ * tries IPv4 first, then IPv6
+ *
+ * input
+ * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
+ *
+ * output
+ * IP: family and the value is set on success
+ *
+ * returns 1 on success, 0 on failure
+ */
+int addr_parse_ip(const char *address, IP *to);
+
+/* ip_equal
+ * compares two IPAny structures
+ * unset means unequal
+ *
+ * returns 0 when not equal or when uninitialized
+ */
+int ip_equal(const IP *a, const IP *b);
+
+/* ipport_equal
+ * compares two IPAny_Port structures
+ * unset means unequal
+ *
+ * returns 0 when not equal or when uninitialized
+ */
+int ipport_equal(const IP_Port *a, const IP_Port *b);
+
+/* nulls out ip */
+void ip_reset(IP *ip);
+/* nulls out ip, sets family according to flag */
+void ip_init(IP *ip, uint8_t ipv6enabled);
+/* checks if ip is valid */
+int ip_isset(const IP *ip);
+/* checks if ip is valid */
+int ipport_isset(const IP_Port *ipport);
+/* copies an ip structure */
+void ip_copy(IP *target, const IP *source);
+/* copies an ip_port structure */
+void ipport_copy(IP_Port *target, const IP_Port *source);
+
+/*
+ * addr_resolve():
+ * uses getaddrinfo to resolve an address into an IP address
+ * uses the first IPv4/IPv6 addresses returned by getaddrinfo
+ *
+ * input
+ * address: a hostname (or something parseable to an IP address)
+ * to: to.family MUST be initialized, either set to a specific IP version
+ * (TOX_AF_INET/TOX_AF_INET6) or to the unspecified TOX_AF_UNSPEC (= 0), if both
+ * IP versions are acceptable
+ * extra can be NULL and is only set in special circumstances, see returns
+ *
+ * returns in *to a valid IPAny (v4/v6),
+ * prefers v6 if ip.family was TOX_AF_UNSPEC and both available
+ * returns in *extra an IPv4 address, if family was TOX_AF_UNSPEC and *to is TOX_AF_INET6
+ * returns 0 on failure
+ */
+int addr_resolve(const char *address, IP *to, IP *extra);
+
+/*
+ * addr_resolve_or_parse_ip
+ * resolves string into an IP address
+ *
+ * address: a hostname (or something parseable to an IP address)
+ * to: to.family MUST be initialized, either set to a specific IP version
+ * (TOX_AF_INET/TOX_AF_INET6) or to the unspecified TOX_AF_UNSPEC (= 0), if both
+ * IP versions are acceptable
+ * extra can be NULL and is only set in special circumstances, see returns
+ *
+ * returns in *tro a matching address (IPv6 or IPv4)
+ * returns in *extra, if not NULL, an IPv4 address, if to->family was TOX_AF_UNSPEC
+ * returns 1 on success
+ * returns 0 on failure
+ */
+int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra);
+
+/* Function to receive data, ip and port of sender is put into ip_port.
+ * Packet data is put into data.
+ * Packet length is put into length.
+ */
+typedef int (*packet_handler_callback)(void *object, IP_Port ip_port, const uint8_t *data, uint16_t len,
+ void *userdata);
+
+typedef struct {
+ packet_handler_callback function;
+ void *object;
+} Packet_Handles;
+
+typedef struct {
+ Logger *log;
+ Packet_Handles packethandlers[256];
+
+ Family family;
+ uint16_t port;
+ /* Our UDP socket. */
+ Socket sock;
+} Networking_Core;
+
+/* Run this before creating sockets.
+ *
+ * return 0 on success
+ * return -1 on failure
+ */
+int networking_at_startup(void);
+
+/* Check if socket is valid.
+ *
+ * return 1 if valid
+ * return 0 if not valid
+ */
+int sock_valid(Socket sock);
+
+/* Close the socket.
+ */
+void kill_sock(Socket sock);
+
+/* Set socket as nonblocking
+ *
+ * return 1 on success
+ * return 0 on failure
+ */
+int set_socket_nonblock(Socket sock);
+
+/* Set socket to not emit SIGPIPE
+ *
+ * return 1 on success
+ * return 0 on failure
+ */
+int set_socket_nosigpipe(Socket sock);
+
+/* Enable SO_REUSEADDR on socket.
+ *
+ * return 1 on success
+ * return 0 on failure
+ */
+int set_socket_reuseaddr(Socket sock);
+
+/* Set socket to dual (IPv4 + IPv6 socket)
+ *
+ * return 1 on success
+ * return 0 on failure
+ */
+int set_socket_dualstack(Socket sock);
+
+/* return current monotonic time in milliseconds (ms). */
+uint64_t current_time_monotonic(void);
+
+/* Basic network functions: */
+
+/* Function to send packet(data) of length length to ip_port. */
+int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint16_t length);
+
+/* Function to call when packet beginning with byte is received. */
+void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object);
+
+/* Call this several times a second. */
+void networking_poll(Networking_Core *net, void *userdata);
+
+/* Connect a socket to the address specified by the ip_port. */
+int net_connect(Socket sock, IP_Port ip_port);
+
+/* High-level getaddrinfo implementation.
+ * Given node, which identifies an Internet host, net_getipport() fills an array
+ * with one or more IP_Port structures, each of which contains an Internet
+ * address that can be specified by calling net_connect(), the port is ignored.
+ *
+ * Skip all addresses with socktype != type (use type = -1 to get all addresses)
+ * To correctly deallocate array memory use net_freeipport()
+ *
+ * return number of elements in res array
+ * and -1 on error.
+ */
+int32_t net_getipport(const char *node, IP_Port **res, int tox_type);
+
+/* Deallocates memory allocated by net_getipport
+ */
+void net_freeipport(IP_Port *ip_ports);
+
+/* return 1 on success
+ * return 0 on failure
+ */
+int bind_to_port(Socket sock, int family, uint16_t port);
+
+size_t net_sendto_ip4(Socket sock, const char *buf, size_t n, IP_Port ip_port);
+
+/* Initialize networking.
+ * bind to ip and port.
+ * ip must be in network order EX: 127.0.0.1 = (7F000001).
+ * port is in host byte order (this means don't worry about it).
+ *
+ * return Networking_Core object if no problems
+ * return NULL if there are problems.
+ *
+ * If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other.
+ */
+Networking_Core *new_networking(Logger *log, IP ip, uint16_t port);
+Networking_Core *new_networking_ex(Logger *log, IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error);
+
+/* Function to cleanup networking stuff (doesn't do much right now). */
+void kill_networking(Networking_Core *net);
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxcore/onion.c b/protocols/Tox/libtox/src/toxcore/onion.c
new file mode 100644
index 0000000000..fbaf7205d9
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/onion.c
@@ -0,0 +1,679 @@
+/*
+ * Implementation of the onion part of docs/Prevent_Tracking.txt
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "onion.h"
+
+#include "util.h"
+
+#define RETURN_1 ONION_RETURN_1
+#define RETURN_2 ONION_RETURN_2
+#define RETURN_3 ONION_RETURN_3
+
+#define SEND_BASE ONION_SEND_BASE
+#define SEND_3 ONION_SEND_3
+#define SEND_2 ONION_SEND_2
+#define SEND_1 ONION_SEND_1
+
+/* Change symmetric keys every 2 hours to make paths expire eventually. */
+#define KEY_REFRESH_INTERVAL (2 * 60 * 60)
+static void change_symmetric_key(Onion *onion)
+{
+ if (is_timeout(onion->timestamp, KEY_REFRESH_INTERVAL)) {
+ new_symmetric_key(onion->secret_symmetric_key);
+ onion->timestamp = unix_time();
+ }
+}
+
+/* packing and unpacking functions */
+static void ip_pack(uint8_t *data, IP source)
+{
+ data[0] = source.family;
+
+ if (source.family == TOX_AF_INET || source.family == TOX_TCP_INET) {
+ memset(data + 1, 0, SIZE_IP6);
+ memcpy(data + 1, source.ip4.uint8, SIZE_IP4);
+ } else {
+ memcpy(data + 1, source.ip6.uint8, SIZE_IP6);
+ }
+}
+
+/* return 0 on success, -1 on failure. */
+static int ip_unpack(IP *target, const uint8_t *data, unsigned int data_size, bool disable_family_check)
+{
+ if (data_size < (1 + SIZE_IP6)) {
+ return -1;
+ }
+
+ target->family = data[0];
+
+ if (target->family == TOX_AF_INET || target->family == TOX_TCP_INET) {
+ memcpy(target->ip4.uint8, data + 1, SIZE_IP4);
+ } else {
+ memcpy(target->ip6.uint8, data + 1, SIZE_IP6);
+ }
+
+ bool valid = disable_family_check ||
+ target->family == TOX_AF_INET ||
+ target->family == TOX_AF_INET6;
+
+ return valid ? 0 : -1;
+}
+
+static void ipport_pack(uint8_t *data, const IP_Port *source)
+{
+ ip_pack(data, source->ip);
+ memcpy(data + SIZE_IP, &source->port, SIZE_PORT);
+}
+
+/* return 0 on success, -1 on failure. */
+static int ipport_unpack(IP_Port *target, const uint8_t *data, unsigned int data_size, bool disable_family_check)
+{
+ if (data_size < (SIZE_IP + SIZE_PORT)) {
+ return -1;
+ }
+
+ if (ip_unpack(&target->ip, data, data_size, disable_family_check) == -1) {
+ return -1;
+ }
+
+ memcpy(&target->port, data + SIZE_IP, SIZE_PORT);
+ return 0;
+}
+
+
+/* Create a new onion path.
+ *
+ * Create a new onion path out of nodes (nodes is a list of ONION_PATH_LENGTH nodes)
+ *
+ * new_path must be an empty memory location of atleast Onion_Path size.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int create_onion_path(const DHT *dht, Onion_Path *new_path, const Node_format *nodes)
+{
+ if (!new_path || !nodes) {
+ return -1;
+ }
+
+ encrypt_precompute(nodes[0].public_key, dht->self_secret_key, new_path->shared_key1);
+ memcpy(new_path->public_key1, dht->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+
+ uint8_t random_public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t random_secret_key[CRYPTO_SECRET_KEY_SIZE];
+
+ crypto_new_keypair(random_public_key, random_secret_key);
+ encrypt_precompute(nodes[1].public_key, random_secret_key, new_path->shared_key2);
+ memcpy(new_path->public_key2, random_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+
+ crypto_new_keypair(random_public_key, random_secret_key);
+ encrypt_precompute(nodes[2].public_key, random_secret_key, new_path->shared_key3);
+ memcpy(new_path->public_key3, random_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+
+ new_path->ip_port1 = nodes[0].ip_port;
+ new_path->ip_port2 = nodes[1].ip_port;
+ new_path->ip_port3 = nodes[2].ip_port;
+
+ memcpy(new_path->node_public_key1, nodes[0].public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(new_path->node_public_key2, nodes[1].public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(new_path->node_public_key3, nodes[2].public_key, CRYPTO_PUBLIC_KEY_SIZE);
+
+ return 0;
+}
+
+/* Dump nodes in onion path to nodes of length num_nodes;
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_Path *path)
+{
+ if (num_nodes < ONION_PATH_LENGTH) {
+ return -1;
+ }
+
+ nodes[0].ip_port = path->ip_port1;
+ nodes[1].ip_port = path->ip_port2;
+ nodes[2].ip_port = path->ip_port3;
+
+ memcpy(nodes[0].public_key, path->node_public_key1, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(nodes[1].public_key, path->node_public_key2, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(nodes[2].public_key, path->node_public_key3, CRYPTO_PUBLIC_KEY_SIZE);
+ return 0;
+}
+
+/* Create a onion packet.
+ *
+ * Use Onion_Path path to create packet for data of length to dest.
+ * Maximum length of data is ONION_MAX_DATA_SIZE.
+ * packet should be at least ONION_MAX_PACKET_SIZE big.
+ *
+ * return -1 on failure.
+ * return length of created packet on success.
+ */
+int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest,
+ const uint8_t *data, uint16_t length)
+{
+ if (1 + length + SEND_1 > max_packet_length || length == 0) {
+ return -1;
+ }
+
+ VLA(uint8_t, step1, SIZE_IPPORT + length);
+
+ ipport_pack(step1, &dest);
+ memcpy(step1 + SIZE_IPPORT, data, length);
+
+ uint8_t nonce[CRYPTO_NONCE_SIZE];
+ random_nonce(nonce);
+
+ VLA(uint8_t, step2, SIZE_IPPORT + SEND_BASE + length);
+ ipport_pack(step2, &path->ip_port3);
+ memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE);
+
+ int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, SIZEOF_VLA(step1),
+ step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
+
+ if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) {
+ return -1;
+ }
+
+ VLA(uint8_t, step3, SIZE_IPPORT + SEND_BASE * 2 + length);
+ ipport_pack(step3, &path->ip_port2);
+ memcpy(step3 + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE);
+ len = encrypt_data_symmetric(path->shared_key2, nonce, step2, SIZEOF_VLA(step2),
+ step3 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
+
+ if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) {
+ return -1;
+ }
+
+ packet[0] = NET_PACKET_ONION_SEND_INITIAL;
+ memcpy(packet + 1, nonce, CRYPTO_NONCE_SIZE);
+ memcpy(packet + 1 + CRYPTO_NONCE_SIZE, path->public_key1, CRYPTO_PUBLIC_KEY_SIZE);
+
+ len = encrypt_data_symmetric(path->shared_key1, nonce, step3, SIZEOF_VLA(step3),
+ packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
+
+ if (len != SIZE_IPPORT + SEND_BASE * 2 + length + CRYPTO_MAC_SIZE) {
+ return -1;
+ }
+
+ return 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + len;
+}
+
+/* Create a onion packet to be sent over tcp.
+ *
+ * Use Onion_Path path to create packet for data of length to dest.
+ * Maximum length of data is ONION_MAX_DATA_SIZE.
+ * packet should be at least ONION_MAX_PACKET_SIZE big.
+ *
+ * return -1 on failure.
+ * return length of created packet on success.
+ */
+int create_onion_packet_tcp(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest,
+ const uint8_t *data, uint16_t length)
+{
+ if (CRYPTO_NONCE_SIZE + SIZE_IPPORT + SEND_BASE * 2 + length > max_packet_length || length == 0) {
+ return -1;
+ }
+
+ VLA(uint8_t, step1, SIZE_IPPORT + length);
+
+ ipport_pack(step1, &dest);
+ memcpy(step1 + SIZE_IPPORT, data, length);
+
+ uint8_t nonce[CRYPTO_NONCE_SIZE];
+ random_nonce(nonce);
+
+ VLA(uint8_t, step2, SIZE_IPPORT + SEND_BASE + length);
+ ipport_pack(step2, &path->ip_port3);
+ memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE);
+
+ int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, SIZEOF_VLA(step1),
+ step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
+
+ if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) {
+ return -1;
+ }
+
+ ipport_pack(packet + CRYPTO_NONCE_SIZE, &path->ip_port2);
+ memcpy(packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE);
+ len = encrypt_data_symmetric(path->shared_key2, nonce, step2, SIZEOF_VLA(step2),
+ packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
+
+ if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) {
+ return -1;
+ }
+
+ memcpy(packet, nonce, CRYPTO_NONCE_SIZE);
+
+ return CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE + len;
+}
+
+/* Create and send a onion packet.
+ *
+ * Use Onion_Path path to send data of length to dest.
+ * Maximum length of data is ONION_MAX_DATA_SIZE.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int send_onion_packet(Networking_Core *net, const Onion_Path *path, IP_Port dest, const uint8_t *data, uint16_t length)
+{
+ uint8_t packet[ONION_MAX_PACKET_SIZE];
+ int len = create_onion_packet(packet, sizeof(packet), path, dest, data, length);
+
+ if (len == -1) {
+ return -1;
+ }
+
+ if (sendpacket(net, path->ip_port1, packet, len) != len) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Create and send a onion response sent initially to dest with.
+ * Maximum length of data is ONION_RESPONSE_MAX_DATA_SIZE.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int send_onion_response(Networking_Core *net, IP_Port dest, const uint8_t *data, uint16_t length, const uint8_t *ret)
+{
+ if (length > ONION_RESPONSE_MAX_DATA_SIZE || length == 0) {
+ return -1;
+ }
+
+ VLA(uint8_t, packet, 1 + RETURN_3 + length);
+ packet[0] = NET_PACKET_ONION_RECV_3;
+ memcpy(packet + 1, ret, RETURN_3);
+ memcpy(packet + 1 + RETURN_3, data, length);
+
+ if ((uint32_t)sendpacket(net, dest, packet, SIZEOF_VLA(packet)) != SIZEOF_VLA(packet)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int handle_send_initial(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
+{
+ Onion *onion = (Onion *)object;
+
+ if (length > ONION_MAX_PACKET_SIZE) {
+ return 1;
+ }
+
+ if (length <= 1 + SEND_1) {
+ return 1;
+ }
+
+ change_symmetric_key(onion);
+
+ uint8_t plain[ONION_MAX_PACKET_SIZE];
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
+ get_shared_key(&onion->shared_keys_1, shared_key, onion->dht->self_secret_key, packet + 1 + CRYPTO_NONCE_SIZE);
+ int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
+ length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), plain);
+
+ if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)) {
+ return 1;
+ }
+
+ return onion_send_1(onion, plain, len, source, packet + 1);
+}
+
+int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port source, const uint8_t *nonce)
+{
+ if (len > ONION_MAX_PACKET_SIZE + SIZE_IPPORT - (1 + CRYPTO_NONCE_SIZE + ONION_RETURN_1)) {
+ return 1;
+ }
+
+ if (len <= SIZE_IPPORT + SEND_BASE * 2) {
+ return 1;
+ }
+
+ IP_Port send_to;
+
+ if (ipport_unpack(&send_to, plain, len, 0) == -1) {
+ return 1;
+ }
+
+ uint8_t ip_port[SIZE_IPPORT];
+ ipport_pack(ip_port, &source);
+
+ uint8_t data[ONION_MAX_PACKET_SIZE];
+ data[0] = NET_PACKET_ONION_SEND_1;
+ memcpy(data + 1, nonce, CRYPTO_NONCE_SIZE);
+ memcpy(data + 1 + CRYPTO_NONCE_SIZE, plain + SIZE_IPPORT, len - SIZE_IPPORT);
+ uint16_t data_len = 1 + CRYPTO_NONCE_SIZE + (len - SIZE_IPPORT);
+ uint8_t *ret_part = data + data_len;
+ random_nonce(ret_part);
+ len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ip_port, SIZE_IPPORT,
+ ret_part + CRYPTO_NONCE_SIZE);
+
+ if (len != SIZE_IPPORT + CRYPTO_MAC_SIZE) {
+ return 1;
+ }
+
+ data_len += CRYPTO_NONCE_SIZE + len;
+
+ if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static int handle_send_1(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
+{
+ Onion *onion = (Onion *)object;
+
+ if (length > ONION_MAX_PACKET_SIZE) {
+ return 1;
+ }
+
+ if (length <= 1 + SEND_2) {
+ return 1;
+ }
+
+ change_symmetric_key(onion);
+
+ uint8_t plain[ONION_MAX_PACKET_SIZE];
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
+ get_shared_key(&onion->shared_keys_2, shared_key, onion->dht->self_secret_key, packet + 1 + CRYPTO_NONCE_SIZE);
+ int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
+ length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1), plain);
+
+ if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1 + CRYPTO_MAC_SIZE)) {
+ return 1;
+ }
+
+ IP_Port send_to;
+
+ if (ipport_unpack(&send_to, plain, len, 0) == -1) {
+ return 1;
+ }
+
+ uint8_t data[ONION_MAX_PACKET_SIZE];
+ data[0] = NET_PACKET_ONION_SEND_2;
+ memcpy(data + 1, packet + 1, CRYPTO_NONCE_SIZE);
+ memcpy(data + 1 + CRYPTO_NONCE_SIZE, plain + SIZE_IPPORT, len - SIZE_IPPORT);
+ uint16_t data_len = 1 + CRYPTO_NONCE_SIZE + (len - SIZE_IPPORT);
+ uint8_t *ret_part = data + data_len;
+ random_nonce(ret_part);
+ uint8_t ret_data[RETURN_1 + SIZE_IPPORT];
+ ipport_pack(ret_data, &source);
+ memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_1), RETURN_1);
+ len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
+ ret_part + CRYPTO_NONCE_SIZE);
+
+ if (len != RETURN_2 - CRYPTO_NONCE_SIZE) {
+ return 1;
+ }
+
+ data_len += CRYPTO_NONCE_SIZE + len;
+
+ if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static int handle_send_2(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
+{
+ Onion *onion = (Onion *)object;
+
+ if (length > ONION_MAX_PACKET_SIZE) {
+ return 1;
+ }
+
+ if (length <= 1 + SEND_3) {
+ return 1;
+ }
+
+ change_symmetric_key(onion);
+
+ uint8_t plain[ONION_MAX_PACKET_SIZE];
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
+ get_shared_key(&onion->shared_keys_3, shared_key, onion->dht->self_secret_key, packet + 1 + CRYPTO_NONCE_SIZE);
+ int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
+ length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2), plain);
+
+ if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2 + CRYPTO_MAC_SIZE)) {
+ return 1;
+ }
+
+ IP_Port send_to;
+
+ if (ipport_unpack(&send_to, plain, len, 0) == -1) {
+ return 1;
+ }
+
+ uint8_t data[ONION_MAX_PACKET_SIZE];
+ memcpy(data, plain + SIZE_IPPORT, len - SIZE_IPPORT);
+ uint16_t data_len = (len - SIZE_IPPORT);
+ uint8_t *ret_part = data + (len - SIZE_IPPORT);
+ random_nonce(ret_part);
+ uint8_t ret_data[RETURN_2 + SIZE_IPPORT];
+ ipport_pack(ret_data, &source);
+ memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_2), RETURN_2);
+ len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
+ ret_part + CRYPTO_NONCE_SIZE);
+
+ if (len != RETURN_3 - CRYPTO_NONCE_SIZE) {
+ return 1;
+ }
+
+ data_len += RETURN_3;
+
+ if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int handle_recv_3(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
+{
+ Onion *onion = (Onion *)object;
+
+ if (length > ONION_MAX_PACKET_SIZE) {
+ return 1;
+ }
+
+ if (length <= 1 + RETURN_3) {
+ return 1;
+ }
+
+ change_symmetric_key(onion);
+
+ uint8_t plain[SIZE_IPPORT + RETURN_2];
+ int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
+ SIZE_IPPORT + RETURN_2 + CRYPTO_MAC_SIZE, plain);
+
+ if ((uint32_t)len != sizeof(plain)) {
+ return 1;
+ }
+
+ IP_Port send_to;
+
+ if (ipport_unpack(&send_to, plain, len, 0) == -1) {
+ return 1;
+ }
+
+ uint8_t data[ONION_MAX_PACKET_SIZE];
+ data[0] = NET_PACKET_ONION_RECV_2;
+ memcpy(data + 1, plain + SIZE_IPPORT, RETURN_2);
+ memcpy(data + 1 + RETURN_2, packet + 1 + RETURN_3, length - (1 + RETURN_3));
+ uint16_t data_len = 1 + RETURN_2 + (length - (1 + RETURN_3));
+
+ if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static int handle_recv_2(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
+{
+ Onion *onion = (Onion *)object;
+
+ if (length > ONION_MAX_PACKET_SIZE) {
+ return 1;
+ }
+
+ if (length <= 1 + RETURN_2) {
+ return 1;
+ }
+
+ change_symmetric_key(onion);
+
+ uint8_t plain[SIZE_IPPORT + RETURN_1];
+ int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
+ SIZE_IPPORT + RETURN_1 + CRYPTO_MAC_SIZE, plain);
+
+ if ((uint32_t)len != sizeof(plain)) {
+ return 1;
+ }
+
+ IP_Port send_to;
+
+ if (ipport_unpack(&send_to, plain, len, 0) == -1) {
+ return 1;
+ }
+
+ uint8_t data[ONION_MAX_PACKET_SIZE];
+ data[0] = NET_PACKET_ONION_RECV_1;
+ memcpy(data + 1, plain + SIZE_IPPORT, RETURN_1);
+ memcpy(data + 1 + RETURN_1, packet + 1 + RETURN_2, length - (1 + RETURN_2));
+ uint16_t data_len = 1 + RETURN_1 + (length - (1 + RETURN_2));
+
+ if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static int handle_recv_1(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
+{
+ Onion *onion = (Onion *)object;
+
+ if (length > ONION_MAX_PACKET_SIZE) {
+ return 1;
+ }
+
+ if (length <= 1 + RETURN_1) {
+ return 1;
+ }
+
+ change_symmetric_key(onion);
+
+ uint8_t plain[SIZE_IPPORT];
+ int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
+ SIZE_IPPORT + CRYPTO_MAC_SIZE, plain);
+
+ if ((uint32_t)len != SIZE_IPPORT) {
+ return 1;
+ }
+
+ IP_Port send_to;
+
+ if (ipport_unpack(&send_to, plain, len, 1) == -1) {
+ return 1;
+ }
+
+ uint16_t data_len = length - (1 + RETURN_1);
+
+ if (onion->recv_1_function &&
+ send_to.ip.family != TOX_AF_INET &&
+ send_to.ip.family != TOX_AF_INET6) {
+ return onion->recv_1_function(onion->callback_object, send_to, packet + (1 + RETURN_1), data_len);
+ }
+
+ if ((uint32_t)sendpacket(onion->net, send_to, packet + (1 + RETURN_1), data_len) != data_len) {
+ return 1;
+ }
+
+ return 0;
+}
+
+void set_callback_handle_recv_1(Onion *onion, int (*function)(void *, IP_Port, const uint8_t *, uint16_t), void *object)
+{
+ onion->recv_1_function = function;
+ onion->callback_object = object;
+}
+
+Onion *new_onion(DHT *dht)
+{
+ if (dht == NULL) {
+ return NULL;
+ }
+
+ Onion *onion = (Onion *)calloc(1, sizeof(Onion));
+
+ if (onion == NULL) {
+ return NULL;
+ }
+
+ onion->dht = dht;
+ onion->net = dht->net;
+ new_symmetric_key(onion->secret_symmetric_key);
+ onion->timestamp = unix_time();
+
+ networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, &handle_send_initial, onion);
+ networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, &handle_send_1, onion);
+ networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_2, &handle_send_2, onion);
+
+ networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_3, &handle_recv_3, onion);
+ networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_2, &handle_recv_2, onion);
+ networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_1, &handle_recv_1, onion);
+
+ return onion;
+}
+
+void kill_onion(Onion *onion)
+{
+ if (onion == NULL) {
+ return;
+ }
+
+ networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, NULL, NULL);
+ networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, NULL, NULL);
+ networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_2, NULL, NULL);
+
+ networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_3, NULL, NULL);
+ networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_2, NULL, NULL);
+ networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_1, NULL, NULL);
+
+ free(onion);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/onion.h b/protocols/Tox/libtox/src/toxcore/onion.h
new file mode 100644
index 0000000000..e81b3a52ae
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/onion.h
@@ -0,0 +1,165 @@
+/*
+ * Implementation of the onion part of docs/Prevent_Tracking.txt
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef ONION_H
+#define ONION_H
+
+#include "DHT.h"
+
+typedef struct {
+ DHT *dht;
+ Networking_Core *net;
+ uint8_t secret_symmetric_key[CRYPTO_SYMMETRIC_KEY_SIZE];
+ uint64_t timestamp;
+
+ Shared_Keys shared_keys_1;
+ Shared_Keys shared_keys_2;
+ Shared_Keys shared_keys_3;
+
+ int (*recv_1_function)(void *, IP_Port, const uint8_t *, uint16_t);
+ void *callback_object;
+} Onion;
+
+#define ONION_MAX_PACKET_SIZE 1400
+
+#define ONION_RETURN_1 (CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_MAC_SIZE)
+#define ONION_RETURN_2 (CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_MAC_SIZE + ONION_RETURN_1)
+#define ONION_RETURN_3 (CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_MAC_SIZE + ONION_RETURN_2)
+
+#define ONION_SEND_BASE (CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT + CRYPTO_MAC_SIZE)
+#define ONION_SEND_3 (CRYPTO_NONCE_SIZE + ONION_SEND_BASE + ONION_RETURN_2)
+#define ONION_SEND_2 (CRYPTO_NONCE_SIZE + ONION_SEND_BASE*2 + ONION_RETURN_1)
+#define ONION_SEND_1 (CRYPTO_NONCE_SIZE + ONION_SEND_BASE*3)
+
+#define ONION_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (ONION_SEND_1 + 1))
+#define ONION_RESPONSE_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (1 + ONION_RETURN_3))
+
+#define ONION_PATH_LENGTH 3
+
+typedef struct {
+ uint8_t shared_key1[CRYPTO_SHARED_KEY_SIZE];
+ uint8_t shared_key2[CRYPTO_SHARED_KEY_SIZE];
+ uint8_t shared_key3[CRYPTO_SHARED_KEY_SIZE];
+
+ uint8_t public_key1[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t public_key2[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t public_key3[CRYPTO_PUBLIC_KEY_SIZE];
+
+ IP_Port ip_port1;
+ uint8_t node_public_key1[CRYPTO_PUBLIC_KEY_SIZE];
+
+ IP_Port ip_port2;
+ uint8_t node_public_key2[CRYPTO_PUBLIC_KEY_SIZE];
+
+ IP_Port ip_port3;
+ uint8_t node_public_key3[CRYPTO_PUBLIC_KEY_SIZE];
+
+ uint32_t path_num;
+} Onion_Path;
+
+/* Create a new onion path.
+ *
+ * Create a new onion path out of nodes (nodes is a list of ONION_PATH_LENGTH nodes)
+ *
+ * new_path must be an empty memory location of atleast Onion_Path size.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int create_onion_path(const DHT *dht, Onion_Path *new_path, const Node_format *nodes);
+
+/* Dump nodes in onion path to nodes of length num_nodes;
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_Path *path);
+
+/* Create a onion packet.
+ *
+ * Use Onion_Path path to create packet for data of length to dest.
+ * Maximum length of data is ONION_MAX_DATA_SIZE.
+ * packet should be at least ONION_MAX_PACKET_SIZE big.
+ *
+ * return -1 on failure.
+ * return length of created packet on success.
+ */
+int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest,
+ const uint8_t *data, uint16_t length);
+
+
+/* Create a onion packet to be sent over tcp.
+ *
+ * Use Onion_Path path to create packet for data of length to dest.
+ * Maximum length of data is ONION_MAX_DATA_SIZE.
+ * packet should be at least ONION_MAX_PACKET_SIZE big.
+ *
+ * return -1 on failure.
+ * return length of created packet on success.
+ */
+int create_onion_packet_tcp(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest,
+ const uint8_t *data, uint16_t length);
+
+/* Create and send a onion packet.
+ *
+ * Use Onion_Path path to send data of length to dest.
+ * Maximum length of data is ONION_MAX_DATA_SIZE.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int send_onion_packet(Networking_Core *net, const Onion_Path *path, IP_Port dest, const uint8_t *data, uint16_t length);
+
+/* Create and send a onion response sent initially to dest with.
+ * Maximum length of data is ONION_RESPONSE_MAX_DATA_SIZE.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int send_onion_response(Networking_Core *net, IP_Port dest, const uint8_t *data, uint16_t length, const uint8_t *ret);
+
+/* Function to handle/send received decrypted versions of the packet sent with send_onion_packet.
+ *
+ * return 0 on success.
+ * return 1 on failure.
+ *
+ * Used to handle these packets that are received in a non traditional way (by TCP for example).
+ *
+ * Source family must be set to something else than TOX_AF_INET6 or TOX_AF_INET so that the callback gets called
+ * when the response is received.
+ */
+int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port source, const uint8_t *nonce);
+
+/* Set the callback to be called when the dest ip_port doesn't have TOX_AF_INET6 or TOX_AF_INET as the family.
+ *
+ * Format: function(void *object, IP_Port dest, uint8_t *data, uint16_t length)
+ */
+void set_callback_handle_recv_1(Onion *onion, int (*function)(void *, IP_Port, const uint8_t *, uint16_t),
+ void *object);
+
+Onion *new_onion(DHT *dht);
+
+void kill_onion(Onion *onion);
+
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxcore/onion_announce.c b/protocols/Tox/libtox/src/toxcore/onion_announce.c
new file mode 100644
index 0000000000..c093800719
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/onion_announce.c
@@ -0,0 +1,497 @@
+/*
+ * Implementation of the announce part of docs/Prevent_Tracking.txt
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "onion_announce.h"
+
+#include "LAN_discovery.h"
+#include "util.h"
+
+#define PING_ID_TIMEOUT ONION_ANNOUNCE_TIMEOUT
+
+#define ANNOUNCE_REQUEST_SIZE_RECV (ONION_ANNOUNCE_REQUEST_SIZE + ONION_RETURN_3)
+
+#define DATA_REQUEST_MIN_SIZE ONION_DATA_REQUEST_MIN_SIZE
+#define DATA_REQUEST_MIN_SIZE_RECV (DATA_REQUEST_MIN_SIZE + ONION_RETURN_3)
+
+/* Create an onion announce request packet in packet of max_packet_length (recommended size ONION_ANNOUNCE_REQUEST_SIZE).
+ *
+ * dest_client_id is the public key of the node the packet will be sent to.
+ * public_key and secret_key is the kepair which will be used to encrypt the request.
+ * ping_id is the ping id that will be sent in the request.
+ * client_id is the client id of the node we are searching for.
+ * data_public_key is the public key we want others to encrypt their data packets with.
+ * sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to
+ * receive back in the response.
+ *
+ * return -1 on failure.
+ * return packet length on success.
+ */
+int create_announce_request(uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id,
+ const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id,
+ const uint8_t *data_public_key, uint64_t sendback_data)
+{
+ if (max_packet_length < ONION_ANNOUNCE_REQUEST_SIZE) {
+ return -1;
+ }
+
+ uint8_t plain[ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE +
+ ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
+ memcpy(plain, ping_id, ONION_PING_ID_SIZE);
+ memcpy(plain + ONION_PING_ID_SIZE, client_id, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE, &sendback_data,
+ sizeof(sendback_data));
+
+ packet[0] = NET_PACKET_ANNOUNCE_REQUEST;
+ random_nonce(packet + 1);
+
+ int len = encrypt_data(dest_client_id, secret_key, packet + 1, plain, sizeof(plain),
+ packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
+
+ if ((uint32_t)len + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE != ONION_ANNOUNCE_REQUEST_SIZE) {
+ return -1;
+ }
+
+ memcpy(packet + 1 + CRYPTO_NONCE_SIZE, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+
+ return ONION_ANNOUNCE_REQUEST_SIZE;
+}
+
+/* Create an onion data request packet in packet of max_packet_length (recommended size ONION_MAX_PACKET_SIZE).
+ *
+ * public_key is the real public key of the node which we want to send the data of length length to.
+ * encrypt_public_key is the public key used to encrypt the data packet.
+ *
+ * nonce is the nonce to encrypt this packet with
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int create_data_request(uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key,
+ const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length)
+{
+ if (DATA_REQUEST_MIN_SIZE + length > max_packet_length) {
+ return -1;
+ }
+
+ if (DATA_REQUEST_MIN_SIZE + length > ONION_MAX_DATA_SIZE) {
+ return -1;
+ }
+
+ packet[0] = NET_PACKET_ONION_DATA_REQUEST;
+ memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
+
+ uint8_t random_public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t random_secret_key[CRYPTO_SECRET_KEY_SIZE];
+ crypto_new_keypair(random_public_key, random_secret_key);
+
+ memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, random_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+
+ int len = encrypt_data(encrypt_public_key, random_secret_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length,
+ packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
+
+ if (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + len != DATA_REQUEST_MIN_SIZE +
+ length) {
+ return -1;
+ }
+
+ return DATA_REQUEST_MIN_SIZE + length;
+}
+
+/* Create and send an onion announce request packet.
+ *
+ * path is the path the request will take before it is sent to dest.
+ *
+ * public_key and secret_key is the kepair which will be used to encrypt the request.
+ * ping_id is the ping id that will be sent in the request.
+ * client_id is the client id of the node we are searching for.
+ * data_public_key is the public key we want others to encrypt their data packets with.
+ * sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to
+ * receive back in the response.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int send_announce_request(Networking_Core *net, const Onion_Path *path, Node_format dest, const uint8_t *public_key,
+ const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id, const uint8_t *data_public_key,
+ uint64_t sendback_data)
+{
+ uint8_t request[ONION_ANNOUNCE_REQUEST_SIZE];
+ int len = create_announce_request(request, sizeof(request), dest.public_key, public_key, secret_key, ping_id, client_id,
+ data_public_key, sendback_data);
+
+ if (len != sizeof(request)) {
+ return -1;
+ }
+
+ uint8_t packet[ONION_MAX_PACKET_SIZE];
+ len = create_onion_packet(packet, sizeof(packet), path, dest.ip_port, request, sizeof(request));
+
+ if (len == -1) {
+ return -1;
+ }
+
+ if (sendpacket(net, path->ip_port1, packet, len) != len) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Create and send an onion data request packet.
+ *
+ * path is the path the request will take before it is sent to dest.
+ * (if dest knows the person with the public_key they should
+ * send the packet to that person in the form of a response)
+ *
+ * public_key is the real public key of the node which we want to send the data of length length to.
+ * encrypt_public_key is the public key used to encrypt the data packet.
+ *
+ * nonce is the nonce to encrypt this packet with
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int send_data_request(Networking_Core *net, const Onion_Path *path, IP_Port dest, const uint8_t *public_key,
+ const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length)
+{
+ uint8_t request[ONION_MAX_DATA_SIZE];
+ int len = create_data_request(request, sizeof(request), public_key, encrypt_public_key, nonce, data, length);
+
+ if (len == -1) {
+ return -1;
+ }
+
+ uint8_t packet[ONION_MAX_PACKET_SIZE];
+ len = create_onion_packet(packet, sizeof(packet), path, dest, request, len);
+
+ if (len == -1) {
+ return -1;
+ }
+
+ if (sendpacket(net, path->ip_port1, packet, len) != len) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Generate a ping_id and put it in ping_id */
+static void generate_ping_id(const Onion_Announce *onion_a, uint64_t time, const uint8_t *public_key,
+ IP_Port ret_ip_port, uint8_t *ping_id)
+{
+ time /= PING_ID_TIMEOUT;
+ uint8_t data[CRYPTO_SYMMETRIC_KEY_SIZE + sizeof(time) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(ret_ip_port)];
+ memcpy(data, onion_a->secret_bytes, CRYPTO_SYMMETRIC_KEY_SIZE);
+ memcpy(data + CRYPTO_SYMMETRIC_KEY_SIZE, &time, sizeof(time));
+ memcpy(data + CRYPTO_SYMMETRIC_KEY_SIZE + sizeof(time), public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(data + CRYPTO_SYMMETRIC_KEY_SIZE + sizeof(time) + CRYPTO_PUBLIC_KEY_SIZE, &ret_ip_port, sizeof(ret_ip_port));
+ crypto_sha256(ping_id, data, sizeof(data));
+}
+
+/* check if public key is in entries list
+ *
+ * return -1 if no
+ * return position in list if yes
+ */
+static int in_entries(const Onion_Announce *onion_a, const uint8_t *public_key)
+{
+ unsigned int i;
+
+ for (i = 0; i < ONION_ANNOUNCE_MAX_ENTRIES; ++i) {
+ if (!is_timeout(onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT)
+ && public_key_cmp(onion_a->entries[i].public_key, public_key) == 0) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+typedef struct {
+ const uint8_t *base_public_key;
+ Onion_Announce_Entry entry;
+} Cmp_data;
+
+static int cmp_entry(const void *a, const void *b)
+{
+ Cmp_data cmp1, cmp2;
+ memcpy(&cmp1, a, sizeof(Cmp_data));
+ memcpy(&cmp2, b, sizeof(Cmp_data));
+ Onion_Announce_Entry entry1 = cmp1.entry;
+ Onion_Announce_Entry entry2 = cmp2.entry;
+ const uint8_t *cmp_public_key = cmp1.base_public_key;
+
+ int t1 = is_timeout(entry1.time, ONION_ANNOUNCE_TIMEOUT);
+ int t2 = is_timeout(entry2.time, ONION_ANNOUNCE_TIMEOUT);
+
+ if (t1 && t2) {
+ return 0;
+ }
+
+ if (t1) {
+ return -1;
+ }
+
+ if (t2) {
+ return 1;
+ }
+
+ int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);
+
+ if (close == 1) {
+ return 1;
+ }
+
+ if (close == 2) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static void sort_onion_announce_list(Onion_Announce_Entry *list, unsigned int length, const uint8_t *comp_public_key)
+{
+ // Pass comp_public_key to qsort with each Client_data entry, so the
+ // comparison function can use it as the base of comparison.
+ VLA(Cmp_data, cmp_list, length);
+
+ for (uint32_t i = 0; i < length; i++) {
+ cmp_list[i].base_public_key = comp_public_key;
+ cmp_list[i].entry = list[i];
+ }
+
+ qsort(cmp_list, length, sizeof(Cmp_data), cmp_entry);
+
+ for (uint32_t i = 0; i < length; i++) {
+ list[i] = cmp_list[i].entry;
+ }
+}
+
+/* add entry to entries list
+ *
+ * return -1 if failure
+ * return position if added
+ */
+static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, const uint8_t *public_key,
+ const uint8_t *data_public_key, const uint8_t *ret)
+{
+
+ int pos = in_entries(onion_a, public_key);
+
+ unsigned int i;
+
+ if (pos == -1) {
+ for (i = 0; i < ONION_ANNOUNCE_MAX_ENTRIES; ++i) {
+ if (is_timeout(onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT)) {
+ pos = i;
+ }
+ }
+ }
+
+ if (pos == -1) {
+ if (id_closest(onion_a->dht->self_public_key, public_key, onion_a->entries[0].public_key) == 1) {
+ pos = 0;
+ }
+ }
+
+ if (pos == -1) {
+ return -1;
+ }
+
+ memcpy(onion_a->entries[pos].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ onion_a->entries[pos].ret_ip_port = ret_ip_port;
+ memcpy(onion_a->entries[pos].ret, ret, ONION_RETURN_3);
+ memcpy(onion_a->entries[pos].data_public_key, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ onion_a->entries[pos].time = unix_time();
+
+ sort_onion_announce_list(onion_a->entries, ONION_ANNOUNCE_MAX_ENTRIES, onion_a->dht->self_public_key);
+ return in_entries(onion_a, public_key);
+}
+
+static int handle_announce_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
+{
+ Onion_Announce *onion_a = (Onion_Announce *)object;
+
+ if (length != ANNOUNCE_REQUEST_SIZE_RECV) {
+ return 1;
+ }
+
+ const uint8_t *packet_public_key = packet + 1 + CRYPTO_NONCE_SIZE;
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
+ get_shared_key(&onion_a->shared_keys_recv, shared_key, onion_a->dht->self_secret_key, packet_public_key);
+
+ uint8_t plain[ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE +
+ ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
+ int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
+ ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH +
+ CRYPTO_MAC_SIZE, plain);
+
+ if ((uint32_t)len != sizeof(plain)) {
+ return 1;
+ }
+
+ uint8_t ping_id1[ONION_PING_ID_SIZE];
+ generate_ping_id(onion_a, unix_time(), packet_public_key, source, ping_id1);
+
+ uint8_t ping_id2[ONION_PING_ID_SIZE];
+ generate_ping_id(onion_a, unix_time() + PING_ID_TIMEOUT, packet_public_key, source, ping_id2);
+
+ int index = -1;
+
+ uint8_t *data_public_key = plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE;
+
+ if (crypto_memcmp(ping_id1, plain, ONION_PING_ID_SIZE) == 0
+ || crypto_memcmp(ping_id2, plain, ONION_PING_ID_SIZE) == 0) {
+ index = add_to_entries(onion_a, source, packet_public_key, data_public_key,
+ packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3));
+ } else {
+ index = in_entries(onion_a, plain + ONION_PING_ID_SIZE);
+ }
+
+ /*Respond with a announce response packet*/
+ Node_format nodes_list[MAX_SENT_NODES];
+ unsigned int num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, 0,
+ LAN_ip(source.ip) == 0, 1);
+ uint8_t nonce[CRYPTO_NONCE_SIZE];
+ random_nonce(nonce);
+
+ uint8_t pl[1 + ONION_PING_ID_SIZE + sizeof(nodes_list)];
+
+ if (index == -1) {
+ pl[0] = 0;
+ memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE);
+ } else {
+ if (public_key_cmp(onion_a->entries[index].public_key, packet_public_key) == 0) {
+ if (public_key_cmp(onion_a->entries[index].data_public_key, data_public_key) != 0) {
+ pl[0] = 0;
+ memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE);
+ } else {
+ pl[0] = 2;
+ memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE);
+ }
+ } else {
+ pl[0] = 1;
+ memcpy(pl + 1, onion_a->entries[index].data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ }
+ }
+
+ int nodes_length = 0;
+
+ if (num_nodes != 0) {
+ nodes_length = pack_nodes(pl + 1 + ONION_PING_ID_SIZE, sizeof(nodes_list), nodes_list, num_nodes);
+
+ if (nodes_length <= 0) {
+ return 1;
+ }
+ }
+
+ uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE];
+ len = encrypt_data_symmetric(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + nodes_length,
+ data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE);
+
+ if (len != 1 + ONION_PING_ID_SIZE + nodes_length + CRYPTO_MAC_SIZE) {
+ return 1;
+ }
+
+ data[0] = NET_PACKET_ANNOUNCE_RESPONSE;
+ memcpy(data + 1, plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
+ ONION_ANNOUNCE_SENDBACK_DATA_LENGTH);
+ memcpy(data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, nonce, CRYPTO_NONCE_SIZE);
+
+ if (send_onion_response(onion_a->net, source, data,
+ 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE + len,
+ packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3)) == -1) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static int handle_data_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
+{
+ Onion_Announce *onion_a = (Onion_Announce *)object;
+
+ if (length <= DATA_REQUEST_MIN_SIZE_RECV) {
+ return 1;
+ }
+
+ if (length > ONION_MAX_PACKET_SIZE) {
+ return 1;
+ }
+
+ int index = in_entries(onion_a, packet + 1);
+
+ if (index == -1) {
+ return 1;
+ }
+
+ VLA(uint8_t, data, length - (CRYPTO_PUBLIC_KEY_SIZE + ONION_RETURN_3));
+ data[0] = NET_PACKET_ONION_DATA_RESPONSE;
+ memcpy(data + 1, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, length - (1 + CRYPTO_PUBLIC_KEY_SIZE + ONION_RETURN_3));
+
+ if (send_onion_response(onion_a->net, onion_a->entries[index].ret_ip_port, data, SIZEOF_VLA(data),
+ onion_a->entries[index].ret) == -1) {
+ return 1;
+ }
+
+ return 0;
+}
+
+Onion_Announce *new_onion_announce(DHT *dht)
+{
+ if (dht == NULL) {
+ return NULL;
+ }
+
+ Onion_Announce *onion_a = (Onion_Announce *)calloc(1, sizeof(Onion_Announce));
+
+ if (onion_a == NULL) {
+ return NULL;
+ }
+
+ onion_a->dht = dht;
+ onion_a->net = dht->net;
+ new_symmetric_key(onion_a->secret_bytes);
+
+ networking_registerhandler(onion_a->net, NET_PACKET_ANNOUNCE_REQUEST, &handle_announce_request, onion_a);
+ networking_registerhandler(onion_a->net, NET_PACKET_ONION_DATA_REQUEST, &handle_data_request, onion_a);
+
+ return onion_a;
+}
+
+void kill_onion_announce(Onion_Announce *onion_a)
+{
+ if (onion_a == NULL) {
+ return;
+ }
+
+ networking_registerhandler(onion_a->net, NET_PACKET_ANNOUNCE_REQUEST, NULL, NULL);
+ networking_registerhandler(onion_a->net, NET_PACKET_ONION_DATA_REQUEST, NULL, NULL);
+ free(onion_a);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/onion_announce.h b/protocols/Tox/libtox/src/toxcore/onion_announce.h
new file mode 100644
index 0000000000..548d4b798b
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/onion_announce.h
@@ -0,0 +1,140 @@
+/*
+ * Implementation of the announce part of docs/Prevent_Tracking.txt
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef ONION_ANNOUNCE_H
+#define ONION_ANNOUNCE_H
+
+#include "onion.h"
+
+#define ONION_ANNOUNCE_MAX_ENTRIES 160
+#define ONION_ANNOUNCE_TIMEOUT 300
+#define ONION_PING_ID_SIZE CRYPTO_SHA256_SIZE
+
+#define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (sizeof(uint64_t))
+
+#define ONION_ANNOUNCE_REQUEST_SIZE (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_MAC_SIZE)
+
+#define ONION_ANNOUNCE_RESPONSE_MIN_SIZE (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE + 1 + ONION_PING_ID_SIZE + CRYPTO_MAC_SIZE)
+#define ONION_ANNOUNCE_RESPONSE_MAX_SIZE (ONION_ANNOUNCE_RESPONSE_MIN_SIZE + sizeof(Node_format)*MAX_SENT_NODES)
+
+#define ONION_DATA_RESPONSE_MIN_SIZE (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)
+
+#if ONION_PING_ID_SIZE != CRYPTO_PUBLIC_KEY_SIZE
+#error announce response packets assume that ONION_PING_ID_SIZE is equal to CRYPTO_PUBLIC_KEY_SIZE
+#endif
+
+#define ONION_DATA_REQUEST_MIN_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)
+#define MAX_DATA_REQUEST_SIZE (ONION_MAX_DATA_SIZE - ONION_DATA_REQUEST_MIN_SIZE)
+
+typedef struct {
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ IP_Port ret_ip_port;
+ uint8_t ret[ONION_RETURN_3];
+ uint8_t data_public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint64_t time;
+} Onion_Announce_Entry;
+
+typedef struct {
+ DHT *dht;
+ Networking_Core *net;
+ Onion_Announce_Entry entries[ONION_ANNOUNCE_MAX_ENTRIES];
+ /* This is CRYPTO_SYMMETRIC_KEY_SIZE long just so we can use new_symmetric_key() to fill it */
+ uint8_t secret_bytes[CRYPTO_SYMMETRIC_KEY_SIZE];
+
+ Shared_Keys shared_keys_recv;
+} Onion_Announce;
+
+/* Create an onion announce request packet in packet of max_packet_length (recommended size ONION_ANNOUNCE_REQUEST_SIZE).
+ *
+ * dest_client_id is the public key of the node the packet will be sent to.
+ * public_key and secret_key is the kepair which will be used to encrypt the request.
+ * ping_id is the ping id that will be sent in the request.
+ * client_id is the client id of the node we are searching for.
+ * data_public_key is the public key we want others to encrypt their data packets with.
+ * sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to
+ * receive back in the response.
+ *
+ * return -1 on failure.
+ * return packet length on success.
+ */
+int create_announce_request(uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id,
+ const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id,
+ const uint8_t *data_public_key, uint64_t sendback_data);
+
+/* Create an onion data request packet in packet of max_packet_length (recommended size ONION_MAX_PACKET_SIZE).
+ *
+ * public_key is the real public key of the node which we want to send the data of length length to.
+ * encrypt_public_key is the public key used to encrypt the data packet.
+ *
+ * nonce is the nonce to encrypt this packet with
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int create_data_request(uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key,
+ const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length);
+
+/* Create and send an onion announce request packet.
+ *
+ * path is the path the request will take before it is sent to dest.
+ *
+ * public_key and secret_key is the kepair which will be used to encrypt the request.
+ * ping_id is the ping id that will be sent in the request.
+ * client_id is the client id of the node we are searching for.
+ * data_public_key is the public key we want others to encrypt their data packets with.
+ * sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to
+ * receive back in the response.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int send_announce_request(Networking_Core *net, const Onion_Path *path, Node_format dest, const uint8_t *public_key,
+ const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id, const uint8_t *data_public_key,
+ uint64_t sendback_data);
+
+/* Create and send an onion data request packet.
+ *
+ * path is the path the request will take before it is sent to dest.
+ * (if dest knows the person with the public_key they should
+ * send the packet to that person in the form of a response)
+ *
+ * public_key is the real public key of the node which we want to send the data of length length to.
+ * encrypt_public_key is the public key used to encrypt the data packet.
+ *
+ * nonce is the nonce to encrypt this packet with
+ *
+ * The maximum length of data is MAX_DATA_REQUEST_SIZE.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int send_data_request(Networking_Core *net, const Onion_Path *path, IP_Port dest, const uint8_t *public_key,
+ const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length);
+
+
+Onion_Announce *new_onion_announce(DHT *dht);
+
+void kill_onion_announce(Onion_Announce *onion_a);
+
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxcore/onion_client.c b/protocols/Tox/libtox/src/toxcore/onion_client.c
new file mode 100644
index 0000000000..94e9c91652
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/onion_client.c
@@ -0,0 +1,1771 @@
+/*
+ * Implementation of the client part of docs/Prevent_Tracking.txt (The part that
+ * uses the onion stuff to connect to the friend)
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "onion_client.h"
+
+#include "LAN_discovery.h"
+#include "util.h"
+
+/* defines for the array size and
+ timeout for onion announce packets. */
+#define ANNOUNCE_ARRAY_SIZE 256
+#define ANNOUNCE_TIMEOUT 10
+
+/* Add a node to the path_nodes bootstrap array.
+ *
+ * return -1 on failure
+ * return 0 on success
+ */
+int onion_add_bs_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key)
+{
+ if (ip_port.ip.family != TOX_AF_INET && ip_port.ip.family != TOX_AF_INET6) {
+ return -1;
+ }
+
+ unsigned int i;
+
+ for (i = 0; i < MAX_PATH_NODES; ++i) {
+ if (public_key_cmp(public_key, onion_c->path_nodes_bs[i].public_key) == 0) {
+ return -1;
+ }
+ }
+
+ onion_c->path_nodes_bs[onion_c->path_nodes_index_bs % MAX_PATH_NODES].ip_port = ip_port;
+ memcpy(onion_c->path_nodes_bs[onion_c->path_nodes_index_bs % MAX_PATH_NODES].public_key, public_key,
+ CRYPTO_PUBLIC_KEY_SIZE);
+
+ uint16_t last = onion_c->path_nodes_index_bs;
+ ++onion_c->path_nodes_index_bs;
+
+ if (onion_c->path_nodes_index_bs < last) {
+ onion_c->path_nodes_index_bs = MAX_PATH_NODES + 1;
+ }
+
+ return 0;
+}
+
+/* Add a node to the path_nodes array.
+ *
+ * return -1 on failure
+ * return 0 on success
+ */
+static int onion_add_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key)
+{
+ if (ip_port.ip.family != TOX_AF_INET && ip_port.ip.family != TOX_AF_INET6) {
+ return -1;
+ }
+
+ unsigned int i;
+
+ for (i = 0; i < MAX_PATH_NODES; ++i) {
+ if (public_key_cmp(public_key, onion_c->path_nodes[i].public_key) == 0) {
+ return -1;
+ }
+ }
+
+ onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].ip_port = ip_port;
+ memcpy(onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].public_key, public_key,
+ CRYPTO_PUBLIC_KEY_SIZE);
+
+ uint16_t last = onion_c->path_nodes_index;
+ ++onion_c->path_nodes_index;
+
+ if (onion_c->path_nodes_index < last) {
+ onion_c->path_nodes_index = MAX_PATH_NODES + 1;
+ }
+
+ return 0;
+}
+
+/* Put up to max_num nodes in nodes.
+ *
+ * return the number of nodes.
+ */
+uint16_t onion_backup_nodes(const Onion_Client *onion_c, Node_format *nodes, uint16_t max_num)
+{
+ unsigned int i;
+
+ if (!max_num) {
+ return 0;
+ }
+
+ unsigned int num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES;
+
+ if (num_nodes == 0) {
+ return 0;
+ }
+
+ if (num_nodes < max_num) {
+ max_num = num_nodes;
+ }
+
+ for (i = 0; i < max_num; ++i) {
+ nodes[i] = onion_c->path_nodes[(onion_c->path_nodes_index - (1 + i)) % num_nodes];
+ }
+
+ return max_num;
+}
+
+/* Put up to max_num random nodes in nodes.
+ *
+ * return the number of nodes.
+ */
+static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format *nodes, uint16_t max_num)
+{
+ unsigned int i;
+
+ if (!max_num) {
+ return 0;
+ }
+
+ unsigned int num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES;
+
+ //if (DHT_non_lan_connected(onion_c->dht)) {
+ if (DHT_isconnected(onion_c->dht)) {
+ if (num_nodes == 0) {
+ return 0;
+ }
+
+ for (i = 0; i < max_num; ++i) {
+ nodes[i] = onion_c->path_nodes[rand() % num_nodes];
+ }
+ } else {
+ int random_tcp = get_random_tcp_con_number(onion_c->c);
+
+ if (random_tcp == -1) {
+ return 0;
+ }
+
+ if (num_nodes >= 2) {
+ nodes[0].ip_port.ip.family = TCP_FAMILY;
+ nodes[0].ip_port.ip.ip4.uint32 = random_tcp;
+
+ for (i = 1; i < max_num; ++i) {
+ nodes[i] = onion_c->path_nodes[rand() % num_nodes];
+ }
+ } else {
+ unsigned int num_nodes_bs = (onion_c->path_nodes_index_bs < MAX_PATH_NODES) ? onion_c->path_nodes_index_bs :
+ MAX_PATH_NODES;
+
+ if (num_nodes_bs == 0) {
+ return 0;
+ }
+
+ nodes[0].ip_port.ip.family = TCP_FAMILY;
+ nodes[0].ip_port.ip.ip4.uint32 = random_tcp;
+
+ for (i = 1; i < max_num; ++i) {
+ nodes[i] = onion_c->path_nodes_bs[rand() % num_nodes_bs];
+ }
+ }
+ }
+
+ return max_num;
+}
+
+/*
+ * return -1 if nodes are suitable for creating a new path.
+ * return path number of already existing similar path if one already exists.
+ */
+static int is_path_used(const Onion_Client_Paths *onion_paths, const Node_format *nodes)
+{
+ unsigned int i;
+
+ for (i = 0; i < NUMBER_ONION_PATHS; ++i) {
+ if (is_timeout(onion_paths->last_path_success[i], ONION_PATH_TIMEOUT)) {
+ continue;
+ }
+
+ if (is_timeout(onion_paths->path_creation_time[i], ONION_PATH_MAX_LIFETIME)) {
+ continue;
+ }
+
+ // TODO(irungentoo): do we really have to check it with the last node?
+ if (ipport_equal(&onion_paths->paths[i].ip_port1, &nodes[ONION_PATH_LENGTH - 1].ip_port)) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/* is path timed out */
+static bool path_timed_out(Onion_Client_Paths *onion_paths, uint32_t pathnum)
+{
+ pathnum = pathnum % NUMBER_ONION_PATHS;
+
+ bool is_new = onion_paths->last_path_success[pathnum] == onion_paths->path_creation_time[pathnum];
+ uint64_t timeout = is_new ? ONION_PATH_FIRST_TIMEOUT : ONION_PATH_TIMEOUT;
+
+ return ((onion_paths->last_path_used_times[pathnum] >= ONION_PATH_MAX_NO_RESPONSE_USES
+ && is_timeout(onion_paths->last_path_used[pathnum], timeout))
+ || is_timeout(onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME));
+}
+
+/* should node be considered to have timed out */
+static bool onion_node_timed_out(const Onion_Node *node)
+{
+ return (node->timestamp == 0
+ || (node->unsuccessful_pings >= ONION_NODE_MAX_PINGS
+ && is_timeout(node->last_pinged, ONION_NODE_TIMEOUT)));
+}
+
+/* Create a new path or use an old suitable one (if pathnum is valid)
+ * or a random one from onion_paths.
+ *
+ * return -1 on failure
+ * return 0 on success
+ *
+ * TODO(irungentoo): Make this function better, it currently probably is
+ * vulnerable to some attacks that could deanonimize us.
+ */
+static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_paths, uint32_t pathnum, Onion_Path *path)
+{
+ if (pathnum == UINT32_MAX) {
+ pathnum = rand() % NUMBER_ONION_PATHS;
+ } else {
+ pathnum = pathnum % NUMBER_ONION_PATHS;
+ }
+
+ if (path_timed_out(onion_paths, pathnum)) {
+ Node_format nodes[ONION_PATH_LENGTH];
+
+ if (random_nodes_path_onion(onion_c, nodes, ONION_PATH_LENGTH) != ONION_PATH_LENGTH) {
+ return -1;
+ }
+
+ int n = is_path_used(onion_paths, nodes);
+
+ if (n == -1) {
+ if (create_onion_path(onion_c->dht, &onion_paths->paths[pathnum], nodes) == -1) {
+ return -1;
+ }
+
+ onion_paths->path_creation_time[pathnum] = unix_time();
+ onion_paths->last_path_success[pathnum] = onion_paths->path_creation_time[pathnum];
+ onion_paths->last_path_used_times[pathnum] = ONION_PATH_MAX_NO_RESPONSE_USES / 2;
+
+ uint32_t path_num = rand();
+ path_num /= NUMBER_ONION_PATHS;
+ path_num *= NUMBER_ONION_PATHS;
+ path_num += pathnum;
+
+ onion_paths->paths[pathnum].path_num = path_num;
+ } else {
+ pathnum = n;
+ }
+ }
+
+ if (onion_paths->last_path_used_times[pathnum] < ONION_PATH_MAX_NO_RESPONSE_USES) {
+ onion_paths->last_path_used[pathnum] = unix_time();
+ }
+
+ ++onion_paths->last_path_used_times[pathnum];
+ memcpy(path, &onion_paths->paths[pathnum], sizeof(Onion_Path));
+ return 0;
+}
+
+/* Does path with path_num exist. */
+static bool path_exists(Onion_Client_Paths *onion_paths, uint32_t path_num)
+{
+ if (path_timed_out(onion_paths, path_num)) {
+ return 0;
+ }
+
+ return onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num;
+}
+
+/* Set path timeouts, return the path number.
+ *
+ */
+static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t path_num)
+{
+ if (num > onion_c->num_friends) {
+ return -1;
+ }
+
+ Onion_Client_Paths *onion_paths;
+
+ if (num == 0) {
+ onion_paths = &onion_c->onion_paths_self;
+ } else {
+ onion_paths = &onion_c->onion_paths_friends;
+ }
+
+ if (onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num) {
+ onion_paths->last_path_success[path_num % NUMBER_ONION_PATHS] = unix_time();
+ onion_paths->last_path_used_times[path_num % NUMBER_ONION_PATHS] = 0;
+
+ Node_format nodes[ONION_PATH_LENGTH];
+
+ if (onion_path_to_nodes(nodes, ONION_PATH_LENGTH, &onion_paths->paths[path_num % NUMBER_ONION_PATHS]) == 0) {
+ unsigned int i;
+
+ for (i = 0; i < ONION_PATH_LENGTH; ++i) {
+ onion_add_path_node(onion_c, nodes[i].ip_port, nodes[i].public_key);
+ }
+ }
+
+ return path_num;
+ }
+
+ return ~0;
+}
+
+/* Function to send onion packet via TCP and UDP.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Path *path, IP_Port dest,
+ const uint8_t *data, uint16_t length)
+{
+ if (path->ip_port1.ip.family == TOX_AF_INET || path->ip_port1.ip.family == TOX_AF_INET6) {
+ uint8_t packet[ONION_MAX_PACKET_SIZE];
+ int len = create_onion_packet(packet, sizeof(packet), path, dest, data, length);
+
+ if (len == -1) {
+ return -1;
+ }
+
+ if (sendpacket(onion_c->net, path->ip_port1, packet, len) != len) {
+ return -1;
+ }
+
+ return 0;
+ }
+
+ if (path->ip_port1.ip.family == TCP_FAMILY) {
+ uint8_t packet[ONION_MAX_PACKET_SIZE];
+ int len = create_onion_packet_tcp(packet, sizeof(packet), path, dest, data, length);
+
+ if (len == -1) {
+ return -1;
+ }
+
+ return send_tcp_onion_request(onion_c->c, path->ip_port1.ip.ip4.uint32, packet, len);
+ }
+
+ return -1;
+}
+
+/* Creates a sendback for use in an announce request.
+ *
+ * num is 0 if we used our secret public key for the announce
+ * num is 1 + friendnum if we use a temporary one.
+ *
+ * Public key is the key we will be sending it to.
+ * ip_port is the ip_port of the node we will be sending
+ * it to.
+ *
+ * sendback must be at least ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big
+ *
+ * return -1 on failure
+ * return 0 on success
+ *
+ */
+static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, IP_Port ip_port,
+ uint32_t path_num, uint64_t *sendback)
+{
+ uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)];
+ memcpy(data, &num, sizeof(uint32_t));
+ memcpy(data + sizeof(uint32_t), public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, &ip_port, sizeof(IP_Port));
+ memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), &path_num, sizeof(uint32_t));
+ *sendback = ping_array_add(&onion_c->announce_ping_array, data, sizeof(data));
+
+ if (*sendback == 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Checks if the sendback is valid and returns the public key contained in it in ret_pubkey and the
+ * ip contained in it in ret_ip_port
+ *
+ * sendback is the sendback ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big
+ * ret_pubkey must be at least CRYPTO_PUBLIC_KEY_SIZE big
+ * ret_ip_port must be at least 1 big
+ *
+ * return ~0 on failure
+ * return num (see new_sendback(...)) on success
+ */
+static uint32_t check_sendback(Onion_Client *onion_c, const uint8_t *sendback, uint8_t *ret_pubkey,
+ IP_Port *ret_ip_port, uint32_t *path_num)
+{
+ uint64_t sback;
+ memcpy(&sback, sendback, sizeof(uint64_t));
+ uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)];
+
+ if (ping_array_check(data, sizeof(data), &onion_c->announce_ping_array, sback) != sizeof(data)) {
+ return ~0;
+ }
+
+ memcpy(ret_pubkey, data + sizeof(uint32_t), CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(ret_ip_port, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, sizeof(IP_Port));
+ memcpy(path_num, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), sizeof(uint32_t));
+
+ uint32_t num;
+ memcpy(&num, data, sizeof(uint32_t));
+ return num;
+}
+
+static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, const uint8_t *dest_pubkey,
+ const uint8_t *ping_id, uint32_t pathnum)
+{
+ if (num > onion_c->num_friends) {
+ return -1;
+ }
+
+ uint64_t sendback;
+ Onion_Path path;
+
+ if (num == 0) {
+ if (random_path(onion_c, &onion_c->onion_paths_self, pathnum, &path) == -1) {
+ return -1;
+ }
+ } else {
+ if (random_path(onion_c, &onion_c->onion_paths_friends, pathnum, &path) == -1) {
+ return -1;
+ }
+ }
+
+ if (new_sendback(onion_c, num, dest_pubkey, dest, path.path_num, &sendback) == -1) {
+ return -1;
+ }
+
+ uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0};
+
+ if (ping_id == NULL) {
+ ping_id = zero_ping_id;
+ }
+
+ uint8_t request[ONION_ANNOUNCE_REQUEST_SIZE];
+ int len;
+
+ if (num == 0) {
+ len = create_announce_request(request, sizeof(request), dest_pubkey, onion_c->c->self_public_key,
+ onion_c->c->self_secret_key, ping_id, onion_c->c->self_public_key, onion_c->temp_public_key, sendback);
+ } else {
+ len = create_announce_request(request, sizeof(request), dest_pubkey, onion_c->friends_list[num - 1].temp_public_key,
+ onion_c->friends_list[num - 1].temp_secret_key, ping_id, onion_c->friends_list[num - 1].real_public_key, zero_ping_id,
+ sendback);
+ }
+
+ if (len == -1) {
+ return -1;
+ }
+
+ return send_onion_packet_tcp_udp(onion_c, &path, dest, request, len);
+}
+
+typedef struct {
+ const uint8_t *base_public_key;
+ Onion_Node entry;
+} Onion_Client_Cmp_data;
+
+static int onion_client_cmp_entry(const void *a, const void *b)
+{
+ Onion_Client_Cmp_data cmp1, cmp2;
+ memcpy(&cmp1, a, sizeof(Onion_Client_Cmp_data));
+ memcpy(&cmp2, b, sizeof(Onion_Client_Cmp_data));
+ Onion_Node entry1 = cmp1.entry;
+ Onion_Node entry2 = cmp2.entry;
+ const uint8_t *cmp_public_key = cmp1.base_public_key;
+
+ int t1 = onion_node_timed_out(&entry1);
+ int t2 = onion_node_timed_out(&entry2);
+
+ if (t1 && t2) {
+ return 0;
+ }
+
+ if (t1) {
+ return -1;
+ }
+
+ if (t2) {
+ return 1;
+ }
+
+ int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);
+
+ if (close == 1) {
+ return 1;
+ }
+
+ if (close == 2) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static void sort_onion_node_list(Onion_Node *list, unsigned int length, const uint8_t *comp_public_key)
+{
+ // Pass comp_public_key to qsort with each Client_data entry, so the
+ // comparison function can use it as the base of comparison.
+ VLA(Onion_Client_Cmp_data, cmp_list, length);
+
+ for (uint32_t i = 0; i < length; i++) {
+ cmp_list[i].base_public_key = comp_public_key;
+ cmp_list[i].entry = list[i];
+ }
+
+ qsort(cmp_list, length, sizeof(Onion_Client_Cmp_data), onion_client_cmp_entry);
+
+ for (uint32_t i = 0; i < length; i++) {
+ list[i] = cmp_list[i].entry;
+ }
+}
+
+static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, IP_Port ip_port,
+ uint8_t is_stored, const uint8_t *pingid_or_key, uint32_t path_used)
+{
+ if (num > onion_c->num_friends) {
+ return -1;
+ }
+
+ Onion_Node *list_nodes = NULL;
+ uint8_t *reference_id = NULL;
+ unsigned int list_length;
+
+ if (num == 0) {
+ list_nodes = onion_c->clients_announce_list;
+ reference_id = onion_c->c->self_public_key;
+ list_length = MAX_ONION_CLIENTS_ANNOUNCE;
+
+ if (is_stored == 1 && public_key_cmp(pingid_or_key, onion_c->temp_public_key) != 0) {
+ is_stored = 0;
+ }
+ } else {
+ if (is_stored >= 2) {
+ return -1;
+ }
+
+ if (is_stored == 1) {
+ onion_c->friends_list[num - 1].last_reported_announced = unix_time();
+ }
+
+ list_nodes = onion_c->friends_list[num - 1].clients_list;
+ reference_id = onion_c->friends_list[num - 1].real_public_key;
+ list_length = MAX_ONION_CLIENTS;
+ }
+
+ sort_onion_node_list(list_nodes, list_length, reference_id);
+
+ int index = -1, stored = 0;
+ unsigned int i;
+
+ if (onion_node_timed_out(&list_nodes[0])
+ || id_closest(reference_id, list_nodes[0].public_key, public_key) == 2) {
+ index = 0;
+ }
+
+ for (i = 0; i < list_length; ++i) {
+ if (public_key_cmp(list_nodes[i].public_key, public_key) == 0) {
+ index = i;
+ stored = 1;
+ break;
+ }
+ }
+
+ if (index == -1) {
+ return 0;
+ }
+
+ memcpy(list_nodes[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ list_nodes[index].ip_port = ip_port;
+
+ // TODO(irungentoo): remove this and find a better source of nodes to use for paths.
+ onion_add_path_node(onion_c, ip_port, public_key);
+
+ if (is_stored == 1) {
+ memcpy(list_nodes[index].data_public_key, pingid_or_key, CRYPTO_PUBLIC_KEY_SIZE);
+ } else {
+ memcpy(list_nodes[index].ping_id, pingid_or_key, ONION_PING_ID_SIZE);
+ }
+
+ list_nodes[index].is_stored = is_stored;
+ list_nodes[index].timestamp = unix_time();
+ list_nodes[index].unsuccessful_pings = 0;
+
+ if (!stored) {
+ list_nodes[index].last_pinged = 0;
+ list_nodes[index].added_time = unix_time();
+ }
+
+ list_nodes[index].path_used = path_used;
+ return 0;
+}
+
+static int good_to_ping(Last_Pinged *last_pinged, uint8_t *last_pinged_index, const uint8_t *public_key)
+{
+ unsigned int i;
+
+ for (i = 0; i < MAX_STORED_PINGED_NODES; ++i) {
+ if (!is_timeout(last_pinged[i].timestamp, MIN_NODE_PING_TIME)) {
+ if (public_key_cmp(last_pinged[i].public_key, public_key) == 0) {
+ return 0;
+ }
+ }
+ }
+
+ memcpy(last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].timestamp = unix_time();
+ ++*last_pinged_index;
+ return 1;
+}
+
+static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_format *nodes, uint16_t num_nodes,
+ IP_Port source)
+{
+ if (num > onion_c->num_friends) {
+ return -1;
+ }
+
+ if (num_nodes == 0) {
+ return 0;
+ }
+
+ Onion_Node *list_nodes = NULL;
+ uint8_t *reference_id = NULL;
+ unsigned int list_length;
+
+ Last_Pinged *last_pinged = NULL;
+ uint8_t *last_pinged_index = NULL;
+
+ if (num == 0) {
+ list_nodes = onion_c->clients_announce_list;
+ reference_id = onion_c->c->self_public_key;
+ list_length = MAX_ONION_CLIENTS_ANNOUNCE;
+ last_pinged = onion_c->last_pinged;
+ last_pinged_index = &onion_c->last_pinged_index;
+ } else {
+ list_nodes = onion_c->friends_list[num - 1].clients_list;
+ reference_id = onion_c->friends_list[num - 1].real_public_key;
+ list_length = MAX_ONION_CLIENTS;
+ last_pinged = onion_c->friends_list[num - 1].last_pinged;
+ last_pinged_index = &onion_c->friends_list[num - 1].last_pinged_index;
+ }
+
+ unsigned int i, j;
+ int lan_ips_accepted = (LAN_ip(source.ip) == 0);
+
+ for (i = 0; i < num_nodes; ++i) {
+
+ if (!lan_ips_accepted) {
+ if (LAN_ip(nodes[i].ip_port.ip) == 0) {
+ continue;
+ }
+ }
+
+ if (onion_node_timed_out(&list_nodes[0])
+ || id_closest(reference_id, list_nodes[0].public_key, nodes[i].public_key) == 2
+ || onion_node_timed_out(&list_nodes[1])
+ || id_closest(reference_id, list_nodes[1].public_key, nodes[i].public_key) == 2) {
+ /* check if node is already in list. */
+ for (j = 0; j < list_length; ++j) {
+ if (public_key_cmp(list_nodes[j].public_key, nodes[i].public_key) == 0) {
+ break;
+ }
+ }
+
+ if (j == list_length && good_to_ping(last_pinged, last_pinged_index, nodes[i].public_key)) {
+ client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].public_key, NULL, ~0);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int handle_announce_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length,
+ void *userdata)
+{
+ Onion_Client *onion_c = (Onion_Client *)object;
+
+ if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) {
+ return 1;
+ }
+
+ uint16_t len_nodes = length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE;
+
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ IP_Port ip_port;
+ uint32_t path_num;
+ uint32_t num = check_sendback(onion_c, packet + 1, public_key, &ip_port, &path_num);
+
+ if (num > onion_c->num_friends) {
+ return 1;
+ }
+
+ VLA(uint8_t, plain, 1 + ONION_PING_ID_SIZE + len_nodes);
+ int len = -1;
+
+ if (num == 0) {
+ len = decrypt_data(public_key, onion_c->c->self_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
+ packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE,
+ length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE), plain);
+ } else {
+ if (onion_c->friends_list[num - 1].status == 0) {
+ return 1;
+ }
+
+ len = decrypt_data(public_key, onion_c->friends_list[num - 1].temp_secret_key,
+ packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
+ packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE,
+ length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE), plain);
+ }
+
+ if ((uint32_t)len != SIZEOF_VLA(plain)) {
+ return 1;
+ }
+
+ uint32_t path_used = set_path_timeouts(onion_c, num, path_num);
+
+ if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, path_used) == -1) {
+ return 1;
+ }
+
+ if (len_nodes != 0) {
+ Node_format nodes[MAX_SENT_NODES];
+ int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, plain + 1 + ONION_PING_ID_SIZE, len_nodes, 0);
+
+ if (num_nodes <= 0) {
+ return 1;
+ }
+
+ if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1) {
+ return 1;
+ }
+ }
+
+ // TODO(irungentoo): LAN vs non LAN ips?, if we are connected only to LAN, are we offline?
+ onion_c->last_packet_recv = unix_time();
+ return 0;
+}
+
+#define DATA_IN_RESPONSE_MIN_SIZE ONION_DATA_IN_RESPONSE_MIN_SIZE
+
+static int handle_data_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
+{
+ Onion_Client *onion_c = (Onion_Client *)object;
+
+ if (length <= (ONION_DATA_RESPONSE_MIN_SIZE + DATA_IN_RESPONSE_MIN_SIZE)) {
+ return 1;
+ }
+
+ if (length > MAX_DATA_REQUEST_SIZE) {
+ return 1;
+ }
+
+ VLA(uint8_t, temp_plain, length - ONION_DATA_RESPONSE_MIN_SIZE);
+ int len = decrypt_data(packet + 1 + CRYPTO_NONCE_SIZE, onion_c->temp_secret_key, packet + 1,
+ packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
+ length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), temp_plain);
+
+ if ((uint32_t)len != SIZEOF_VLA(temp_plain)) {
+ return 1;
+ }
+
+ VLA(uint8_t, plain, SIZEOF_VLA(temp_plain) - DATA_IN_RESPONSE_MIN_SIZE);
+ len = decrypt_data(temp_plain, onion_c->c->self_secret_key, packet + 1, temp_plain + CRYPTO_PUBLIC_KEY_SIZE,
+ SIZEOF_VLA(temp_plain) - CRYPTO_PUBLIC_KEY_SIZE, plain);
+
+ if ((uint32_t)len != SIZEOF_VLA(plain)) {
+ return 1;
+ }
+
+ if (!onion_c->Onion_Data_Handlers[plain[0]].function) {
+ return 1;
+ }
+
+ return onion_c->Onion_Data_Handlers[plain[0]].function(onion_c->Onion_Data_Handlers[plain[0]].object, temp_plain, plain,
+ SIZEOF_VLA(plain), userdata);
+}
+
+#define DHTPK_DATA_MIN_LENGTH (1 + sizeof(uint64_t) + CRYPTO_PUBLIC_KEY_SIZE)
+#define DHTPK_DATA_MAX_LENGTH (DHTPK_DATA_MIN_LENGTH + sizeof(Node_format)*MAX_SENT_NODES)
+static int handle_dhtpk_announce(void *object, const uint8_t *source_pubkey, const uint8_t *data, uint16_t length,
+ void *userdata)
+{
+ Onion_Client *onion_c = (Onion_Client *)object;
+
+ if (length < DHTPK_DATA_MIN_LENGTH) {
+ return 1;
+ }
+
+ if (length > DHTPK_DATA_MAX_LENGTH) {
+ return 1;
+ }
+
+ int friend_num = onion_friend_num(onion_c, source_pubkey);
+
+ if (friend_num == -1) {
+ return 1;
+ }
+
+ uint64_t no_replay;
+ memcpy(&no_replay, data + 1, sizeof(uint64_t));
+ net_to_host((uint8_t *) &no_replay, sizeof(no_replay));
+
+ if (no_replay <= onion_c->friends_list[friend_num].last_noreplay) {
+ return 1;
+ }
+
+ onion_c->friends_list[friend_num].last_noreplay = no_replay;
+
+ if (onion_c->friends_list[friend_num].dht_pk_callback) {
+ onion_c->friends_list[friend_num].dht_pk_callback(onion_c->friends_list[friend_num].dht_pk_callback_object,
+ onion_c->friends_list[friend_num].dht_pk_callback_number, data + 1 + sizeof(uint64_t), userdata);
+ }
+
+ onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t));
+ onion_c->friends_list[friend_num].last_seen = unix_time();
+
+ uint16_t len_nodes = length - DHTPK_DATA_MIN_LENGTH;
+
+ if (len_nodes != 0) {
+ Node_format nodes[MAX_SENT_NODES];
+ int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, data + 1 + sizeof(uint64_t) + CRYPTO_PUBLIC_KEY_SIZE,
+ len_nodes, 1);
+
+ if (num_nodes <= 0) {
+ return 1;
+ }
+
+ int i;
+
+ for (i = 0; i < num_nodes; ++i) {
+ uint8_t family = nodes[i].ip_port.ip.family;
+
+ if (family == TOX_AF_INET || family == TOX_AF_INET6) {
+ DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].public_key, onion_c->friends_list[friend_num].dht_public_key);
+ } else if (family == TCP_INET || family == TCP_INET6) {
+ if (onion_c->friends_list[friend_num].tcp_relay_node_callback) {
+ void *obj = onion_c->friends_list[friend_num].tcp_relay_node_callback_object;
+ uint32_t number = onion_c->friends_list[friend_num].tcp_relay_node_callback_number;
+ onion_c->friends_list[friend_num].tcp_relay_node_callback(obj, number, nodes[i].ip_port, nodes[i].public_key);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int handle_tcp_onion(void *object, const uint8_t *data, uint16_t length, void *userdata)
+{
+ if (length == 0) {
+ return 1;
+ }
+
+ IP_Port ip_port = {{0}};
+ ip_port.ip.family = TCP_FAMILY;
+
+ if (data[0] == NET_PACKET_ANNOUNCE_RESPONSE) {
+ return handle_announce_response(object, ip_port, data, length, userdata);
+ }
+
+ if (data[0] == NET_PACKET_ONION_DATA_RESPONSE) {
+ return handle_data_response(object, ip_port, data, length, userdata);
+ }
+
+ return 1;
+}
+
+/* Send data of length length to friendnum.
+ * This data will be received by the friend using the Onion_Data_Handlers callbacks.
+ *
+ * Even if this function succeeds, the friend might not receive any data.
+ *
+ * return the number of packets sent on success
+ * return -1 on failure.
+ */
+int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length)
+{
+ if ((uint32_t)friend_num >= onion_c->num_friends) {
+ return -1;
+ }
+
+ if (length + DATA_IN_RESPONSE_MIN_SIZE > MAX_DATA_REQUEST_SIZE) {
+ return -1;
+ }
+
+ if (length == 0) {
+ return -1;
+ }
+
+ unsigned int i, good_nodes[MAX_ONION_CLIENTS], num_good = 0, num_nodes = 0;
+ Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list;
+
+ for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
+ if (onion_node_timed_out(&list_nodes[i])) {
+ continue;
+ }
+
+ ++num_nodes;
+
+ if (list_nodes[i].is_stored) {
+ good_nodes[num_good] = i;
+ ++num_good;
+ }
+ }
+
+ if (num_good < (num_nodes - 1) / 4 + 1) {
+ return -1;
+ }
+
+ uint8_t nonce[CRYPTO_NONCE_SIZE];
+ random_nonce(nonce);
+
+ VLA(uint8_t, packet, DATA_IN_RESPONSE_MIN_SIZE + length);
+ memcpy(packet, onion_c->c->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key, onion_c->c->self_secret_key, nonce, data,
+ length, packet + CRYPTO_PUBLIC_KEY_SIZE);
+
+ if ((uint32_t)len + CRYPTO_PUBLIC_KEY_SIZE != SIZEOF_VLA(packet)) {
+ return -1;
+ }
+
+ unsigned int good = 0;
+
+ for (i = 0; i < num_good; ++i) {
+ Onion_Path path;
+
+ if (random_path(onion_c, &onion_c->onion_paths_friends, ~0, &path) == -1) {
+ continue;
+ }
+
+ uint8_t o_packet[ONION_MAX_PACKET_SIZE];
+ len = create_data_request(o_packet, sizeof(o_packet), onion_c->friends_list[friend_num].real_public_key,
+ list_nodes[good_nodes[i]].data_public_key, nonce, packet, SIZEOF_VLA(packet));
+
+ if (len == -1) {
+ continue;
+ }
+
+ if (send_onion_packet_tcp_udp(onion_c, &path, list_nodes[good_nodes[i]].ip_port, o_packet, len) == 0) {
+ ++good;
+ }
+ }
+
+ return good;
+}
+
+/* Try to send the dht public key via the DHT instead of onion
+ *
+ * Even if this function succeeds, the friend might not receive any data.
+ *
+ * return the number of packets sent on success
+ * return -1 on failure.
+ */
+static int send_dht_dhtpk(const Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length)
+{
+ if ((uint32_t)friend_num >= onion_c->num_friends) {
+ return -1;
+ }
+
+ if (!onion_c->friends_list[friend_num].know_dht_public_key) {
+ return -1;
+ }
+
+ uint8_t nonce[CRYPTO_NONCE_SIZE];
+ random_nonce(nonce);
+
+ VLA(uint8_t, temp, DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE + length);
+ memcpy(temp, onion_c->c->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ memcpy(temp + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
+ int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key, onion_c->c->self_secret_key, nonce, data,
+ length, temp + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
+
+ if ((uint32_t)len + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE != SIZEOF_VLA(temp)) {
+ return -1;
+ }
+
+ uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
+ len = create_request(onion_c->dht->self_public_key, onion_c->dht->self_secret_key, packet,
+ onion_c->friends_list[friend_num].dht_public_key, temp, SIZEOF_VLA(temp), CRYPTO_PACKET_DHTPK);
+
+ if (len == -1) {
+ return -1;
+ }
+
+ return route_tofriend(onion_c->dht, onion_c->friends_list[friend_num].dht_public_key, packet, len);
+}
+
+static int handle_dht_dhtpk(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet,
+ uint16_t length, void *userdata)
+{
+ Onion_Client *onion_c = (Onion_Client *)object;
+
+ if (length < DHTPK_DATA_MIN_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE) {
+ return 1;
+ }
+
+ if (length > DHTPK_DATA_MAX_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE) {
+ return 1;
+ }
+
+ uint8_t plain[DHTPK_DATA_MAX_LENGTH];
+ int len = decrypt_data(packet, onion_c->c->self_secret_key, packet + CRYPTO_PUBLIC_KEY_SIZE,
+ packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
+ length - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE), plain);
+
+ if (len != length - (DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE)) {
+ return 1;
+ }
+
+ if (public_key_cmp(source_pubkey, plain + 1 + sizeof(uint64_t)) != 0) {
+ return 1;
+ }
+
+ return handle_dhtpk_announce(onion_c, packet, plain, len, userdata);
+}
+/* Send the packets to tell our friends what our DHT public key is.
+ *
+ * if onion_dht_both is 0, use only the onion to send the packet.
+ * if it is 1, use only the dht.
+ * if it is something else, use both.
+ *
+ * return the number of packets sent on success
+ * return -1 on failure.
+ */
+static int send_dhtpk_announce(Onion_Client *onion_c, uint16_t friend_num, uint8_t onion_dht_both)
+{
+ if (friend_num >= onion_c->num_friends) {
+ return -1;
+ }
+
+ uint8_t data[DHTPK_DATA_MAX_LENGTH];
+ data[0] = ONION_DATA_DHTPK;
+ uint64_t no_replay = unix_time();
+ host_to_net((uint8_t *)&no_replay, sizeof(no_replay));
+ memcpy(data + 1, &no_replay, sizeof(no_replay));
+ memcpy(data + 1 + sizeof(uint64_t), onion_c->dht->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ Node_format nodes[MAX_SENT_NODES];
+ uint16_t num_relays = copy_connected_tcp_relays(onion_c->c, nodes, (MAX_SENT_NODES / 2));
+ uint16_t num_nodes = closelist_nodes(onion_c->dht, &nodes[num_relays], MAX_SENT_NODES - num_relays);
+ num_nodes += num_relays;
+ int nodes_len = 0;
+
+ if (num_nodes != 0) {
+ nodes_len = pack_nodes(data + DHTPK_DATA_MIN_LENGTH, DHTPK_DATA_MAX_LENGTH - DHTPK_DATA_MIN_LENGTH, nodes,
+ num_nodes);
+
+ if (nodes_len <= 0) {
+ return -1;
+ }
+ }
+
+ int num1 = -1, num2 = -1;
+
+ if (onion_dht_both != 1) {
+ num1 = send_onion_data(onion_c, friend_num, data, DHTPK_DATA_MIN_LENGTH + nodes_len);
+ }
+
+ if (onion_dht_both != 0) {
+ num2 = send_dht_dhtpk(onion_c, friend_num, data, DHTPK_DATA_MIN_LENGTH + nodes_len);
+ }
+
+ if (num1 == -1) {
+ return num2;
+ }
+
+ if (num2 == -1) {
+ return num1;
+ }
+
+ return num1 + num2;
+}
+
+/* Get the friend_num of a friend.
+ *
+ * return -1 on failure.
+ * return friend number on success.
+ */
+int onion_friend_num(const Onion_Client *onion_c, const uint8_t *public_key)
+{
+ unsigned int i;
+
+ for (i = 0; i < onion_c->num_friends; ++i) {
+ if (onion_c->friends_list[i].status == 0) {
+ continue;
+ }
+
+ if (public_key_cmp(public_key, onion_c->friends_list[i].real_public_key) == 0) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/* Set the size of the friend list to num.
+ *
+ * return -1 if realloc fails.
+ * return 0 if it succeeds.
+ */
+static int realloc_onion_friends(Onion_Client *onion_c, uint32_t num)
+{
+ if (num == 0) {
+ free(onion_c->friends_list);
+ onion_c->friends_list = NULL;
+ return 0;
+ }
+
+ Onion_Friend *newonion_friends = (Onion_Friend *)realloc(onion_c->friends_list, num * sizeof(Onion_Friend));
+
+ if (newonion_friends == NULL) {
+ return -1;
+ }
+
+ onion_c->friends_list = newonion_friends;
+ return 0;
+}
+
+/* Add a friend who we want to connect to.
+ *
+ * return -1 on failure.
+ * return the friend number on success or if the friend was already added.
+ */
+int onion_addfriend(Onion_Client *onion_c, const uint8_t *public_key)
+{
+ int num = onion_friend_num(onion_c, public_key);
+
+ if (num != -1) {
+ return num;
+ }
+
+ unsigned int i, index = ~0;
+
+ for (i = 0; i < onion_c->num_friends; ++i) {
+ if (onion_c->friends_list[i].status == 0) {
+ index = i;
+ break;
+ }
+ }
+
+ if (index == (uint32_t)~0) {
+ if (realloc_onion_friends(onion_c, onion_c->num_friends + 1) == -1) {
+ return -1;
+ }
+
+ index = onion_c->num_friends;
+ memset(&(onion_c->friends_list[onion_c->num_friends]), 0, sizeof(Onion_Friend));
+ ++onion_c->num_friends;
+ }
+
+ onion_c->friends_list[index].status = 1;
+ memcpy(onion_c->friends_list[index].real_public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ crypto_new_keypair(onion_c->friends_list[index].temp_public_key, onion_c->friends_list[index].temp_secret_key);
+ return index;
+}
+
+/* Delete a friend.
+ *
+ * return -1 on failure.
+ * return the deleted friend number on success.
+ */
+int onion_delfriend(Onion_Client *onion_c, int friend_num)
+{
+ if ((uint32_t)friend_num >= onion_c->num_friends) {
+ return -1;
+ }
+
+ //if (onion_c->friends_list[friend_num].know_dht_public_key)
+ // DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].dht_public_key, 0);
+
+ crypto_memzero(&(onion_c->friends_list[friend_num]), sizeof(Onion_Friend));
+ unsigned int i;
+
+ for (i = onion_c->num_friends; i != 0; --i) {
+ if (onion_c->friends_list[i - 1].status != 0) {
+ break;
+ }
+ }
+
+ if (onion_c->num_friends != i) {
+ onion_c->num_friends = i;
+ realloc_onion_friends(onion_c, onion_c->num_friends);
+ }
+
+ return friend_num;
+}
+
+/* Set the function for this friend that will be callbacked with object and number
+ * when that friends gives us one of the TCP relays he is connected to.
+ *
+ * object and number will be passed as argument to this function.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*tcp_relay_node_callback)(void *object,
+ uint32_t number, IP_Port ip_port, const uint8_t *public_key), void *object, uint32_t number)
+{
+ if ((uint32_t)friend_num >= onion_c->num_friends) {
+ return -1;
+ }
+
+ onion_c->friends_list[friend_num].tcp_relay_node_callback = tcp_relay_node_callback;
+ onion_c->friends_list[friend_num].tcp_relay_node_callback_object = object;
+ onion_c->friends_list[friend_num].tcp_relay_node_callback_number = number;
+ return 0;
+}
+
+/* Set the function for this friend that will be callbacked with object and number
+ * when that friend gives us his DHT temporary public key.
+ *
+ * object and number will be passed as argument to this function.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num, void (*function)(void *data, int32_t number,
+ const uint8_t *dht_public_key, void *userdata), void *object, uint32_t number)
+{
+ if ((uint32_t)friend_num >= onion_c->num_friends) {
+ return -1;
+ }
+
+ onion_c->friends_list[friend_num].dht_pk_callback = function;
+ onion_c->friends_list[friend_num].dht_pk_callback_object = object;
+ onion_c->friends_list[friend_num].dht_pk_callback_number = number;
+ return 0;
+}
+
+/* Set a friends DHT public key.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uint8_t *dht_key)
+{
+ if ((uint32_t)friend_num >= onion_c->num_friends) {
+ return -1;
+ }
+
+ if (onion_c->friends_list[friend_num].status == 0) {
+ return -1;
+ }
+
+ if (onion_c->friends_list[friend_num].know_dht_public_key) {
+ if (public_key_cmp(dht_key, onion_c->friends_list[friend_num].dht_public_key) == 0) {
+ return -1;
+ }
+
+ onion_c->friends_list[friend_num].know_dht_public_key = 0;
+ }
+
+ onion_c->friends_list[friend_num].last_seen = unix_time();
+ onion_c->friends_list[friend_num].know_dht_public_key = 1;
+ memcpy(onion_c->friends_list[friend_num].dht_public_key, dht_key, CRYPTO_PUBLIC_KEY_SIZE);
+
+ return 0;
+}
+
+/* Copy friends DHT public key into dht_key.
+ *
+ * return 0 on failure (no key copied).
+ * return 1 on success (key copied).
+ */
+unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key)
+{
+ if ((uint32_t)friend_num >= onion_c->num_friends) {
+ return 0;
+ }
+
+ if (onion_c->friends_list[friend_num].status == 0) {
+ return 0;
+ }
+
+ if (!onion_c->friends_list[friend_num].know_dht_public_key) {
+ return 0;
+ }
+
+ memcpy(dht_key, onion_c->friends_list[friend_num].dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ return 1;
+}
+
+/* Get the ip of friend friendnum and put it in ip_port
+ *
+ * return -1, -- if public_key does NOT refer to a friend
+ * return 0, -- if public_key refers to a friend and we failed to find the friend (yet)
+ * return 1, ip if public_key refers to a friend and we found him
+ *
+ */
+int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_port)
+{
+ uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
+
+ if (onion_getfriend_DHT_pubkey(onion_c, friend_num, dht_public_key) == 0) {
+ return -1;
+ }
+
+ return DHT_getfriendip(onion_c->dht, dht_public_key, ip_port);
+}
+
+
+/* Set if friend is online or not.
+ * NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online.
+ *
+ * is_online 1 means friend is online.
+ * is_online 0 means friend is offline
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_online)
+{
+ if ((uint32_t)friend_num >= onion_c->num_friends) {
+ return -1;
+ }
+
+ if (is_online == 0 && onion_c->friends_list[friend_num].is_online == 1) {
+ onion_c->friends_list[friend_num].last_seen = unix_time();
+ }
+
+ onion_c->friends_list[friend_num].is_online = is_online;
+
+ /* This should prevent some clock related issues */
+ if (!is_online) {
+ onion_c->friends_list[friend_num].last_noreplay = 0;
+ onion_c->friends_list[friend_num].run_count = 0;
+ }
+
+ return 0;
+}
+
+static void populate_path_nodes(Onion_Client *onion_c)
+{
+ Node_format nodes_list[MAX_FRIEND_CLIENTS];
+
+ unsigned int num_nodes = randfriends_nodes(onion_c->dht, nodes_list, MAX_FRIEND_CLIENTS);
+
+ unsigned int i;
+
+ for (i = 0; i < num_nodes; ++i) {
+ onion_add_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].public_key);
+ }
+}
+
+static void populate_path_nodes_tcp(Onion_Client *onion_c)
+{
+ Node_format nodes_list[MAX_SENT_NODES];
+
+ unsigned int num_nodes = copy_connected_tcp_relays(onion_c->c, nodes_list, MAX_SENT_NODES);;
+ unsigned int i;
+
+ for (i = 0; i < num_nodes; ++i) {
+ onion_add_bs_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].public_key);
+ }
+}
+
+#define ANNOUNCE_FRIEND (ONION_NODE_PING_INTERVAL * 6)
+#define ANNOUNCE_FRIEND_BEGINNING 3
+
+#define RUN_COUNT_FRIEND_ANNOUNCE_BEGINNING 17
+
+#define ONION_FRIEND_BACKOFF_FACTOR 4
+#define ONION_FRIEND_MAX_PING_INTERVAL (5*60*MAX_ONION_CLIENTS)
+
+static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
+{
+ if (friendnum >= onion_c->num_friends) {
+ return;
+ }
+
+ if (onion_c->friends_list[friendnum].status == 0) {
+ return;
+ }
+
+ unsigned int interval = ANNOUNCE_FRIEND;
+
+ if (onion_c->friends_list[friendnum].run_count < RUN_COUNT_FRIEND_ANNOUNCE_BEGINNING) {
+ interval = ANNOUNCE_FRIEND_BEGINNING;
+ } else {
+ if (onion_c->friends_list[friendnum].last_reported_announced == 0) {
+ onion_c->friends_list[friendnum].last_reported_announced = unix_time();
+ }
+
+ uint64_t backoff_interval = (unix_time() - onion_c->friends_list[friendnum].last_reported_announced)
+ / ONION_FRIEND_BACKOFF_FACTOR;
+
+ if (backoff_interval > ONION_FRIEND_MAX_PING_INTERVAL) {
+ backoff_interval = ONION_FRIEND_MAX_PING_INTERVAL;
+ }
+
+ if (interval < backoff_interval) {
+ interval = backoff_interval;
+ }
+ }
+
+ unsigned int i, count = 0;
+ Onion_Node *list_nodes = onion_c->friends_list[friendnum].clients_list;
+
+ if (!onion_c->friends_list[friendnum].is_online) {
+ // ensure we get a response from some node roughly once per
+ // (interval / MAX_ONION_CLIENTS)
+ bool ping_random = true;
+
+ for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
+ if (!(is_timeout(list_nodes[i].timestamp, interval / MAX_ONION_CLIENTS)
+ && is_timeout(list_nodes[i].last_pinged, ONION_NODE_PING_INTERVAL))) {
+ ping_random = false;
+ break;
+ }
+ }
+
+ for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
+ if (onion_node_timed_out(&list_nodes[i])) {
+ continue;
+ }
+
+ ++count;
+
+
+ if (list_nodes[i].last_pinged == 0) {
+ list_nodes[i].last_pinged = unix_time();
+ continue;
+ }
+
+ if (list_nodes[i].unsuccessful_pings >= ONION_NODE_MAX_PINGS) {
+ continue;
+ }
+
+ if (is_timeout(list_nodes[i].last_pinged, interval)
+ || (ping_random && rand() % (MAX_ONION_CLIENTS - i) == 0)) {
+ if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].public_key, 0, ~0) == 0) {
+ list_nodes[i].last_pinged = unix_time();
+ ++list_nodes[i].unsuccessful_pings;
+ ping_random = false;
+ }
+ }
+ }
+
+ if (count != MAX_ONION_CLIENTS) {
+ unsigned int num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES;
+
+ unsigned int n = num_nodes;
+
+ if (num_nodes > (MAX_ONION_CLIENTS / 2)) {
+ n = (MAX_ONION_CLIENTS / 2);
+ }
+
+ if (count <= (uint32_t)rand() % MAX_ONION_CLIENTS) {
+ if (num_nodes != 0) {
+ unsigned int j;
+
+ for (j = 0; j < n; ++j) {
+ unsigned int num = rand() % num_nodes;
+ client_send_announce_request(onion_c, friendnum + 1, onion_c->path_nodes[num].ip_port,
+ onion_c->path_nodes[num].public_key, 0, ~0);
+ }
+
+ ++onion_c->friends_list[friendnum].run_count;
+ }
+ }
+ } else {
+ ++onion_c->friends_list[friendnum].run_count;
+ }
+
+ /* send packets to friend telling them our DHT public key. */
+ if (is_timeout(onion_c->friends_list[friendnum].last_dht_pk_onion_sent, ONION_DHTPK_SEND_INTERVAL)) {
+ if (send_dhtpk_announce(onion_c, friendnum, 0) >= 1) {
+ onion_c->friends_list[friendnum].last_dht_pk_onion_sent = unix_time();
+ }
+ }
+
+ if (is_timeout(onion_c->friends_list[friendnum].last_dht_pk_dht_sent, DHT_DHTPK_SEND_INTERVAL)) {
+ if (send_dhtpk_announce(onion_c, friendnum, 1) >= 1) {
+ onion_c->friends_list[friendnum].last_dht_pk_dht_sent = unix_time();
+ }
+ }
+ }
+}
+
+
+/* Function to call when onion data packet with contents beginning with byte is received. */
+void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object)
+{
+ onion_c->Onion_Data_Handlers[byte].function = cb;
+ onion_c->Onion_Data_Handlers[byte].object = object;
+}
+
+#define ANNOUNCE_INTERVAL_NOT_ANNOUNCED 3
+#define ANNOUNCE_INTERVAL_ANNOUNCED ONION_NODE_PING_INTERVAL
+
+#define TIME_TO_STABLE (ONION_NODE_PING_INTERVAL * 6)
+#define ANNOUNCE_INTERVAL_STABLE (ONION_NODE_PING_INTERVAL * 8)
+
+static void do_announce(Onion_Client *onion_c)
+{
+ unsigned int i, count = 0;
+ Onion_Node *list_nodes = onion_c->clients_announce_list;
+
+ for (i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) {
+ if (onion_node_timed_out(&list_nodes[i])) {
+ continue;
+ }
+
+ ++count;
+
+ /* Don't announce ourselves the first time this is run to new peers */
+ if (list_nodes[i].last_pinged == 0) {
+ list_nodes[i].last_pinged = 1;
+ continue;
+ }
+
+ if (list_nodes[i].unsuccessful_pings >= ONION_NODE_MAX_PINGS) {
+ continue;
+ }
+
+
+ unsigned int interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED;
+
+ if (list_nodes[i].is_stored && path_exists(&onion_c->onion_paths_self, list_nodes[i].path_used)) {
+ interval = ANNOUNCE_INTERVAL_ANNOUNCED;
+
+ uint32_t pathnum = list_nodes[i].path_used % NUMBER_ONION_PATHS;
+
+ /* A node/path is considered 'stable', and can be pinged less
+ * aggressively, if it has survived for at least TIME_TO_STABLE
+ * and the latest packets sent to it are not timing out.
+ */
+ if (is_timeout(list_nodes[i].added_time, TIME_TO_STABLE)
+ && !(list_nodes[i].unsuccessful_pings > 0
+ && is_timeout(list_nodes[i].last_pinged, ONION_NODE_TIMEOUT))
+ && is_timeout(onion_c->onion_paths_self.path_creation_time[pathnum], TIME_TO_STABLE)
+ && !(onion_c->onion_paths_self.last_path_used_times[pathnum] > 0
+ && is_timeout(onion_c->onion_paths_self.last_path_used[pathnum], ONION_PATH_TIMEOUT))) {
+ interval = ANNOUNCE_INTERVAL_STABLE;
+ }
+ }
+
+ if (is_timeout(list_nodes[i].last_pinged, interval)
+ || (is_timeout(onion_c->last_announce, ONION_NODE_PING_INTERVAL)
+ && rand() % (MAX_ONION_CLIENTS_ANNOUNCE - i) == 0)) {
+ uint32_t path_to_use = list_nodes[i].path_used;
+
+ if (list_nodes[i].unsuccessful_pings == ONION_NODE_MAX_PINGS - 1
+ && is_timeout(list_nodes[i].added_time, TIME_TO_STABLE)) {
+ /* Last chance for a long-lived node - try a random path */
+ path_to_use = ~0;
+ }
+
+ if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].public_key,
+ list_nodes[i].ping_id, path_to_use) == 0) {
+ list_nodes[i].last_pinged = unix_time();
+ ++list_nodes[i].unsuccessful_pings;
+ onion_c->last_announce = unix_time();
+ }
+ }
+ }
+
+ if (count != MAX_ONION_CLIENTS_ANNOUNCE) {
+ unsigned int num_nodes;
+ Node_format *path_nodes;
+
+ if (rand() % 2 == 0 || onion_c->path_nodes_index == 0) {
+ num_nodes = (onion_c->path_nodes_index_bs < MAX_PATH_NODES) ? onion_c->path_nodes_index_bs : MAX_PATH_NODES;
+ path_nodes = onion_c->path_nodes_bs;
+ } else {
+ num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES;
+ path_nodes = onion_c->path_nodes;
+ }
+
+ if (count <= (uint32_t)rand() % MAX_ONION_CLIENTS_ANNOUNCE) {
+ if (num_nodes != 0) {
+ for (i = 0; i < (MAX_ONION_CLIENTS_ANNOUNCE / 2); ++i) {
+ unsigned int num = rand() % num_nodes;
+ client_send_announce_request(onion_c, 0, path_nodes[num].ip_port, path_nodes[num].public_key, 0, ~0);
+ }
+ }
+ }
+ }
+}
+
+/* return 0 if we are not connected to the network.
+ * return 1 if we are.
+ */
+static int onion_isconnected(const Onion_Client *onion_c)
+{
+ unsigned int i, num = 0, announced = 0;
+
+ if (is_timeout(onion_c->last_packet_recv, ONION_OFFLINE_TIMEOUT)) {
+ return 0;
+ }
+
+ if (onion_c->path_nodes_index == 0) {
+ return 0;
+ }
+
+ for (i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) {
+ if (!onion_node_timed_out(&onion_c->clients_announce_list[i])) {
+ ++num;
+
+ if (onion_c->clients_announce_list[i].is_stored) {
+ ++announced;
+ }
+ }
+ }
+
+ unsigned int pnodes = onion_c->path_nodes_index;
+
+ if (pnodes > MAX_ONION_CLIENTS_ANNOUNCE) {
+ pnodes = MAX_ONION_CLIENTS_ANNOUNCE;
+ }
+
+ /* Consider ourselves online if we are announced to half or more nodes
+ we are connected to */
+ if (num && announced) {
+ if ((num / 2) <= announced && (pnodes / 2) <= num) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#define ONION_CONNECTION_SECONDS 3
+
+/* return 0 if we are not connected to the network.
+ * return 1 if we are connected with TCP only.
+ * return 2 if we are also connected with UDP.
+ */
+unsigned int onion_connection_status(const Onion_Client *onion_c)
+{
+ if (onion_c->onion_connected >= ONION_CONNECTION_SECONDS) {
+ if (onion_c->UDP_connected) {
+ return 2;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+void do_onion_client(Onion_Client *onion_c)
+{
+ unsigned int i;
+
+ if (onion_c->last_run == unix_time()) {
+ return;
+ }
+
+ if (is_timeout(onion_c->first_run, ONION_CONNECTION_SECONDS)) {
+ populate_path_nodes(onion_c);
+ do_announce(onion_c);
+ }
+
+ if (onion_isconnected(onion_c)) {
+ if (onion_c->onion_connected < ONION_CONNECTION_SECONDS * 2) {
+ ++onion_c->onion_connected;
+ }
+ } else {
+ populate_path_nodes_tcp(onion_c);
+
+ if (onion_c->onion_connected != 0) {
+ --onion_c->onion_connected;
+ }
+ }
+
+ bool UDP_connected = DHT_non_lan_connected(onion_c->dht);
+
+ if (is_timeout(onion_c->first_run, ONION_CONNECTION_SECONDS * 2)) {
+ set_tcp_onion_status(onion_c->c->tcp_c, !UDP_connected);
+ }
+
+ onion_c->UDP_connected = UDP_connected
+ || get_random_tcp_onion_conn_number(onion_c->c->tcp_c) == -1; /* Check if connected to any TCP relays. */
+
+ if (onion_connection_status(onion_c)) {
+ for (i = 0; i < onion_c->num_friends; ++i) {
+ do_friend(onion_c, i);
+ }
+ }
+
+ if (onion_c->last_run == 0) {
+ onion_c->first_run = unix_time();
+ }
+
+ onion_c->last_run = unix_time();
+}
+
+Onion_Client *new_onion_client(Net_Crypto *c)
+{
+ if (c == NULL) {
+ return NULL;
+ }
+
+ Onion_Client *onion_c = (Onion_Client *)calloc(1, sizeof(Onion_Client));
+
+ if (onion_c == NULL) {
+ return NULL;
+ }
+
+ if (ping_array_init(&onion_c->announce_ping_array, ANNOUNCE_ARRAY_SIZE, ANNOUNCE_TIMEOUT) != 0) {
+ free(onion_c);
+ return NULL;
+ }
+
+ onion_c->dht = c->dht;
+ onion_c->net = c->dht->net;
+ onion_c->c = c;
+ new_symmetric_key(onion_c->secret_symmetric_key);
+ crypto_new_keypair(onion_c->temp_public_key, onion_c->temp_secret_key);
+ networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c);
+ networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c);
+ oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, &handle_dhtpk_announce, onion_c);
+ cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_DHTPK, &handle_dht_dhtpk, onion_c);
+ set_onion_packet_tcp_connection_callback(onion_c->c->tcp_c, &handle_tcp_onion, onion_c);
+
+ return onion_c;
+}
+
+void kill_onion_client(Onion_Client *onion_c)
+{
+ if (onion_c == NULL) {
+ return;
+ }
+
+ ping_array_free_all(&onion_c->announce_ping_array);
+ realloc_onion_friends(onion_c, 0);
+ networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, NULL, NULL);
+ networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL);
+ oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, NULL, NULL);
+ cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_DHTPK, NULL, NULL);
+ set_onion_packet_tcp_connection_callback(onion_c->c->tcp_c, NULL, NULL);
+ crypto_memzero(onion_c, sizeof(Onion_Client));
+ free(onion_c);
+}
+
diff --git a/protocols/Tox/libtox/src/toxcore/onion_client.h b/protocols/Tox/libtox/src/toxcore/onion_client.h
new file mode 100644
index 0000000000..216dbec050
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/onion_client.h
@@ -0,0 +1,302 @@
+/*
+ * Implementation of the client part of docs/Prevent_Tracking.txt (The part that
+ * uses the onion stuff to connect to the friend)
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef ONION_CLIENT_H
+#define ONION_CLIENT_H
+
+#include "net_crypto.h"
+#include "onion_announce.h"
+#include "ping_array.h"
+
+#define MAX_ONION_CLIENTS 8
+#define MAX_ONION_CLIENTS_ANNOUNCE 12 /* Number of nodes to announce ourselves to. */
+#define ONION_NODE_PING_INTERVAL 15
+#define ONION_NODE_TIMEOUT ONION_NODE_PING_INTERVAL
+
+/* The interval in seconds at which to tell our friends where we are */
+#define ONION_DHTPK_SEND_INTERVAL 30
+#define DHT_DHTPK_SEND_INTERVAL 20
+
+#define NUMBER_ONION_PATHS 6
+
+/* The timeout the first time the path is added and
+ then for all the next consecutive times */
+#define ONION_PATH_FIRST_TIMEOUT 4
+#define ONION_PATH_TIMEOUT 10
+#define ONION_PATH_MAX_LIFETIME 1200
+#define ONION_PATH_MAX_NO_RESPONSE_USES 4
+
+#define MAX_STORED_PINGED_NODES 9
+#define MIN_NODE_PING_TIME 10
+
+#define ONION_NODE_MAX_PINGS 3
+
+#define MAX_PATH_NODES 32
+
+/* If no announce response packets are received within this interval tox will
+ * be considered offline. We give time for a node to be pinged often enough
+ * that it times out, which leads to the network being thoroughly tested as it
+ * is replaced.
+ */
+#define ONION_OFFLINE_TIMEOUT (ONION_NODE_PING_INTERVAL * (ONION_NODE_MAX_PINGS+2))
+
+/* Onion data packet ids. */
+#define ONION_DATA_FRIEND_REQ CRYPTO_PACKET_FRIEND_REQ
+#define ONION_DATA_DHTPK CRYPTO_PACKET_DHTPK
+
+typedef struct {
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ IP_Port ip_port;
+ uint8_t ping_id[ONION_PING_ID_SIZE];
+ uint8_t data_public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t is_stored;
+
+ uint64_t added_time;
+
+ uint64_t timestamp;
+
+ uint64_t last_pinged;
+
+ uint8_t unsuccessful_pings;
+
+ uint32_t path_used;
+} Onion_Node;
+
+typedef struct {
+ Onion_Path paths[NUMBER_ONION_PATHS];
+ uint64_t last_path_success[NUMBER_ONION_PATHS];
+ uint64_t last_path_used[NUMBER_ONION_PATHS];
+ uint64_t path_creation_time[NUMBER_ONION_PATHS];
+ /* number of times used without success. */
+ unsigned int last_path_used_times[NUMBER_ONION_PATHS];
+} Onion_Client_Paths;
+
+typedef struct {
+ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint64_t timestamp;
+} Last_Pinged;
+
+typedef struct {
+ uint8_t status; /* 0 if friend is not valid, 1 if friend is valid.*/
+ uint8_t is_online; /* Set by the onion_set_friend_status function. */
+
+ uint8_t know_dht_public_key; /* 0 if we don't know the dht public key of the other, 1 if we do. */
+ uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t real_public_key[CRYPTO_PUBLIC_KEY_SIZE];
+
+ Onion_Node clients_list[MAX_ONION_CLIENTS];
+ uint8_t temp_public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE];
+
+ uint64_t last_reported_announced;
+
+ uint64_t last_dht_pk_onion_sent;
+ uint64_t last_dht_pk_dht_sent;
+
+ uint64_t last_noreplay;
+
+ uint64_t last_seen;
+
+ Last_Pinged last_pinged[MAX_STORED_PINGED_NODES];
+ uint8_t last_pinged_index;
+
+ int (*tcp_relay_node_callback)(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key);
+ void *tcp_relay_node_callback_object;
+ uint32_t tcp_relay_node_callback_number;
+
+ void (*dht_pk_callback)(void *data, int32_t number, const uint8_t *dht_public_key, void *userdata);
+ void *dht_pk_callback_object;
+ uint32_t dht_pk_callback_number;
+
+ uint32_t run_count;
+} Onion_Friend;
+
+typedef int (*oniondata_handler_callback)(void *object, const uint8_t *source_pubkey, const uint8_t *data,
+ uint16_t len, void *userdata);
+
+typedef struct {
+ DHT *dht;
+ Net_Crypto *c;
+ Networking_Core *net;
+ Onion_Friend *friends_list;
+ uint16_t num_friends;
+
+ Onion_Node clients_announce_list[MAX_ONION_CLIENTS_ANNOUNCE];
+ uint64_t last_announce;
+
+ Onion_Client_Paths onion_paths_self;
+ Onion_Client_Paths onion_paths_friends;
+
+ uint8_t secret_symmetric_key[CRYPTO_SYMMETRIC_KEY_SIZE];
+ uint64_t last_run, first_run;
+
+ uint8_t temp_public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE];
+
+ Last_Pinged last_pinged[MAX_STORED_PINGED_NODES];
+
+ Node_format path_nodes[MAX_PATH_NODES];
+ uint16_t path_nodes_index;
+
+ Node_format path_nodes_bs[MAX_PATH_NODES];
+ uint16_t path_nodes_index_bs;
+
+ Ping_Array announce_ping_array;
+ uint8_t last_pinged_index;
+ struct {
+ oniondata_handler_callback function;
+ void *object;
+ } Onion_Data_Handlers[256];
+
+ uint64_t last_packet_recv;
+
+ unsigned int onion_connected;
+ bool UDP_connected;
+} Onion_Client;
+
+
+/* Add a node to the path_nodes bootstrap array.
+ *
+ * return -1 on failure
+ * return 0 on success
+ */
+int onion_add_bs_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key);
+
+/* Put up to max_num nodes in nodes.
+ *
+ * return the number of nodes.
+ */
+uint16_t onion_backup_nodes(const Onion_Client *onion_c, Node_format *nodes, uint16_t max_num);
+
+/* Add a friend who we want to connect to.
+ *
+ * return -1 on failure.
+ * return the friend number on success or if the friend was already added.
+ */
+int onion_friend_num(const Onion_Client *onion_c, const uint8_t *public_key);
+
+/* Add a friend who we want to connect to.
+ *
+ * return -1 on failure.
+ * return the friend number on success.
+ */
+int onion_addfriend(Onion_Client *onion_c, const uint8_t *public_key);
+
+/* Delete a friend.
+ *
+ * return -1 on failure.
+ * return the deleted friend number on success.
+ */
+int onion_delfriend(Onion_Client *onion_c, int friend_num);
+
+/* Set if friend is online or not.
+ * NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online.
+ *
+ * is_online 1 means friend is online.
+ * is_online 0 means friend is offline
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_online);
+
+/* Get the ip of friend friendnum and put it in ip_port
+ *
+ * return -1, -- if public_key does NOT refer to a friend
+ * return 0, -- if public_key refers to a friend and we failed to find the friend (yet)
+ * return 1, ip if public_key refers to a friend and we found him
+ *
+ */
+int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_port);
+
+/* Set the function for this friend that will be callbacked with object and number
+ * when that friends gives us one of the TCP relays he is connected to.
+ *
+ * object and number will be passed as argument to this function.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*tcp_relay_node_callback)(void *object,
+ uint32_t number, IP_Port ip_port, const uint8_t *public_key), void *object, uint32_t number);
+
+
+/* Set the function for this friend that will be callbacked with object and number
+ * when that friend gives us his DHT temporary public key.
+ *
+ * object and number will be passed as argument to this function.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num, void (*function)(void *data, int32_t number,
+ const uint8_t *dht_public_key, void *userdata), void *object, uint32_t number);
+
+/* Set a friends DHT public key.
+ * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to
+ * the other peer.
+ *
+ * return -1 on failure.
+ * return 0 on success.
+ */
+int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uint8_t *dht_key);
+
+/* Copy friends DHT public key into dht_key.
+ *
+ * return 0 on failure (no key copied).
+ * return 1 on success (key copied).
+ */
+unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key);
+
+#define ONION_DATA_IN_RESPONSE_MIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)
+#define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE)
+
+/* Send data of length length to friendnum.
+ * Maximum length of data is ONION_CLIENT_MAX_DATA_SIZE.
+ * This data will be received by the friend using the Onion_Data_Handlers callbacks.
+ *
+ * Even if this function succeeds, the friend might not receive any data.
+ *
+ * return the number of packets sent on success
+ * return -1 on failure.
+ */
+int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length);
+
+/* Function to call when onion data packet with contents beginning with byte is received. */
+void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object);
+
+void do_onion_client(Onion_Client *onion_c);
+
+Onion_Client *new_onion_client(Net_Crypto *c);
+
+void kill_onion_client(Onion_Client *onion_c);
+
+
+/* return 0 if we are not connected to the network.
+ * return 1 if we are connected with TCP only.
+ * return 2 if we are also connected with UDP.
+ */
+unsigned int onion_connection_status(const Onion_Client *onion_c);
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxcore/ping.c b/protocols/Tox/libtox/src/toxcore/ping.c
new file mode 100644
index 0000000000..72b3fe6259
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/ping.c
@@ -0,0 +1,381 @@
+/*
+ * Buffered pinging using cyclic arrays.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ * Copyright © 2013 plutooo
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ * This file is donated to the Tox Project.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ping.h"
+
+#include "DHT.h"
+#include "network.h"
+#include "ping_array.h"
+#include "util.h"
+
+#include <stdint.h>
+
+#define PING_NUM_MAX 512
+
+/* Maximum newly announced nodes to ping per TIME_TO_PING seconds. */
+#define MAX_TO_PING 32
+
+/* Ping newly announced nodes to ping per TIME_TO_PING seconds*/
+#define TIME_TO_PING 2
+
+
+struct PING {
+ DHT *dht;
+
+ Ping_Array ping_array;
+ Node_format to_ping[MAX_TO_PING];
+ uint64_t last_to_ping;
+};
+
+
+#define PING_PLAIN_SIZE (1 + sizeof(uint64_t))
+#define DHT_PING_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + PING_PLAIN_SIZE + CRYPTO_MAC_SIZE)
+#define PING_DATA_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port))
+
+int send_ping_request(PING *ping, IP_Port ipp, const uint8_t *public_key)
+{
+ uint8_t pk[DHT_PING_SIZE];
+ int rc;
+ uint64_t ping_id;
+
+ if (id_equal(public_key, ping->dht->self_public_key)) {
+ return 1;
+ }
+
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
+
+ // generate key to encrypt ping_id with recipient privkey
+ DHT_get_shared_key_sent(ping->dht, shared_key, public_key);
+ // Generate random ping_id.
+ uint8_t data[PING_DATA_SIZE];
+ id_copy(data, public_key);
+ memcpy(data + CRYPTO_PUBLIC_KEY_SIZE, &ipp, sizeof(IP_Port));
+ ping_id = ping_array_add(&ping->ping_array, data, sizeof(data));
+
+ if (ping_id == 0) {
+ return 1;
+ }
+
+ uint8_t ping_plain[PING_PLAIN_SIZE];
+ ping_plain[0] = NET_PACKET_PING_REQUEST;
+ memcpy(ping_plain + 1, &ping_id, sizeof(ping_id));
+
+ pk[0] = NET_PACKET_PING_REQUEST;
+ id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey
+ random_nonce(pk + 1 + CRYPTO_PUBLIC_KEY_SIZE); // Generate new nonce
+
+
+ rc = encrypt_data_symmetric(shared_key,
+ pk + 1 + CRYPTO_PUBLIC_KEY_SIZE,
+ ping_plain, sizeof(ping_plain),
+ pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
+
+ if (rc != PING_PLAIN_SIZE + CRYPTO_MAC_SIZE) {
+ return 1;
+ }
+
+ return sendpacket(ping->dht->net, ipp, pk, sizeof(pk));
+}
+
+static int send_ping_response(PING *ping, IP_Port ipp, const uint8_t *public_key, uint64_t ping_id,
+ uint8_t *shared_encryption_key)
+{
+ uint8_t pk[DHT_PING_SIZE];
+ int rc;
+
+ if (id_equal(public_key, ping->dht->self_public_key)) {
+ return 1;
+ }
+
+ uint8_t ping_plain[PING_PLAIN_SIZE];
+ ping_plain[0] = NET_PACKET_PING_RESPONSE;
+ memcpy(ping_plain + 1, &ping_id, sizeof(ping_id));
+
+ pk[0] = NET_PACKET_PING_RESPONSE;
+ id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey
+ random_nonce(pk + 1 + CRYPTO_PUBLIC_KEY_SIZE); // Generate new nonce
+
+ // Encrypt ping_id using recipient privkey
+ rc = encrypt_data_symmetric(shared_encryption_key,
+ pk + 1 + CRYPTO_PUBLIC_KEY_SIZE,
+ ping_plain, sizeof(ping_plain),
+ pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
+
+ if (rc != PING_PLAIN_SIZE + CRYPTO_MAC_SIZE) {
+ return 1;
+ }
+
+ return sendpacket(ping->dht->net, ipp, pk, sizeof(pk));
+}
+
+static int handle_ping_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
+{
+ DHT *dht = (DHT *)object;
+ int rc;
+
+ if (length != DHT_PING_SIZE) {
+ return 1;
+ }
+
+ PING *ping = dht->ping;
+
+ if (id_equal(packet + 1, ping->dht->self_public_key)) {
+ return 1;
+ }
+
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
+
+ uint8_t ping_plain[PING_PLAIN_SIZE];
+ // Decrypt ping_id
+ DHT_get_shared_key_recv(dht, shared_key, packet + 1);
+ rc = decrypt_data_symmetric(shared_key,
+ packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
+ packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
+ PING_PLAIN_SIZE + CRYPTO_MAC_SIZE,
+ ping_plain);
+
+ if (rc != sizeof(ping_plain)) {
+ return 1;
+ }
+
+ if (ping_plain[0] != NET_PACKET_PING_REQUEST) {
+ return 1;
+ }
+
+ uint64_t ping_id;
+ memcpy(&ping_id, ping_plain + 1, sizeof(ping_id));
+ // Send response
+ send_ping_response(ping, source, packet + 1, ping_id, shared_key);
+ add_to_ping(ping, packet + 1, source);
+
+ return 0;
+}
+
+static int handle_ping_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
+{
+ DHT *dht = (DHT *)object;
+ int rc;
+
+ if (length != DHT_PING_SIZE) {
+ return 1;
+ }
+
+ PING *ping = dht->ping;
+
+ if (id_equal(packet + 1, ping->dht->self_public_key)) {
+ return 1;
+ }
+
+ uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
+
+ // generate key to encrypt ping_id with recipient privkey
+ DHT_get_shared_key_sent(ping->dht, shared_key, packet + 1);
+
+ uint8_t ping_plain[PING_PLAIN_SIZE];
+ // Decrypt ping_id
+ rc = decrypt_data_symmetric(shared_key,
+ packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
+ packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
+ PING_PLAIN_SIZE + CRYPTO_MAC_SIZE,
+ ping_plain);
+
+ if (rc != sizeof(ping_plain)) {
+ return 1;
+ }
+
+ if (ping_plain[0] != NET_PACKET_PING_RESPONSE) {
+ return 1;
+ }
+
+ uint64_t ping_id;
+ memcpy(&ping_id, ping_plain + 1, sizeof(ping_id));
+ uint8_t data[PING_DATA_SIZE];
+
+ if (ping_array_check(data, sizeof(data), &ping->ping_array, ping_id) != sizeof(data)) {
+ return 1;
+ }
+
+ if (!id_equal(packet + 1, data)) {
+ return 1;
+ }
+
+ IP_Port ipp;
+ memcpy(&ipp, data + CRYPTO_PUBLIC_KEY_SIZE, sizeof(IP_Port));
+
+ if (!ipport_equal(&ipp, &source)) {
+ return 1;
+ }
+
+ addto_lists(dht, source, packet + 1);
+ return 0;
+}
+
+/* Check if public_key with ip_port is in the list.
+ *
+ * return 1 if it is.
+ * return 0 if it isn't.
+ */
+static int in_list(const Client_data *list, uint16_t length, const uint8_t *public_key, IP_Port ip_port)
+{
+ unsigned int i;
+
+ for (i = 0; i < length; ++i) {
+ if (id_equal(list[i].public_key, public_key)) {
+ const IPPTsPng *ipptp;
+
+ if (ip_port.ip.family == TOX_AF_INET) {
+ ipptp = &list[i].assoc4;
+ } else {
+ ipptp = &list[i].assoc6;
+ }
+
+ if (!is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT) && ipport_equal(&ipptp->ip_port, &ip_port)) {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* Add nodes to the to_ping list.
+ * All nodes in this list are pinged every TIME_TO_PING seconds
+ * and are then removed from the list.
+ * If the list is full the nodes farthest from our public_key are replaced.
+ * The purpose of this list is to enable quick integration of new nodes into the
+ * network while preventing amplification attacks.
+ *
+ * return 0 if node was added.
+ * return -1 if node was not added.
+ */
+int add_to_ping(PING *ping, const uint8_t *public_key, IP_Port ip_port)
+{
+ if (!ip_isset(&ip_port.ip)) {
+ return -1;
+ }
+
+ if (!node_addable_to_close_list(ping->dht, public_key, ip_port)) {
+ return -1;
+ }
+
+ if (in_list(ping->dht->close_clientlist, LCLIENT_LIST, public_key, ip_port)) {
+ return -1;
+ }
+
+ IP_Port temp;
+
+ if (DHT_getfriendip(ping->dht, public_key, &temp) == 0) {
+ send_ping_request(ping, ip_port, public_key);
+ return -1;
+ }
+
+ unsigned int i;
+
+ for (i = 0; i < MAX_TO_PING; ++i) {
+ if (!ip_isset(&ping->to_ping[i].ip_port.ip)) {
+ memcpy(ping->to_ping[i].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ ipport_copy(&ping->to_ping[i].ip_port, &ip_port);
+ return 0;
+ }
+
+ if (public_key_cmp(ping->to_ping[i].public_key, public_key) == 0) {
+ return -1;
+ }
+ }
+
+ if (add_to_list(ping->to_ping, MAX_TO_PING, public_key, ip_port, ping->dht->self_public_key)) {
+ return 0;
+ }
+
+ return -1;
+}
+
+
+/* Ping all the valid nodes in the to_ping list every TIME_TO_PING seconds.
+ * This function must be run at least once every TIME_TO_PING seconds.
+ */
+void do_to_ping(PING *ping)
+{
+ if (!is_timeout(ping->last_to_ping, TIME_TO_PING)) {
+ return;
+ }
+
+ if (!ip_isset(&ping->to_ping[0].ip_port.ip)) {
+ return;
+ }
+
+ unsigned int i;
+
+ for (i = 0; i < MAX_TO_PING; ++i) {
+ if (!ip_isset(&ping->to_ping[i].ip_port.ip)) {
+ break;
+ }
+
+ if (!node_addable_to_close_list(ping->dht, ping->to_ping[i].public_key, ping->to_ping[i].ip_port)) {
+ continue;
+ }
+
+ send_ping_request(ping, ping->to_ping[i].ip_port, ping->to_ping[i].public_key);
+ ip_reset(&ping->to_ping[i].ip_port.ip);
+ }
+
+ if (i != 0) {
+ ping->last_to_ping = unix_time();
+ }
+}
+
+
+PING *new_ping(DHT *dht)
+{
+ PING *ping = (PING *)calloc(1, sizeof(PING));
+
+ if (ping == NULL) {
+ return NULL;
+ }
+
+ if (ping_array_init(&ping->ping_array, PING_NUM_MAX, PING_TIMEOUT) != 0) {
+ free(ping);
+ return NULL;
+ }
+
+ ping->dht = dht;
+ networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, &handle_ping_request, dht);
+ networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, dht);
+
+ return ping;
+}
+
+void kill_ping(PING *ping)
+{
+ networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, NULL, NULL);
+ networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, NULL, NULL);
+ ping_array_free_all(&ping->ping_array);
+
+ free(ping);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/ping.h b/protocols/Tox/libtox/src/toxcore/ping.h
new file mode 100644
index 0000000000..cc3428c548
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/ping.h
@@ -0,0 +1,54 @@
+/*
+ * Buffered pinging using cyclic arrays.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ * Copyright © 2013 plutooo
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ * This file is donated to the Tox Project.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef PING_H
+#define PING_H
+
+#include "DHT.h"
+#include "network.h"
+
+#include <stdint.h>
+
+typedef struct PING PING;
+
+/* Add nodes to the to_ping list.
+ * All nodes in this list are pinged every TIME_TOPING seconds
+ * and are then removed from the list.
+ * If the list is full the nodes farthest from our public_key are replaced.
+ * The purpose of this list is to enable quick integration of new nodes into the
+ * network while preventing amplification attacks.
+ *
+ * return 0 if node was added.
+ * return -1 if node was not added.
+ */
+int add_to_ping(PING *ping, const uint8_t *public_key, IP_Port ip_port);
+void do_to_ping(PING *ping);
+
+PING *new_ping(DHT *dht);
+void kill_ping(PING *ping);
+
+int send_ping_request(PING *ping, IP_Port ipp, const uint8_t *public_key);
+
+#endif /* PING_H */
diff --git a/protocols/Tox/libtox/src/toxcore/ping_array.c b/protocols/Tox/libtox/src/toxcore/ping_array.c
new file mode 100644
index 0000000000..ea3e5101b1
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/ping_array.c
@@ -0,0 +1,172 @@
+/*
+ * Implementation of an efficient array to store that we pinged something.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2014 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ping_array.h"
+
+#include "crypto_core.h"
+#include "util.h"
+
+static void clear_entry(Ping_Array *array, uint32_t index)
+{
+ free(array->entries[index].data);
+ array->entries[index].data = NULL;
+ array->entries[index].length =
+ array->entries[index].time =
+ array->entries[index].ping_id = 0;
+}
+
+/* Clear timed out entries.
+ */
+static void ping_array_clear_timedout(Ping_Array *array)
+{
+ while (array->last_deleted != array->last_added) {
+ uint32_t index = array->last_deleted % array->total_size;
+
+ if (!is_timeout(array->entries[index].time, array->timeout)) {
+ break;
+ }
+
+ clear_entry(array, index);
+ ++array->last_deleted;
+ }
+}
+
+/* Add a data with length to the Ping_Array list and return a ping_id.
+ *
+ * return ping_id on success.
+ * return 0 on failure.
+ */
+uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length)
+{
+ ping_array_clear_timedout(array);
+ uint32_t index = array->last_added % array->total_size;
+
+ if (array->entries[index].data != NULL) {
+ array->last_deleted = array->last_added - array->total_size;
+ clear_entry(array, index);
+ }
+
+ array->entries[index].data = malloc(length);
+
+ if (array->entries[index].data == NULL) {
+ return 0;
+ }
+
+ memcpy(array->entries[index].data, data, length);
+ array->entries[index].length = length;
+ array->entries[index].time = unix_time();
+ ++array->last_added;
+ uint64_t ping_id = random_64b();
+ ping_id /= array->total_size;
+ ping_id *= array->total_size;
+ ping_id += index;
+
+ if (ping_id == 0) {
+ ping_id += array->total_size;
+ }
+
+ array->entries[index].ping_id = ping_id;
+ return ping_id;
+}
+
+
+/* Check if ping_id is valid and not timed out.
+ *
+ * On success, copies the data into data of length,
+ *
+ * return length of data copied on success.
+ * return -1 on failure.
+ */
+int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, uint64_t ping_id)
+{
+ if (ping_id == 0) {
+ return -1;
+ }
+
+ uint32_t index = ping_id % array->total_size;
+
+ if (array->entries[index].ping_id != ping_id) {
+ return -1;
+ }
+
+ if (is_timeout(array->entries[index].time, array->timeout)) {
+ return -1;
+ }
+
+ if (array->entries[index].length > length) {
+ return -1;
+ }
+
+ if (array->entries[index].data == NULL) {
+ return -1;
+ }
+
+ memcpy(data, array->entries[index].data, array->entries[index].length);
+ uint32_t len = array->entries[index].length;
+ clear_entry(array, index);
+ return len;
+}
+
+/* Initialize a Ping_Array.
+ * size represents the total size of the array and should be a power of 2.
+ * timeout represents the maximum timeout in seconds for the entry.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int ping_array_init(Ping_Array *empty_array, uint32_t size, uint32_t timeout)
+{
+ if (size == 0 || timeout == 0 || empty_array == NULL) {
+ return -1;
+ }
+
+ empty_array->entries = (Ping_Array_Entry *)calloc(size, sizeof(Ping_Array_Entry));
+
+ if (empty_array->entries == NULL) {
+ return -1;
+ }
+
+ empty_array->last_deleted = empty_array->last_added = 0;
+ empty_array->total_size = size;
+ empty_array->timeout = timeout;
+ return 0;
+}
+
+/* Free all the allocated memory in a Ping_Array.
+ */
+void ping_array_free_all(Ping_Array *array)
+{
+ while (array->last_deleted != array->last_added) {
+ uint32_t index = array->last_deleted % array->total_size;
+ clear_entry(array, index);
+ ++array->last_deleted;
+ }
+
+ free(array->entries);
+ array->entries = NULL;
+}
+
diff --git a/protocols/Tox/libtox/src/toxcore/ping_array.h b/protocols/Tox/libtox/src/toxcore/ping_array.h
new file mode 100644
index 0000000000..bdf3c6db3d
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/ping_array.h
@@ -0,0 +1,76 @@
+/*
+ * Implementation of an efficient array to store that we pinged something.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef PING_ARRAY_H
+#define PING_ARRAY_H
+
+#include "network.h"
+
+typedef struct {
+ void *data;
+ uint32_t length;
+ uint64_t time;
+ uint64_t ping_id;
+} Ping_Array_Entry;
+
+
+typedef struct {
+ Ping_Array_Entry *entries;
+
+ uint32_t last_deleted; /* number representing the next entry to be deleted. */
+ uint32_t last_added; /* number representing the last entry to be added. */
+ uint32_t total_size; /* The length of entries */
+ uint32_t timeout; /* The timeout after which entries are cleared. */
+} Ping_Array;
+
+
+/* Add a data with length to the Ping_Array list and return a ping_id.
+ *
+ * return ping_id on success.
+ * return 0 on failure.
+ */
+uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length);
+
+/* Check if ping_id is valid and not timed out.
+ *
+ * On success, copies the data into data of length,
+ *
+ * return length of data copied on success.
+ * return -1 on failure.
+ */
+int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, uint64_t ping_id);
+
+/* Initialize a Ping_Array.
+ * size represents the total size of the array and should be a power of 2.
+ * timeout represents the maximum timeout in seconds for the entry.
+ *
+ * return 0 on success.
+ * return -1 on failure.
+ */
+int ping_array_init(Ping_Array *empty_array, uint32_t size, uint32_t timeout);
+
+/* Free all the allocated memory in a Ping_Array.
+ */
+void ping_array_free_all(Ping_Array *array);
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxcore/tox.api.h b/protocols/Tox/libtox/src/toxcore/tox.api.h
new file mode 100644
index 0000000000..0763c7789d
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/tox.api.h
@@ -0,0 +1,2583 @@
+%{
+/*
+ * The Tox public API.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TOX_H
+#define TOX_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+%}
+
+
+/*****************************************************************************
+ * `tox.h` SHOULD *NOT* BE EDITED MANUALLY – any changes should be made to *
+ * `tox.api.h`, located in `toxcore/`. For instructions on how to *
+ * generate `tox.h` from `tox.api.h` please refer to `docs/apidsl.md` *
+ *****************************************************************************/
+
+
+/** \page core Public core API for Tox clients.
+ *
+ * Every function that can fail takes a function-specific error code pointer
+ * that can be used to diagnose problems with the Tox state or the function
+ * arguments. The error code pointer can be NULL, which does not influence the
+ * function's behaviour, but can be done if the reason for failure is irrelevant
+ * to the client.
+ *
+ * The exception to this rule are simple allocation functions whose only failure
+ * mode is allocation failure. They return NULL in that case, and do not set an
+ * error code.
+ *
+ * Every error code type has an OK value to which functions will set their error
+ * code value on success. Clients can keep their error code uninitialised before
+ * passing it to a function. The library guarantees that after returning, the
+ * value pointed to by the error code pointer has been initialised.
+ *
+ * Functions with pointer parameters often have a NULL error code, meaning they
+ * could not perform any operation, because one of the required parameters was
+ * NULL. Some functions operate correctly or are defined as effectless on NULL.
+ *
+ * Some functions additionally return a value outside their
+ * return type domain, or a bool containing true on success and false on
+ * failure.
+ *
+ * All functions that take a Tox instance pointer will cause undefined behaviour
+ * when passed a NULL Tox pointer.
+ *
+ * All integer values are expected in host byte order.
+ *
+ * Functions with parameters with enum types cause unspecified behaviour if the
+ * enumeration value is outside the valid range of the type. If possible, the
+ * function will try to use a sane default, but there will be no error code,
+ * and one possible action for the function to take is to have no effect.
+ *
+ * Integer constants and the memory layout of publicly exposed structs are not
+ * part of the ABI.
+ */
+
+/** \subsection events Events and callbacks
+ *
+ * Events are handled by callbacks. One callback can be registered per event.
+ * All events have a callback function type named `tox_{event}_cb` and a
+ * function to register it named `tox_callback_{event}`. Passing a NULL
+ * callback will result in no callback being registered for that event. Only
+ * one callback per event can be registered, so if a client needs multiple
+ * event listeners, it needs to implement the dispatch functionality itself.
+ *
+ * The last argument to a callback is the user data pointer. It is passed from
+ * ${tox.iterate} to each callback in sequence.
+ *
+ * The user data pointer is never stored or dereferenced by any library code, so
+ * can be any pointer, including NULL. Callbacks must all operate on the same
+ * object type. In the apidsl code (tox.in.h), this is denoted with `any`. The
+ * `any` in ${tox.iterate} must be the same `any` as in all callbacks. In C,
+ * lacking parametric polymorphism, this is a pointer to void.
+ *
+ * Old style callbacks that are registered together with a user data pointer
+ * receive that pointer as argument when they are called. They can each have
+ * their own user data pointer of their own type.
+ */
+
+/** \subsection threading Threading implications
+ *
+ * It is possible to run multiple concurrent threads with a Tox instance for
+ * each thread. It is also possible to run all Tox instances in the same thread.
+ * A common way to run Tox (multiple or single instance) is to have one thread
+ * running a simple ${tox.iterate} loop, sleeping for ${tox.iteration_interval}
+ * milliseconds on each iteration.
+ *
+ * If you want to access a single Tox instance from multiple threads, access
+ * to the instance must be synchronised. While multiple threads can concurrently
+ * access multiple different Tox instances, no more than one API function can
+ * operate on a single instance at any given time.
+ *
+ * Functions that write to variable length byte arrays will always have a size
+ * function associated with them. The result of this size function is only valid
+ * until another mutating function (one that takes a pointer to non-const Tox)
+ * is called. Thus, clients must ensure that no other thread calls a mutating
+ * function between the call to the size function and the call to the retrieval
+ * function.
+ *
+ * E.g. to get the current nickname, one would write
+ *
+ * \code
+ * size_t length = ${tox.self.name.size}(tox);
+ * uint8_t *name = malloc(length);
+ * if (!name) abort();
+ * ${tox.self.name.get}(tox, name);
+ * \endcode
+ *
+ * If any other thread calls ${tox.self.name.set} while this thread is allocating
+ * memory, the length may have become invalid, and the call to
+ * ${tox.self.name.get} may cause undefined behaviour.
+ */
+
+// The rest of this file is in class tox.
+class tox {
+
+/**
+ * The Tox instance type. All the state associated with a connection is held
+ * within the instance. Multiple instances can exist and operate concurrently.
+ * The maximum number of Tox instances that can exist on a single network
+ * device is limited. Note that this is not just a per-process limit, since the
+ * limiting factor is the number of usable ports on a device.
+ */
+struct this;
+
+
+/*******************************************************************************
+ *
+ * :: API version
+ *
+ ******************************************************************************/
+
+
+/**
+ * The major version number. Incremented when the API or ABI changes in an
+ * incompatible way.
+ *
+ * The function variants of these constants return the version number of the
+ * library. They can be used to display the Tox library version or to check
+ * whether the client is compatible with the dynamically linked version of Tox.
+ */
+const VERSION_MAJOR = 0;
+
+/**
+ * The minor version number. Incremented when functionality is added without
+ * breaking the API or ABI. Set to 0 when the major version number is
+ * incremented.
+ */
+const VERSION_MINOR = 1;
+
+/**
+ * The patch or revision number. Incremented when bugfixes are applied without
+ * changing any functionality or API or ABI.
+ */
+const VERSION_PATCH = 10;
+
+/**
+ * A macro to check at preprocessing time whether the client code is compatible
+ * with the installed version of Tox. Leading zeros in the version number are
+ * ignored. E.g. 0.1.5 is to 0.1.4 what 1.5 is to 1.4, that is: it can add new
+ * features, but can't break the API.
+ */
+#define TOX_VERSION_IS_API_COMPATIBLE(MAJOR, MINOR, PATCH) \
+ (TOX_VERSION_MAJOR > 0 && TOX_VERSION_MAJOR == MAJOR) && ( \
+ /* 1.x.x, 2.x.x, etc. with matching major version. */ \
+ TOX_VERSION_MINOR > MINOR || \
+ TOX_VERSION_MINOR == MINOR && TOX_VERSION_PATCH >= PATCH \
+ ) || (TOX_VERSION_MAJOR == 0 && MAJOR == 0) && ( \
+ /* 0.x.x makes minor behave like major above. */ \
+ (TOX_VERSION_MINOR > 0 && TOX_VERSION_MINOR == MINOR) && ( \
+ TOX_VERSION_PATCH >= PATCH \
+ ) || (TOX_VERSION_MINOR == 0 && MINOR == 0) && ( \
+ /* 0.0.x and 0.0.y are only compatible if x == y. */ \
+ TOX_VERSION_PATCH == PATCH \
+ ) \
+ )
+
+static namespace version {
+
+ /**
+ * Return whether the compiled library version is compatible with the passed
+ * version numbers.
+ */
+ bool is_compatible(uint32_t major, uint32_t minor, uint32_t patch);
+
+}
+
+/**
+ * A convenience macro to call tox_version_is_compatible with the currently
+ * compiling API version.
+ */
+#define TOX_VERSION_IS_ABI_COMPATIBLE() \
+ tox_version_is_compatible(TOX_VERSION_MAJOR, TOX_VERSION_MINOR, TOX_VERSION_PATCH)
+
+/*******************************************************************************
+ *
+ * :: Numeric constants
+ *
+ * The values of these are not part of the ABI. Prefer to use the function
+ * versions of them for code that should remain compatible with future versions
+ * of toxcore.
+ *
+ ******************************************************************************/
+
+
+/**
+ * The size of a Tox Public Key in bytes.
+ */
+const PUBLIC_KEY_SIZE = 32;
+
+/**
+ * The size of a Tox Secret Key in bytes.
+ */
+const SECRET_KEY_SIZE = 32;
+
+/**
+ * The size of the nospam in bytes when written in a Tox address.
+ */
+const NOSPAM_SIZE = sizeof(uint32_t);
+
+/**
+ * The size of a Tox address in bytes. Tox addresses are in the format
+ * [Public Key ($PUBLIC_KEY_SIZE bytes)][nospam (4 bytes)][checksum (2 bytes)].
+ *
+ * The checksum is computed over the Public Key and the nospam value. The first
+ * byte is an XOR of all the even bytes (0, 2, 4, ...), the second byte is an
+ * XOR of all the odd bytes (1, 3, 5, ...) of the Public Key and nospam.
+ */
+const ADDRESS_SIZE = PUBLIC_KEY_SIZE + NOSPAM_SIZE + sizeof(uint16_t);
+
+/**
+ * Maximum length of a nickname in bytes.
+ */
+const MAX_NAME_LENGTH = 128;
+
+/**
+ * Maximum length of a status message in bytes.
+ */
+const MAX_STATUS_MESSAGE_LENGTH = 1007;
+
+/**
+ * Maximum length of a friend request message in bytes.
+ */
+const MAX_FRIEND_REQUEST_LENGTH = 1016;
+
+/**
+ * Maximum length of a single message after which it should be split.
+ */
+const MAX_MESSAGE_LENGTH = 1372;
+
+/**
+ * Maximum size of custom packets. TODO(iphydf): should be LENGTH?
+ */
+const MAX_CUSTOM_PACKET_SIZE = 1373;
+
+/**
+ * The number of bytes in a hash generated by $hash.
+ */
+const HASH_LENGTH = 32;
+
+/**
+ * The number of bytes in a file id.
+ */
+const FILE_ID_LENGTH = 32;
+
+/**
+ * Maximum file name length for file transfers.
+ */
+const MAX_FILENAME_LENGTH = 255;
+
+
+/*******************************************************************************
+ *
+ * :: Global enumerations
+ *
+ ******************************************************************************/
+
+
+/**
+ * Represents the possible statuses a client can have.
+ */
+enum class USER_STATUS {
+ /**
+ * User is online and available.
+ */
+ NONE,
+ /**
+ * User is away. Clients can set this e.g. after a user defined
+ * inactivity time.
+ */
+ AWAY,
+ /**
+ * User is busy. Signals to other clients that this client does not
+ * currently wish to communicate.
+ */
+ BUSY,
+}
+
+
+/**
+ * Represents message types for ${tox.friend.send.message} and conference
+ * messages.
+ */
+enum class MESSAGE_TYPE {
+ /**
+ * Normal text message. Similar to PRIVMSG on IRC.
+ */
+ NORMAL,
+ /**
+ * A message describing an user action. This is similar to /me (CTCP ACTION)
+ * on IRC.
+ */
+ ACTION,
+}
+
+
+/*******************************************************************************
+ *
+ * :: Startup options
+ *
+ ******************************************************************************/
+
+
+/**
+ * Type of proxy used to connect to TCP relays.
+ */
+enum class PROXY_TYPE {
+ /**
+ * Don't use a proxy.
+ */
+ NONE,
+ /**
+ * HTTP proxy using CONNECT.
+ */
+ HTTP,
+ /**
+ * SOCKS proxy for simple socket pipes.
+ */
+ SOCKS5,
+}
+
+/**
+ * Type of savedata to create the Tox instance from.
+ */
+enum class SAVEDATA_TYPE {
+ /**
+ * No savedata.
+ */
+ NONE,
+ /**
+ * Savedata is one that was obtained from ${savedata.get}.
+ */
+ TOX_SAVE,
+ /**
+ * Savedata is a secret key of length $SECRET_KEY_SIZE.
+ */
+ SECRET_KEY,
+}
+
+
+/**
+ * Severity level of log messages.
+ */
+enum class LOG_LEVEL {
+ /**
+ * Very detailed traces including all network activity.
+ */
+ TRACE,
+ /**
+ * Debug messages such as which port we bind to.
+ */
+ DEBUG,
+ /**
+ * Informational log messages such as video call status changes.
+ */
+ INFO,
+ /**
+ * Warnings about internal inconsistency or logic errors.
+ */
+ WARNING,
+ /**
+ * Severe unexpected errors caused by external or internal inconsistency.
+ */
+ ERROR,
+}
+
+/**
+ * This event is triggered when the toxcore library logs an internal message.
+ * This is mostly useful for debugging. This callback can be called from any
+ * function, not just $iterate. This means the user data lifetime must at
+ * least extend between registering and unregistering it or $kill.
+ *
+ * Other toxcore modules such as toxav may concurrently call this callback at
+ * any time. Thus, user code must make sure it is equipped to handle concurrent
+ * execution, e.g. by employing appropriate mutex locking.
+ *
+ * @param level The severity of the log message.
+ * @param file The source file from which the message originated.
+ * @param line The source line from which the message originated.
+ * @param func The function from which the message originated.
+ * @param message The log message.
+ * @param user_data The user data pointer passed to $new in options.
+ */
+typedef void log_cb(LOG_LEVEL level, string file, uint32_t line, string func, string message, any user_data);
+
+
+static class options {
+ /**
+ * This struct contains all the startup options for Tox. You must $new to
+ * allocate an object of this type.
+ *
+ * WARNING: Although this struct happens to be visible in the API, it is
+ * effectively private. Do not allocate this yourself or access members
+ * directly, as it *will* break binary compatibility frequently.
+ *
+ * @deprecated The memory layout of this struct (size, alignment, and field
+ * order) is not part of the ABI. To remain compatible, prefer to use $new to
+ * allocate the object and accessor functions to set the members. The struct
+ * will become opaque (i.e. the definition will become private) in v0.2.0.
+ */
+ struct this [get, set] {
+ /**
+ * The type of socket to create.
+ *
+ * If this is set to false, an IPv4 socket is created, which subsequently
+ * only allows IPv4 communication.
+ * If it is set to true, an IPv6 socket is created, allowing both IPv4 and
+ * IPv6 communication.
+ */
+ bool ipv6_enabled;
+
+ /**
+ * Enable the use of UDP communication when available.
+ *
+ * Setting this to false will force Tox to use TCP only. Communications will
+ * need to be relayed through a TCP relay node, potentially slowing them down.
+ * Disabling UDP support is necessary when using anonymous proxies or Tor.
+ */
+ bool udp_enabled;
+
+ /**
+ * Enable local network peer discovery.
+ *
+ * Disabling this will cause Tox to not look for peers on the local network.
+ */
+ bool local_discovery_enabled;
+
+ namespace proxy {
+ /**
+ * Pass communications through a proxy.
+ */
+ PROXY_TYPE type;
+
+ /**
+ * The IP address or DNS name of the proxy to be used.
+ *
+ * If used, this must be non-NULL and be a valid DNS name. The name must not
+ * exceed 255 characters, and be in a NUL-terminated C string format
+ * (255 chars + 1 NUL byte).
+ *
+ * This member is ignored (it can be NULL) if proxy_type is ${PROXY_TYPE.NONE}.
+ *
+ * The data pointed at by this member is owned by the user, so must
+ * outlive the options object.
+ */
+ string host;
+
+ /**
+ * The port to use to connect to the proxy server.
+ *
+ * Ports must be in the range (1, 65535). The value is ignored if
+ * proxy_type is ${PROXY_TYPE.NONE}.
+ */
+ uint16_t port;
+ }
+
+ /**
+ * The start port of the inclusive port range to attempt to use.
+ *
+ * If both start_port and end_port are 0, the default port range will be
+ * used: [33445, 33545].
+ *
+ * If either start_port or end_port is 0 while the other is non-zero, the
+ * non-zero port will be the only port in the range.
+ *
+ * Having start_port > end_port will yield the same behavior as if start_port
+ * and end_port were swapped.
+ */
+ uint16_t start_port;
+
+ /**
+ * The end port of the inclusive port range to attempt to use.
+ */
+ uint16_t end_port;
+
+ /**
+ * The port to use for the TCP server (relay). If 0, the TCP server is
+ * disabled.
+ *
+ * Enabling it is not required for Tox to function properly.
+ *
+ * When enabled, your Tox instance can act as a TCP relay for other Tox
+ * instance. This leads to increased traffic, thus when writing a client
+ * it is recommended to enable TCP server only if the user has an option
+ * to disable it.
+ */
+ uint16_t tcp_port;
+
+ /**
+ * Enables or disables UDP hole-punching in toxcore. (Default: enabled).
+ */
+ bool hole_punching_enabled;
+
+ namespace savedata {
+ /**
+ * The type of savedata to load from.
+ */
+ SAVEDATA_TYPE type;
+
+ /**
+ * The savedata.
+ *
+ * The data pointed at by this member is owned by the user, so must
+ * outlive the options object.
+ */
+ const uint8_t[length] data;
+
+ /**
+ * The length of the savedata.
+ */
+ size_t length;
+ }
+
+ namespace log {
+ /**
+ * Logging callback for the new tox instance.
+ */
+ log_cb *callback;
+
+ /**
+ * User data pointer passed to the logging callback.
+ */
+ any user_data;
+ }
+ }
+
+
+ /**
+ * Initialises a $this object with the default options.
+ *
+ * The result of this function is independent of the original options. All
+ * values will be overwritten, no values will be read (so it is permissible
+ * to pass an uninitialised object).
+ *
+ * If options is NULL, this function has no effect.
+ *
+ * @param options An options object to be filled with default options.
+ */
+ void default();
+
+
+ /**
+ * Allocates a new $this object and initialises it with the default
+ * options. This function can be used to preserve long term ABI compatibility by
+ * giving the responsibility of allocation and deallocation to the Tox library.
+ *
+ * Objects returned from this function must be freed using the $free
+ * function.
+ *
+ * @return A new $this object with default options or NULL on failure.
+ */
+ static this new() {
+ /**
+ * The function failed to allocate enough memory for the options struct.
+ */
+ MALLOC,
+ }
+
+
+ /**
+ * Releases all resources associated with an options objects.
+ *
+ * Passing a pointer that was not returned by $new results in
+ * undefined behaviour.
+ */
+ void free();
+}
+
+
+/*******************************************************************************
+ *
+ * :: Creation and destruction
+ *
+ ******************************************************************************/
+
+
+/**
+ * @brief Creates and initialises a new Tox instance with the options passed.
+ *
+ * This function will bring the instance into a valid state. Running the event
+ * loop with a new instance will operate correctly.
+ *
+ * If loading failed or succeeded only partially, the new or partially loaded
+ * instance is returned and an error code is set.
+ *
+ * @param options An options object as described above. If this parameter is
+ * NULL, the default options are used.
+ *
+ * @see $iterate for the event loop.
+ *
+ * @return A new Tox instance pointer on success or NULL on failure.
+ */
+static this new(const options_t *options) {
+ NULL,
+ /**
+ * The function was unable to allocate enough memory to store the internal
+ * structures for the Tox object.
+ */
+ MALLOC,
+ /**
+ * The function was unable to bind to a port. This may mean that all ports
+ * have already been bound, e.g. by other Tox instances, or it may mean
+ * a permission error. You may be able to gather more information from errno.
+ */
+ PORT_ALLOC,
+
+ namespace PROXY {
+ /**
+ * proxy_type was invalid.
+ */
+ BAD_TYPE,
+ /**
+ * proxy_type was valid but the proxy_host passed had an invalid format
+ * or was NULL.
+ */
+ BAD_HOST,
+ /**
+ * proxy_type was valid, but the proxy_port was invalid.
+ */
+ BAD_PORT,
+ /**
+ * The proxy address passed could not be resolved.
+ */
+ NOT_FOUND,
+ }
+
+ namespace LOAD {
+ /**
+ * The byte array to be loaded contained an encrypted save.
+ */
+ ENCRYPTED,
+ /**
+ * The data format was invalid. This can happen when loading data that was
+ * saved by an older version of Tox, or when the data has been corrupted.
+ * When loading from badly formatted data, some data may have been loaded,
+ * and the rest is discarded. Passing an invalid length parameter also
+ * causes this error.
+ */
+ BAD_FORMAT,
+ }
+}
+
+
+/**
+ * Releases all resources associated with the Tox instance and disconnects from
+ * the network.
+ *
+ * After calling this function, the Tox pointer becomes invalid. No other
+ * functions can be called, and the pointer value can no longer be read.
+ */
+void kill();
+
+
+uint8_t[size] savedata {
+ /**
+ * Calculates the number of bytes required to store the tox instance with
+ * $get. This function cannot fail. The result is always greater than 0.
+ *
+ * @see threading for concurrency implications.
+ */
+ size();
+
+ /**
+ * Store all information associated with the tox instance to a byte array.
+ *
+ * @param savedata A memory region large enough to store the tox instance
+ * data. Call $size to find the number of bytes required. If this parameter
+ * is NULL, this function has no effect.
+ */
+ get();
+}
+
+
+/*******************************************************************************
+ *
+ * :: Connection lifecycle and event loop
+ *
+ ******************************************************************************/
+
+
+/**
+ * Sends a "get nodes" request to the given bootstrap node with IP, port, and
+ * public key to setup connections.
+ *
+ * This function will attempt to connect to the node using UDP. You must use
+ * this function even if ${options.this.udp_enabled} was set to false.
+ *
+ * @param address The hostname or IP address (IPv4 or IPv6) of the node.
+ * @param port The port on the host on which the bootstrap Tox instance is
+ * listening.
+ * @param public_key The long term public key of the bootstrap node
+ * ($PUBLIC_KEY_SIZE bytes).
+ * @return true on success.
+ */
+bool bootstrap(string address, uint16_t port, const uint8_t[PUBLIC_KEY_SIZE] public_key) {
+ NULL,
+ /**
+ * The address could not be resolved to an IP address, or the IP address
+ * passed was invalid.
+ */
+ BAD_HOST,
+ /**
+ * The port passed was invalid. The valid port range is (1, 65535).
+ */
+ BAD_PORT,
+}
+
+
+/**
+ * Adds additional host:port pair as TCP relay.
+ *
+ * This function can be used to initiate TCP connections to different ports on
+ * the same bootstrap node, or to add TCP relays without using them as
+ * bootstrap nodes.
+ *
+ * @param address The hostname or IP address (IPv4 or IPv6) of the TCP relay.
+ * @param port The port on the host on which the TCP relay is listening.
+ * @param public_key The long term public key of the TCP relay
+ * ($PUBLIC_KEY_SIZE bytes).
+ * @return true on success.
+ */
+bool add_tcp_relay(string address, uint16_t port, const uint8_t[PUBLIC_KEY_SIZE] public_key)
+ with error for bootstrap;
+
+
+/**
+ * Protocols that can be used to connect to the network or friends.
+ */
+enum class CONNECTION {
+ /**
+ * There is no connection. This instance, or the friend the state change is
+ * about, is now offline.
+ */
+ NONE,
+ /**
+ * A TCP connection has been established. For the own instance, this means it
+ * is connected through a TCP relay, only. For a friend, this means that the
+ * connection to that particular friend goes through a TCP relay.
+ */
+ TCP,
+ /**
+ * A UDP connection has been established. For the own instance, this means it
+ * is able to send UDP packets to DHT nodes, but may still be connected to
+ * a TCP relay. For a friend, this means that the connection to that
+ * particular friend was built using direct UDP packets.
+ */
+ UDP,
+}
+
+
+inline namespace self {
+
+ CONNECTION connection_status {
+ /**
+ * Return whether we are connected to the DHT. The return value is equal to the
+ * last value received through the `${event connection_status}` callback.
+ */
+ get();
+ }
+
+
+ /**
+ * This event is triggered whenever there is a change in the DHT connection
+ * state. When disconnected, a client may choose to call $bootstrap again, to
+ * reconnect to the DHT. Note that this state may frequently change for short
+ * amounts of time. Clients should therefore not immediately bootstrap on
+ * receiving a disconnect.
+ *
+ * TODO(iphydf): how long should a client wait before bootstrapping again?
+ */
+ event connection_status const {
+ /**
+ * @param connection_status Whether we are connected to the DHT.
+ */
+ typedef void(CONNECTION connection_status);
+ }
+
+}
+
+
+/**
+ * Return the time in milliseconds before $iterate() should be called again
+ * for optimal performance.
+ */
+const uint32_t iteration_interval();
+
+
+/**
+ * The main loop that needs to be run in intervals of $iteration_interval()
+ * milliseconds.
+ */
+void iterate(any user_data);
+
+
+/*******************************************************************************
+ *
+ * :: Internal client information (Tox address/id)
+ *
+ ******************************************************************************/
+
+
+inline namespace self {
+
+ uint8_t[ADDRESS_SIZE] address {
+ /**
+ * Writes the Tox friend address of the client to a byte array. The address is
+ * not in human-readable format. If a client wants to display the address,
+ * formatting is required.
+ *
+ * @param address A memory region of at least $ADDRESS_SIZE bytes. If this
+ * parameter is NULL, this function has no effect.
+ * @see $ADDRESS_SIZE for the address format.
+ */
+ get();
+ }
+
+
+ uint32_t nospam {
+ /**
+ * Set the 4-byte nospam part of the address. This value is expected in host
+ * byte order. I.e. 0x12345678 will form the bytes [12, 34, 56, 78] in the
+ * nospam part of the Tox friend address.
+ *
+ * @param nospam Any 32 bit unsigned integer.
+ */
+ set();
+
+ /**
+ * Get the 4-byte nospam part of the address. This value is returned in host
+ * byte order.
+ */
+ get();
+ }
+
+
+ uint8_t[PUBLIC_KEY_SIZE] public_key {
+ /**
+ * Copy the Tox Public Key (long term) from the Tox object.
+ *
+ * @param public_key A memory region of at least $PUBLIC_KEY_SIZE bytes. If
+ * this parameter is NULL, this function has no effect.
+ */
+ get();
+ }
+
+
+ uint8_t[SECRET_KEY_SIZE] secret_key {
+ /**
+ * Copy the Tox Secret Key from the Tox object.
+ *
+ * @param secret_key A memory region of at least $SECRET_KEY_SIZE bytes. If
+ * this parameter is NULL, this function has no effect.
+ */
+ get();
+ }
+
+}
+
+
+/*******************************************************************************
+ *
+ * :: User-visible client information (nickname/status)
+ *
+ ******************************************************************************/
+
+
+/**
+ * Common error codes for all functions that set a piece of user-visible
+ * client information.
+ */
+error for set_info {
+ NULL,
+ /**
+ * Information length exceeded maximum permissible size.
+ */
+ TOO_LONG,
+}
+
+
+inline namespace self {
+
+ uint8_t[length <= MAX_NAME_LENGTH] name {
+ /**
+ * Set the nickname for the Tox client.
+ *
+ * Nickname length cannot exceed $MAX_NAME_LENGTH. If length is 0, the name
+ * parameter is ignored (it can be NULL), and the nickname is set back to empty.
+ *
+ * @param name A byte array containing the new nickname.
+ * @param length The size of the name byte array.
+ *
+ * @return true on success.
+ */
+ set() with error for set_info;
+
+ /**
+ * Return the length of the current nickname as passed to $set.
+ *
+ * If no nickname was set before calling this function, the name is empty,
+ * and this function returns 0.
+ *
+ * @see threading for concurrency implications.
+ */
+ size();
+
+ /**
+ * Write the nickname set by $set to a byte array.
+ *
+ * If no nickname was set before calling this function, the name is empty,
+ * and this function has no effect.
+ *
+ * Call $size to find out how much memory to allocate for
+ * the result.
+ *
+ * @param name A valid memory location large enough to hold the nickname.
+ * If this parameter is NULL, the function has no effect.
+ */
+ get();
+ }
+
+
+ uint8_t[length <= MAX_STATUS_MESSAGE_LENGTH] status_message {
+ /**
+ * Set the client's status message.
+ *
+ * Status message length cannot exceed $MAX_STATUS_MESSAGE_LENGTH. If
+ * length is 0, the status parameter is ignored (it can be NULL), and the
+ * user status is set back to empty.
+ */
+ set() with error for set_info;
+
+ /**
+ * Return the length of the current status message as passed to $set.
+ *
+ * If no status message was set before calling this function, the status
+ * is empty, and this function returns 0.
+ *
+ * @see threading for concurrency implications.
+ */
+ size();
+
+ /**
+ * Write the status message set by $set to a byte array.
+ *
+ * If no status message was set before calling this function, the status is
+ * empty, and this function has no effect.
+ *
+ * Call $size to find out how much memory to allocate for
+ * the result.
+ *
+ * @param status_message A valid memory location large enough to hold the
+ * status message. If this parameter is NULL, the function has no effect.
+ */
+ get();
+ }
+
+
+ USER_STATUS status {
+ /**
+ * Set the client's user status.
+ *
+ * @param status One of the user statuses listed in the enumeration above.
+ */
+ set();
+
+ /**
+ * Returns the client's user status.
+ */
+ get();
+ }
+
+}
+
+
+/*******************************************************************************
+ *
+ * :: Friend list management
+ *
+ ******************************************************************************/
+
+
+namespace friend {
+
+ /**
+ * Add a friend to the friend list and send a friend request.
+ *
+ * A friend request message must be at least 1 byte long and at most
+ * $MAX_FRIEND_REQUEST_LENGTH.
+ *
+ * Friend numbers are unique identifiers used in all functions that operate on
+ * friends. Once added, a friend number is stable for the lifetime of the Tox
+ * object. After saving the state and reloading it, the friend numbers may not
+ * be the same as before. Deleting a friend creates a gap in the friend number
+ * set, which is filled by the next adding of a friend. Any pattern in friend
+ * numbers should not be relied on.
+ *
+ * If more than INT32_MAX friends are added, this function causes undefined
+ * behaviour.
+ *
+ * @param address The address of the friend (returned by ${self.address.get} of
+ * the friend you wish to add) it must be $ADDRESS_SIZE bytes.
+ * @param message The message that will be sent along with the friend request.
+ * @param length The length of the data byte array.
+ *
+ * @return the friend number on success, UINT32_MAX on failure.
+ */
+ uint32_t add(
+ const uint8_t[ADDRESS_SIZE] address,
+ const uint8_t[length <= MAX_FRIEND_REQUEST_LENGTH] message
+ ) {
+ NULL,
+ /**
+ * The length of the friend request message exceeded
+ * $MAX_FRIEND_REQUEST_LENGTH.
+ */
+ TOO_LONG,
+ /**
+ * The friend request message was empty. This, and the TOO_LONG code will
+ * never be returned from $add_norequest.
+ */
+ NO_MESSAGE,
+ /**
+ * The friend address belongs to the sending client.
+ */
+ OWN_KEY,
+ /**
+ * A friend request has already been sent, or the address belongs to a friend
+ * that is already on the friend list.
+ */
+ ALREADY_SENT,
+ /**
+ * The friend address checksum failed.
+ */
+ BAD_CHECKSUM,
+ /**
+ * The friend was already there, but the nospam value was different.
+ */
+ SET_NEW_NOSPAM,
+ /**
+ * A memory allocation failed when trying to increase the friend list size.
+ */
+ MALLOC,
+ }
+
+
+ /**
+ * Add a friend without sending a friend request.
+ *
+ * This function is used to add a friend in response to a friend request. If the
+ * client receives a friend request, it can be reasonably sure that the other
+ * client added this client as a friend, eliminating the need for a friend
+ * request.
+ *
+ * This function is also useful in a situation where both instances are
+ * controlled by the same entity, so that this entity can perform the mutual
+ * friend adding. In this case, there is no need for a friend request, either.
+ *
+ * @param public_key A byte array of length $PUBLIC_KEY_SIZE containing the
+ * Public Key (not the Address) of the friend to add.
+ *
+ * @return the friend number on success, UINT32_MAX on failure.
+ * @see $add for a more detailed description of friend numbers.
+ */
+ uint32_t add_norequest(const uint8_t[PUBLIC_KEY_SIZE] public_key)
+ with error for add;
+
+
+ /**
+ * Remove a friend from the friend list.
+ *
+ * This does not notify the friend of their deletion. After calling this
+ * function, this client will appear offline to the friend and no communication
+ * can occur between the two.
+ *
+ * @param friend_number Friend number for the friend to be deleted.
+ *
+ * @return true on success.
+ */
+ bool delete(uint32_t friend_number) {
+ /**
+ * There was no friend with the given friend number. No friends were deleted.
+ */
+ FRIEND_NOT_FOUND,
+ }
+
+}
+
+
+/*******************************************************************************
+ *
+ * :: Friend list queries
+ *
+ ******************************************************************************/
+
+namespace friend {
+
+ /**
+ * Return the friend number associated with that Public Key.
+ *
+ * @return the friend number on success, UINT32_MAX on failure.
+ * @param public_key A byte array containing the Public Key.
+ */
+ const uint32_t by_public_key(const uint8_t[PUBLIC_KEY_SIZE] public_key) {
+ NULL,
+ /**
+ * No friend with the given Public Key exists on the friend list.
+ */
+ NOT_FOUND,
+ }
+
+
+ /**
+ * Checks if a friend with the given friend number exists and returns true if
+ * it does.
+ */
+ const bool exists(uint32_t friend_number);
+
+}
+
+inline namespace self {
+
+ uint32_t[size] friend_list {
+ /**
+ * Return the number of friends on the friend list.
+ *
+ * This function can be used to determine how much memory to allocate for
+ * $get.
+ */
+ size();
+
+
+ /**
+ * Copy a list of valid friend numbers into an array.
+ *
+ * Call $size to determine the number of elements to allocate.
+ *
+ * @param friend_list A memory region with enough space to hold the friend
+ * list. If this parameter is NULL, this function has no effect.
+ */
+ get();
+ }
+
+}
+
+
+
+namespace friend {
+
+ uint8_t[PUBLIC_KEY_SIZE] public_key {
+ /**
+ * Copies the Public Key associated with a given friend number to a byte array.
+ *
+ * @param friend_number The friend number you want the Public Key of.
+ * @param public_key A memory region of at least $PUBLIC_KEY_SIZE bytes. If
+ * this parameter is NULL, this function has no effect.
+ *
+ * @return true on success.
+ */
+ get(uint32_t friend_number) {
+ /**
+ * No friend with the given number exists on the friend list.
+ */
+ FRIEND_NOT_FOUND,
+ }
+ }
+
+}
+
+namespace friend {
+
+ uint64_t last_online {
+ /**
+ * Return a unix-time timestamp of the last time the friend associated with a given
+ * friend number was seen online. This function will return UINT64_MAX on error.
+ *
+ * @param friend_number The friend number you want to query.
+ */
+ get(uint32_t friend_number) {
+ /**
+ * No friend with the given number exists on the friend list.
+ */
+ FRIEND_NOT_FOUND,
+ }
+ }
+
+}
+
+/*******************************************************************************
+ *
+ * :: Friend-specific state queries (can also be received through callbacks)
+ *
+ ******************************************************************************/
+
+
+namespace friend {
+
+ /**
+ * Common error codes for friend state query functions.
+ */
+ error for query {
+ /**
+ * The pointer parameter for storing the query result (name, message) was
+ * NULL. Unlike the `_self_` variants of these functions, which have no effect
+ * when a parameter is NULL, these functions return an error in that case.
+ */
+ NULL,
+ /**
+ * The friend_number did not designate a valid friend.
+ */
+ FRIEND_NOT_FOUND,
+ }
+
+
+ uint8_t[length <= MAX_NAME_LENGTH] name {
+ /**
+ * Return the length of the friend's name. If the friend number is invalid, the
+ * return value is unspecified.
+ *
+ * The return value is equal to the `length` argument received by the last
+ * `${event name}` callback.
+ */
+ size(uint32_t friend_number)
+ with error for query;
+
+ /**
+ * Write the name of the friend designated by the given friend number to a byte
+ * array.
+ *
+ * Call $size to determine the allocation size for the `name`
+ * parameter.
+ *
+ * The data written to `name` is equal to the data received by the last
+ * `${event name}` callback.
+ *
+ * @param name A valid memory region large enough to store the friend's name.
+ *
+ * @return true on success.
+ */
+ get(uint32_t friend_number)
+ with error for query;
+ }
+
+
+ /**
+ * This event is triggered when a friend changes their name.
+ */
+ event name const {
+ /**
+ * @param friend_number The friend number of the friend whose name changed.
+ * @param name A byte array containing the same data as
+ * ${name.get} would write to its `name` parameter.
+ * @param length A value equal to the return value of
+ * ${name.size}.
+ */
+ typedef void(uint32_t friend_number, const uint8_t[length <= MAX_NAME_LENGTH] name);
+ }
+
+
+ uint8_t[length <= MAX_STATUS_MESSAGE_LENGTH] status_message {
+ /**
+ * Return the length of the friend's status message. If the friend number is
+ * invalid, the return value is SIZE_MAX.
+ */
+ size(uint32_t friend_number)
+ with error for query;
+
+ /**
+ * Write the status message of the friend designated by the given friend number to a byte
+ * array.
+ *
+ * Call $size to determine the allocation size for the `status_name`
+ * parameter.
+ *
+ * The data written to `status_message` is equal to the data received by the last
+ * `${event status_message}` callback.
+ *
+ * @param status_message A valid memory region large enough to store the friend's status message.
+ */
+ get(uint32_t friend_number)
+ with error for query;
+ }
+
+
+ /**
+ * This event is triggered when a friend changes their status message.
+ */
+ event status_message const {
+ /**
+ * @param friend_number The friend number of the friend whose status message
+ * changed.
+ * @param message A byte array containing the same data as
+ * ${status_message.get} would write to its `status_message` parameter.
+ * @param length A value equal to the return value of
+ * ${status_message.size}.
+ */
+ typedef void(uint32_t friend_number, const uint8_t[length <= MAX_STATUS_MESSAGE_LENGTH] message);
+ }
+
+
+ USER_STATUS status {
+ /**
+ * Return the friend's user status (away/busy/...). If the friend number is
+ * invalid, the return value is unspecified.
+ *
+ * The status returned is equal to the last status received through the
+ * `${event status}` callback.
+ */
+ get(uint32_t friend_number)
+ with error for query;
+ }
+
+
+ /**
+ * This event is triggered when a friend changes their user status.
+ */
+ event status const {
+ /**
+ * @param friend_number The friend number of the friend whose user status
+ * changed.
+ * @param status The new user status.
+ */
+ typedef void(uint32_t friend_number, USER_STATUS status);
+ }
+
+
+ CONNECTION connection_status {
+ /**
+ * Check whether a friend is currently connected to this client.
+ *
+ * The result of this function is equal to the last value received by the
+ * `${event connection_status}` callback.
+ *
+ * @param friend_number The friend number for which to query the connection
+ * status.
+ *
+ * @return the friend's connection status as it was received through the
+ * `${event connection_status}` event.
+ */
+ get(uint32_t friend_number)
+ with error for query;
+ }
+
+
+ /**
+ * This event is triggered when a friend goes offline after having been online,
+ * or when a friend goes online.
+ *
+ * This callback is not called when adding friends. It is assumed that when
+ * adding friends, their connection status is initially offline.
+ */
+ event connection_status const {
+ /**
+ * @param friend_number The friend number of the friend whose connection status
+ * changed.
+ * @param connection_status The result of calling
+ * ${connection_status.get} on the passed friend_number.
+ */
+ typedef void(uint32_t friend_number, CONNECTION connection_status);
+ }
+
+
+ bool typing {
+ /**
+ * Check whether a friend is currently typing a message.
+ *
+ * @param friend_number The friend number for which to query the typing status.
+ *
+ * @return true if the friend is typing.
+ * @return false if the friend is not typing, or the friend number was
+ * invalid. Inspect the error code to determine which case it is.
+ */
+ get(uint32_t friend_number)
+ with error for query;
+ }
+
+
+ /**
+ * This event is triggered when a friend starts or stops typing.
+ */
+ event typing const {
+ /**
+ * @param friend_number The friend number of the friend who started or stopped
+ * typing.
+ * @param is_typing The result of calling ${typing.get} on the passed
+ * friend_number.
+ */
+ typedef void(uint32_t friend_number, bool is_typing);
+ }
+
+}
+
+
+/*******************************************************************************
+ *
+ * :: Sending private messages
+ *
+ ******************************************************************************/
+
+
+inline namespace self {
+
+ bool typing {
+ /**
+ * Set the client's typing status for a friend.
+ *
+ * The client is responsible for turning it on or off.
+ *
+ * @param friend_number The friend to which the client is typing a message.
+ * @param typing The typing status. True means the client is typing.
+ *
+ * @return true on success.
+ */
+ set(uint32_t friend_number) {
+ /**
+ * The friend number did not designate a valid friend.
+ */
+ FRIEND_NOT_FOUND,
+ }
+ }
+
+}
+
+
+namespace friend {
+
+ namespace send {
+
+ /**
+ * Send a text chat message to an online friend.
+ *
+ * This function creates a chat message packet and pushes it into the send
+ * queue.
+ *
+ * The message length may not exceed $MAX_MESSAGE_LENGTH. Larger messages
+ * must be split by the client and sent as separate messages. Other clients can
+ * then reassemble the fragments. Messages may not be empty.
+ *
+ * The return value of this function is the message ID. If a read receipt is
+ * received, the triggered `${event read_receipt}` event will be passed this message ID.
+ *
+ * Message IDs are unique per friend. The first message ID is 0. Message IDs are
+ * incremented by 1 each time a message is sent. If UINT32_MAX messages were
+ * sent, the next message ID is 0.
+ *
+ * @param type Message type (normal, action, ...).
+ * @param friend_number The friend number of the friend to send the message to.
+ * @param message A non-NULL pointer to the first element of a byte array
+ * containing the message text.
+ * @param length Length of the message to be sent.
+ */
+ uint32_t message(uint32_t friend_number, MESSAGE_TYPE type,
+ const uint8_t[length <= MAX_MESSAGE_LENGTH] message) {
+ NULL,
+ /**
+ * The friend number did not designate a valid friend.
+ */
+ FRIEND_NOT_FOUND,
+ /**
+ * This client is currently not connected to the friend.
+ */
+ FRIEND_NOT_CONNECTED,
+ /**
+ * An allocation error occurred while increasing the send queue size.
+ */
+ SENDQ,
+ /**
+ * Message length exceeded $MAX_MESSAGE_LENGTH.
+ */
+ TOO_LONG,
+ /**
+ * Attempted to send a zero-length message.
+ */
+ EMPTY,
+ }
+
+ }
+
+
+ /**
+ * This event is triggered when the friend receives the message sent with
+ * ${send.message} with the corresponding message ID.
+ */
+ event read_receipt const {
+ /**
+ * @param friend_number The friend number of the friend who received the message.
+ * @param message_id The message ID as returned from ${send.message}
+ * corresponding to the message sent.
+ */
+ typedef void(uint32_t friend_number, uint32_t message_id);
+ }
+
+}
+
+
+/*******************************************************************************
+ *
+ * :: Receiving private messages and friend requests
+ *
+ ******************************************************************************/
+
+
+namespace friend {
+
+ /**
+ * This event is triggered when a friend request is received.
+ */
+ event request const {
+ /**
+ * @param public_key The Public Key of the user who sent the friend request.
+ * @param message The message they sent along with the request.
+ * @param length The size of the message byte array.
+ */
+ typedef void(const uint8_t[PUBLIC_KEY_SIZE] public_key,
+ const uint8_t[length <= MAX_MESSAGE_LENGTH] message);
+ }
+
+
+ /**
+ * This event is triggered when a message from a friend is received.
+ */
+ event message const {
+ /**
+ * @param friend_number The friend number of the friend who sent the message.
+ * @param message The message data they sent.
+ * @param length The size of the message byte array.
+ */
+ typedef void(uint32_t friend_number, MESSAGE_TYPE type,
+ const uint8_t[length <= MAX_MESSAGE_LENGTH] message);
+ }
+
+}
+
+
+/*******************************************************************************
+ *
+ * :: File transmission: common between sending and receiving
+ *
+ ******************************************************************************/
+
+
+/**
+ * Generates a cryptographic hash of the given data.
+ *
+ * This function may be used by clients for any purpose, but is provided
+ * primarily for validating cached avatars. This use is highly recommended to
+ * avoid unnecessary avatar updates.
+ *
+ * If hash is NULL or data is NULL while length is not 0 the function returns false,
+ * otherwise it returns true.
+ *
+ * This function is a wrapper to internal message-digest functions.
+ *
+ * @param hash A valid memory location the hash data. It must be at least
+ * $HASH_LENGTH bytes in size.
+ * @param data Data to be hashed or NULL.
+ * @param length Size of the data array or 0.
+ *
+ * @return true if hash was not NULL.
+ */
+static bool hash(uint8_t[HASH_LENGTH] hash, const uint8_t[length] data);
+
+
+namespace file {
+
+ enum KIND {
+ /**
+ * Arbitrary file data. Clients can choose to handle it based on the file name
+ * or magic or any other way they choose.
+ */
+ DATA,
+ /**
+ * Avatar file_id. This consists of $hash(image).
+ * Avatar data. This consists of the image data.
+ *
+ * Avatars can be sent at any time the client wishes. Generally, a client will
+ * send the avatar to a friend when that friend comes online, and to all
+ * friends when the avatar changed. A client can save some traffic by
+ * remembering which friend received the updated avatar already and only send
+ * it if the friend has an out of date avatar.
+ *
+ * Clients who receive avatar send requests can reject it (by sending
+ * ${CONTROL.CANCEL} before any other controls), or accept it (by
+ * sending ${CONTROL.RESUME}). The file_id of length $HASH_LENGTH bytes
+ * (same length as $FILE_ID_LENGTH) will contain the hash. A client can compare
+ * this hash with a saved hash and send ${CONTROL.CANCEL} to terminate the avatar
+ * transfer if it matches.
+ *
+ * When file_size is set to 0 in the transfer request it means that the client
+ * has no avatar.
+ */
+ AVATAR,
+ }
+
+
+ enum class CONTROL {
+ /**
+ * Sent by the receiving side to accept a file send request. Also sent after a
+ * $PAUSE command to continue sending or receiving.
+ */
+ RESUME,
+ /**
+ * Sent by clients to pause the file transfer. The initial state of a file
+ * transfer is always paused on the receiving side and running on the sending
+ * side. If both the sending and receiving side pause the transfer, then both
+ * need to send $RESUME for the transfer to resume.
+ */
+ PAUSE,
+ /**
+ * Sent by the receiving side to reject a file send request before any other
+ * commands are sent. Also sent by either side to terminate a file transfer.
+ */
+ CANCEL,
+ }
+
+
+ /**
+ * Sends a file control command to a friend for a given file transfer.
+ *
+ * @param friend_number The friend number of the friend the file is being
+ * transferred to or received from.
+ * @param file_number The friend-specific identifier for the file transfer.
+ * @param control The control command to send.
+ *
+ * @return true on success.
+ */
+ bool control(uint32_t friend_number, uint32_t file_number, CONTROL control) {
+ /**
+ * The friend_number passed did not designate a valid friend.
+ */
+ FRIEND_NOT_FOUND,
+ /**
+ * This client is currently not connected to the friend.
+ */
+ FRIEND_NOT_CONNECTED,
+ /**
+ * No file transfer with the given file number was found for the given friend.
+ */
+ NOT_FOUND,
+ /**
+ * A RESUME control was sent, but the file transfer is running normally.
+ */
+ NOT_PAUSED,
+ /**
+ * A RESUME control was sent, but the file transfer was paused by the other
+ * party. Only the party that paused the transfer can resume it.
+ */
+ DENIED,
+ /**
+ * A PAUSE control was sent, but the file transfer was already paused.
+ */
+ ALREADY_PAUSED,
+ /**
+ * Packet queue is full.
+ */
+ SENDQ,
+ }
+
+
+ /**
+ * This event is triggered when a file control command is received from a
+ * friend.
+ */
+ event recv_control const {
+ /**
+ * When receiving ${CONTROL.CANCEL}, the client should release the
+ * resources associated with the file number and consider the transfer failed.
+ *
+ * @param friend_number The friend number of the friend who is sending the file.
+ * @param file_number The friend-specific file number the data received is
+ * associated with.
+ * @param control The file control command received.
+ */
+ typedef void(uint32_t friend_number, uint32_t file_number, CONTROL control);
+ }
+
+ /**
+ * Sends a file seek control command to a friend for a given file transfer.
+ *
+ * This function can only be called to resume a file transfer right before
+ * ${CONTROL.RESUME} is sent.
+ *
+ * @param friend_number The friend number of the friend the file is being
+ * received from.
+ * @param file_number The friend-specific identifier for the file transfer.
+ * @param position The position that the file should be seeked to.
+ */
+ bool seek(uint32_t friend_number, uint32_t file_number, uint64_t position) {
+ /**
+ * The friend_number passed did not designate a valid friend.
+ */
+ FRIEND_NOT_FOUND,
+ /**
+ * This client is currently not connected to the friend.
+ */
+ FRIEND_NOT_CONNECTED,
+ /**
+ * No file transfer with the given file number was found for the given friend.
+ */
+ NOT_FOUND,
+ /**
+ * File was not in a state where it could be seeked.
+ */
+ DENIED,
+ /**
+ * Seek position was invalid
+ */
+ INVALID_POSITION,
+ /**
+ * Packet queue is full.
+ */
+ SENDQ,
+ }
+
+
+ error for get {
+ NULL,
+ /**
+ * The friend_number passed did not designate a valid friend.
+ */
+ FRIEND_NOT_FOUND,
+ /**
+ * No file transfer with the given file number was found for the given friend.
+ */
+ NOT_FOUND,
+ }
+
+ uint8_t[FILE_ID_LENGTH] file_id {
+ /**
+ * Copy the file id associated to the file transfer to a byte array.
+ *
+ * @param friend_number The friend number of the friend the file is being
+ * transferred to or received from.
+ * @param file_number The friend-specific identifier for the file transfer.
+ * @param file_id A memory region of at least $FILE_ID_LENGTH bytes. If
+ * this parameter is NULL, this function has no effect.
+ *
+ * @return true on success.
+ */
+ get(uint32_t friend_number, uint32_t file_number)
+ with error for get;
+ }
+
+}
+
+
+/*******************************************************************************
+ *
+ * :: File transmission: sending
+ *
+ ******************************************************************************/
+
+
+namespace file {
+
+ /**
+ * Send a file transmission request.
+ *
+ * Maximum filename length is $MAX_FILENAME_LENGTH bytes. The filename
+ * should generally just be a file name, not a path with directory names.
+ *
+ * If a non-UINT64_MAX file size is provided, it can be used by both sides to
+ * determine the sending progress. File size can be set to UINT64_MAX for streaming
+ * data of unknown size.
+ *
+ * File transmission occurs in chunks, which are requested through the
+ * `${event chunk_request}` event.
+ *
+ * When a friend goes offline, all file transfers associated with the friend are
+ * purged from core.
+ *
+ * If the file contents change during a transfer, the behaviour is unspecified
+ * in general. What will actually happen depends on the mode in which the file
+ * was modified and how the client determines the file size.
+ *
+ * - If the file size was increased
+ * - and sending mode was streaming (file_size = UINT64_MAX), the behaviour
+ * will be as expected.
+ * - and sending mode was file (file_size != UINT64_MAX), the
+ * ${event chunk_request} callback will receive length = 0 when Core thinks
+ * the file transfer has finished. If the client remembers the file size as
+ * it was when sending the request, it will terminate the transfer normally.
+ * If the client re-reads the size, it will think the friend cancelled the
+ * transfer.
+ * - If the file size was decreased
+ * - and sending mode was streaming, the behaviour is as expected.
+ * - and sending mode was file, the callback will return 0 at the new
+ * (earlier) end-of-file, signalling to the friend that the transfer was
+ * cancelled.
+ * - If the file contents were modified
+ * - at a position before the current read, the two files (local and remote)
+ * will differ after the transfer terminates.
+ * - at a position after the current read, the file transfer will succeed as
+ * expected.
+ * - In either case, both sides will regard the transfer as complete and
+ * successful.
+ *
+ * @param friend_number The friend number of the friend the file send request
+ * should be sent to.
+ * @param kind The meaning of the file to be sent.
+ * @param file_size Size in bytes of the file the client wants to send, UINT64_MAX if
+ * unknown or streaming.
+ * @param file_id A file identifier of length $FILE_ID_LENGTH that can be used to
+ * uniquely identify file transfers across core restarts. If NULL, a random one will
+ * be generated by core. It can then be obtained by using ${file_id.get}().
+ * @param filename Name of the file. Does not need to be the actual name. This
+ * name will be sent along with the file send request.
+ * @param filename_length Size in bytes of the filename.
+ *
+ * @return A file number used as an identifier in subsequent callbacks. This
+ * number is per friend. File numbers are reused after a transfer terminates.
+ * On failure, this function returns UINT32_MAX. Any pattern in file numbers
+ * should not be relied on.
+ */
+ uint32_t send(uint32_t friend_number, uint32_t kind, uint64_t file_size,
+ const uint8_t[FILE_ID_LENGTH] file_id,
+ const uint8_t[filename_length <= MAX_FILENAME_LENGTH] filename) {
+ NULL,
+ /**
+ * The friend_number passed did not designate a valid friend.
+ */
+ FRIEND_NOT_FOUND,
+ /**
+ * This client is currently not connected to the friend.
+ */
+ FRIEND_NOT_CONNECTED,
+ /**
+ * Filename length exceeded $MAX_FILENAME_LENGTH bytes.
+ */
+ NAME_TOO_LONG,
+ /**
+ * Too many ongoing transfers. The maximum number of concurrent file transfers
+ * is 256 per friend per direction (sending and receiving).
+ */
+ TOO_MANY,
+ }
+
+
+ /**
+ * Send a chunk of file data to a friend.
+ *
+ * This function is called in response to the `${event chunk_request}` callback. The
+ * length parameter should be equal to the one received though the callback.
+ * If it is zero, the transfer is assumed complete. For files with known size,
+ * Core will know that the transfer is complete after the last byte has been
+ * received, so it is not necessary (though not harmful) to send a zero-length
+ * chunk to terminate. For streams, core will know that the transfer is finished
+ * if a chunk with length less than the length requested in the callback is sent.
+ *
+ * @param friend_number The friend number of the receiving friend for this file.
+ * @param file_number The file transfer identifier returned by tox_file_send.
+ * @param position The file or stream position from which to continue reading.
+ * @return true on success.
+ */
+ bool send_chunk(uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t[length] data) {
+ /**
+ * The length parameter was non-zero, but data was NULL.
+ */
+ NULL,
+ /**
+ * The friend_number passed did not designate a valid friend.
+ */
+ FRIEND_NOT_FOUND,
+ /**
+ * This client is currently not connected to the friend.
+ */
+ FRIEND_NOT_CONNECTED,
+ /**
+ * No file transfer with the given file number was found for the given friend.
+ */
+ NOT_FOUND,
+ /**
+ * File transfer was found but isn't in a transferring state: (paused, done,
+ * broken, etc...) (happens only when not called from the request chunk callback).
+ */
+ NOT_TRANSFERRING,
+ /**
+ * Attempted to send more or less data than requested. The requested data size is
+ * adjusted according to maximum transmission unit and the expected end of
+ * the file. Trying to send less or more than requested will return this error.
+ */
+ INVALID_LENGTH,
+ /**
+ * Packet queue is full.
+ */
+ SENDQ,
+ /**
+ * Position parameter was wrong.
+ */
+ WRONG_POSITION,
+ }
+
+
+ /**
+ * This event is triggered when Core is ready to send more file data.
+ */
+ event chunk_request const {
+ /**
+ * If the length parameter is 0, the file transfer is finished, and the client's
+ * resources associated with the file number should be released. After a call
+ * with zero length, the file number can be reused for future file transfers.
+ *
+ * If the requested position is not equal to the client's idea of the current
+ * file or stream position, it will need to seek. In case of read-once streams,
+ * the client should keep the last read chunk so that a seek back can be
+ * supported. A seek-back only ever needs to read from the last requested chunk.
+ * This happens when a chunk was requested, but the send failed. A seek-back
+ * request can occur an arbitrary number of times for any given chunk.
+ *
+ * In response to receiving this callback, the client should call the function
+ * `$send_chunk` with the requested chunk. If the number of bytes sent
+ * through that function is zero, the file transfer is assumed complete. A
+ * client must send the full length of data requested with this callback.
+ *
+ * @param friend_number The friend number of the receiving friend for this file.
+ * @param file_number The file transfer identifier returned by $send.
+ * @param position The file or stream position from which to continue reading.
+ * @param length The number of bytes requested for the current chunk.
+ */
+ typedef void(uint32_t friend_number, uint32_t file_number, uint64_t position, size_t length);
+ }
+
+}
+
+
+/*******************************************************************************
+ *
+ * :: File transmission: receiving
+ *
+ ******************************************************************************/
+
+
+namespace file {
+
+ /**
+ * This event is triggered when a file transfer request is received.
+ */
+ event recv const {
+ /**
+ * The client should acquire resources to be associated with the file transfer.
+ * Incoming file transfers start in the PAUSED state. After this callback
+ * returns, a transfer can be rejected by sending a ${CONTROL.CANCEL}
+ * control command before any other control commands. It can be accepted by
+ * sending ${CONTROL.RESUME}.
+ *
+ * @param friend_number The friend number of the friend who is sending the file
+ * transfer request.
+ * @param file_number The friend-specific file number the data received is
+ * associated with.
+ * @param kind The meaning of the file to be sent.
+ * @param file_size Size in bytes of the file the client wants to send,
+ * UINT64_MAX if unknown or streaming.
+ * @param filename Name of the file. Does not need to be the actual name. This
+ * name will be sent along with the file send request.
+ * @param filename_length Size in bytes of the filename.
+ */
+ typedef void(uint32_t friend_number, uint32_t file_number, uint32_t kind,
+ uint64_t file_size, const uint8_t[filename_length <= MAX_FILENAME_LENGTH] filename);
+ }
+
+
+ /**
+ * This event is first triggered when a file transfer request is received, and
+ * subsequently when a chunk of file data for an accepted request was received.
+ */
+ event recv_chunk const {
+ /**
+ * When length is 0, the transfer is finished and the client should release the
+ * resources it acquired for the transfer. After a call with length = 0, the
+ * file number can be reused for new file transfers.
+ *
+ * If position is equal to file_size (received in the file_receive callback)
+ * when the transfer finishes, the file was received completely. Otherwise, if
+ * file_size was UINT64_MAX, streaming ended successfully when length is 0.
+ *
+ * @param friend_number The friend number of the friend who is sending the file.
+ * @param file_number The friend-specific file number the data received is
+ * associated with.
+ * @param position The file position of the first byte in data.
+ * @param data A byte array containing the received chunk.
+ * @param length The length of the received chunk.
+ */
+ typedef void(uint32_t friend_number, uint32_t file_number, uint64_t position,
+ const uint8_t[length] data);
+ }
+
+}
+
+
+/*******************************************************************************
+ *
+ * :: Conference management
+ *
+ ******************************************************************************/
+
+namespace conference {
+
+ /**
+ * Conference types for the ${event invite} event.
+ */
+ enum class TYPE {
+ /**
+ * Text-only conferences that must be accepted with the $join function.
+ */
+ TEXT,
+ /**
+ * Video conference. The function to accept these is in toxav.
+ */
+ AV,
+ }
+
+
+ /**
+ * This event is triggered when the client is invited to join a conference.
+ */
+ event invite const {
+ /**
+ * The invitation will remain valid until the inviting friend goes offline
+ * or exits the conference.
+ *
+ * @param friend_number The friend who invited us.
+ * @param type The conference type (text only or audio/video).
+ * @param cookie A piece of data of variable length required to join the
+ * conference.
+ * @param length The length of the cookie.
+ */
+ typedef void(uint32_t friend_number, TYPE type, const uint8_t[length] cookie);
+ }
+
+
+ /**
+ * This event is triggered when the client receives a conference message.
+ */
+ event message const {
+ /**
+ * @param conference_number The conference number of the conference the message is intended for.
+ * @param peer_number The ID of the peer who sent the message.
+ * @param type The type of message (normal, action, ...).
+ * @param message The message data.
+ * @param length The length of the message.
+ */
+ typedef void(uint32_t conference_number, uint32_t peer_number, MESSAGE_TYPE type,
+ const uint8_t[length] message);
+ }
+
+
+ /**
+ * This event is triggered when a peer changes the conference title.
+ *
+ * If peer_number == UINT32_MAX, then author is unknown (e.g. initial joining the conference).
+ */
+ event title const {
+ /**
+ * @param conference_number The conference number of the conference the title change is intended for.
+ * @param peer_number The ID of the peer who changed the title.
+ * @param title The title data.
+ * @param length The title length.
+ */
+ typedef void(uint32_t conference_number, uint32_t peer_number, const uint8_t[length] title);
+ }
+
+ /**
+ * Peer list state change types.
+ */
+ enum class STATE_CHANGE {
+ /**
+ * A peer has joined the conference.
+ */
+ PEER_JOIN,
+ /**
+ * A peer has exited the conference.
+ */
+ PEER_EXIT,
+ /**
+ * A peer has changed their name.
+ */
+ PEER_NAME_CHANGE,
+ }
+
+ /**
+ * This event is triggered when the peer list changes (name change, peer join, peer exit).
+ */
+ event namelist_change const {
+ /**
+ * @param conference_number The conference number of the conference the title change is intended for.
+ * @param peer_number The ID of the peer who changed the title.
+ * @param change The type of change (one of $STATE_CHANGE).
+ */
+ typedef void(uint32_t conference_number, uint32_t peer_number, STATE_CHANGE change);
+ }
+
+
+ /**
+ * Creates a new conference.
+ *
+ * This function creates a new text conference.
+ *
+ * @return conference number on success, or UINT32_MAX on failure.
+ */
+ uint32_t new() {
+ /**
+ * The conference instance failed to initialize.
+ */
+ INIT,
+ }
+
+ /**
+ * This function deletes a conference.
+ *
+ * @param conference_number The conference number of the conference to be deleted.
+ *
+ * @return true on success.
+ */
+ bool delete(uint32_t conference_number) {
+ /**
+ * The conference number passed did not designate a valid conference.
+ */
+ CONFERENCE_NOT_FOUND,
+ }
+
+
+ namespace peer {
+
+ /**
+ * Error codes for peer info queries.
+ */
+ error for query {
+ /**
+ * The conference number passed did not designate a valid conference.
+ */
+ CONFERENCE_NOT_FOUND,
+ /**
+ * The peer number passed did not designate a valid peer.
+ */
+ PEER_NOT_FOUND,
+ /**
+ * The client is not connected to the conference.
+ */
+ NO_CONNECTION,
+ }
+
+ /**
+ * Return the number of peers in the conference. Return value is unspecified on failure.
+ */
+ const uint32_t count(uint32_t conference_number)
+ with error for query;
+
+ uint8_t[size] name {
+
+ /**
+ * Return the length of the peer's name. Return value is unspecified on failure.
+ */
+ size(uint32_t conference_number, uint32_t peer_number)
+ with error for query;
+
+ /**
+ * Copy the name of peer_number who is in conference_number to name.
+ * name must be at least $MAX_NAME_LENGTH long.
+ *
+ * @return true on success.
+ */
+ get(uint32_t conference_number, uint32_t peer_number)
+ with error for query;
+ }
+
+ /**
+ * Copy the public key of peer_number who is in conference_number to public_key.
+ * public_key must be $PUBLIC_KEY_SIZE long.
+ *
+ * @return true on success.
+ */
+ uint8_t[PUBLIC_KEY_SIZE] public_key {
+ get(uint32_t conference_number, uint32_t peer_number)
+ with error for query;
+ }
+
+ /**
+ * Return true if passed peer_number corresponds to our own.
+ */
+ const bool number_is_ours(uint32_t conference_number, uint32_t peer_number)
+ with error for query;
+
+ }
+
+
+ /**
+ * Invites a friend to a conference.
+ *
+ * @param friend_number The friend number of the friend we want to invite.
+ * @param conference_number The conference number of the conference we want to invite the friend to.
+ *
+ * @return true on success.
+ */
+ bool invite(uint32_t friend_number, uint32_t conference_number) {
+ /**
+ * The conference number passed did not designate a valid conference.
+ */
+ CONFERENCE_NOT_FOUND,
+ /**
+ * The invite packet failed to send.
+ */
+ FAIL_SEND,
+ }
+
+
+ /**
+ * Joins a conference that the client has been invited to.
+ *
+ * @param friend_number The friend number of the friend who sent the invite.
+ * @param cookie Received via the `${event invite}` event.
+ * @param length The size of cookie.
+ *
+ * @return conference number on success, UINT32_MAX on failure.
+ */
+ uint32_t join(uint32_t friend_number, const uint8_t[length] cookie) {
+ /**
+ * The cookie passed has an invalid length.
+ */
+ INVALID_LENGTH,
+ /**
+ * The conference is not the expected type. This indicates an invalid cookie.
+ */
+ WRONG_TYPE,
+ /**
+ * The friend number passed does not designate a valid friend.
+ */
+ FRIEND_NOT_FOUND,
+ /**
+ * Client is already in this conference.
+ */
+ DUPLICATE,
+ /**
+ * Conference instance failed to initialize.
+ */
+ INIT_FAIL,
+ /**
+ * The join packet failed to send.
+ */
+ FAIL_SEND,
+ }
+
+
+ namespace send {
+
+ /**
+ * Send a text chat message to the conference.
+ *
+ * This function creates a conference message packet and pushes it into the send
+ * queue.
+ *
+ * The message length may not exceed $MAX_MESSAGE_LENGTH. Larger messages
+ * must be split by the client and sent as separate messages. Other clients can
+ * then reassemble the fragments.
+ *
+ * @param conference_number The conference number of the conference the message is intended for.
+ * @param type Message type (normal, action, ...).
+ * @param message A non-NULL pointer to the first element of a byte array
+ * containing the message text.
+ * @param length Length of the message to be sent.
+ *
+ * @return true on success.
+ */
+ bool message(uint32_t conference_number, MESSAGE_TYPE type, const uint8_t[length] message) {
+ /**
+ * The conference number passed did not designate a valid conference.
+ */
+ CONFERENCE_NOT_FOUND,
+ /**
+ * The message is too long.
+ */
+ TOO_LONG,
+ /**
+ * The client is not connected to the conference.
+ */
+ NO_CONNECTION,
+ /**
+ * The message packet failed to send.
+ */
+ FAIL_SEND,
+ }
+ }
+
+ error for title {
+ /**
+ * The conference number passed did not designate a valid conference.
+ */
+ CONFERENCE_NOT_FOUND,
+ /**
+ * The title is too long or empty.
+ */
+ INVALID_LENGTH,
+ /**
+ * The title packet failed to send.
+ */
+ FAIL_SEND,
+ }
+
+ uint8_t[length <= MAX_NAME_LENGTH] title {
+
+ /**
+ * Return the length of the conference title. Return value is unspecified on failure.
+ *
+ * The return value is equal to the `length` argument received by the last
+ * `${event title}` callback.
+ */
+ size(uint32_t conference_number)
+ with error for title;
+
+ /**
+ * Write the title designated by the given conference number to a byte array.
+ *
+ * Call $size to determine the allocation size for the `title` parameter.
+ *
+ * The data written to `title` is equal to the data received by the last
+ * `${event title}` callback.
+ *
+ * @param title A valid memory region large enough to store the title.
+ * If this parameter is NULL, this function has no effect.
+ *
+ * @return true on success.
+ */
+ get(uint32_t conference_number)
+ with error for title;
+
+ /**
+ * Set the conference title and broadcast it to the rest of the conference.
+ *
+ * Title length cannot be longer than $MAX_NAME_LENGTH.
+ *
+ * @return true on success.
+ */
+ set(uint32_t conference_number)
+ with error for title;
+ }
+
+
+ uint32_t[size] chatlist {
+ /**
+ * Return the number of conferences in the Tox instance.
+ * This should be used to determine how much memory to allocate for `$get`.
+ */
+ size();
+
+ /**
+ * Copy a list of valid conference IDs into the array chatlist. Determine how much space
+ * to allocate for the array with the `$size` function.
+ */
+ get();
+ }
+
+
+ /**
+ * Returns the type of conference ($TYPE) that conference_number is. Return value is
+ * unspecified on failure.
+ */
+ TYPE type {
+ get(uint32_t conference_number) {
+ /**
+ * The conference number passed did not designate a valid conference.
+ */
+ CONFERENCE_NOT_FOUND,
+ }
+ }
+
+}
+
+
+/*******************************************************************************
+ *
+ * :: Low-level custom packet sending and receiving
+ *
+ ******************************************************************************/
+
+
+namespace friend {
+
+ inline namespace send {
+
+ error for custom_packet {
+ NULL,
+ /**
+ * The friend number did not designate a valid friend.
+ */
+ FRIEND_NOT_FOUND,
+ /**
+ * This client is currently not connected to the friend.
+ */
+ FRIEND_NOT_CONNECTED,
+ /**
+ * The first byte of data was not in the specified range for the packet type.
+ * This range is 200-254 for lossy, and 160-191 for lossless packets.
+ */
+ INVALID,
+ /**
+ * Attempted to send an empty packet.
+ */
+ EMPTY,
+ /**
+ * Packet data length exceeded $MAX_CUSTOM_PACKET_SIZE.
+ */
+ TOO_LONG,
+ /**
+ * Packet queue is full.
+ */
+ SENDQ,
+ }
+
+ /**
+ * Send a custom lossy packet to a friend.
+ *
+ * The first byte of data must be in the range 200-254. Maximum length of a
+ * custom packet is $MAX_CUSTOM_PACKET_SIZE.
+ *
+ * Lossy packets behave like UDP packets, meaning they might never reach the
+ * other side or might arrive more than once (if someone is messing with the
+ * connection) or might arrive in the wrong order.
+ *
+ * Unless latency is an issue, it is recommended that you use lossless custom
+ * packets instead.
+ *
+ * @param friend_number The friend number of the friend this lossy packet
+ * should be sent to.
+ * @param data A byte array containing the packet data.
+ * @param length The length of the packet data byte array.
+ *
+ * @return true on success.
+ */
+ bool lossy_packet(uint32_t friend_number, const uint8_t[length <= MAX_CUSTOM_PACKET_SIZE] data)
+ with error for custom_packet;
+
+
+ /**
+ * Send a custom lossless packet to a friend.
+ *
+ * The first byte of data must be in the range 160-191. Maximum length of a
+ * custom packet is $MAX_CUSTOM_PACKET_SIZE.
+ *
+ * Lossless packet behaviour is comparable to TCP (reliability, arrive in order)
+ * but with packets instead of a stream.
+ *
+ * @param friend_number The friend number of the friend this lossless packet
+ * should be sent to.
+ * @param data A byte array containing the packet data.
+ * @param length The length of the packet data byte array.
+ *
+ * @return true on success.
+ */
+ bool lossless_packet(uint32_t friend_number, const uint8_t[length <= MAX_CUSTOM_PACKET_SIZE] data)
+ with error for custom_packet;
+
+ }
+
+
+ event lossy_packet const {
+ /**
+ * @param friend_number The friend number of the friend who sent a lossy packet.
+ * @param data A byte array containing the received packet data.
+ * @param length The length of the packet data byte array.
+ */
+ typedef void(uint32_t friend_number, const uint8_t[length <= MAX_CUSTOM_PACKET_SIZE] data);
+ }
+
+
+ event lossless_packet const {
+ /**
+ * @param friend_number The friend number of the friend who sent the packet.
+ * @param data A byte array containing the received packet data.
+ * @param length The length of the packet data byte array.
+ */
+ typedef void(uint32_t friend_number, const uint8_t[length <= MAX_CUSTOM_PACKET_SIZE] data);
+ }
+
+}
+
+
+
+/*******************************************************************************
+ *
+ * :: Low-level network information
+ *
+ ******************************************************************************/
+
+
+inline namespace self {
+
+ uint8_t[PUBLIC_KEY_SIZE] dht_id {
+ /**
+ * Writes the temporary DHT public key of this instance to a byte array.
+ *
+ * This can be used in combination with an externally accessible IP address and
+ * the bound port (from ${udp_port.get}) to run a temporary bootstrap node.
+ *
+ * Be aware that every time a new instance is created, the DHT public key
+ * changes, meaning this cannot be used to run a permanent bootstrap node.
+ *
+ * @param dht_id A memory region of at least $PUBLIC_KEY_SIZE bytes. If this
+ * parameter is NULL, this function has no effect.
+ */
+ get();
+ }
+
+
+ error for get_port {
+ /**
+ * The instance was not bound to any port.
+ */
+ NOT_BOUND,
+ }
+
+
+ uint16_t udp_port {
+ /**
+ * Return the UDP port this Tox instance is bound to.
+ */
+ get() with error for get_port;
+ }
+
+
+ uint16_t tcp_port {
+ /**
+ * Return the TCP port this Tox instance is bound to. This is only relevant if
+ * the instance is acting as a TCP relay.
+ */
+ get() with error for get_port;
+ }
+
+}
+
+} // class tox
+
+%{
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+%}
diff --git a/protocols/Tox/libtox/src/toxcore/tox.c b/protocols/Tox/libtox/src/toxcore/tox.c
new file mode 100644
index 0000000000..12f3762083
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/tox.c
@@ -0,0 +1,1551 @@
+/*
+ * The Tox public API.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define _XOPEN_SOURCE 600
+
+#define TOX_DEFINED
+typedef struct Messenger Tox;
+#include "tox.h"
+
+#include "Messenger.h"
+#include "group.h"
+#include "logger.h"
+
+#include "../toxencryptsave/defines.h"
+
+#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}}
+
+#if TOX_HASH_LENGTH != CRYPTO_SHA256_SIZE
+#error TOX_HASH_LENGTH is assumed to be equal to CRYPTO_SHA256_SIZE
+#endif
+
+#if FILE_ID_LENGTH != CRYPTO_SYMMETRIC_KEY_SIZE
+#error FILE_ID_LENGTH is assumed to be equal to CRYPTO_SYMMETRIC_KEY_SIZE
+#endif
+
+#if TOX_FILE_ID_LENGTH != CRYPTO_SYMMETRIC_KEY_SIZE
+#error TOX_FILE_ID_LENGTH is assumed to be equal to CRYPTO_SYMMETRIC_KEY_SIZE
+#endif
+
+#if TOX_FILE_ID_LENGTH != TOX_HASH_LENGTH
+#error TOX_FILE_ID_LENGTH is assumed to be equal to TOX_HASH_LENGTH
+#endif
+
+#if TOX_PUBLIC_KEY_SIZE != CRYPTO_PUBLIC_KEY_SIZE
+#error TOX_PUBLIC_KEY_SIZE is assumed to be equal to CRYPTO_PUBLIC_KEY_SIZE
+#endif
+
+#if TOX_SECRET_KEY_SIZE != CRYPTO_SECRET_KEY_SIZE
+#error TOX_SECRET_KEY_SIZE is assumed to be equal to CRYPTO_SECRET_KEY_SIZE
+#endif
+
+#if TOX_MAX_NAME_LENGTH != MAX_NAME_LENGTH
+#error TOX_MAX_NAME_LENGTH is assumed to be equal to MAX_NAME_LENGTH
+#endif
+
+#if TOX_MAX_STATUS_MESSAGE_LENGTH != MAX_STATUSMESSAGE_LENGTH
+#error TOX_MAX_STATUS_MESSAGE_LENGTH is assumed to be equal to MAX_STATUSMESSAGE_LENGTH
+#endif
+
+
+bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch)
+{
+ return TOX_VERSION_IS_API_COMPATIBLE(major, minor, patch);
+}
+
+
+Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error)
+{
+ Messenger_Options m_options = {0};
+
+ bool load_savedata_sk = 0, load_savedata_tox = 0;
+
+ if (options == NULL) {
+ m_options.ipv6enabled = TOX_ENABLE_IPV6_DEFAULT;
+ } else {
+ if (tox_options_get_savedata_type(options) != TOX_SAVEDATA_TYPE_NONE) {
+ if (tox_options_get_savedata_data(options) == NULL || tox_options_get_savedata_length(options) == 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
+ return NULL;
+ }
+ }
+
+ if (tox_options_get_savedata_type(options) == TOX_SAVEDATA_TYPE_SECRET_KEY) {
+ if (tox_options_get_savedata_length(options) != TOX_SECRET_KEY_SIZE) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
+ return NULL;
+ }
+
+ load_savedata_sk = 1;
+ } else if (tox_options_get_savedata_type(options) == TOX_SAVEDATA_TYPE_TOX_SAVE) {
+ if (tox_options_get_savedata_length(options) < TOX_ENC_SAVE_MAGIC_LENGTH) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
+ return NULL;
+ }
+
+ if (crypto_memcmp(tox_options_get_savedata_data(options), TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_ENCRYPTED);
+ return NULL;
+ }
+
+ load_savedata_tox = 1;
+ }
+
+ m_options.ipv6enabled = tox_options_get_ipv6_enabled(options);
+ m_options.udp_disabled = !tox_options_get_udp_enabled(options);
+ m_options.port_range[0] = tox_options_get_start_port(options);
+ m_options.port_range[1] = tox_options_get_end_port(options);
+ m_options.tcp_server_port = tox_options_get_tcp_port(options);
+ m_options.hole_punching_enabled = tox_options_get_hole_punching_enabled(options);
+ m_options.local_discovery_enabled = tox_options_get_local_discovery_enabled(options);
+
+ m_options.log_callback = (logger_cb *)tox_options_get_log_callback(options);
+ m_options.log_user_data = tox_options_get_log_user_data(options);
+
+ switch (tox_options_get_proxy_type(options)) {
+ case TOX_PROXY_TYPE_HTTP:
+ m_options.proxy_info.proxy_type = TCP_PROXY_HTTP;
+ break;
+
+ case TOX_PROXY_TYPE_SOCKS5:
+ m_options.proxy_info.proxy_type = TCP_PROXY_SOCKS5;
+ break;
+
+ case TOX_PROXY_TYPE_NONE:
+ m_options.proxy_info.proxy_type = TCP_PROXY_NONE;
+ break;
+
+ default:
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_TYPE);
+ return NULL;
+ }
+
+ if (m_options.proxy_info.proxy_type != TCP_PROXY_NONE) {
+ if (tox_options_get_proxy_port(options) == 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_PORT);
+ return NULL;
+ }
+
+ ip_init(&m_options.proxy_info.ip_port.ip, m_options.ipv6enabled);
+
+ if (m_options.ipv6enabled) {
+ m_options.proxy_info.ip_port.ip.family = TOX_AF_UNSPEC;
+ }
+
+ if (!addr_resolve_or_parse_ip(tox_options_get_proxy_host(options), &m_options.proxy_info.ip_port.ip, NULL)) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_HOST);
+ // TODO(irungentoo): TOX_ERR_NEW_PROXY_NOT_FOUND if domain.
+ return NULL;
+ }
+
+ m_options.proxy_info.ip_port.port = net_htons(tox_options_get_proxy_port(options));
+ }
+ }
+
+ unsigned int m_error;
+ Messenger *m = new_messenger(&m_options, &m_error);
+
+ if (!new_groupchats(m)) {
+ kill_messenger(m);
+
+ if (m_error == MESSENGER_ERROR_PORT) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PORT_ALLOC);
+ } else if (m_error == MESSENGER_ERROR_TCP_SERVER) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PORT_ALLOC);
+ } else {
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
+ }
+
+ return NULL;
+ }
+
+ if (load_savedata_tox
+ && messenger_load(m, tox_options_get_savedata_data(options), tox_options_get_savedata_length(options)) == -1) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
+ } else if (load_savedata_sk) {
+ load_secret_key(m->net_crypto, tox_options_get_savedata_data(options));
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK);
+ } else {
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK);
+ }
+
+ return m;
+}
+
+void tox_kill(Tox *tox)
+{
+ if (tox == NULL) {
+ return;
+ }
+
+ Messenger *m = tox;
+ kill_groupchats((Group_Chats *)m->conferences_object);
+ kill_messenger(m);
+}
+
+size_t tox_get_savedata_size(const Tox *tox)
+{
+ const Messenger *m = tox;
+ return messenger_size(m);
+}
+
+void tox_get_savedata(const Tox *tox, uint8_t *savedata)
+{
+ if (savedata) {
+ const Messenger *m = tox;
+ messenger_save(m, savedata);
+ }
+}
+
+bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error)
+{
+ if (!address || !public_key) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_NULL);
+ return 0;
+ }
+
+ if (port == 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_PORT);
+ return 0;
+ }
+
+ IP_Port *root;
+
+ int32_t count = net_getipport(address, &root, TOX_SOCK_DGRAM);
+
+ if (count == -1) {
+ net_freeipport(root);
+ SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
+ return 0;
+ }
+
+ unsigned int i;
+
+ for (i = 0; i < count; i++) {
+ root[i].port = net_htons(port);
+
+ Messenger *m = tox;
+ onion_add_bs_path_node(m->onion_c, root[i], public_key);
+ DHT_bootstrap(m->dht, root[i], public_key);
+ }
+
+ net_freeipport(root);
+
+ if (count) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK);
+ return 1;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
+ return 0;
+}
+
+bool tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key,
+ TOX_ERR_BOOTSTRAP *error)
+{
+ if (!address || !public_key) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_NULL);
+ return 0;
+ }
+
+ if (port == 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_PORT);
+ return 0;
+ }
+
+ IP_Port *root;
+
+ int32_t count = net_getipport(address, &root, TOX_SOCK_STREAM);
+
+ if (count == -1) {
+ net_freeipport(root);
+ SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
+ return 0;
+ }
+
+ unsigned int i;
+
+ for (i = 0; i < count; i++) {
+ root[i].port = net_htons(port);
+
+ Messenger *m = tox;
+ add_tcp_relay(m->net_crypto, root[i], public_key);
+ }
+
+ net_freeipport(root);
+
+ if (count) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK);
+ return 1;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
+ return 0;
+}
+
+TOX_CONNECTION tox_self_get_connection_status(const Tox *tox)
+{
+ const Messenger *m = tox;
+
+ unsigned int ret = onion_connection_status(m->onion_c);
+
+ if (ret == 2) {
+ return TOX_CONNECTION_UDP;
+ }
+
+ if (ret == 1) {
+ return TOX_CONNECTION_TCP;
+ }
+
+ return TOX_CONNECTION_NONE;
+}
+
+
+void tox_callback_self_connection_status(Tox *tox, tox_self_connection_status_cb *callback)
+{
+ Messenger *m = tox;
+ m_callback_core_connection(m, (void (*)(Messenger *, unsigned int, void *))callback);
+}
+
+uint32_t tox_iteration_interval(const Tox *tox)
+{
+ const Messenger *m = tox;
+ return messenger_run_interval(m);
+}
+
+void tox_iterate(Tox *tox, void *user_data)
+{
+ Messenger *m = tox;
+ do_messenger(m, user_data);
+ do_groupchats((Group_Chats *)m->conferences_object, user_data);
+}
+
+void tox_self_get_address(const Tox *tox, uint8_t *address)
+{
+ if (address) {
+ const Messenger *m = tox;
+ getaddress(m, address);
+ }
+}
+
+void tox_self_set_nospam(Tox *tox, uint32_t nospam)
+{
+ Messenger *m = tox;
+ set_nospam(&(m->fr), net_htonl(nospam));
+}
+
+uint32_t tox_self_get_nospam(const Tox *tox)
+{
+ const Messenger *m = tox;
+ return net_ntohl(get_nospam(&(m->fr)));
+}
+
+void tox_self_get_public_key(const Tox *tox, uint8_t *public_key)
+{
+ const Messenger *m = tox;
+
+ if (public_key) {
+ memcpy(public_key, m->net_crypto->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ }
+}
+
+void tox_self_get_secret_key(const Tox *tox, uint8_t *secret_key)
+{
+ const Messenger *m = tox;
+
+ if (secret_key) {
+ memcpy(secret_key, m->net_crypto->self_secret_key, CRYPTO_SECRET_KEY_SIZE);
+ }
+}
+
+bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, TOX_ERR_SET_INFO *error)
+{
+ if (!name && length != 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_NULL);
+ return 0;
+ }
+
+ Messenger *m = tox;
+
+ if (setname(m, name, length) == 0) {
+ // TODO(irungentoo): function to set different per group names?
+ send_name_all_groups((Group_Chats *)m->conferences_object);
+ SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_OK);
+ return 1;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_TOO_LONG);
+ return 0;
+}
+
+size_t tox_self_get_name_size(const Tox *tox)
+{
+ const Messenger *m = tox;
+ return m_get_self_name_size(m);
+}
+
+void tox_self_get_name(const Tox *tox, uint8_t *name)
+{
+ if (name) {
+ const Messenger *m = tox;
+ getself_name(m, name);
+ }
+}
+
+bool tox_self_set_status_message(Tox *tox, const uint8_t *status_message, size_t length, TOX_ERR_SET_INFO *error)
+{
+ if (!status_message && length != 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_NULL);
+ return 0;
+ }
+
+ Messenger *m = tox;
+
+ if (m_set_statusmessage(m, status_message, length) == 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_OK);
+ return 1;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_TOO_LONG);
+ return 0;
+}
+
+size_t tox_self_get_status_message_size(const Tox *tox)
+{
+ const Messenger *m = tox;
+ return m_get_self_statusmessage_size(m);
+}
+
+void tox_self_get_status_message(const Tox *tox, uint8_t *status_message)
+{
+ if (status_message) {
+ const Messenger *m = tox;
+ m_copy_self_statusmessage(m, status_message);
+ }
+}
+
+void tox_self_set_status(Tox *tox, TOX_USER_STATUS status)
+{
+ Messenger *m = tox;
+ m_set_userstatus(m, status);
+}
+
+TOX_USER_STATUS tox_self_get_status(const Tox *tox)
+{
+ const Messenger *m = tox;
+ return (TOX_USER_STATUS)m_get_self_userstatus(m);
+}
+
+static void set_friend_error(int32_t ret, TOX_ERR_FRIEND_ADD *error)
+{
+ switch (ret) {
+ case FAERR_TOOLONG:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_TOO_LONG);
+ break;
+
+ case FAERR_NOMESSAGE:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_NO_MESSAGE);
+ break;
+
+ case FAERR_OWNKEY:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OWN_KEY);
+ break;
+
+ case FAERR_ALREADYSENT:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_ALREADY_SENT);
+ break;
+
+ case FAERR_BADCHECKSUM:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_BAD_CHECKSUM);
+ break;
+
+ case FAERR_SETNEWNOSPAM:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM);
+ break;
+
+ case FAERR_NOMEM:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_MALLOC);
+ break;
+ }
+}
+
+uint32_t tox_friend_add(Tox *tox, const uint8_t *address, const uint8_t *message, size_t length,
+ TOX_ERR_FRIEND_ADD *error)
+{
+ if (!address || !message) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_NULL);
+ return UINT32_MAX;
+ }
+
+ Messenger *m = tox;
+ int32_t ret = m_addfriend(m, address, message, length);
+
+ if (ret >= 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OK);
+ return ret;
+ }
+
+ set_friend_error(ret, error);
+ return UINT32_MAX;
+}
+
+uint32_t tox_friend_add_norequest(Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_ADD *error)
+{
+ if (!public_key) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_NULL);
+ return UINT32_MAX;
+ }
+
+ Messenger *m = tox;
+ int32_t ret = m_addfriend_norequest(m, public_key);
+
+ if (ret >= 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OK);
+ return ret;
+ }
+
+ set_friend_error(ret, error);
+ return UINT32_MAX;
+}
+
+bool tox_friend_delete(Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_DELETE *error)
+{
+ Messenger *m = tox;
+ int ret = m_delfriend(m, friend_number);
+
+ // TODO(irungentoo): handle if realloc fails?
+ if (ret == -1) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND);
+ return 0;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_DELETE_OK);
+ return 1;
+}
+
+uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_BY_PUBLIC_KEY *error)
+{
+ if (!public_key) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL);
+ return UINT32_MAX;
+ }
+
+ const Messenger *m = tox;
+ int32_t ret = getfriend_id(m, public_key);
+
+ if (ret == -1) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND);
+ return UINT32_MAX;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK);
+ return ret;
+}
+
+bool tox_friend_get_public_key(const Tox *tox, uint32_t friend_number, uint8_t *public_key,
+ TOX_ERR_FRIEND_GET_PUBLIC_KEY *error)
+{
+ if (!public_key) {
+ return 0;
+ }
+
+ const Messenger *m = tox;
+
+ if (get_real_pk(m, friend_number, public_key) == -1) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND);
+ return 0;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK);
+ return 1;
+}
+
+bool tox_friend_exists(const Tox *tox, uint32_t friend_number)
+{
+ const Messenger *m = tox;
+ return m_friend_exists(m, friend_number);
+}
+
+uint64_t tox_friend_get_last_online(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_GET_LAST_ONLINE *error)
+{
+ const Messenger *m = tox;
+ uint64_t timestamp = m_get_last_online(m, friend_number);
+
+ if (timestamp == UINT64_MAX) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_LAST_ONLINE_FRIEND_NOT_FOUND)
+ return UINT64_MAX;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_LAST_ONLINE_OK);
+ return timestamp;
+}
+
+size_t tox_self_get_friend_list_size(const Tox *tox)
+{
+ const Messenger *m = tox;
+ return count_friendlist(m);
+}
+
+void tox_self_get_friend_list(const Tox *tox, uint32_t *friend_list)
+{
+ if (friend_list) {
+ const Messenger *m = tox;
+ // TODO(irungentoo): size parameter?
+ copy_friendlist(m, friend_list, tox_self_get_friend_list_size(tox));
+ }
+}
+
+size_t tox_friend_get_name_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
+{
+ const Messenger *m = tox;
+ int ret = m_get_name_size(m, friend_number);
+
+ if (ret == -1) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
+ return SIZE_MAX;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
+ return ret;
+}
+
+bool tox_friend_get_name(const Tox *tox, uint32_t friend_number, uint8_t *name, TOX_ERR_FRIEND_QUERY *error)
+{
+ if (!name) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_NULL);
+ return 0;
+ }
+
+ const Messenger *m = tox;
+ int ret = getname(m, friend_number, name);
+
+ if (ret == -1) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
+ return 0;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
+ return 1;
+}
+
+void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *callback)
+{
+ Messenger *m = tox;
+ m_callback_namechange(m, callback);
+}
+
+size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
+{
+ const Messenger *m = tox;
+ int ret = m_get_statusmessage_size(m, friend_number);
+
+ if (ret == -1) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
+ return SIZE_MAX;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
+ return ret;
+}
+
+bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8_t *status_message,
+ TOX_ERR_FRIEND_QUERY *error)
+{
+ if (!status_message) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_NULL);
+ return 0;
+ }
+
+ const Messenger *m = tox;
+ // TODO(irungentoo): size parameter?
+ int ret = m_copy_statusmessage(m, friend_number, status_message, m_get_statusmessage_size(m, friend_number));
+
+ if (ret == -1) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
+ return 0;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
+ return 1;
+}
+
+void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *callback)
+{
+ Messenger *m = tox;
+ m_callback_statusmessage(m, callback);
+}
+
+TOX_USER_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
+{
+ const Messenger *m = tox;
+
+ int ret = m_get_userstatus(m, friend_number);
+
+ if (ret == USERSTATUS_INVALID) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
+ return (TOX_USER_STATUS)(TOX_USER_STATUS_BUSY + 1);
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
+ return (TOX_USER_STATUS)ret;
+}
+
+void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *callback)
+{
+ Messenger *m = tox;
+ m_callback_userstatus(m, (void (*)(Messenger *, uint32_t, unsigned int, void *))callback);
+}
+
+TOX_CONNECTION tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
+{
+ const Messenger *m = tox;
+
+ int ret = m_get_friend_connectionstatus(m, friend_number);
+
+ if (ret == -1) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
+ return TOX_CONNECTION_NONE;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
+ return (TOX_CONNECTION)ret;
+}
+
+void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_status_cb *callback)
+{
+ Messenger *m = tox;
+ m_callback_connectionstatus(m, (void (*)(Messenger *, uint32_t, unsigned int, void *))callback);
+}
+
+bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
+{
+ const Messenger *m = tox;
+ int ret = m_get_istyping(m, friend_number);
+
+ if (ret == -1) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
+ return 0;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
+ return !!ret;
+}
+
+void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *callback)
+{
+ Messenger *m = tox;
+ m_callback_typingchange(m, callback);
+}
+
+bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool typing, TOX_ERR_SET_TYPING *error)
+{
+ Messenger *m = tox;
+
+ if (m_set_usertyping(m, friend_number, typing) == -1) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND);
+ return 0;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_SET_TYPING_OK);
+ return 1;
+}
+
+static void set_message_error(int ret, TOX_ERR_FRIEND_SEND_MESSAGE *error)
+{
+ switch (ret) {
+ case 0:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_OK);
+ break;
+
+ case -1:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_FOUND);
+ break;
+
+ case -2:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG);
+ break;
+
+ case -3:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_CONNECTED);
+ break;
+
+ case -4:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ);
+ break;
+
+ case -5:
+ /* can't happen */
+ break;
+ }
+}
+
+uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, const uint8_t *message,
+ size_t length, TOX_ERR_FRIEND_SEND_MESSAGE *error)
+{
+ if (!message) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_NULL);
+ return 0;
+ }
+
+ if (!length) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY);
+ return 0;
+ }
+
+ Messenger *m = tox;
+ uint32_t message_id = 0;
+ set_message_error(m_send_message_generic(m, friend_number, type, message, length, &message_id), error);
+ return message_id;
+}
+
+void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *callback)
+{
+ Messenger *m = tox;
+ m_callback_read_receipt(m, callback);
+}
+
+void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *callback)
+{
+ Messenger *m = tox;
+ m_callback_friendrequest(m, callback);
+}
+
+void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *callback)
+{
+ Messenger *m = tox;
+ m_callback_friendmessage(m, (void (*)(Messenger *, uint32_t, unsigned int, const uint8_t *, size_t, void *))callback);
+}
+
+bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length)
+{
+ if (!hash || (length && !data)) {
+ return 0;
+ }
+
+ crypto_sha256(hash, data, length);
+ return 1;
+}
+
+bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control,
+ TOX_ERR_FILE_CONTROL *error)
+{
+ Messenger *m = tox;
+ int ret = file_control(m, friend_number, file_number, control);
+
+ if (ret == 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_OK);
+ return 1;
+ }
+
+ switch (ret) {
+ case -1:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND);
+ return 0;
+
+ case -2:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED);
+ return 0;
+
+ case -3:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_NOT_FOUND);
+ return 0;
+
+ case -4:
+ /* can't happen */
+ return 0;
+
+ case -5:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_ALREADY_PAUSED);
+ return 0;
+
+ case -6:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_DENIED);
+ return 0;
+
+ case -7:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_NOT_PAUSED);
+ return 0;
+
+ case -8:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_SENDQ);
+ return 0;
+ }
+
+ /* can't happen */
+ return 0;
+}
+
+bool tox_file_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position,
+ TOX_ERR_FILE_SEEK *error)
+{
+ Messenger *m = tox;
+ int ret = file_seek(m, friend_number, file_number, position);
+
+ if (ret == 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_OK);
+ return 1;
+ }
+
+ switch (ret) {
+ case -1:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_FRIEND_NOT_FOUND);
+ return 0;
+
+ case -2:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED);
+ return 0;
+
+ case -3:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_NOT_FOUND);
+ return 0;
+
+ case -4: // fall-through
+ case -5:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_DENIED);
+ return 0;
+
+ case -6:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_INVALID_POSITION);
+ return 0;
+
+ case -8:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_SENDQ);
+ return 0;
+ }
+
+ /* can't happen */
+ return 0;
+}
+
+void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *callback)
+{
+ Messenger *m = tox;
+ callback_file_control(m, (void (*)(Messenger *, uint32_t, uint32_t, unsigned int, void *))callback);
+}
+
+bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id,
+ TOX_ERR_FILE_GET *error)
+{
+ if (!file_id) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_NULL);
+ return 0;
+ }
+
+ const Messenger *m = tox;
+ int ret = file_get_id(m, friend_number, file_number, file_id);
+
+ if (ret == 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_OK);
+ return 1;
+ }
+
+ if (ret == -1) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_FRIEND_NOT_FOUND);
+ } else {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_NOT_FOUND);
+ }
+
+ return 0;
+}
+
+uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *file_id,
+ const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error)
+{
+ if (filename_length && !filename) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NULL);
+ return UINT32_MAX;
+ }
+
+ uint8_t f_id[FILE_ID_LENGTH];
+
+ if (!file_id) {
+ /* Tox keys are 32 bytes like FILE_ID_LENGTH. */
+ new_symmetric_key(f_id);
+ file_id = f_id;
+ }
+
+ Messenger *m = tox;
+ long int file_num = new_filesender(m, friend_number, kind, file_size, file_id, filename, filename_length);
+
+ if (file_num >= 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_OK);
+ return file_num;
+ }
+
+ switch (file_num) {
+ case -1:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND);
+ return UINT32_MAX;
+
+ case -2:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NAME_TOO_LONG);
+ return UINT32_MAX;
+
+ case -3:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_TOO_MANY);
+ return UINT32_MAX;
+
+ case -4:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED);
+ return UINT32_MAX;
+ }
+
+ /* can't happen */
+ return UINT32_MAX;
+}
+
+bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t *data,
+ size_t length, TOX_ERR_FILE_SEND_CHUNK *error)
+{
+ Messenger *m = tox;
+ int ret = file_data(m, friend_number, file_number, position, data, length);
+
+ if (ret == 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_OK);
+ return 1;
+ }
+
+ switch (ret) {
+ case -1:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_FOUND);
+ return 0;
+
+ case -2:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED);
+ return 0;
+
+ case -3:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND);
+ return 0;
+
+ case -4:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING);
+ return 0;
+
+ case -5:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_INVALID_LENGTH);
+ return 0;
+
+ case -6:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_SENDQ);
+ return 0;
+
+ case -7:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_WRONG_POSITION);
+ return 0;
+ }
+
+ /* can't happen */
+ return 0;
+}
+
+void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *callback)
+{
+ Messenger *m = tox;
+ callback_file_reqchunk(m, callback);
+}
+
+void tox_callback_file_recv(Tox *tox, tox_file_recv_cb *callback)
+{
+ Messenger *m = tox;
+ callback_file_sendrequest(m, callback);
+}
+
+void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *callback)
+{
+ Messenger *m = tox;
+ callback_file_data(m, callback);
+}
+
+void tox_callback_conference_invite(Tox *tox, tox_conference_invite_cb *callback)
+{
+ Messenger *m = tox;
+ g_callback_group_invite((Group_Chats *)m->conferences_object, (void (*)(Messenger * m, uint32_t, int, const uint8_t *,
+ size_t,
+ void *))callback);
+}
+
+void tox_callback_conference_message(Tox *tox, tox_conference_message_cb *callback)
+{
+ Messenger *m = tox;
+ g_callback_group_message((Group_Chats *)m->conferences_object, (void (*)(Messenger * m, uint32_t, uint32_t, int,
+ const uint8_t *,
+ size_t, void *))callback);
+}
+
+void tox_callback_conference_title(Tox *tox, tox_conference_title_cb *callback)
+{
+ Messenger *m = tox;
+ g_callback_group_title((Group_Chats *)m->conferences_object, callback);
+}
+
+void tox_callback_conference_namelist_change(Tox *tox, tox_conference_namelist_change_cb *callback)
+{
+ Messenger *m = tox;
+ g_callback_group_namelistchange((Group_Chats *)m->conferences_object, (void (*)(struct Messenger *, int, int, uint8_t,
+ void *))callback);
+}
+
+uint32_t tox_conference_new(Tox *tox, TOX_ERR_CONFERENCE_NEW *error)
+{
+ Messenger *m = tox;
+ int ret = add_groupchat((Group_Chats *)m->conferences_object, GROUPCHAT_TYPE_TEXT);
+
+ if (ret == -1) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_NEW_INIT);
+ return UINT32_MAX;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_NEW_OK);
+ return ret;
+}
+
+bool tox_conference_delete(Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_DELETE *error)
+{
+ Messenger *m = tox;
+ int ret = del_groupchat((Group_Chats *)m->conferences_object, conference_number);
+
+ if (ret == -1) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND);
+ return false;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_DELETE_OK);
+ return true;
+}
+
+uint32_t tox_conference_peer_count(const Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_PEER_QUERY *error)
+{
+ const Messenger *m = tox;
+ int ret = group_number_peers((Group_Chats *)m->conferences_object, conference_number);
+
+ if (ret == -1) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
+ return UINT32_MAX;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
+ return ret;
+}
+
+size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
+ TOX_ERR_CONFERENCE_PEER_QUERY *error)
+{
+ const Messenger *m = tox;
+ int ret = group_peername_size((Group_Chats *)m->conferences_object, conference_number, peer_number);
+
+ switch (ret) {
+ case -1:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
+ return -1;
+
+ case -2:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
+ return -1;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
+ return ret;
+}
+
+bool tox_conference_peer_get_name(const Tox *tox, uint32_t conference_number, uint32_t peer_number, uint8_t *name,
+ TOX_ERR_CONFERENCE_PEER_QUERY *error)
+{
+ const Messenger *m = tox;
+ int ret = group_peername((Group_Chats *)m->conferences_object, conference_number, peer_number, name);
+
+ switch (ret) {
+ case -1:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
+ return false;
+
+ case -2:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
+ return false;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
+ return true;
+}
+
+bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
+ uint8_t *public_key, TOX_ERR_CONFERENCE_PEER_QUERY *error)
+{
+ const Messenger *m = tox;
+ int ret = group_peer_pubkey((Group_Chats *)m->conferences_object, conference_number, peer_number, public_key);
+
+ switch (ret) {
+ case -1:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
+ return false;
+
+ case -2:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
+ return false;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
+ return true;
+}
+
+bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
+ TOX_ERR_CONFERENCE_PEER_QUERY *error)
+{
+ const Messenger *m = tox;
+ int ret = group_peernumber_is_ours((Group_Chats *)m->conferences_object, conference_number, peer_number);
+
+ switch (ret) {
+ case -1:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
+ return false;
+
+ case -2:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
+ return false;
+
+ case -3:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_NO_CONNECTION);
+ return false;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
+ return ret;
+}
+
+bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference_number,
+ TOX_ERR_CONFERENCE_INVITE *error)
+{
+ Messenger *m = tox;
+ int ret = invite_friend((Group_Chats *)m->conferences_object, friend_number, conference_number);
+
+ switch (ret) {
+ case -1:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_CONFERENCE_NOT_FOUND);
+ return false;
+
+ case -2:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_FAIL_SEND);
+ return false;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_OK);
+ return true;
+}
+
+uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *cookie, size_t length,
+ TOX_ERR_CONFERENCE_JOIN *error)
+{
+ Messenger *m = tox;
+ int ret = join_groupchat((Group_Chats *)m->conferences_object, friend_number, GROUPCHAT_TYPE_TEXT, cookie, length);
+
+ switch (ret) {
+ case -1:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH);
+ return UINT32_MAX;
+
+ case -2:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE);
+ return UINT32_MAX;
+
+ case -3:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_FRIEND_NOT_FOUND);
+ return UINT32_MAX;
+
+ case -4:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_DUPLICATE);
+ return UINT32_MAX;
+
+ case -5:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_INIT_FAIL);
+ return UINT32_MAX;
+
+ case -6:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_FAIL_SEND);
+ return UINT32_MAX;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_OK);
+ return ret;
+}
+
+bool tox_conference_send_message(Tox *tox, uint32_t conference_number, TOX_MESSAGE_TYPE type, const uint8_t *message,
+ size_t length, TOX_ERR_CONFERENCE_SEND_MESSAGE *error)
+{
+ Messenger *m = tox;
+ int ret = 0;
+
+ if (type == TOX_MESSAGE_TYPE_NORMAL) {
+ ret = group_message_send((Group_Chats *)m->conferences_object, conference_number, message, length);
+ } else {
+ ret = group_action_send((Group_Chats *)m->conferences_object, conference_number, message, length);
+ }
+
+ switch (ret) {
+ case -1:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND);
+ return false;
+
+ case -2:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_TOO_LONG);
+ return false;
+
+ case -3:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_NO_CONNECTION);
+ return false;
+
+ case -4:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_FAIL_SEND);
+ return false;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_OK);
+ return true;
+}
+
+size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_TITLE *error)
+{
+ const Messenger *m = tox;
+ int ret = group_title_get_size((Group_Chats *)m->conferences_object, conference_number);
+
+ switch (ret) {
+ case -1:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);
+ return -1;
+
+ case -2:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);
+ return -1;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK);
+ return ret;
+}
+
+bool tox_conference_get_title(const Tox *tox, uint32_t conference_number, uint8_t *title,
+ TOX_ERR_CONFERENCE_TITLE *error)
+{
+ const Messenger *m = tox;
+ int ret = group_title_get((Group_Chats *)m->conferences_object, conference_number, title);
+
+ switch (ret) {
+ case -1:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);
+ return false;
+
+ case -2:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);
+ return false;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK);
+ return true;
+}
+
+bool tox_conference_set_title(Tox *tox, uint32_t conference_number, const uint8_t *title, size_t length,
+ TOX_ERR_CONFERENCE_TITLE *error)
+{
+ Messenger *m = tox;
+ int ret = group_title_send((Group_Chats *)m->conferences_object, conference_number, title, length);
+
+ switch (ret) {
+ case -1:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);
+ return false;
+
+ case -2:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);
+ return false;
+
+ case -3:
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_FAIL_SEND);
+ return false;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK);
+ return true;
+}
+
+size_t tox_conference_get_chatlist_size(const Tox *tox)
+{
+ const Messenger *m = tox;
+ return count_chatlist((Group_Chats *)m->conferences_object);
+}
+
+void tox_conference_get_chatlist(const Tox *tox, uint32_t *chatlist)
+{
+ const Messenger *m = tox;
+ size_t list_size = tox_conference_get_chatlist_size(tox);
+ copy_chatlist((Group_Chats *)m->conferences_object, chatlist, list_size);
+}
+
+TOX_CONFERENCE_TYPE tox_conference_get_type(const Tox *tox, uint32_t conference_number,
+ TOX_ERR_CONFERENCE_GET_TYPE *error)
+{
+ const Messenger *m = tox;
+ int ret = group_get_type((Group_Chats *)m->conferences_object, conference_number);
+
+ if (ret == -1) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND);
+ return (TOX_CONFERENCE_TYPE)ret;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_GET_TYPE_OK);
+ return (TOX_CONFERENCE_TYPE)ret;
+}
+
+static void set_custom_packet_error(int ret, TOX_ERR_FRIEND_CUSTOM_PACKET *error)
+{
+ switch (ret) {
+ case 0:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_OK);
+ break;
+
+ case -1:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_FOUND);
+ break;
+
+ case -2:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_TOO_LONG);
+ break;
+
+ case -3:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID);
+ break;
+
+ case -4:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED);
+ break;
+
+ case -5:
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_SENDQ);
+ break;
+ }
+}
+
+bool tox_friend_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
+ TOX_ERR_FRIEND_CUSTOM_PACKET *error)
+{
+ if (!data) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_NULL);
+ return 0;
+ }
+
+ Messenger *m = tox;
+
+ if (length == 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY);
+ return 0;
+ }
+
+ if (data[0] < (PACKET_ID_LOSSY_RANGE_START + PACKET_LOSSY_AV_RESERVED)) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID);
+ return 0;
+ }
+
+ int ret = m_send_custom_lossy_packet(m, friend_number, data, length);
+
+ set_custom_packet_error(ret, error);
+
+ if (ret == 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *callback)
+{
+ Messenger *m = tox;
+ custom_lossy_packet_registerhandler(m, callback);
+}
+
+bool tox_friend_send_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
+ TOX_ERR_FRIEND_CUSTOM_PACKET *error)
+{
+ if (!data) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_NULL);
+ return 0;
+ }
+
+ Messenger *m = tox;
+
+ if (length == 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY);
+ return 0;
+ }
+
+ int ret = send_custom_lossless_packet(m, friend_number, data, length);
+
+ set_custom_packet_error(ret, error);
+
+ if (ret == 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb *callback)
+{
+ Messenger *m = tox;
+ custom_lossless_packet_registerhandler(m, callback);
+}
+
+void tox_self_get_dht_id(const Tox *tox, uint8_t *dht_id)
+{
+ if (dht_id) {
+ const Messenger *m = tox;
+ memcpy(dht_id, m->dht->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ }
+}
+
+uint16_t tox_self_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error)
+{
+ const Messenger *m = tox;
+ uint16_t port = net_htons(m->net->port);
+
+ if (port) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK);
+ } else {
+ SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND);
+ }
+
+ return port;
+}
+
+uint16_t tox_self_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error)
+{
+ const Messenger *m = tox;
+
+ if (m->tcp_server) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK);
+ return m->options.tcp_server_port;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND);
+ return 0;
+}
diff --git a/protocols/Tox/include/tox.h b/protocols/Tox/libtox/src/toxcore/tox.h
index 373138c4eb..30bc950964 100644
--- a/protocols/Tox/include/tox.h
+++ b/protocols/Tox/libtox/src/toxcore/tox.h
@@ -24,7 +24,7 @@
#ifndef TOX_H
#define TOX_H
-#include <msapi/stdbool.h>
+#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
diff --git a/protocols/Tox/libtox/src/toxcore/tox_api.c b/protocols/Tox/libtox/src/toxcore/tox_api.c
new file mode 100644
index 0000000000..b6c8c38618
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/tox_api.c
@@ -0,0 +1,97 @@
+#include "tox.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}}
+
+
+#define CONST_FUNCTION(lowercase, uppercase) \
+uint32_t tox_##lowercase(void) \
+{ \
+ return TOX_##uppercase; \
+}
+
+CONST_FUNCTION(version_major, VERSION_MAJOR)
+CONST_FUNCTION(version_minor, VERSION_MINOR)
+CONST_FUNCTION(version_patch, VERSION_PATCH)
+CONST_FUNCTION(public_key_size, PUBLIC_KEY_SIZE)
+CONST_FUNCTION(secret_key_size, SECRET_KEY_SIZE)
+CONST_FUNCTION(address_size, ADDRESS_SIZE)
+CONST_FUNCTION(max_name_length, MAX_NAME_LENGTH)
+CONST_FUNCTION(max_status_message_length, MAX_STATUS_MESSAGE_LENGTH)
+CONST_FUNCTION(max_friend_request_length, MAX_FRIEND_REQUEST_LENGTH)
+CONST_FUNCTION(max_message_length, MAX_MESSAGE_LENGTH)
+CONST_FUNCTION(max_custom_packet_size, MAX_CUSTOM_PACKET_SIZE)
+CONST_FUNCTION(hash_length, HASH_LENGTH)
+CONST_FUNCTION(file_id_length, FILE_ID_LENGTH)
+CONST_FUNCTION(max_filename_length, MAX_FILENAME_LENGTH)
+
+
+#define ACCESSORS(type, ns, name) \
+type tox_options_get_##ns##name(const struct Tox_Options *options) \
+{ \
+ return options->ns##name; \
+} \
+void tox_options_set_##ns##name(struct Tox_Options *options, type name) \
+{ \
+ options->ns##name = name; \
+}
+
+ACCESSORS(bool, , ipv6_enabled)
+ACCESSORS(bool, , udp_enabled)
+ACCESSORS(TOX_PROXY_TYPE, proxy_ , type)
+ACCESSORS(const char *, proxy_ , host)
+ACCESSORS(uint16_t, proxy_ , port)
+ACCESSORS(uint16_t, , start_port)
+ACCESSORS(uint16_t, , end_port)
+ACCESSORS(uint16_t, , tcp_port)
+ACCESSORS(bool, , hole_punching_enabled)
+ACCESSORS(TOX_SAVEDATA_TYPE, savedata_, type)
+ACCESSORS(size_t, savedata_, length)
+ACCESSORS(tox_log_cb *, log_, callback)
+ACCESSORS(void *, log_, user_data)
+ACCESSORS(bool, , local_discovery_enabled)
+
+const uint8_t *tox_options_get_savedata_data(const struct Tox_Options *options)
+{
+ return options->savedata_data;
+}
+
+void tox_options_set_savedata_data(struct Tox_Options *options, const uint8_t *data, size_t length)
+{
+ options->savedata_data = data;
+ options->savedata_length = length;
+}
+
+void tox_options_default(struct Tox_Options *options)
+{
+ if (options) {
+ struct Tox_Options default_options = { 0 };
+ *options = default_options;
+ tox_options_set_ipv6_enabled(options, true);
+ tox_options_set_udp_enabled(options, true);
+ tox_options_set_proxy_type(options, TOX_PROXY_TYPE_NONE);
+ tox_options_set_hole_punching_enabled(options, true);
+ tox_options_set_local_discovery_enabled(options, true);
+ }
+}
+
+struct Tox_Options *tox_options_new(TOX_ERR_OPTIONS_NEW *error)
+{
+ struct Tox_Options *options = (struct Tox_Options *)malloc(sizeof(struct Tox_Options));
+
+ if (options) {
+ tox_options_default(options);
+ SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_OK);
+ return options;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_MALLOC);
+ return NULL;
+}
+
+void tox_options_free(struct Tox_Options *options)
+{
+ free(options);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/util.c b/protocols/Tox/libtox/src/toxcore/util.c
new file mode 100644
index 0000000000..92bbb68c1f
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/util.c
@@ -0,0 +1,195 @@
+/*
+ * Utilities.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ * Copyright © 2013 plutooo
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ * This file is donated to the Tox Project.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define _XOPEN_SOURCE 600
+
+#include "util.h"
+
+#include "crypto_core.h" /* for CRYPTO_PUBLIC_KEY_SIZE */
+#include "network.h" /* for current_time_monotonic */
+
+#include <time.h>
+
+
+/* don't call into system billions of times for no reason */
+static uint64_t unix_time_value;
+static uint64_t unix_base_time_value;
+
+/* XXX: note that this is not thread-safe; if multiple threads call unix_time_update() concurrently, the return value of
+ * unix_time() may fail to increase monotonically with increasing time */
+void unix_time_update(void)
+{
+ if (unix_base_time_value == 0) {
+ unix_base_time_value = ((uint64_t)time(NULL) - (current_time_monotonic() / 1000ULL));
+ }
+
+ unix_time_value = (current_time_monotonic() / 1000ULL) + unix_base_time_value;
+}
+
+uint64_t unix_time(void)
+{
+ return unix_time_value;
+}
+
+int is_timeout(uint64_t timestamp, uint64_t timeout)
+{
+ return timestamp + timeout <= unix_time();
+}
+
+
+/* id functions */
+bool id_equal(const uint8_t *dest, const uint8_t *src)
+{
+ return public_key_cmp(dest, src) == 0;
+}
+
+uint32_t id_copy(uint8_t *dest, const uint8_t *src)
+{
+ memcpy(dest, src, CRYPTO_PUBLIC_KEY_SIZE);
+ return CRYPTO_PUBLIC_KEY_SIZE;
+}
+
+void host_to_net(uint8_t *num, uint16_t numbytes)
+{
+#ifndef WORDS_BIGENDIAN
+ uint32_t i;
+ VLA(uint8_t, buff, numbytes);
+
+ for (i = 0; i < numbytes; ++i) {
+ buff[i] = num[numbytes - i - 1];
+ }
+
+ memcpy(num, buff, numbytes);
+#endif
+}
+
+uint16_t lendian_to_host16(uint16_t lendian)
+{
+#ifdef WORDS_BIGENDIAN
+ return (lendian << 8) | (lendian >> 8);
+#else
+ return lendian;
+#endif
+}
+
+void host_to_lendian32(uint8_t *dest, uint32_t num)
+{
+#ifdef WORDS_BIGENDIAN
+ num = ((num << 8) & 0xFF00FF00) | ((num >> 8) & 0xFF00FF);
+ num = (num << 16) | (num >> 16);
+#endif
+ memcpy(dest, &num, sizeof(uint32_t));
+}
+
+void lendian_to_host32(uint32_t *dest, const uint8_t *lendian)
+{
+ uint32_t d;
+ memcpy(&d, lendian, sizeof(uint32_t));
+#ifdef WORDS_BIGENDIAN
+ d = ((d << 8) & 0xFF00FF00) | ((d >> 8) & 0xFF00FF);
+ d = (d << 16) | (d >> 16);
+#endif
+ *dest = d;
+}
+
+/* state load/save */
+int load_state(load_state_callback_func load_state_callback, Logger *log, void *outer,
+ const uint8_t *data, uint32_t length, uint16_t cookie_inner)
+{
+ if (!load_state_callback || !data) {
+ LOGGER_ERROR(log, "load_state() called with invalid args.\n");
+ return -1;
+ }
+
+
+ uint16_t type;
+ uint32_t length_sub, cookie_type;
+ uint32_t size_head = sizeof(uint32_t) * 2;
+
+ while (length >= size_head) {
+ lendian_to_host32(&length_sub, data);
+ lendian_to_host32(&cookie_type, data + sizeof(length_sub));
+ data += size_head;
+ length -= size_head;
+
+ if (length < length_sub) {
+ /* file truncated */
+ LOGGER_ERROR(log, "state file too short: %u < %u\n", length, length_sub);
+ return -1;
+ }
+
+ if (lendian_to_host16((cookie_type >> 16)) != cookie_inner) {
+ /* something is not matching up in a bad way, give up */
+ LOGGER_ERROR(log, "state file garbled: %04x != %04x\n", (cookie_type >> 16), cookie_inner);
+ return -1;
+ }
+
+ type = lendian_to_host16(cookie_type & 0xFFFF);
+
+ int ret = load_state_callback(outer, data, length_sub, type);
+
+ if (ret == -1) {
+ return -1;
+ }
+
+ /* -2 means end of save. */
+ if (ret == -2) {
+ return 0;
+ }
+
+ data += length_sub;
+ length -= length_sub;
+ }
+
+ return length == 0 ? 0 : -1;
+}
+
+int create_recursive_mutex(pthread_mutex_t *mutex)
+{
+ pthread_mutexattr_t attr;
+
+ if (pthread_mutexattr_init(&attr) != 0) {
+ return -1;
+ }
+
+ if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) {
+ pthread_mutexattr_destroy(&attr);
+ return -1;
+ }
+
+ /* Create queue mutex */
+ if (pthread_mutex_init(mutex, &attr) != 0) {
+ pthread_mutexattr_destroy(&attr);
+ return -1;
+ }
+
+ pthread_mutexattr_destroy(&attr);
+
+ return 0;
+}
diff --git a/protocols/Tox/libtox/src/toxcore/util.h b/protocols/Tox/libtox/src/toxcore/util.h
new file mode 100644
index 0000000000..8777e191d8
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/util.h
@@ -0,0 +1,64 @@
+/*
+ * Utilities.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ * Copyright © 2013 plutooo
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ * This file is donated to the Tox Project.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "logger.h"
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#define PAIR(TYPE1__, TYPE2__) struct { TYPE1__ first; TYPE2__ second; }
+
+void unix_time_update(void);
+uint64_t unix_time(void);
+int is_timeout(uint64_t timestamp, uint64_t timeout);
+
+
+/* id functions */
+bool id_equal(const uint8_t *dest, const uint8_t *src);
+uint32_t id_copy(uint8_t *dest, const uint8_t *src); /* return value is CLIENT_ID_SIZE */
+
+void host_to_net(uint8_t *num, uint16_t numbytes);
+#define net_to_host(x, y) host_to_net(x, y)
+
+uint16_t lendian_to_host16(uint16_t lendian);
+#define host_tolendian16(x) lendian_to_host16(x)
+
+void host_to_lendian32(uint8_t *dest, uint32_t num);
+void lendian_to_host32(uint32_t *dest, const uint8_t *lendian);
+
+/* state load/save */
+typedef int (*load_state_callback_func)(void *outer, const uint8_t *data, uint32_t len, uint16_t type);
+int load_state(load_state_callback_func load_state_callback, Logger *log, void *outer,
+ const uint8_t *data, uint32_t length, uint16_t cookie_inner);
+
+/* Returns -1 if failed or 0 if success */
+int create_recursive_mutex(pthread_mutex_t *mutex);
+
+#endif /* UTIL_H */
diff --git a/protocols/Tox/libtox/src/toxdns/toxdns.c b/protocols/Tox/libtox/src/toxdns/toxdns.c
new file mode 100644
index 0000000000..96f3081f80
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxdns/toxdns.c
@@ -0,0 +1,243 @@
+/*
+ * Tox secure username DNS toxid resolving functions.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "../toxcore/Messenger.h"
+#include "../toxcore/logger.h"
+#include "toxdns.h"
+
+static const char base32[32] = {
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5',
+};
+
+#define _encode(a, b, c) \
+{ \
+ uint8_t _i = 0; \
+ while (_i != c) { \
+ *a++ = base32[((b[0] >> bits) | (b[1] << (8 - bits))) & 0x1F]; \
+ bits += 5; \
+ if(bits >= 8) { \
+ bits -= 8; \
+ b++; \
+ _i++; \
+ } \
+ } \
+}
+
+typedef struct {
+ uint8_t temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t temp_sk[CRYPTO_SECRET_KEY_SIZE];
+ uint8_t server_public_key[CRYPTO_PUBLIC_KEY_SIZE];
+ uint8_t shared_key[CRYPTO_SYMMETRIC_KEY_SIZE];
+ uint32_t nonce;
+ uint32_t nonce_start;
+} DNS_Object;
+
+static void dns_new_temp_keys(DNS_Object *d)
+{
+ d->nonce = d->nonce_start = random_int();
+ crypto_new_keypair(d->temp_pk, d->temp_sk);
+ encrypt_precompute(d->server_public_key, d->temp_sk, d->shared_key);
+}
+
+/* Create a new tox_dns3 object for server with server_public_key.
+ *
+ * return Null on failure.
+ * return pointer object on success.
+ */
+void *tox_dns3_new(uint8_t *server_public_key)
+{
+ DNS_Object *d = (DNS_Object *)malloc(sizeof(DNS_Object));
+
+ if (d == NULL) {
+ return NULL;
+ }
+
+ memcpy(d->server_public_key, server_public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ dns_new_temp_keys(d);
+ return d;
+}
+
+/* Destroy the tox dns3 object.
+ */
+void tox_dns3_kill(void *dns3_object)
+{
+ memset(dns3_object, 0, sizeof(DNS_Object));
+ free(dns3_object);
+}
+
+/* Generate a dns3 string of string_max_len used to query the dns server referred to by to
+ * dns3_object for a tox id registered to user with name of name_len.
+ *
+ * the uint32_t pointed by request_id will be set to the request id which must be passed to
+ * tox_decrypt_dns3_TXT() to correctly decode the response.
+ *
+ * This is what the string returned looks like:
+ * 4haaaaipr1o3mz0bxweox541airydbovqlbju51mb4p0ebxq.rlqdj4kkisbep2ks3fj2nvtmk4daduqiueabmexqva1jc
+ *
+ * returns length of string on success.
+ * returns -1 on failure.
+ */
+int tox_generate_dns3_string(void *dns3_object, uint8_t *string, uint16_t string_max_len, uint32_t *request_id,
+ uint8_t *name, uint8_t name_len)
+{
+#define DOT_INTERVAL (6 * 5)
+ int base = (sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + name_len + CRYPTO_MAC_SIZE);
+ int end_len = ((base * 8) / 5) + (base / DOT_INTERVAL) + !!(base % 5);
+ end_len -= !(base % DOT_INTERVAL);
+
+ if (end_len > string_max_len) {
+ return -1;
+ }
+
+ DNS_Object *d = (DNS_Object *)dns3_object;
+ uint8_t buffer[1024];
+ uint8_t nonce[CRYPTO_NONCE_SIZE] = {0};
+ memcpy(nonce, &d->nonce, sizeof(uint32_t));
+ memcpy(buffer, &d->nonce, sizeof(uint32_t));
+ memcpy(buffer + sizeof(uint32_t), d->temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
+ int len = encrypt_data_symmetric(d->shared_key, nonce, name, name_len,
+ buffer + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE);
+
+ if (len == -1) {
+ return -1;
+ }
+
+ int total_len = len + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE;
+ uint8_t *buff = buffer, *old_str = string;
+ buffer[total_len] = 0;
+ uint8_t bits = 0;
+ int i;
+
+ for (i = !(total_len % DOT_INTERVAL); i < (total_len / DOT_INTERVAL); ++i) {
+ _encode(string, buff, DOT_INTERVAL);
+ *string = '.';
+ ++string;
+ }
+
+ int left = total_len - (buff - buffer);
+ _encode(string, buff, left);
+#undef DOT_INTERVAL
+ *request_id = d->nonce;
+ ++d->nonce;
+
+ if (d->nonce == d->nonce_start) {
+ dns_new_temp_keys(d);
+ }
+
+ if (end_len != string - old_str) {
+ // TODO(iphydf): This currently has no access to a logger.
+ LOGGER_ERROR(NULL, "tox_generate_dns3_string Fail, %u != %lu\n", end_len, string - old_str);
+ return -1;
+ }
+
+ return string - old_str;
+}
+
+
+static int decode(uint8_t *dest, uint8_t *src)
+{
+ uint8_t *p = src, *op = dest, bits = 0;
+ *op = 0;
+
+ while (*p) {
+ uint8_t ch = *p++;
+
+ if ('A' <= ch && ch <= 'Z') {
+ ch = ch - 'A';
+ } else if ('a' <= ch && ch <= 'z') {
+ ch = ch - 'a';
+ } else if ('0' <= ch && ch <= '5') {
+ ch = ch - '0' + 26;
+ } else {
+ return - 1;
+ }
+
+ *op |= (ch << bits);
+ bits += 5;
+
+ if (bits >= 8) {
+ bits -= 8;
+ ++op;
+ *op = (ch >> (5 - bits));
+ }
+ }
+
+ return op - dest;
+}
+
+/* Decode and decrypt the id_record returned of length id_record_len into
+ * tox_id (needs to be at least TOX_FRIEND_ADDRESS_SIZE).
+ *
+ * request_id is the request id given by tox_generate_dns3_string() when creating the request.
+ *
+ * the id_record passed to this function should look somewhat like this:
+ * 2vgcxuycbuctvauik3plsv3d3aadv4zfjfhi3thaizwxinelrvigchv0ah3qjcsx5qhmaksb2lv2hm5cwbtx0yp
+ *
+ * returns -1 on failure.
+ * returns 0 on success.
+ *
+ */
+int tox_decrypt_dns3_TXT(void *dns3_object, uint8_t *tox_id, uint8_t *id_record, uint32_t id_record_len,
+ uint32_t request_id)
+{
+ DNS_Object *d = (DNS_Object *)dns3_object;
+
+ if (id_record_len != 87) {
+ return -1;
+ }
+
+#if 0
+
+ if (id_record_len > 255 || id_record_len <= (sizeof(uint32_t) + CRYPTO_MAC_SIZE)) {
+ return -1;
+ }
+
+#endif
+
+ VLA(uint8_t, id_record_null, id_record_len + 1);
+ memcpy(id_record_null, id_record, id_record_len);
+ id_record_null[id_record_len] = 0;
+ VLA(uint8_t, data, id_record_len);
+ int length = decode(data, id_record_null);
+
+ if (length == -1) {
+ return -1;
+ }
+
+ uint8_t nonce[CRYPTO_NONCE_SIZE] = {0};
+ memcpy(nonce, &request_id, sizeof(uint32_t));
+ nonce[sizeof(uint32_t)] = 1;
+ int len = decrypt_data_symmetric(d->shared_key, nonce, data, length, tox_id);
+
+ if (len != FRIEND_ADDRESS_SIZE) {
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/protocols/Tox/include/toxdns.h b/protocols/Tox/libtox/src/toxdns/toxdns.h
index b280925eb1..b280925eb1 100644
--- a/protocols/Tox/include/toxdns.h
+++ b/protocols/Tox/libtox/src/toxdns/toxdns.h
diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h
new file mode 100644
index 0000000000..5cb32f8dcf
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h
@@ -0,0 +1,92 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
+
+#ifndef crypto_pwhash_scryptsalsa208sha256_H
+#define crypto_pwhash_scryptsalsa208sha256_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "export.h"
+
+#ifdef __cplusplus
+# if __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_pwhash_scryptsalsa208sha256_SALTBYTES 32U
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_saltbytes(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_STRBYTES 102U
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_strbytes(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_STRPREFIX "$7$"
+SODIUM_EXPORT
+const char *crypto_pwhash_scryptsalsa208sha256_strprefix(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE 524288ULL
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE 16777216ULL
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE 33554432ULL
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void);
+
+#define crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE 1073741824ULL
+SODIUM_EXPORT
+size_t crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void);
+
+SODIUM_EXPORT
+int crypto_pwhash_scryptsalsa208sha256(unsigned char * const out,
+ unsigned long long outlen,
+ const char * const passwd,
+ unsigned long long passwdlen,
+ const unsigned char * const salt,
+ unsigned long long opslimit,
+ size_t memlimit);
+
+SODIUM_EXPORT
+int crypto_pwhash_scryptsalsa208sha256_str(char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
+ const char * const passwd,
+ unsigned long long passwdlen,
+ unsigned long long opslimit,
+ size_t memlimit);
+
+SODIUM_EXPORT
+int crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
+ const char * const passwd,
+ unsigned long long passwdlen);
+
+SODIUM_EXPORT
+int crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t * passwd, size_t passwdlen,
+ const uint8_t * salt, size_t saltlen,
+ uint64_t N, uint32_t r, uint32_t p,
+ uint8_t * buf, size_t buflen);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Backward compatibility with version 0.5.0 */
+
+#define crypto_pwhash_scryptxsalsa208sha256_SALTBYTES crypto_pwhash_scryptsalsa208sha256_SALTBYTES
+#define crypto_pwhash_scryptxsalsa208sha256_saltbytes crypto_pwhash_scryptsalsa208sha256_saltbytes
+#define crypto_pwhash_scryptxsalsa208sha256_STRBYTES crypto_pwhash_scryptsalsa208sha256_STRBYTES
+#define crypto_pwhash_scryptxsalsa208sha256_strbytes crypto_pwhash_scryptsalsa208sha256_strbytes
+#define crypto_pwhash_scryptxsalsa208sha256 crypto_pwhash_scryptsalsa208sha256
+#define crypto_pwhash_scryptxsalsa208sha256_str crypto_pwhash_scryptsalsa208sha256_str
+#define crypto_pwhash_scryptxsalsa208sha256_str_verify crypto_pwhash_scryptsalsa208sha256_str_verify
+
+#endif
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt-common.c b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt-common.c
new file mode 100644
index 0000000000..5a5c5525f3
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt-common.c
@@ -0,0 +1,257 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
+
+/*-
+ * Copyright 2013 Alexander Peslyak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include "crypto_pwhash_scryptsalsa208sha256.h"
+#include "crypto_scrypt.h"
+#include "runtime.h"
+#include "utils.h"
+
+static const char * const itoa64 =
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+static uint8_t *
+encode64_uint32(uint8_t * dst, size_t dstlen, uint32_t src, uint32_t srcbits)
+{
+ uint32_t bit;
+
+ for (bit = 0; bit < srcbits; bit += 6) {
+ if (dstlen < 1) {
+ return NULL;
+ }
+ *dst++ = itoa64[src & 0x3f];
+ dstlen--;
+ src >>= 6;
+ }
+
+ return dst;
+}
+
+static uint8_t *
+encode64(uint8_t * dst, size_t dstlen, const uint8_t * src, size_t srclen)
+{
+ size_t i;
+
+ for (i = 0; i < srclen; ) {
+ uint8_t * dnext;
+ uint32_t value = 0, bits = 0;
+ do {
+ value |= (uint32_t)src[i++] << bits;
+ bits += 8;
+ } while (bits < 24 && i < srclen);
+ dnext = encode64_uint32(dst, dstlen, value, bits);
+ if (!dnext) {
+ return NULL;
+ }
+ dstlen -= dnext - dst;
+ dst = dnext;
+ }
+
+ return dst;
+}
+
+static int
+decode64_one(uint32_t * dst, uint8_t src)
+{
+ const char *ptr = strchr(itoa64, src);
+
+ if (ptr) {
+ *dst = ptr - itoa64;
+ return 0;
+ }
+ *dst = 0;
+ return -1;
+}
+
+static const uint8_t *
+decode64_uint32(uint32_t * dst, uint32_t dstbits, const uint8_t * src)
+{
+ uint32_t bit;
+ uint32_t value;
+
+ value = 0;
+ for (bit = 0; bit < dstbits; bit += 6) {
+ uint32_t one;
+ if (decode64_one(&one, *src)) {
+ *dst = 0;
+ return NULL;
+ }
+ src++;
+ value |= one << bit;
+ }
+
+ *dst = value;
+ return src;
+}
+
+uint8_t *
+escrypt_r(escrypt_local_t * local, const uint8_t * passwd, size_t passwdlen,
+ const uint8_t * setting, uint8_t * buf, size_t buflen)
+{
+ uint8_t hash[crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES];
+ escrypt_kdf_t escrypt_kdf;
+ const uint8_t *src;
+ const uint8_t *salt;
+ uint8_t *dst;
+ size_t prefixlen;
+ size_t saltlen;
+ size_t need;
+ uint64_t N;
+ uint32_t N_log2;
+ uint32_t r;
+ uint32_t p;
+
+ if (setting[0] != '$' || setting[1] != '7' || setting[2] != '$') {
+ return NULL;
+ }
+ src = setting + 3;
+
+ if (decode64_one(&N_log2, *src)) {
+ return NULL;
+ }
+ src++;
+ N = (uint64_t)1 << N_log2;
+
+ src = decode64_uint32(&r, 30, src);
+ if (!src) {
+ return NULL;
+ }
+ src = decode64_uint32(&p, 30, src);
+ if (!src) {
+ return NULL;
+ }
+ prefixlen = src - setting;
+
+ salt = src;
+ src = (uint8_t *) strrchr((char *)salt, '$');
+ if (src) {
+ saltlen = src - salt;
+ } else {
+ saltlen = strlen((char *)salt);
+ }
+ need = prefixlen + saltlen + 1 +
+ crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1;
+ if (need > buflen || need < saltlen) {
+ return NULL;
+ }
+#if defined(HAVE_EMMINTRIN_H) || defined(_MSC_VER)
+ escrypt_kdf =
+ sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse;
+#else
+ escrypt_kdf = escrypt_kdf_nosse;
+#endif
+ if (escrypt_kdf(local, passwd, passwdlen, salt, saltlen,
+ N, r, p, hash, sizeof(hash))) {
+ return NULL;
+ }
+
+ dst = buf;
+ memcpy(dst, setting, prefixlen + saltlen);
+ dst += prefixlen + saltlen;
+ *dst++ = '$';
+
+ dst = encode64(dst, buflen - (dst - buf), hash, sizeof(hash));
+ sodium_memzero(hash, sizeof hash);
+ if (!dst || dst >= buf + buflen) { /* Can't happen */
+ return NULL;
+ }
+ *dst = 0; /* NUL termination */
+
+ return buf;
+}
+
+uint8_t *
+escrypt_gensalt_r(uint32_t N_log2, uint32_t r, uint32_t p,
+ const uint8_t * src, size_t srclen,
+ uint8_t * buf, size_t buflen)
+{
+ uint8_t *dst;
+ size_t prefixlen =
+ (sizeof "$7$" - 1U) + (1U /* N_log2 */) + (5U /* r */) + (5U /* p */);
+ size_t saltlen = BYTES2CHARS(srclen);
+ size_t need;
+
+ need = prefixlen + saltlen + 1;
+ if (need > buflen || need < saltlen || saltlen < srclen) {
+ return NULL;
+ }
+ if (N_log2 > 63 || ((uint64_t)r * (uint64_t)p >= (1U << 30))) {
+ return NULL;
+ }
+ dst = buf;
+ *dst++ = '$';
+ *dst++ = '7';
+ *dst++ = '$';
+
+ *dst++ = itoa64[N_log2];
+
+ dst = encode64_uint32(dst, buflen - (dst - buf), r, 30);
+ if (!dst) { /* Can't happen */
+ return NULL;
+ }
+ dst = encode64_uint32(dst, buflen - (dst - buf), p, 30);
+ if (!dst) { /* Can't happen */
+ return NULL;
+ }
+ dst = encode64(dst, buflen - (dst - buf), src, srclen);
+ if (!dst || dst >= buf + buflen) { /* Can't happen */
+ return NULL;
+ }
+ *dst = 0; /* NUL termination */
+
+ return buf;
+}
+
+int
+crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t * passwd, size_t passwdlen,
+ const uint8_t * salt, size_t saltlen,
+ uint64_t N, uint32_t r, uint32_t p,
+ uint8_t * buf, size_t buflen)
+{
+ escrypt_kdf_t escrypt_kdf;
+ escrypt_local_t local;
+ int retval;
+
+ if (escrypt_init_local(&local)) {
+ return -1;
+ }
+#if defined(HAVE_EMMINTRIN_H) || defined(_MSC_VER)
+ escrypt_kdf =
+ sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse;
+#else
+ escrypt_kdf = escrypt_kdf_nosse;
+#endif
+ retval = escrypt_kdf(&local,
+ passwd, passwdlen, salt, saltlen,
+ N, r, p, buf, buflen);
+ if (escrypt_free_local(&local)) {
+ return -1;
+ }
+ return retval;
+}
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt.h b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt.h
new file mode 100644
index 0000000000..3f0b7d72f5
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt.h
@@ -0,0 +1,93 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
+
+/*-
+ * Copyright 2009 Colin Percival
+ * Copyright 2013 Alexander Peslyak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#ifndef _CRYPTO_SCRYPT_H_
+#define _CRYPTO_SCRYPT_H_
+
+#include <stdint.h>
+
+#define crypto_pwhash_scryptsalsa208sha256_STRPREFIXBYTES 14
+#define crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES 57
+#define crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES 32
+#define crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES_ENCODED 43
+#define crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES 32
+#define crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED 43
+
+#define BYTES2CHARS(bytes) ((((bytes) * 8) + 5) / 6)
+
+typedef struct {
+ void * base, * aligned;
+ size_t size;
+} escrypt_region_t;
+
+typedef escrypt_region_t escrypt_local_t;
+
+extern int escrypt_init_local(escrypt_local_t * __local);
+
+extern int escrypt_free_local(escrypt_local_t * __local);
+
+extern void *alloc_region(escrypt_region_t * region, size_t size);
+extern int free_region(escrypt_region_t * region);
+
+typedef int (*escrypt_kdf_t)(escrypt_local_t * __local,
+ const uint8_t * __passwd, size_t __passwdlen,
+ const uint8_t * __salt, size_t __saltlen,
+ uint64_t __N, uint32_t __r, uint32_t __p,
+ uint8_t * __buf, size_t __buflen);
+
+extern int escrypt_kdf_nosse(escrypt_local_t * __local,
+ const uint8_t * __passwd, size_t __passwdlen,
+ const uint8_t * __salt, size_t __saltlen,
+ uint64_t __N, uint32_t __r, uint32_t __p,
+ uint8_t * __buf, size_t __buflen);
+
+extern int escrypt_kdf_sse(escrypt_local_t * __local,
+ const uint8_t * __passwd, size_t __passwdlen,
+ const uint8_t * __salt, size_t __saltlen,
+ uint64_t __N, uint32_t __r, uint32_t __p,
+ uint8_t * __buf, size_t __buflen);
+
+extern uint8_t * escrypt_r(escrypt_local_t * __local,
+ const uint8_t * __passwd, size_t __passwdlen,
+ const uint8_t * __setting,
+ uint8_t * __buf, size_t __buflen);
+
+extern uint8_t * escrypt_gensalt_r(
+ uint32_t __N_log2, uint32_t __r, uint32_t __p,
+ const uint8_t * __src, size_t __srclen,
+ uint8_t * __buf, size_t __buflen);
+
+#endif /* !_CRYPTO_SCRYPT_H_ */
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/export.h b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/export.h
new file mode 100644
index 0000000000..ee5b30f7f1
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/export.h
@@ -0,0 +1,38 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
+
+#ifndef __SODIUM_EXPORT_H__
+#define __SODIUM_EXPORT_H__
+
+#ifndef __GNUC__
+# ifdef __attribute__
+# undef __attribute__
+# endif
+# define __attribute__(a)
+#endif
+
+#ifdef SODIUM_STATIC
+# define SODIUM_EXPORT
+#else
+# if defined(_MSC_VER)
+# ifdef DLL_EXPORT
+# define SODIUM_EXPORT __declspec(dllexport)
+# else
+# define SODIUM_EXPORT __declspec(dllimport)
+# endif
+# else
+# if defined(__SUNPRO_C)
+# define SODIUM_EXPORT __attribute__ __global
+# elif defined(_MSG_VER)
+# define SODIUM_EXPORT extern __declspec(dllexport)
+# else
+# define SODIUM_EXPORT __attribute__ ((visibility ("default")))
+# endif
+# endif
+#endif
+
+#endif
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c
new file mode 100644
index 0000000000..97d9ba6878
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c
@@ -0,0 +1,309 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
+
+/*-
+ * Copyright 2009 Colin Percival
+ * Copyright 2013 Alexander Peslyak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../pbkdf2-sha256.h"
+#include "../sysendian.h"
+#include "../crypto_scrypt.h"
+
+static inline void
+blkcpy(void * dest, const void * src, size_t len)
+{
+ size_t * D = (size_t *) dest;
+ const size_t * S = (const size_t *) src;
+ size_t L = len / sizeof(size_t);
+ size_t i;
+
+ for (i = 0; i < L; i++)
+ D[i] = S[i];
+}
+
+static inline void
+blkxor(void * dest, const void * src, size_t len)
+{
+ size_t * D = (size_t *) dest;
+ const size_t * S = (const size_t *) src;
+ size_t L = len / sizeof(size_t);
+ size_t i;
+
+ for (i = 0; i < L; i++)
+ D[i] ^= S[i];
+}
+
+/**
+ * salsa20_8(B):
+ * Apply the salsa20/8 core to the provided block.
+ */
+static void
+salsa20_8(uint32_t B[16])
+{
+ uint32_t x[16];
+ size_t i;
+
+ blkcpy(x, B, 64);
+ for (i = 0; i < 8; i += 2) {
+#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
+ /* Operate on columns. */
+ x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9);
+ x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18);
+
+ x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9);
+ x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18);
+
+ x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9);
+ x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18);
+
+ x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9);
+ x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18);
+
+ /* Operate on rows. */
+ x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9);
+ x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18);
+
+ x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9);
+ x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18);
+
+ x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9);
+ x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18);
+
+ x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9);
+ x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18);
+#undef R
+ }
+ for (i = 0; i < 16; i++)
+ B[i] += x[i];
+}
+
+/**
+ * blockmix_salsa8(Bin, Bout, X, r):
+ * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
+ * bytes in length; the output Bout must also be the same size. The
+ * temporary space X must be 64 bytes.
+ */
+static void
+blockmix_salsa8(const uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r)
+{
+ size_t i;
+
+ /* 1: X <-- B_{2r - 1} */
+ blkcpy(X, &Bin[(2 * r - 1) * 16], 64);
+
+ /* 2: for i = 0 to 2r - 1 do */
+ for (i = 0; i < 2 * r; i += 2) {
+ /* 3: X <-- H(X \xor B_i) */
+ blkxor(X, &Bin[i * 16], 64);
+ salsa20_8(X);
+
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ blkcpy(&Bout[i * 8], X, 64);
+
+ /* 3: X <-- H(X \xor B_i) */
+ blkxor(X, &Bin[i * 16 + 16], 64);
+ salsa20_8(X);
+
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ blkcpy(&Bout[i * 8 + r * 16], X, 64);
+ }
+}
+
+/**
+ * integerify(B, r):
+ * Return the result of parsing B_{2r-1} as a little-endian integer.
+ */
+static inline uint64_t
+integerify(const void * B, size_t r)
+{
+ const uint32_t * X = (const uint32_t *)((uintptr_t)(B) + (2 * r - 1) * 64);
+
+ return (((uint64_t)(X[1]) << 32) + X[0]);
+}
+
+/**
+ * smix(B, r, N, V, XY):
+ * Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
+ * the temporary storage V must be 128rN bytes in length; the temporary
+ * storage XY must be 256r + 64 bytes in length. The value N must be a
+ * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
+ * multiple of 64 bytes.
+ */
+static void
+smix(uint8_t * B, size_t r, uint64_t N, uint32_t * V, uint32_t * XY)
+{
+ uint32_t * X = XY;
+ uint32_t * Y = &XY[32 * r];
+ uint32_t * Z = &XY[64 * r];
+ uint64_t i;
+ uint64_t j;
+ size_t k;
+
+ /* 1: X <-- B */
+ for (k = 0; k < 32 * r; k++)
+ X[k] = le32dec(&B[4 * k]);
+
+ /* 2: for i = 0 to N - 1 do */
+ for (i = 0; i < N; i += 2) {
+ /* 3: V_i <-- X */
+ blkcpy(&V[i * (32 * r)], X, 128 * r);
+
+ /* 4: X <-- H(X) */
+ blockmix_salsa8(X, Y, Z, r);
+
+ /* 3: V_i <-- X */
+ blkcpy(&V[(i + 1) * (32 * r)], Y, 128 * r);
+
+ /* 4: X <-- H(X) */
+ blockmix_salsa8(Y, X, Z, r);
+ }
+
+ /* 6: for i = 0 to N - 1 do */
+ for (i = 0; i < N; i += 2) {
+ /* 7: j <-- Integerify(X) mod N */
+ j = integerify(X, r) & (N - 1);
+
+ /* 8: X <-- H(X \xor V_j) */
+ blkxor(X, &V[j * (32 * r)], 128 * r);
+ blockmix_salsa8(X, Y, Z, r);
+
+ /* 7: j <-- Integerify(X) mod N */
+ j = integerify(Y, r) & (N - 1);
+
+ /* 8: X <-- H(X \xor V_j) */
+ blkxor(Y, &V[j * (32 * r)], 128 * r);
+ blockmix_salsa8(Y, X, Z, r);
+ }
+ /* 10: B' <-- X */
+ for (k = 0; k < 32 * r; k++)
+ le32enc(&B[4 * k], X[k]);
+}
+
+/**
+ * escrypt_kdf(local, passwd, passwdlen, salt, saltlen,
+ * N, r, p, buf, buflen):
+ * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
+ * p, buflen) and write the result into buf. The parameters r, p, and buflen
+ * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
+ * must be a power of 2 greater than 1.
+ *
+ * Return 0 on success; or -1 on error.
+ */
+int
+escrypt_kdf_nosse(escrypt_local_t * local,
+ const uint8_t * passwd, size_t passwdlen,
+ const uint8_t * salt, size_t saltlen,
+ uint64_t N, uint32_t _r, uint32_t _p,
+ uint8_t * buf, size_t buflen)
+{
+ size_t B_size, V_size, XY_size, need;
+ uint8_t * B;
+ uint32_t * V, * XY;
+ size_t r = _r, p = _p;
+ uint32_t i;
+
+ /* Sanity-check parameters. */
+#if SIZE_MAX > UINT32_MAX
+ if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
+ errno = EFBIG;
+ return -1;
+ }
+#endif
+ if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (((N & (N - 1)) != 0) || (N < 2)) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (r == 0 || p == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ if ((r > SIZE_MAX / 128 / p) ||
+#if SIZE_MAX / 256 <= UINT32_MAX
+ (r > SIZE_MAX / 256) ||
+#endif
+ (N > SIZE_MAX / 128 / r)) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /* Allocate memory. */
+ B_size = (size_t)128 * r * p;
+ V_size = (size_t)128 * r * N;
+ need = B_size + V_size;
+ if (need < V_size) {
+ errno = ENOMEM;
+ return -1;
+ }
+ XY_size = (size_t)256 * r + 64;
+ need += XY_size;
+ if (need < XY_size) {
+ errno = ENOMEM;
+ return -1;
+ }
+ if (local->size < need) {
+ if (free_region(local))
+ return -1;
+ if (!alloc_region(local, need))
+ return -1;
+ }
+ B = (uint8_t *)local->aligned;
+ V = (uint32_t *)((uint8_t *)B + B_size);
+ XY = (uint32_t *)((uint8_t *)V + V_size);
+
+ /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
+ PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, B_size);
+
+ /* 2: for i = 0 to p - 1 do */
+ for (i = 0; i < p; i++) {
+ /* 3: B_i <-- MF(B_i, N) */
+ smix(&B[(size_t)128 * i * r], r, N, V, XY);
+ }
+
+ /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
+ PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, buf, buflen);
+
+ /* Success! */
+ return 0;
+}
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/note_to_maintainers.txt b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/note_to_maintainers.txt
new file mode 100644
index 0000000000..66bbfe2db9
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/note_to_maintainers.txt
@@ -0,0 +1,14 @@
+This folder is only meant for use with nacl, i.e. when sodium is unavailable.
+
+
+The files in this folder were mostly copied from
+https://github.com/jedisct1/libsodium/tree/0.7.0/src/libsodium/crypto_pwhash/scryptsalsa208sha256,
+with #ifdef VANILLA_NACL added around each of them as required for this module.
+
+export.h, utils.h, and runtime.h were copied from
+https://github.com/jedisct1/libsodium/tree/0.7.0/src/libsodium/include/sodium.
+utils.h was significantly truncated.
+
+utils.c and runtime.c were copied from
+https://github.com/jedisct1/libsodium/blob/0.7.0/src/libsodium/sodium.
+utils.c was also significantly truncated.
diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.c b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.c
new file mode 100644
index 0000000000..3dfe54db5f
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.c
@@ -0,0 +1,97 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
+
+/*-
+ * Copyright 2005,2007,2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <crypto_hash_sha256.h>
+#include <crypto_auth_hmacsha256.h>
+
+#include "pbkdf2-sha256.h"
+#include "sysendian.h"
+#include "utils.h"
+
+/**
+ * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
+ * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
+ * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
+ */
+void
+PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
+ size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
+{
+ uint8_t key[32] = {0};
+ size_t i;
+ uint8_t salt_and_ivec[saltlen + 4];
+ uint8_t U[32];
+ uint8_t T[32];
+ uint64_t j;
+ int k;
+ size_t clen;
+
+ if (passwdlen > 32) {
+ /* For some reason libsodium allows 64byte keys meaning keys
+ * between 32byte and 64bytes are not compatible with libsodium.
+ toxencryptsave should only give 32byte passwds so this isn't an issue here.*/
+ crypto_hash_sha256(key, passwd, passwdlen);
+ } else {
+ memcpy(key, passwd, passwdlen);
+ }
+
+ memcpy(salt_and_ivec, salt, saltlen);
+
+ for (i = 0; i * 32 < dkLen; i++) {
+ be32enc(salt_and_ivec + saltlen, (uint32_t)(i + 1));
+ crypto_auth_hmacsha256(U, salt_and_ivec, sizeof(salt_and_ivec), key);
+
+ memcpy(T, U, 32);
+
+ for (j = 2; j <= c; j++) {
+ crypto_auth_hmacsha256(U, U, 32, key);
+
+ for (k = 0; k < 32; k++) {
+ T[k] ^= U[k];
+ }
+ }
+
+ clen = dkLen - i * 32;
+ if (clen > 32) {
+ clen = 32;
+ }
+ memcpy(&buf[i * 32], T, clen);
+ }
+ sodium_memzero((void *) key, sizeof(key));
+}
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.h b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.h
new file mode 100644
index 0000000000..b74bc6a340
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.h
@@ -0,0 +1,52 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
+
+/*-
+ * Copyright 2005,2007,2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _SHA256_H_
+#define _SHA256_H_
+
+#include <sys/types.h>
+
+#include <stdint.h>
+
+#include "crypto_auth_hmacsha256.h"
+
+/**
+ * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
+ * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
+ * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
+ */
+void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t,
+ uint64_t, uint8_t *, size_t);
+
+#endif /* !_SHA256_H_ */
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c
new file mode 100644
index 0000000000..52c51abc3b
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c
@@ -0,0 +1,211 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+//#include <stdio.h>
+
+#include "crypto_pwhash_scryptsalsa208sha256.h"
+#include "crypto_scrypt.h"
+#include "randombytes.h"
+#include "utils.h"
+
+#define SETTING_SIZE(saltbytes) \
+ (sizeof "$7$" - 1U) + \
+ (1U /* N_log2 */) + (5U /* r */) + (5U /* p */) + BYTES2CHARS(saltbytes)
+
+static int
+pickparams(unsigned long long opslimit, const size_t memlimit,
+ uint32_t * const N_log2, uint32_t * const p, uint32_t * const r)
+{
+ unsigned long long maxN;
+ unsigned long long maxrp;
+
+ if (opslimit < 32768) {
+ opslimit = 32768;
+ }
+ *r = 8;
+ if (opslimit < memlimit / 32) {
+ *p = 1;
+ maxN = opslimit / (*r * 4);
+ for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) {
+ if ((uint64_t)(1) << *N_log2 > maxN / 2) {
+ break;
+ }
+ }
+ } else {
+ maxN = memlimit / (*r * 128);
+ for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) {
+ if ((uint64_t) (1) << *N_log2 > maxN / 2) {
+ break;
+ }
+ }
+ maxrp = (opslimit / 4) / ((uint64_t) (1) << *N_log2);
+ if (maxrp > 0x3fffffff) {
+ maxrp = 0x3fffffff;
+ }
+ *p = (uint32_t) (maxrp) / *r;
+ }
+ return 0;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_saltbytes(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_strbytes(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_STRBYTES;
+}
+
+const char *
+crypto_pwhash_scryptsalsa208sha256_strprefix(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_STRPREFIX;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE;
+}
+
+size_t
+crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void)
+{
+ return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE;
+}
+
+int
+crypto_pwhash_scryptsalsa208sha256(unsigned char * const out,
+ unsigned long long outlen,
+ const char * const passwd,
+ unsigned long long passwdlen,
+ const unsigned char * const salt,
+ unsigned long long opslimit,
+ size_t memlimit)
+{
+ //fprintf(stderr, "Doing that dirty thang!!!!\n");
+ uint32_t N_log2;
+ uint32_t p;
+ uint32_t r;
+
+ memset(out, 0, outlen);
+ if (passwdlen > SIZE_MAX || outlen > SIZE_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ return crypto_pwhash_scryptsalsa208sha256_ll((const uint8_t *) passwd,
+ (size_t) passwdlen,
+ (const uint8_t *) salt,
+ crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
+ (uint64_t) (1) << N_log2, r, p,
+ out, (size_t) outlen);
+}
+
+int
+crypto_pwhash_scryptsalsa208sha256_str(char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
+ const char * const passwd,
+ unsigned long long passwdlen,
+ unsigned long long opslimit,
+ size_t memlimit)
+{
+ uint8_t salt[crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES];
+ char setting[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U];
+ escrypt_local_t escrypt_local;
+ uint32_t N_log2;
+ uint32_t p;
+ uint32_t r;
+
+ memset(out, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES);
+ if (passwdlen > SIZE_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ randombytes(salt, sizeof salt);
+ if (escrypt_gensalt_r(N_log2, r, p, salt, sizeof salt,
+ (uint8_t *) setting, sizeof setting) == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (escrypt_init_local(&escrypt_local) != 0) {
+ return -1;
+ }
+ if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen,
+ (const uint8_t *) setting, (uint8_t *) out,
+ crypto_pwhash_scryptsalsa208sha256_STRBYTES) == NULL) {
+ escrypt_free_local(&escrypt_local);
+ errno = EINVAL;
+ return -1;
+ }
+ escrypt_free_local(&escrypt_local);
+
+ (void) sizeof
+ (int[SETTING_SIZE(crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES)
+ == crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES ? 1 : -1]);
+ (void) sizeof
+ (int[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U +
+ crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1U
+ == crypto_pwhash_scryptsalsa208sha256_STRBYTES ? 1 : -1]);
+
+ return 0;
+}
+
+int
+crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
+ const char * const passwd,
+ unsigned long long passwdlen)
+{
+ char wanted[crypto_pwhash_scryptsalsa208sha256_STRBYTES];
+ escrypt_local_t escrypt_local;
+ int ret = -1;
+
+ if (memchr(str, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES) !=
+ &str[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U]) {
+ return -1;
+ }
+ if (escrypt_init_local(&escrypt_local) != 0) {
+ return -1;
+ }
+ if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen,
+ (const uint8_t *) str, (uint8_t *) wanted,
+ sizeof wanted) == NULL) {
+ escrypt_free_local(&escrypt_local);
+ return -1;
+ }
+ escrypt_free_local(&escrypt_local);
+ ret = sodium_memcmp(wanted, str, sizeof wanted);
+ sodium_memzero(wanted, sizeof wanted);
+
+ return ret;
+}
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.c b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.c
new file mode 100644
index 0000000000..9b5c513193
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.c
@@ -0,0 +1,140 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
+
+#ifdef HAVE_ANDROID_GETCPUFEATURES
+# include <cpu-features.h>
+#endif
+
+#include "runtime.h"
+
+typedef struct CPUFeatures_ {
+ int initialized;
+ int has_neon;
+ int has_sse2;
+ int has_sse3;
+} CPUFeatures;
+
+static CPUFeatures _cpu_features;
+
+#define CPUID_SSE2 0x04000000
+#define CPUIDECX_SSE3 0x00000001
+
+static int
+_sodium_runtime_arm_cpu_features(CPUFeatures * const cpu_features)
+{
+#ifndef __arm__
+ cpu_features->has_neon = 0;
+ return -1;
+#else
+# ifdef __APPLE__
+# ifdef __ARM_NEON__
+ cpu_features->has_neon = 1;
+# else
+ cpu_features->has_neon = 0;
+# endif
+# elif defined(HAVE_ANDROID_GETCPUFEATURES) && defined(ANDROID_CPU_ARM_FEATURE_NEON)
+ cpu_features->has_neon =
+ (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0x0;
+# else
+ cpu_features->has_neon = 0;
+# endif
+ return 0;
+#endif
+}
+
+static void
+_cpuid(unsigned int cpu_info[4U], const unsigned int cpu_info_type)
+{
+#ifdef _MSC_VER
+ __cpuidex((int *) cpu_info, cpu_info_type, 0);
+#elif defined(HAVE_CPUID)
+ cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0;
+# ifdef __i386__
+ __asm__ __volatile__ ("pushfl; pushfl; "
+ "popl %0; "
+ "movl %0, %1; xorl %2, %0; "
+ "pushl %0; "
+ "popfl; pushfl; popl %0; popfl" :
+ "=&r" (cpu_info[0]), "=&r" (cpu_info[1]) :
+ "i" (0x200000));
+ if (((cpu_info[0] ^ cpu_info[1]) & 0x200000) == 0x0) {
+ return;
+ }
+# endif
+# ifdef __i386__
+ __asm__ __volatile__ ("xchgl %%ebx, %k1; cpuid; xchgl %%ebx, %k1" :
+ "=a" (cpu_info[0]), "=&r" (cpu_info[1]),
+ "=c" (cpu_info[2]), "=d" (cpu_info[3]) :
+ "0" (cpu_info_type), "2" (0U));
+# elif defined(__x86_64__)
+ __asm__ __volatile__ ("xchgq %%rbx, %q1; cpuid; xchgq %%rbx, %q1" :
+ "=a" (cpu_info[0]), "=&r" (cpu_info[1]),
+ "=c" (cpu_info[2]), "=d" (cpu_info[3]) :
+ "0" (cpu_info_type), "2" (0U));
+# else
+ __asm__ __volatile__ ("cpuid" :
+ "=a" (cpu_info[0]), "=b" (cpu_info[1]),
+ "=c" (cpu_info[2]), "=d" (cpu_info[3]) :
+ "0" (cpu_info_type), "2" (0U));
+# endif
+#else
+ cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0;
+#endif
+}
+
+static int
+_sodium_runtime_intel_cpu_features(CPUFeatures * const cpu_features)
+{
+ unsigned int cpu_info[4];
+ unsigned int id;
+
+ _cpuid(cpu_info, 0x0);
+ if ((id = cpu_info[0]) == 0U) {
+ return -1;
+ }
+ _cpuid(cpu_info, 0x00000001);
+#ifndef HAVE_EMMINTRIN_H
+ cpu_features->has_sse2 = 0;
+#else
+ cpu_features->has_sse2 = ((cpu_info[3] & CPUID_SSE2) != 0x0);
+#endif
+
+#ifndef HAVE_PMMINTRIN_H
+ cpu_features->has_sse3 = 0;
+#else
+ cpu_features->has_sse3 = ((cpu_info[2] & CPUIDECX_SSE3) != 0x0);
+#endif
+
+ return 0;
+}
+
+int
+sodium_runtime_get_cpu_features(void)
+{
+ int ret = -1;
+
+ ret &= _sodium_runtime_arm_cpu_features(&_cpu_features);
+ ret &= _sodium_runtime_intel_cpu_features(&_cpu_features);
+ _cpu_features.initialized = 1;
+
+ return ret;
+}
+
+int
+sodium_runtime_has_neon(void) {
+ return _cpu_features.has_neon;
+}
+
+int
+sodium_runtime_has_sse2(void) {
+ return _cpu_features.has_sse2;
+}
+
+int
+sodium_runtime_has_sse3(void) {
+ return _cpu_features.has_sse3;
+}
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.h b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.h
new file mode 100644
index 0000000000..874915ef42
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.h
@@ -0,0 +1,33 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
+
+#ifndef __SODIUM_RUNTIME_H__
+#define __SODIUM_RUNTIME_H__ 1
+
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SODIUM_EXPORT
+int sodium_runtime_get_cpu_features(void);
+
+SODIUM_EXPORT
+int sodium_runtime_has_neon(void);
+
+SODIUM_EXPORT
+int sodium_runtime_has_sse2(void);
+
+SODIUM_EXPORT
+int sodium_runtime_has_sse3(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/scrypt_platform.c b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/scrypt_platform.c
new file mode 100644
index 0000000000..5819651454
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/scrypt_platform.c
@@ -0,0 +1,107 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
+
+/*-
+ * Copyright 2013 Alexander Peslyak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+#include <errno.h>
+#include <stdlib.h>
+
+#include "crypto_scrypt.h"
+#include "runtime.h"
+
+#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
+# define MAP_ANON MAP_ANONYMOUS
+#endif
+
+void *
+alloc_region(escrypt_region_t * region, size_t size)
+{
+ uint8_t * base, * aligned;
+#ifdef MAP_ANON
+ if ((base = (uint8_t *) mmap(NULL, size, PROT_READ | PROT_WRITE,
+#ifdef MAP_NOCORE
+ MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
+#else
+ MAP_ANON | MAP_PRIVATE,
+#endif
+ -1, 0)) == MAP_FAILED)
+ base = NULL;
+ aligned = base;
+#elif defined(HAVE_POSIX_MEMALIGN)
+ if ((errno = posix_memalign((void **) &base, 64, size)) != 0)
+ base = NULL;
+ aligned = base;
+#else
+ base = aligned = NULL;
+ if (size + 63 < size)
+ errno = ENOMEM;
+ else if ((base = (uint8_t *) malloc(size + 63)) != NULL) {
+ aligned = base + 63;
+ aligned -= (uintptr_t)aligned & 63;
+ }
+#endif
+ region->base = base;
+ region->aligned = aligned;
+ region->size = base ? size : 0;
+ return aligned;
+}
+
+static inline void
+init_region(escrypt_region_t * region)
+{
+ region->base = region->aligned = NULL;
+ region->size = 0;
+}
+
+int
+free_region(escrypt_region_t * region)
+{
+ if (region->base) {
+#ifdef MAP_ANON
+ if (munmap(region->base, region->size))
+ return -1;
+#else
+ free(region->base);
+#endif
+ }
+ init_region(region);
+ return 0;
+}
+
+int
+escrypt_init_local(escrypt_local_t * local)
+{
+ init_region(local);
+ return 0;
+}
+
+int
+escrypt_free_local(escrypt_local_t * local)
+{
+ return free_region(local);
+}
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c
new file mode 100644
index 0000000000..856a655e3f
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c
@@ -0,0 +1,398 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
+
+/*-
+ * Copyright 2009 Colin Percival
+ * Copyright 2012,2013 Alexander Peslyak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+
+#if defined(HAVE_EMMINTRIN_H) || defined(_MSC_VER)
+#if __GNUC__
+# pragma GCC target("sse2")
+#endif
+#include <emmintrin.h>
+#if defined(__XOP__) && defined(DISABLED)
+# include <x86intrin.h>
+#endif
+
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../pbkdf2-sha256.h"
+#include "../sysendian.h"
+#include "../crypto_scrypt.h"
+
+#if defined(__XOP__) && defined(DISABLED)
+#define ARX(out, in1, in2, s) \
+ out = _mm_xor_si128(out, _mm_roti_epi32(_mm_add_epi32(in1, in2), s));
+#else
+#define ARX(out, in1, in2, s) \
+ { \
+ __m128i T = _mm_add_epi32(in1, in2); \
+ out = _mm_xor_si128(out, _mm_slli_epi32(T, s)); \
+ out = _mm_xor_si128(out, _mm_srli_epi32(T, 32-s)); \
+ }
+#endif
+
+#define SALSA20_2ROUNDS \
+ /* Operate on "columns". */ \
+ ARX(X1, X0, X3, 7) \
+ ARX(X2, X1, X0, 9) \
+ ARX(X3, X2, X1, 13) \
+ ARX(X0, X3, X2, 18) \
+\
+ /* Rearrange data. */ \
+ X1 = _mm_shuffle_epi32(X1, 0x93); \
+ X2 = _mm_shuffle_epi32(X2, 0x4E); \
+ X3 = _mm_shuffle_epi32(X3, 0x39); \
+\
+ /* Operate on "rows". */ \
+ ARX(X3, X0, X1, 7) \
+ ARX(X2, X3, X0, 9) \
+ ARX(X1, X2, X3, 13) \
+ ARX(X0, X1, X2, 18) \
+\
+ /* Rearrange data. */ \
+ X1 = _mm_shuffle_epi32(X1, 0x39); \
+ X2 = _mm_shuffle_epi32(X2, 0x4E); \
+ X3 = _mm_shuffle_epi32(X3, 0x93);
+
+/**
+ * Apply the salsa20/8 core to the block provided in (X0 ... X3) ^ (Z0 ... Z3).
+ */
+#define SALSA20_8_XOR(in, out) \
+ { \
+ __m128i Y0 = X0 = _mm_xor_si128(X0, (in)[0]); \
+ __m128i Y1 = X1 = _mm_xor_si128(X1, (in)[1]); \
+ __m128i Y2 = X2 = _mm_xor_si128(X2, (in)[2]); \
+ __m128i Y3 = X3 = _mm_xor_si128(X3, (in)[3]); \
+ SALSA20_2ROUNDS \
+ SALSA20_2ROUNDS \
+ SALSA20_2ROUNDS \
+ SALSA20_2ROUNDS \
+ (out)[0] = X0 = _mm_add_epi32(X0, Y0); \
+ (out)[1] = X1 = _mm_add_epi32(X1, Y1); \
+ (out)[2] = X2 = _mm_add_epi32(X2, Y2); \
+ (out)[3] = X3 = _mm_add_epi32(X3, Y3); \
+ }
+
+/**
+ * blockmix_salsa8(Bin, Bout, r):
+ * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
+ * bytes in length; the output Bout must also be the same size.
+ */
+static inline void
+blockmix_salsa8(const __m128i * Bin, __m128i * Bout, size_t r)
+{
+ __m128i X0, X1, X2, X3;
+ size_t i;
+
+ /* 1: X <-- B_{2r - 1} */
+ X0 = Bin[8 * r - 4];
+ X1 = Bin[8 * r - 3];
+ X2 = Bin[8 * r - 2];
+ X3 = Bin[8 * r - 1];
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ SALSA20_8_XOR(Bin, Bout)
+
+ /* 2: for i = 0 to 2r - 1 do */
+ r--;
+ for (i = 0; i < r;) {
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ SALSA20_8_XOR(&Bin[i * 8 + 4], &Bout[(r + i) * 4 + 4])
+
+ i++;
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ SALSA20_8_XOR(&Bin[i * 8], &Bout[i * 4])
+ }
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ SALSA20_8_XOR(&Bin[i * 8 + 4], &Bout[(r + i) * 4 + 4])
+}
+
+#define XOR4(in) \
+ X0 = _mm_xor_si128(X0, (in)[0]); \
+ X1 = _mm_xor_si128(X1, (in)[1]); \
+ X2 = _mm_xor_si128(X2, (in)[2]); \
+ X3 = _mm_xor_si128(X3, (in)[3]);
+
+#define XOR4_2(in1, in2) \
+ X0 = _mm_xor_si128((in1)[0], (in2)[0]); \
+ X1 = _mm_xor_si128((in1)[1], (in2)[1]); \
+ X2 = _mm_xor_si128((in1)[2], (in2)[2]); \
+ X3 = _mm_xor_si128((in1)[3], (in2)[3]);
+
+static inline uint32_t
+blockmix_salsa8_xor(const __m128i * Bin1, const __m128i * Bin2, __m128i * Bout,
+ size_t r)
+{
+ __m128i X0, X1, X2, X3;
+ size_t i;
+
+ /* 1: X <-- B_{2r - 1} */
+ XOR4_2(&Bin1[8 * r - 4], &Bin2[8 * r - 4])
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ XOR4(Bin1)
+ SALSA20_8_XOR(Bin2, Bout)
+
+ /* 2: for i = 0 to 2r - 1 do */
+ r--;
+ for (i = 0; i < r;) {
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ XOR4(&Bin1[i * 8 + 4])
+ SALSA20_8_XOR(&Bin2[i * 8 + 4], &Bout[(r + i) * 4 + 4])
+
+ i++;
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ XOR4(&Bin1[i * 8])
+ SALSA20_8_XOR(&Bin2[i * 8], &Bout[i * 4])
+ }
+
+ /* 3: X <-- H(X \xor B_i) */
+ /* 4: Y_i <-- X */
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+ XOR4(&Bin1[i * 8 + 4])
+ SALSA20_8_XOR(&Bin2[i * 8 + 4], &Bout[(r + i) * 4 + 4])
+
+ return _mm_cvtsi128_si32(X0);
+}
+
+#undef ARX
+#undef SALSA20_2ROUNDS
+#undef SALSA20_8_XOR
+#undef XOR4
+#undef XOR4_2
+
+/**
+ * integerify(B, r):
+ * Return the result of parsing B_{2r-1} as a little-endian integer.
+ */
+static inline uint32_t
+integerify(const void * B, size_t r)
+{
+ return *(const uint32_t *)((uintptr_t)(B) + (2 * r - 1) * 64);
+}
+
+/**
+ * smix(B, r, N, V, XY):
+ * Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
+ * the temporary storage V must be 128rN bytes in length; the temporary
+ * storage XY must be 256r + 64 bytes in length. The value N must be a
+ * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
+ * multiple of 64 bytes.
+ */
+static void
+smix(uint8_t * B, size_t r, uint32_t N, void * V, void * XY)
+{
+ size_t s = 128 * r;
+ __m128i * X = (__m128i *) V, * Y;
+ uint32_t * X32 = (uint32_t *) V;
+ uint32_t i, j;
+ size_t k;
+
+ /* 1: X <-- B */
+ /* 3: V_i <-- X */
+ for (k = 0; k < 2 * r; k++) {
+ for (i = 0; i < 16; i++) {
+ X32[k * 16 + i] =
+ le32dec(&B[(k * 16 + (i * 5 % 16)) * 4]);
+ }
+ }
+
+ /* 2: for i = 0 to N - 1 do */
+ for (i = 1; i < N - 1; i += 2) {
+ /* 4: X <-- H(X) */
+ /* 3: V_i <-- X */
+ Y = (__m128i *)((uintptr_t)(V) + i * s);
+ blockmix_salsa8(X, Y, r);
+
+ /* 4: X <-- H(X) */
+ /* 3: V_i <-- X */
+ X = (__m128i *)((uintptr_t)(V) + (i + 1) * s);
+ blockmix_salsa8(Y, X, r);
+ }
+
+ /* 4: X <-- H(X) */
+ /* 3: V_i <-- X */
+ Y = (__m128i *)((uintptr_t)(V) + i * s);
+ blockmix_salsa8(X, Y, r);
+
+ /* 4: X <-- H(X) */
+ /* 3: V_i <-- X */
+ X = (__m128i *) XY;
+ blockmix_salsa8(Y, X, r);
+
+ X32 = (uint32_t *) XY;
+ Y = (__m128i *)((uintptr_t)(XY) + s);
+
+ /* 7: j <-- Integerify(X) mod N */
+ j = integerify(X, r) & (N - 1);
+
+ /* 6: for i = 0 to N - 1 do */
+ for (i = 0; i < N; i += 2) {
+ __m128i * V_j = (__m128i *)((uintptr_t)(V) + j * s);
+
+ /* 8: X <-- H(X \xor V_j) */
+ /* 7: j <-- Integerify(X) mod N */
+ j = blockmix_salsa8_xor(X, V_j, Y, r) & (N - 1);
+ V_j = (__m128i *)((uintptr_t)(V) + j * s);
+
+ /* 8: X <-- H(X \xor V_j) */
+ /* 7: j <-- Integerify(X) mod N */
+ j = blockmix_salsa8_xor(Y, V_j, X, r) & (N - 1);
+ }
+
+ /* 10: B' <-- X */
+ for (k = 0; k < 2 * r; k++) {
+ for (i = 0; i < 16; i++) {
+ le32enc(&B[(k * 16 + (i * 5 % 16)) * 4],
+ X32[k * 16 + i]);
+ }
+ }
+}
+
+/**
+ * escrypt_kdf(local, passwd, passwdlen, salt, saltlen,
+ * N, r, p, buf, buflen):
+ * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
+ * p, buflen) and write the result into buf. The parameters r, p, and buflen
+ * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
+ * must be a power of 2 greater than 1.
+ *
+ * Return 0 on success; or -1 on error.
+ */
+int
+escrypt_kdf_sse(escrypt_local_t * local,
+ const uint8_t * passwd, size_t passwdlen,
+ const uint8_t * salt, size_t saltlen,
+ uint64_t N, uint32_t _r, uint32_t _p,
+ uint8_t * buf, size_t buflen)
+{
+ size_t B_size, V_size, XY_size, need;
+ uint8_t * B;
+ uint32_t * V, * XY;
+ size_t r = _r, p = _p;
+ uint32_t i;
+
+ /* Sanity-check parameters. */
+#if SIZE_MAX > UINT32_MAX
+ if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
+ errno = EFBIG;
+ return -1;
+ }
+#endif
+ if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (N > UINT32_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ if (((N & (N - 1)) != 0) || (N < 2)) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (r == 0 || p == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ if ((r > SIZE_MAX / 128 / p) ||
+#if SIZE_MAX / 256 <= UINT32_MAX
+ (r > SIZE_MAX / 256) ||
+#endif
+ (N > SIZE_MAX / 128 / r)) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /* Allocate memory. */
+ B_size = (size_t)128 * r * p;
+ V_size = (size_t)128 * r * N;
+ need = B_size + V_size;
+ if (need < V_size) {
+ errno = ENOMEM;
+ return -1;
+ }
+ XY_size = (size_t)256 * r + 64;
+ need += XY_size;
+ if (need < XY_size) {
+ errno = ENOMEM;
+ return -1;
+ }
+ if (local->size < need) {
+ if (free_region(local))
+ return -1;
+ if (!alloc_region(local, need))
+ return -1;
+ }
+ B = (uint8_t *)local->aligned;
+ V = (uint32_t *)((uint8_t *)B + B_size);
+ XY = (uint32_t *)((uint8_t *)V + V_size);
+
+ /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
+ PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, B_size);
+
+ /* 2: for i = 0 to p - 1 do */
+ for (i = 0; i < p; i++) {
+ /* 3: B_i <-- MF(B_i, N) */
+ smix(&B[(size_t)128 * i * r], r, N, V, XY);
+ }
+
+ /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
+ PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, buf, buflen);
+
+ /* Success! */
+ return 0;
+}
+#endif
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sysendian.h b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sysendian.h
new file mode 100644
index 0000000000..04e5c1ed45
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sysendian.h
@@ -0,0 +1,153 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
+
+#ifndef _SYSENDIAN_H_
+#define _SYSENDIAN_H_
+
+#include <stdint.h>
+
+/* Avoid namespace collisions with BSD <sys/endian.h>. */
+#define be16dec scrypt_be16dec
+#define be16enc scrypt_be16enc
+#define be32dec scrypt_be32dec
+#define be32enc scrypt_be32enc
+#define be64dec scrypt_be64dec
+#define be64enc scrypt_be64enc
+#define le16dec scrypt_le16dec
+#define le16enc scrypt_le16enc
+#define le32dec scrypt_le32dec
+#define le32enc scrypt_le32enc
+#define le64dec scrypt_le64dec
+#define le64enc scrypt_le64enc
+
+static inline uint16_t
+be16dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint16_t)(p[1]) + ((uint16_t)(p[0]) << 8));
+}
+
+static inline void
+be16enc(void *pp, uint16_t x)
+{
+ uint8_t * p = (uint8_t *)pp;
+
+ p[1] = x & 0xff;
+ p[0] = (x >> 8) & 0xff;
+}
+
+static inline uint32_t
+be32dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
+ ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
+}
+
+static inline void
+be32enc(void *pp, uint32_t x)
+{
+ uint8_t * p = (uint8_t *)pp;
+
+ p[3] = x & 0xff;
+ p[2] = (x >> 8) & 0xff;
+ p[1] = (x >> 16) & 0xff;
+ p[0] = (x >> 24) & 0xff;
+}
+
+static inline uint64_t
+be64dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) +
+ ((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) +
+ ((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) +
+ ((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56));
+}
+
+static inline void
+be64enc(void *pp, uint64_t x)
+{
+ uint8_t * p = (uint8_t *)pp;
+
+ p[7] = x & 0xff;
+ p[6] = (x >> 8) & 0xff;
+ p[5] = (x >> 16) & 0xff;
+ p[4] = (x >> 24) & 0xff;
+ p[3] = (x >> 32) & 0xff;
+ p[2] = (x >> 40) & 0xff;
+ p[1] = (x >> 48) & 0xff;
+ p[0] = (x >> 56) & 0xff;
+}
+
+static inline uint16_t
+le16dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint16_t)(p[0]) + ((uint16_t)(p[1]) << 8));
+}
+
+static inline void
+le16enc(void *pp, uint16_t x)
+{
+ uint8_t * p = (uint8_t *)pp;
+
+ p[0] = x & 0xff;
+ p[1] = (x >> 8) & 0xff;
+}
+
+static inline uint32_t
+le32dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) +
+ ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24));
+}
+
+static inline void
+le32enc(void *pp, uint32_t x)
+{
+ uint8_t * p = (uint8_t *)pp;
+
+ p[0] = x & 0xff;
+ p[1] = (x >> 8) & 0xff;
+ p[2] = (x >> 16) & 0xff;
+ p[3] = (x >> 24) & 0xff;
+}
+
+static inline uint64_t
+le64dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) +
+ ((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) +
+ ((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) +
+ ((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56));
+}
+
+static inline void
+le64enc(void *pp, uint64_t x)
+{
+ uint8_t * p = (uint8_t *)pp;
+
+ p[0] = x & 0xff;
+ p[1] = (x >> 8) & 0xff;
+ p[2] = (x >> 16) & 0xff;
+ p[3] = (x >> 24) & 0xff;
+ p[4] = (x >> 32) & 0xff;
+ p[5] = (x >> 40) & 0xff;
+ p[6] = (x >> 48) & 0xff;
+ p[7] = (x >> 56) & 0xff;
+}
+
+#endif /* !_SYSENDIAN_H_ */
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.c b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.c
new file mode 100644
index 0000000000..e61ccf3ecf
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.c
@@ -0,0 +1,78 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
+
+#ifndef __STDC_WANT_LIB_EXT1__
+# define __STDC_WANT_LIB_EXT1__ 1
+#endif
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+
+#include "utils.h"
+
+#ifdef _WIN32
+# include <windows.h>
+# include <wincrypt.h>
+#else
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_WEAK_SYMBOLS
+__attribute__((weak)) void
+__sodium_dummy_symbol_to_prevent_lto(void * const pnt, const size_t len)
+{
+ (void) pnt;
+ (void) len;
+}
+#endif
+
+void
+sodium_memzero(void * const pnt, const size_t len)
+{
+#ifdef _WIN32
+ SecureZeroMemory(pnt, len);
+#elif defined(HAVE_MEMSET_S)
+ if (memset_s(pnt, (rsize_t) len, 0, (rsize_t) len) != 0) {
+ abort();
+ }
+#elif defined(HAVE_EXPLICIT_BZERO)
+ explicit_bzero(pnt, len);
+#elif HAVE_WEAK_SYMBOLS
+ memset(pnt, 0, len);
+ __sodium_dummy_symbol_to_prevent_lto(pnt, len);
+#else
+ volatile unsigned char *pnt_ = (volatile unsigned char *) pnt;
+ size_t i = (size_t) 0U;
+
+ while (i < len) {
+ pnt_[i++] = 0U;
+ }
+#endif
+}
+
+int
+sodium_memcmp(const void * const b1_, const void * const b2_, size_t len)
+{
+ const unsigned char *b1 = (const unsigned char *) b1_;
+ const unsigned char *b2 = (const unsigned char *) b2_;
+ size_t i;
+ unsigned char d = (unsigned char) 0U;
+
+ for (i = 0U; i < len; i++) {
+ d |= b1[i] ^ b2[i];
+ }
+ return (int) ((1 & ((d - 1) >> 8)) - 1);
+}
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.h b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.h
new file mode 100644
index 0000000000..fb2020c35d
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.h
@@ -0,0 +1,40 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
+
+#ifndef __SODIUM_UTILS_H__
+#define __SODIUM_UTILS_H__
+
+#include <stddef.h>
+
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__cplusplus) || !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
+# define _SODIUM_C99(X)
+#else
+# define _SODIUM_C99(X) X
+#endif
+
+SODIUM_EXPORT
+void sodium_memzero(void * const pnt, const size_t len);
+
+/* WARNING: sodium_memcmp() must be used to verify if two secret keys
+ * are equal, in constant time.
+ * It returns 0 if the keys are equal, and -1 if they differ.
+ * This function is not designed for lexicographical comparisons.
+ */
+SODIUM_EXPORT
+int sodium_memcmp(const void * const b1_, const void * const b2_, size_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#endif
diff --git a/protocols/Tox/libtox/src/toxencryptsave/defines.h b/protocols/Tox/libtox/src/toxencryptsave/defines.h
new file mode 100644
index 0000000000..e3fca073e3
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/defines.h
@@ -0,0 +1,2 @@
+#define TOX_ENC_SAVE_MAGIC_NUMBER "toxEsave"
+#define TOX_ENC_SAVE_MAGIC_LENGTH 8
diff --git a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.api.h b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.api.h
new file mode 100644
index 0000000000..61f685f86b
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.api.h
@@ -0,0 +1,327 @@
+%{
+/*
+ * Batch encryption functions.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013-2016 Tox Developers.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TOXENCRYPTSAVE_H
+#define TOXENCRYPTSAVE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+%}
+
+/*******************************************************************************
+ *
+ * This module is organized into two parts.
+ *
+ * 1. A simple API operating on plain text/cipher text data and a password to
+ * encrypt or decrypt it.
+ * 2. A more advanced API that splits key derivation and encryption into two
+ * separate function calls.
+ *
+ * The first part is implemented in terms of the second part and simply calls
+ * the separate functions in sequence. Since key derivation is very expensive
+ * compared to the actual encryption, clients that do a lot of crypto should
+ * prefer the advanced API and reuse pass-key objects.
+ *
+ * To use the second part, first derive an encryption key from a password with
+ * ${tox.pass_Key.derive}, then use the derived key to encrypt the data.
+ *
+ * The encrypted data is prepended with a magic number, to aid validity
+ * checking (no guarantees are made of course). Any data to be decrypted must
+ * start with the magic number.
+ *
+ * Clients should consider alerting their users that, unlike plain data, if
+ * even one bit becomes corrupted, the data will be entirely unrecoverable.
+ * Ditto if they forget their password, there is no way to recover the data.
+ *
+ *******************************************************************************/
+
+class tox {
+
+/**
+ * The size of the salt part of a pass-key.
+ */
+const PASS_SALT_LENGTH = 32;
+/**
+ * The size of the key part of a pass-key.
+ */
+const PASS_KEY_LENGTH = 32;
+/**
+ * The amount of additional data required to store any encrypted byte array.
+ * Encrypting an array of N bytes requires N + $PASS_ENCRYPTION_EXTRA_LENGTH
+ * bytes in the encrypted byte array.
+ */
+const PASS_ENCRYPTION_EXTRA_LENGTH = 80;
+
+error for key_derivation {
+ NULL,
+ /**
+ * The crypto lib was unable to derive a key from the given passphrase,
+ * which is usually a lack of memory issue. The functions accepting keys
+ * do not produce this error.
+ */
+ FAILED,
+}
+
+error for encryption {
+ NULL,
+ /**
+ * The crypto lib was unable to derive a key from the given passphrase,
+ * which is usually a lack of memory issue. The functions accepting keys
+ * do not produce this error.
+ */
+ KEY_DERIVATION_FAILED,
+ /**
+ * The encryption itself failed.
+ */
+ FAILED,
+}
+
+error for decryption {
+ NULL,
+ /**
+ * The input data was shorter than $PASS_ENCRYPTION_EXTRA_LENGTH bytes
+ */
+ INVALID_LENGTH,
+ /**
+ * The input data is missing the magic number (i.e. wasn't created by this
+ * module, or is corrupted).
+ */
+ BAD_FORMAT,
+ /**
+ * The crypto lib was unable to derive a key from the given passphrase,
+ * which is usually a lack of memory issue. The functions accepting keys
+ * do not produce this error.
+ */
+ KEY_DERIVATION_FAILED,
+ /**
+ * The encrypted byte array could not be decrypted. Either the data was
+ * corrupted or the password/key was incorrect.
+ */
+ FAILED,
+}
+
+
+/*******************************************************************************
+ *
+ * BEGIN PART 1
+ *
+ * The simple API is presented first. If your code spends too much time using
+ * these functions, consider using the advanced functions instead and caching
+ * the generated pass-key.
+ *
+ *******************************************************************************/
+
+/**
+ * Encrypts the given data with the given passphrase.
+ *
+ * The output array must be at least `plaintext_len + $PASS_ENCRYPTION_EXTRA_LENGTH`
+ * bytes long. This delegates to ${pass_Key.derive} and
+ * ${pass_Key.encrypt}.
+ *
+ * @param plaintext A byte array of length `plaintext_len`.
+ * @param plaintext_len The length of the plain text array. Bigger than 0.
+ * @param passphrase The user-provided password. Can be empty.
+ * @param passphrase_len The length of the password.
+ * @param ciphertext The cipher text array to write the encrypted data to.
+ *
+ * @return true on success.
+ */
+static bool pass_encrypt(const uint8_t[plaintext_len] plaintext, const uint8_t[passphrase_len] passphrase, uint8_t *ciphertext)
+ with error for encryption;
+
+
+/**
+ * Decrypts the given data with the given passphrase.
+ *
+ * The output array must be at least `ciphertext_len - $PASS_ENCRYPTION_EXTRA_LENGTH`
+ * bytes long. This delegates to ${pass_Key.decrypt}.
+ *
+ * @param ciphertext A byte array of length `ciphertext_len`.
+ * @param ciphertext_len The length of the cipher text array. At least $PASS_ENCRYPTION_EXTRA_LENGTH.
+ * @param passphrase The user-provided password. Can be empty.
+ * @param passphrase_len The length of the password.
+ * @param plaintext The plain text array to write the decrypted data to.
+ *
+ * @return true on success.
+ */
+static bool pass_decrypt(const uint8_t[ciphertext_len] ciphertext, const uint8_t[passphrase_len] passphrase, uint8_t *plaintext)
+ with error for decryption;
+
+
+/*******************************************************************************
+ *
+ * BEGIN PART 2
+ *
+ * And now part 2, which does the actual encryption, and can be used to write
+ * less CPU intensive client code than part one.
+ *
+ *******************************************************************************/
+
+class pass_Key {
+ /**
+ * This type represents a pass-key.
+ *
+ * A pass-key and a password are two different concepts: a password is given
+ * by the user in plain text. A pass-key is the generated symmetric key used
+ * for encryption and decryption. It is derived from a salt and the user-
+ * provided password.
+ *
+ * The $this structure is hidden in the implementation. It can be allocated
+ * using $new and must be deallocated using $free.
+ */
+ struct this;
+
+ /**
+ * Create a new $this. The initial value of it is indeterminate. To
+ * initialise it, use one of the derive_* functions below.
+ *
+ * In case of failure, this function returns NULL. The only failure mode at
+ * this time is memory allocation failure, so this function has no error code.
+ */
+ static this new();
+
+ /**
+ * Deallocate a $this. This function behaves like free(), so NULL is an
+ * acceptable argument value.
+ */
+ void free();
+
+ /**
+ * Generates a secret symmetric key from the given passphrase.
+ *
+ * Be sure to not compromise the key! Only keep it in memory, do not write
+ * it to disk.
+ *
+ * Note that this function is not deterministic; to derive the same key from
+ * a password, you also must know the random salt that was used. A
+ * deterministic version of this function is $derive_with_salt.
+ *
+ * @param passphrase The user-provided password. Can be empty.
+ * @param passphrase_len The length of the password.
+ *
+ * @return true on success.
+ */
+ bool derive(const uint8_t[passphrase_len] passphrase)
+ with error for key_derivation;
+
+ /**
+ * Same as above, except use the given salt for deterministic key derivation.
+ *
+ * @param passphrase The user-provided password. Can be empty.
+ * @param passphrase_len The length of the password.
+ * @param salt An array of at least $PASS_SALT_LENGTH bytes.
+ *
+ * @return true on success.
+ */
+ bool derive_with_salt(const uint8_t[passphrase_len] passphrase, const uint8_t[PASS_SALT_LENGTH] salt)
+ with error for key_derivation;
+
+ /**
+ * Encrypt a plain text with a key produced by $derive or $derive_with_salt.
+ *
+ * The output array must be at least `plaintext_len + $PASS_ENCRYPTION_EXTRA_LENGTH`
+ * bytes long.
+ *
+ * @param plaintext A byte array of length `plaintext_len`.
+ * @param plaintext_len The length of the plain text array. Bigger than 0.
+ * @param ciphertext The cipher text array to write the encrypted data to.
+ *
+ * @return true on success.
+ */
+ const bool encrypt(const uint8_t[plaintext_len] plaintext, uint8_t *ciphertext)
+ with error for encryption;
+
+ /**
+ * This is the inverse of $encrypt, also using only keys produced by
+ * $derive or $derive_with_salt.
+ *
+ * @param ciphertext A byte array of length `ciphertext_len`.
+ * @param ciphertext_len The length of the cipher text array. At least $PASS_ENCRYPTION_EXTRA_LENGTH.
+ * @param plaintext The plain text array to write the decrypted data to.
+ *
+ * @return true on success.
+ */
+ const bool decrypt(const uint8_t[ciphertext_len] ciphertext, uint8_t *plaintext)
+ with error for decryption;
+}
+
+/**
+ * Retrieves the salt used to encrypt the given data.
+ *
+ * The retrieved salt can then be passed to ${pass_Key.derive_with_salt} to
+ * produce the same key as was previously used. Any data encrypted with this
+ * module can be used as input.
+ *
+ * The cipher text must be at least $PASS_ENCRYPTION_EXTRA_LENGTH bytes in length.
+ * The salt must be $PASS_SALT_LENGTH bytes in length.
+ * If the passed byte arrays are smaller than required, the behaviour is
+ * undefined.
+ *
+ * If the cipher text pointer or the salt is NULL, this function returns false.
+ *
+ * Success does not say anything about the validity of the data, only that
+ * data of the appropriate size was copied.
+ *
+ * @return true on success.
+ */
+static bool get_salt(const uint8_t *ciphertext, uint8_t[PASS_SALT_LENGTH] salt) {
+ NULL,
+ /**
+ * The input data is missing the magic number (i.e. wasn't created by this
+ * module, or is corrupted).
+ */
+ BAD_FORMAT,
+}
+
+/**
+ * Determines whether or not the given data is encrypted by this module.
+ *
+ * It does this check by verifying that the magic number is the one put in
+ * place by the encryption functions.
+ *
+ * The data must be at least $PASS_ENCRYPTION_EXTRA_LENGTH bytes in length.
+ * If the passed byte array is smaller than required, the behaviour is
+ * undefined.
+ *
+ * If the data pointer is NULL, the behaviour is undefined
+ *
+ * @return true if the data is encrypted by this module.
+ */
+static bool is_data_encrypted(const uint8_t *data);
+
+}
+
+%{
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+%}
diff --git a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c
new file mode 100644
index 0000000000..5640e82fc7
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c
@@ -0,0 +1,338 @@
+/*
+ * Batch encryption functions.
+ */
+
+/*
+ * Copyright © 2016-2017 The TokTok team.
+ * Copyright © 2013 Tox project.
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "../toxcore/crypto_core.h"
+#include "defines.h"
+#include "toxencryptsave.h"
+#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}}
+
+#ifdef VANILLA_NACL
+#include <crypto_box.h>
+#include <crypto_hash_sha256.h>
+#include "crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h"
+#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
+#else
+#include <sodium.h>
+#endif
+
+#include <string.h>
+
+#if TOX_PASS_SALT_LENGTH != crypto_pwhash_scryptsalsa208sha256_SALTBYTES
+#error TOX_PASS_SALT_LENGTH is assumed to be equal to crypto_pwhash_scryptsalsa208sha256_SALTBYTES
+#endif
+
+#if TOX_PASS_KEY_LENGTH != CRYPTO_SHARED_KEY_SIZE
+#error TOX_PASS_KEY_LENGTH is assumed to be equal to CRYPTO_SHARED_KEY_SIZE
+#endif
+
+#if TOX_PASS_ENCRYPTION_EXTRA_LENGTH != (crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH)
+#error TOX_PASS_ENCRYPTION_EXTRA_LENGTH is assumed to be equal to (crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH)
+#endif
+
+uint32_t tox_pass_salt_length(void)
+{
+ return TOX_PASS_SALT_LENGTH;
+}
+uint32_t tox_pass_key_length(void)
+{
+ return TOX_PASS_KEY_LENGTH;
+}
+uint32_t tox_pass_encryption_extra_length(void)
+{
+ return TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
+}
+
+struct Tox_Pass_Key {
+ uint8_t salt[TOX_PASS_SALT_LENGTH];
+ uint8_t key[TOX_PASS_KEY_LENGTH];
+};
+
+Tox_Pass_Key *tox_pass_key_new(void)
+{
+ return (Tox_Pass_Key *)malloc(sizeof(Tox_Pass_Key));
+}
+
+void tox_pass_key_free(Tox_Pass_Key *pass_key)
+{
+ free(pass_key);
+}
+
+/* Clients should consider alerting their users that, unlike plain data, if even one bit
+ * becomes corrupted, the data will be entirely unrecoverable.
+ * Ditto if they forget their password, there is no way to recover the data.
+ */
+
+/* This retrieves the salt used to encrypt the given data, which can then be passed to
+ * tox_pass_key_derive_with_salt to produce the same key as was previously used. Any encrpyted
+ * data with this module can be used as input.
+ *
+ * returns true if magic number matches
+ * success does not say anything about the validity of the data, only that data of
+ * the appropriate size was copied
+ */
+bool tox_get_salt(const uint8_t *data, uint8_t *salt, TOX_ERR_GET_SALT *error)
+{
+ if (!data || !salt) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_GET_SALT_NULL);
+ return false;
+ }
+
+ if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_GET_SALT_BAD_FORMAT);
+ return false;
+ }
+
+ data += TOX_ENC_SAVE_MAGIC_LENGTH;
+ memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GET_SALT_OK);
+ return true;
+}
+
+/* Generates a secret symmetric key from the given passphrase. out_key must be at least
+ * TOX_PASS_KEY_LENGTH bytes long.
+ * Be sure to not compromise the key! Only keep it in memory, do not write to disk.
+ * The password is zeroed after key derivation.
+ * The key should only be used with the other functions in this module, as it
+ * includes a salt.
+ * Note that this function is not deterministic; to derive the same key from a
+ * password, you also must know the random salt that was used. See below.
+ *
+ * returns true on success
+ */
+bool tox_pass_key_derive(Tox_Pass_Key *out_key, const uint8_t *passphrase, size_t pplength,
+ TOX_ERR_KEY_DERIVATION *error)
+{
+ uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
+ randombytes(salt, sizeof salt);
+ return tox_pass_key_derive_with_salt(out_key, passphrase, pplength, salt, error);
+}
+
+/* Same as above, except with use the given salt for deterministic key derivation.
+ * The salt must be TOX_PASS_SALT_LENGTH bytes in length.
+ */
+bool tox_pass_key_derive_with_salt(Tox_Pass_Key *out_key, const uint8_t *passphrase, size_t pplength,
+ const uint8_t *salt, TOX_ERR_KEY_DERIVATION *error)
+{
+ if (!salt || !out_key || (!passphrase && pplength != 0)) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_NULL);
+ return 0;
+ }
+
+ uint8_t passkey[crypto_hash_sha256_BYTES];
+ crypto_hash_sha256(passkey, passphrase, pplength);
+
+ uint8_t key[CRYPTO_SHARED_KEY_SIZE];
+
+ /* Derive a key from the password */
+ /* http://doc.libsodium.org/key_derivation/README.html */
+ /* note that, according to the documentation, a generic pwhash interface will be created
+ * once the pwhash competition (https://password-hashing.net/) is over */
+ if (crypto_pwhash_scryptsalsa208sha256(
+ key, sizeof(key), (char *)passkey, sizeof(passkey), salt,
+ crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */
+ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) {
+ /* out of memory most likely */
+ SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_FAILED);
+ return 0;
+ }
+
+ sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */
+ memcpy(out_key->salt, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
+ memcpy(out_key->key, key, CRYPTO_SHARED_KEY_SIZE);
+ SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_OK);
+ return 1;
+}
+
+/* Encrypt arbitrary with a key produced by tox_derive_key_*. The output
+ * array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long.
+ * key must be TOX_PASS_KEY_LENGTH bytes.
+ * If you already have a symmetric key from somewhere besides this module, simply
+ * call encrypt_data_symmetric in toxcore/crypto_core directly.
+ *
+ * returns true on success
+ */
+bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t *data, size_t data_len, uint8_t *out,
+ TOX_ERR_ENCRYPTION *error)
+{
+ if (data_len == 0 || !data || !key || !out) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL);
+ return 0;
+ }
+
+ /* the output data consists of, in order:
+ * salt, nonce, mac, enc_data
+ * where the mac is automatically prepended by the encrypt()
+ * the salt+nonce is called the prefix
+ * I'm not sure what else I'm supposed to do with the salt and nonce, since we
+ * need them to decrypt the data
+ */
+
+ /* first add the magic number */
+ memcpy(out, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH);
+ out += TOX_ENC_SAVE_MAGIC_LENGTH;
+
+ /* then add the rest prefix */
+ memcpy(out, key->salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
+ out += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
+
+ uint8_t nonce[crypto_box_NONCEBYTES];
+ random_nonce(nonce);
+ memcpy(out, nonce, crypto_box_NONCEBYTES);
+ out += crypto_box_NONCEBYTES;
+
+ /* now encrypt */
+ if (encrypt_data_symmetric(key->key, nonce, data, data_len, out)
+ != data_len + crypto_box_MACBYTES) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_FAILED);
+ return 0;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_OK);
+ return 1;
+}
+
+/* Encrypts the given data with the given passphrase. The output array must be
+ * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
+ * to tox_derive_key and tox_pass_key_encrypt.
+ *
+ * returns true on success
+ */
+bool tox_pass_encrypt(const uint8_t *data, size_t data_len, const uint8_t *passphrase, size_t pplength, uint8_t *out,
+ TOX_ERR_ENCRYPTION *error)
+{
+ Tox_Pass_Key key;
+ TOX_ERR_KEY_DERIVATION _error;
+
+ if (!tox_pass_key_derive(&key, passphrase, pplength, &_error)) {
+ if (_error == TOX_ERR_KEY_DERIVATION_NULL) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL);
+ } else if (_error == TOX_ERR_KEY_DERIVATION_FAILED) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED);
+ }
+
+ return 0;
+ }
+
+ return tox_pass_key_encrypt(&key, data, data_len, out, error);
+}
+
+/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by
+ * tox_derive_key.
+ *
+ * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH
+ *
+ * returns true on success
+ */
+bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t *data, size_t length, uint8_t *out,
+ TOX_ERR_DECRYPTION *error)
+{
+ if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH);
+ return 0;
+ }
+
+ if (!data || !key || !out) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_NULL);
+ return 0;
+ }
+
+ if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT);
+ return 0;
+ }
+
+ data += TOX_ENC_SAVE_MAGIC_LENGTH;
+ data += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; // salt only affects key derivation
+
+ size_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
+
+ uint8_t nonce[crypto_box_NONCEBYTES];
+ memcpy(nonce, data, crypto_box_NONCEBYTES);
+ data += crypto_box_NONCEBYTES;
+
+ /* decrypt the data */
+ if (decrypt_data_symmetric(key->key, nonce, data, decrypt_length + crypto_box_MACBYTES, out)
+ != decrypt_length) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_FAILED);
+ return 0;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_OK);
+ return 1;
+}
+
+/* Decrypts the given data with the given passphrase. The output array must be
+ * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
+ * to tox_pass_key_decrypt.
+ *
+ * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH
+ *
+ * returns true on success
+ */
+bool tox_pass_decrypt(const uint8_t *data, size_t length, const uint8_t *passphrase, size_t pplength, uint8_t *out,
+ TOX_ERR_DECRYPTION *error)
+{
+ if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH);
+ return 0;
+ }
+
+ if (!data || !passphrase || !out) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_NULL);
+ return 0;
+ }
+
+ if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT);
+ return 0;
+ }
+
+ uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
+ memcpy(salt, data + TOX_ENC_SAVE_MAGIC_LENGTH, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
+
+ /* derive the key */
+ Tox_Pass_Key key;
+
+ if (!tox_pass_key_derive_with_salt(&key, passphrase, pplength, salt, NULL)) {
+ /* out of memory most likely */
+ SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED);
+ return 0;
+ }
+
+ return tox_pass_key_decrypt(&key, data, length, out, error);
+}
+
+/* Determines whether or not the given data is encrypted (by checking the magic number)
+ */
+bool tox_is_data_encrypted(const uint8_t *data)
+{
+ if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) {
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/protocols/Tox/include/toxencryptsave.h b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h
index 738d9757cb..ef1ab15289 100644
--- a/protocols/Tox/include/toxencryptsave.h
+++ b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h
@@ -28,7 +28,7 @@
extern "C" {
#endif
-#include <msapi/stdbool.h>
+#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
diff --git a/protocols/Tox/res/Icons/audio_call.ico b/protocols/Tox/res/Icons/audio_call.ico
deleted file mode 100644
index 555d0cb874..0000000000
--- a/protocols/Tox/res/Icons/audio_call.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/Tox/res/Icons/audio_end.ico b/protocols/Tox/res/Icons/audio_end.ico
deleted file mode 100644
index 9698282053..0000000000
--- a/protocols/Tox/res/Icons/audio_end.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/Tox/res/Icons/audio_ring.ico b/protocols/Tox/res/Icons/audio_ring.ico
deleted file mode 100644
index 77c4aa9640..0000000000
--- a/protocols/Tox/res/Icons/audio_ring.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/Tox/res/Icons/audio_start.ico b/protocols/Tox/res/Icons/audio_start.ico
deleted file mode 100644
index 4863643b52..0000000000
--- a/protocols/Tox/res/Icons/audio_start.ico
+++ /dev/null
Binary files differ
diff --git a/protocols/Tox/res/resource.rc b/protocols/Tox/res/resource.rc
index eb42763582..b501959882 100644
--- a/protocols/Tox/res/resource.rc
+++ b/protocols/Tox/res/resource.rc
@@ -64,14 +64,6 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
// remains consistent on all systems.
IDI_TOX ICON "icons\\tox.ico"
-IDI_AUDIO_CALL ICON "icons\\audio_call.ico"
-
-IDI_AUDIO_END ICON "icons\\audio_end.ico"
-
-IDI_AUDIO_RING ICON "icons\\audio_ring.ico"
-
-IDI_AUDIO_START ICON "icons\\audio_start.ico"
-
/////////////////////////////////////////////////////////////////////////////
//
@@ -107,24 +99,29 @@ BEGIN
EDITTEXT IDC_TOXID,81,15,217,12,ES_AUTOHSCROLL | ES_READONLY | WS_DISABLED
LTEXT "Name:",IDC_STATIC,12,48,69,11
EDITTEXT IDC_NAME,81,46,217,12,ES_AUTOHSCROLL
- LTEXT "Password:",IDC_STATIC,12,64,69,8,NOT WS_VISIBLE
- EDITTEXT IDC_PASSWORD,81,62,217,12,ES_PASSWORD | ES_AUTOHSCROLL | NOT WS_VISIBLE
LTEXT "Default group:",IDC_STATIC,12,80,69,12
EDITTEXT IDC_GROUP,81,78,217,12,ES_AUTOHSCROLL
PUSHBUTTON "Create Tox profile",IDC_PROFILE_NEW,81,30,107,13
PUSHBUTTON "Import Tox profile",IDC_PROFILE_IMPORT,191,30,107,13
PUSHBUTTON "Copy Tox ID",IDC_CLIPBOARD,81,30,107,13,NOT WS_VISIBLE
PUSHBUTTON "Export Tox profile",IDC_PROFILE_EXPORT,191,30,107,13,NOT WS_VISIBLE
- GROUPBOX "Connection settings",IDC_STATIC,7,99,296,75
+ GROUPBOX "Connection settings",IDC_STATIC,7,99,296,106
CONTROL "Enable UDP (otherwise force Tox to use TCP)",IDC_ENABLE_UDP,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,111,286,10
- CONTROL "Enable IPv6",IDC_ENABLE_IPV6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,125,286,10
- LTEXT "Max connect retries:",IDC_STATIC,12,142,121,8
- EDITTEXT IDC_MAXCONNECTRETRIES,133,139,43,14,ES_NUMBER
- CONTROL "",IDC_MAXCONNECTRETRIESSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,166,139,10,14
- EDITTEXT IDC_MAXRECONNECTRETRIES,133,155,43,14,ES_NUMBER
- CONTROL "",IDC_MAXRECONNECTRETRIESSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,166,155,10,14
- LTEXT "Max reconnect retries:",IDC_STATIC,12,158,121,8
+ CONTROL "Enable IPv6",IDC_ENABLE_IPV6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,139,286,10
+ LTEXT "Max connect retries:",IDC_STATIC,12,171,121,8
+ EDITTEXT IDC_MAXCONNECTRETRIES,133,168,43,14,ES_NUMBER
+ CONTROL "",IDC_MAXCONNECTRETRIESSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,166,168,10,14
+ EDITTEXT IDC_MAXRECONNECTRETRIES,133,184,43,14,ES_NUMBER
+ CONTROL "",IDC_MAXRECONNECTRETRIESSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,166,184,10,14
+ LTEXT "Max reconnect retries:",IDC_STATIC,12,186,121,8
+ CONTROL "Enable UDP hole-punching",IDC_ENABLE_HOLEPUNCHING,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,125,274,10
+ CONTROL "Enable local network peer discovery",IDC_ENABLE_LOCALDISCOVERY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,153,286,10
+ PUSHBUTTON "Remove password",IDC_PASSWORD_REMOVE,81,62,107,13
+ PUSHBUTTON "Change password",IDC_PASSWORD_CHANGE,191,62,107,13
+ PUSHBUTTON "Set password",IDC_PASSWORD_CREATE,136,62,107,13
END
IDD_SEARCH DIALOGEX 0, 0, 109, 113
@@ -145,17 +142,16 @@ BEGIN
EDITTEXT IDC_DNS_ID,2,13,217,14,ES_AUTOHSCROLL
END
-IDD_PASSWORD DIALOGEX 0, 0, 209, 75
+IDD_PASSWORD_ENTER DIALOGEX 0, 0, 211, 70
STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-EXSTYLE WS_EX_TOOLWINDOW | WS_EX_APPWINDOW
+EXSTYLE WS_EX_TOPMOST | WS_EX_TOOLWINDOW | WS_EX_CONTROLPARENT | WS_EX_APPWINDOW
CAPTION "Enter password"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
- EDITTEXT IDC_PASSWORD,7,24,197,12,ES_PASSWORD | ES_AUTOHSCROLL
- CONTROL "Save password",IDC_SAVEPERMANENTLY,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,7,40,197,12
- DEFPUSHBUTTON "OK",IDOK,101,56,50,14
- PUSHBUTTON "Cancel",IDCANCEL,154,56,50,14
- LTEXT "Tox profile is encrypted. Enter the password to continue.",IDC_STATIC,7,5,197,18
+ EDITTEXT IDC_PASSWORD,7,24,199,12,ES_PASSWORD | ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK",IDOK,101,51,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,156,51,50,14
+ LTEXT "Tox profile is encrypted. Enter the password to continue.",IDC_STATIC,7,5,199,18
END
IDD_OPTIONS_NODES DIALOGEX 0, 0, 310, 230
@@ -185,74 +181,36 @@ BEGIN
PUSHBUTTON "Cancel",IDCANCEL,156,97,50,14
END
-IDD_OPTIONS_MULTIMEDIA DIALOGEX 0, 0, 310, 230
-STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
-EXSTYLE WS_EX_CONTROLPARENT
+IDD_PASSWORD_CHANGE DIALOGEX 0, 0, 209, 112
+STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_TOPMOST | WS_EX_TOOLWINDOW | WS_EX_CONTROLPARENT | WS_EX_APPWINDOW
+CAPTION "Change password"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
- GROUPBOX "Multimedia",-1,7,7,296,89
- LTEXT "Audio input device",-1,12,17,60,8
- COMBOBOX IDC_AUDIOINPUT,12,26,286,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
- LTEXT "Audio output device",-1,12,42,65,8
- COMBOBOX IDC_AUDIOOUTPUT,12,52,286,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
- LTEXT "Video input device",-1,15,68,59,8,NOT WS_VISIBLE
- COMBOBOX IDC_COMBO_VIDEOINPUT,12,78,286,30,CBS_DROPDOWN | CBS_SORT | NOT WS_VISIBLE | WS_VSCROLL | WS_TABSTOP
-END
-
-IDD_CHATROOM_INVITE DIALOGEX 0, 0, 190, 179
-STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
-EXSTYLE WS_EX_TOPMOST
-CAPTION "Invite contacts to chat room"
-FONT 8, "MS Shell Dlg", 0, 0, 0x0
-BEGIN
- PUSHBUTTON "&Invite",IDOK,87,158,46,14
- PUSHBUTTON "&Cancel",IDCANCEL,138,158,45,14
- CONTROL "",IDC_CCLIST,"CListControl",WS_TABSTOP | 0x16f,7,7,176,145,WS_EX_CLIENTEDGE
-END
-
-IDD_CALL DIALOGEX 0, 0, 319, 226
-STYLE DS_SYSMODAL | DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
-EXSTYLE WS_EX_TOPMOST
-CAPTION "Call"
-FONT 8, "MS Shell Dlg", 400, 0, 0x1
-BEGIN
- DEFPUSHBUTTON "End",IDCANCEL,262,204,50,15
+ EDITTEXT IDC_PASSWORD,7,14,197,12,ES_PASSWORD | ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK",IDOK,101,93,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,154,93,50,14
+ EDITTEXT IDC_PASSWORD_NEW,7,40,197,12,ES_PASSWORD | ES_AUTOHSCROLL
+ LTEXT "Old password:",IDC_STATIC,7,4,197,8
+ LTEXT "New password:",IDC_STATIC,7,30,197,8
+ EDITTEXT IDC_PASSWORD_CONFIRM,7,65,197,12,ES_PASSWORD | ES_AUTOHSCROLL
+ LTEXT "Confirm password:",IDC_STATIC,7,55,197,8
+ LTEXT "",IDC_PASSWORD_VALIDATION,7,81,197,8
END
-IDD_CALL_RECEIVE DIALOGEX 0, 0, 239, 111
-STYLE DS_SYSMODAL | DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
-EXSTYLE WS_EX_TOPMOST
-CAPTION "Incoming call"
-FONT 8, "MS Shell Dlg", 400, 0, 0x1
-BEGIN
- DEFPUSHBUTTON "Answer",IDOK,64,89,50,15
- PUSHBUTTON "Reject",IDCANCEL,127,90,50,14
- LTEXT "From:",IDC_STATIC,8,22,24,9,SS_CENTERIMAGE
- CONTROL "",IDC_FROM,"Static",SS_SIMPLE | SS_NOPREFIX | WS_GROUP,41,23,191,9
- LTEXT "Date:",IDC_STATIC,8,37,28,9,SS_CENTERIMAGE
- CONTROL "",IDC_DATE,"Static",SS_SIMPLE | SS_NOPREFIX | WS_GROUP,41,36,191,9
- CONTROL "&User menu",IDC_USERMENU,"MButtonClass",NOT WS_VISIBLE | WS_TABSTOP,178,7,16,14,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "User &details",IDC_DETAILS,"MButtonClass",NOT WS_VISIBLE | WS_TABSTOP,197,7,16,14,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "&History",IDC_HISTORY,"MButtonClass",NOT WS_VISIBLE | WS_TABSTOP,216,7,16,14,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "",IDC_PROTOCOL,"Button",BS_OWNERDRAW | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,7,9,12,12
- LTEXT "",IDC_NAME2,21,9,137,9,SS_NOPREFIX | SS_CENTERIMAGE
-END
-
-IDD_CALL_SEND DIALOGEX 0, 0, 239, 95
-STYLE DS_SYSMODAL | DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
-EXSTYLE WS_EX_TOPMOST
-CAPTION "Outgoing call"
-FONT 8, "MS Shell Dlg", 400, 0, 0x1
+IDD_PASSWORD_CREATE DIALOGEX 0, 0, 209, 84
+STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_TOPMOST | WS_EX_TOOLWINDOW | WS_EX_CONTROLPARENT | WS_EX_APPWINDOW
+CAPTION "Set password"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
- DEFPUSHBUTTON "Call",IDOK,64,73,50,15
- PUSHBUTTON "Cancel",IDCANCEL,127,74,50,14
- LTEXT "To:",-1,8,22,24,9,SS_CENTERIMAGE
- CONTROL "",IDC_FROM,"Static",SS_SIMPLE | SS_NOPREFIX | WS_GROUP,41,23,191,9
- CONTROL "&User menu",IDC_USERMENU,"MButtonClass",NOT WS_VISIBLE | WS_TABSTOP,178,7,16,14,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "User &details",IDC_DETAILS,"MButtonClass",NOT WS_VISIBLE | WS_TABSTOP,197,7,16,14,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "&History",IDC_HISTORY,"MButtonClass",NOT WS_VISIBLE | WS_TABSTOP,216,7,16,14,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "",IDC_PROTOCOL,"Button",BS_OWNERDRAW | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,7,9,12,12
- LTEXT "",IDC_NAME2,21,9,137,9,SS_NOPREFIX | SS_CENTERIMAGE
+ DEFPUSHBUTTON "OK",IDOK,101,65,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,154,65,50,14
+ EDITTEXT IDC_PASSWORD_NEW,7,14,197,12,ES_PASSWORD | ES_AUTOHSCROLL
+ LTEXT "New password:",-1,7,4,197,8
+ EDITTEXT IDC_PASSWORD_CONFIRM,7,39,197,12,ES_PASSWORD | ES_AUTOHSCROLL
+ LTEXT "Confirm password:",-1,7,29,197,8
+ LTEXT "",IDC_PASSWORD_VALIDATION,7,55,197,8
END
@@ -276,6 +234,7 @@ BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 303
VERTGUIDE, 12
+ VERTGUIDE, 24
VERTGUIDE, 81
VERTGUIDE, 133
VERTGUIDE, 298
@@ -293,11 +252,11 @@ BEGIN
VERTGUIDE, 219
END
- IDD_PASSWORD, DIALOG
+ IDD_PASSWORD_ENTER, DIALOG
BEGIN
- RIGHTMARGIN, 204
+ RIGHTMARGIN, 206
VERTGUIDE, 7
- BOTTOMMARGIN, 70
+ BOTTOMMARGIN, 65
END
IDD_OPTIONS_NODES, DIALOG
@@ -319,49 +278,18 @@ BEGIN
HORZGUIDE, 67
END
- IDD_OPTIONS_MULTIMEDIA, DIALOG
+ IDD_PASSWORD_CHANGE, DIALOG
BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 303
- VERTGUIDE, 12
- VERTGUIDE, 81
- VERTGUIDE, 298
- TOPMARGIN, 7
- BOTTOMMARGIN, 228
- END
-
- IDD_CHATROOM_INVITE, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 183
- TOPMARGIN, 7
- BOTTOMMARGIN, 172
- HORZGUIDE, 152
- HORZGUIDE, 158
- END
-
- IDD_CALL, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 312
- TOPMARGIN, 7
- BOTTOMMARGIN, 219
- END
-
- IDD_CALL_RECEIVE, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 232
- TOPMARGIN, 7
- BOTTOMMARGIN, 104
+ RIGHTMARGIN, 204
+ VERTGUIDE, 7
+ BOTTOMMARGIN, 107
END
- IDD_CALL_SEND, DIALOG
+ IDD_PASSWORD_CREATE, DIALOG
BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 232
- TOPMARGIN, 7
- BOTTOMMARGIN, 88
+ RIGHTMARGIN, 204
+ VERTGUIDE, 7
+ BOTTOMMARGIN, 79
END
END
#endif // APSTUDIO_INVOKED
@@ -372,17 +300,27 @@ END
// AFX_DIALOG_LAYOUT
//
-IDD_OPTIONS_MULTIMEDIA AFX_DIALOG_LAYOUT
+IDD_OPTIONS_MAIN AFX_DIALOG_LAYOUT
BEGIN
0
END
-IDD_OPTIONS_MAIN AFX_DIALOG_LAYOUT
+IDD_PASSWORD_ENTER AFX_DIALOG_LAYOUT
+BEGIN
+ 0
+END
+
+IDD_PASSWORD_CHANGE AFX_DIALOG_LAYOUT
+BEGIN
+ 0
+END
+
+IDD_PASSWORD_CHANGE2 AFX_DIALOG_LAYOUT
BEGIN
0
END
-IDD_PASSWORD AFX_DIALOG_LAYOUT
+IDD_PASSWORD_CREATE AFX_DIALOG_LAYOUT
BEGIN
0
END
diff --git a/protocols/Tox/src/api_av.cpp b/protocols/Tox/src/api_av.cpp
deleted file mode 100644
index c46e549a35..0000000000
--- a/protocols/Tox/src/api_av.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-#include "stdafx.h"
-
-/* COMMON A/V FUNCTIONS */
-
-ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error)
-{
- return CreateFunction<ToxAV*(*)(Tox*, TOXAV_ERR_NEW*)>(__FUNCTION__)(tox, error);
-}
-
-void toxav_kill(ToxAV *toxAV)
-{
- CreateFunction<void(*)(ToxAV*)>(__FUNCTION__)(toxAV);
-}
-
-Tox *toxav_get_tox(const ToxAV *toxAV)
-{
- return CreateFunction<Tox*(*)(const ToxAV*)>(__FUNCTION__)(toxAV);
-}
-
-uint32_t toxav_iteration_interval(ToxAV *toxAV)
-{
- return CreateFunction<uint32_t(*)(ToxAV*)>(__FUNCTION__)(toxAV);
-}
-
-void toxav_iterate(ToxAV *toxAV)
-{
- CreateFunction<void(*)(ToxAV*)>(__FUNCTION__)(toxAV);
-}
-
-bool toxav_call(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL *error)
-{
- return CreateFunction<bool(*)(ToxAV*, int32_t, uint32_t, uint32_t, TOXAV_ERR_CALL*)>(__FUNCTION__)(toxAV, friend_number, audio_bit_rate, video_bit_rate, error);
-}
-
-void toxav_callback_call(ToxAV *toxAV, toxav_call_cb *callback, void *user_data)
-{
- CreateFunction<void(*)(ToxAV*, toxav_call_cb, void*)>(__FUNCTION__)(toxAV, callback, user_data);
-}
-
-bool toxav_answer(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER *error)
-{
- return CreateFunction<bool(*)(ToxAV*, int32_t, uint32_t, uint32_t, TOXAV_ERR_ANSWER*)>(__FUNCTION__)(toxAV, friend_number, audio_bit_rate, video_bit_rate, error);
-}
-
-void toxav_callback_call_state(ToxAV *toxAV, toxav_call_state_cb *callback, void *user_data)
-{
- CreateFunction<void(*)(ToxAV*, toxav_call_state_cb, void*)>(__FUNCTION__)(toxAV, callback, user_data);
-}
-
-bool toxav_call_control(ToxAV *toxAV, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error)
-{
- return CreateFunction<bool(*)(ToxAV*, uint32_t, TOXAV_CALL_CONTROL, TOXAV_ERR_CALL_CONTROL*)>(__FUNCTION__)(toxAV, friend_number, control, error);
-}
-
-bool toxav_bit_rate_set(ToxAV *toxAV, uint32_t friend_number, int32_t audio_bit_rate, int32_t video_bit_rate, TOXAV_ERR_BIT_RATE_SET *error)
-{
- return CreateFunction<bool(*)(ToxAV*, int32_t, uint32_t, uint32_t, TOXAV_ERR_BIT_RATE_SET*)>(__FUNCTION__)(toxAV, friend_number, audio_bit_rate, video_bit_rate, error);
-}
-
-void toxav_callback_bit_rate_status(ToxAV *toxAV, toxav_bit_rate_status_cb *callback, void *user_data)
-{
- CreateFunction<void(*)(ToxAV*, toxav_bit_rate_status_cb, void*)>(__FUNCTION__)(toxAV, callback, user_data);
-}
-
-bool toxav_audio_send_frame(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME *error)
-{
- return CreateFunction<bool(*)(ToxAV*, int32_t, const int16_t*, size_t, uint8_t, uint32_t, TOXAV_ERR_SEND_FRAME*)>(__FUNCTION__)(toxAV, friend_number, pcm, sample_count, channels, sampling_rate, error);
-}
-
-bool toxav_video_send_frame(ToxAV *toxAV, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, TOXAV_ERR_SEND_FRAME *error)
-{
- return CreateFunction<bool(*)(ToxAV*, int32_t, int16_t, uint16_t, const uint8_t*, const uint8_t*, const uint8_t*, TOXAV_ERR_SEND_FRAME*)>(__FUNCTION__)(toxAV, friend_number, width, height, y, u, v, error);
-}
-
-void toxav_callback_audio_receive_frame(ToxAV *toxAV, toxav_audio_receive_frame_cb *callback, void *user_data)
-{
- CreateFunction<void(*)(ToxAV*, toxav_audio_receive_frame_cb, void*)>(__FUNCTION__)(toxAV, callback, user_data);
-}
-
-void toxav_callback_video_receive_frame(ToxAV *toxAV, toxav_video_receive_frame_cb *callback, void *user_data)
-{
- CreateFunction<void(*)(ToxAV*, toxav_video_receive_frame_cb, void*)>(__FUNCTION__)(toxAV, callback, user_data);
-}
-
-int toxav_add_av_groupchat(Tox *tox, void(*audio_callback)(void *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *), void *userdata)
-{
- return CreateFunction<int(*)(Tox*, void(*)(void*, int, int, const int16_t*, unsigned int, uint8_t, unsigned int, void*), void*)>(__FUNCTION__)(tox, audio_callback, userdata);
-}
-
-int toxav_join_av_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length, void(*audio_callback)(void *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *), void *userdata)
-{
- return CreateFunction<int(*)(Tox*, int32_t, const uint8_t*, uint16_t, void(*)(void*, int, int, const int16_t*, unsigned int, uint8_t, unsigned int, void*), void*)>(__FUNCTION__)(tox, friendnumber, data, length, audio_callback, userdata);
-}
-
-int toxav_group_send_audio(Tox *tox, int groupnumber, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate)
-{
- return CreateFunction<int(*)(Tox*, int, const int16_t*, unsigned int, uint8_t, unsigned int)>(__FUNCTION__)(tox, groupnumber, pcm, samples, channels, sample_rate);
-} \ No newline at end of file
diff --git a/protocols/Tox/src/api_avatars.cpp b/protocols/Tox/src/api_avatars.cpp
deleted file mode 100644
index 658b835a68..0000000000
--- a/protocols/Tox/src/api_avatars.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-#include "stdafx.h"
-
-/* AVATAR FUNCTIONS */
-
-void tox_callback_avatar_info(Tox *tox, void(*function)(Tox *tox, int32_t, uint8_t, uint8_t *, void *), void *userdata)
-{
- CreateFunction<int(*)(Tox*, void(*)(Tox*, int32_t, uint8_t, uint8_t*, void*), void*)>(__FUNCTION__)(tox, function, userdata);
-}
-
-void tox_callback_avatar_data(Tox *tox, void(*function)(Tox *tox, int32_t, uint8_t, uint8_t *, uint8_t *, uint32_t, void *), void *userdata)
-{
- CreateFunction<int(*)(Tox*, void(*)(Tox*, int32_t, uint8_t, uint8_t*, uint8_t*, uint32_t, void*), void*)>(__FUNCTION__)(tox, function, userdata);
-}
-
-int tox_set_avatar(Tox *tox, uint8_t format, const uint8_t *data, uint32_t length)
-{
- return CreateFunction<int(*)(Tox*, uint8_t, const uint8_t*, uint32_t)>(__FUNCTION__)(tox, format, data, length);
-}
-
-int tox_unset_avatar(Tox *tox)
-{
- return CreateFunction<int(*)(const Tox*)>(__FUNCTION__)(tox);
-}
-
-int tox_get_self_avatar(const Tox *tox, uint8_t *format, uint8_t *buf, uint32_t *length, uint32_t maxlen, uint8_t *hash)
-{
- return CreateFunction<int(*)(const Tox*, uint8_t*, uint8_t*, uint32_t*, uint32_t, uint8_t*)>(__FUNCTION__)(tox, format, buf, length, maxlen, hash);
-}
-
-int tox_request_avatar_info(const Tox *tox, const int32_t friendnumber)
-{
- return CreateFunction<int(*)(const Tox*, const int32_t)>(__FUNCTION__)(tox, friendnumber);
-}
-
-int tox_send_avatar_info(Tox *tox, const int32_t friendnumber)
-{
- return CreateFunction<int(*)(const Tox*, const int32_t)>(__FUNCTION__)(tox, friendnumber);
-}
-
-int tox_request_avatar_data(const Tox *tox, const int32_t friendnumber)
-{
- return CreateFunction<int(*)(const Tox*, const int32_t)>(__FUNCTION__)(tox, friendnumber);
-} \ No newline at end of file
diff --git a/protocols/Tox/src/api_connection.cpp b/protocols/Tox/src/api_connection.cpp
deleted file mode 100644
index 1ed6b51d40..0000000000
--- a/protocols/Tox/src/api_connection.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "stdafx.h"
-
-/* CONNECTION FUNCTIONS */
-
-bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error)
-{
- return CreateFunction<bool(*)(Tox*, const char*, uint16_t, const uint8_t*, TOX_ERR_BOOTSTRAP*)>(__FUNCTION__)(tox, host, port, public_key, error);
-}
-
-bool tox_add_tcp_relay(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error)
-{
- return CreateFunction<bool(*)(Tox*, const char*, uint16_t, const uint8_t*, TOX_ERR_BOOTSTRAP*)>(__FUNCTION__)(tox, host, port, public_key, error);
-}
-
-TOX_CONNECTION tox_self_get_connection_status(const Tox *tox)
-{
- return CreateFunction<TOX_CONNECTION(*)(const Tox*)>(__FUNCTION__)(tox);
-}
-
-uint32_t tox_iteration_interval(const Tox *tox)
-{
- return CreateFunction<uint32_t(*)(const Tox*)>(__FUNCTION__)(tox);
-}
-
-void tox_iterate(Tox *tox, void *user_data)
-{
- CreateFunction<int(*)(const Tox*, void*)>(__FUNCTION__)(tox, user_data);
-} \ No newline at end of file
diff --git a/protocols/Tox/src/api_dns.cpp b/protocols/Tox/src/api_dns.cpp
deleted file mode 100644
index 57db01e57c..0000000000
--- a/protocols/Tox/src/api_dns.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "stdafx.h"
-
-/* DNS TOXID RESOILVING FUNCTIONS */
-
-void *tox_dns3_new(uint8_t *server_public_key)
-{
- return CreateFunction<void*(*)(uint8_t*)>(__FUNCTION__)(server_public_key);
-}
-
-void tox_dns3_kill(void *dns3_object)
-{
- CreateFunction<void(*)(void*)>(__FUNCTION__)(dns3_object);
-}
-
-int tox_generate_dns3_string(void *dns3_object, uint8_t *string, uint16_t string_max_len, uint32_t *request_id, uint8_t *name, uint8_t name_len)
-{
- return CreateFunction<int(*)(void*, uint8_t*, uint16_t, uint32_t*, uint8_t*, uint8_t)>(__FUNCTION__)(dns3_object, string, string_max_len, request_id, name, name_len);
-}
-
-int tox_decrypt_dns3_TXT(void *dns3_object, uint8_t *tox_id, uint8_t *id_record, uint32_t id_record_len, uint32_t request_id)
-{
- return CreateFunction<int(*)(void*, uint8_t*, uint8_t*, uint32_t, uint32_t)>(__FUNCTION__)(dns3_object, tox_id, id_record, id_record_len, request_id);
-} \ No newline at end of file
diff --git a/protocols/Tox/src/api_encryption.cpp b/protocols/Tox/src/api_encryption.cpp
deleted file mode 100644
index 85e77c06ad..0000000000
--- a/protocols/Tox/src/api_encryption.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#include "stdafx.h"
-
-/* ENCRYPTION FUNCTIONS */
-
-bool tox_pass_decrypt(const uint8_t *data, size_t length, const uint8_t *passphrase, size_t pplength, uint8_t *out, TOX_ERR_DECRYPTION *error)
-{
- return CreateFunction<bool(*)(const uint8_t *, size_t, const uint8_t*, size_t, uint8_t*, TOX_ERR_DECRYPTION*)>(__FUNCTION__)(data, length, passphrase, pplength, out, error);
-}
-
-bool tox_pass_encrypt(const uint8_t *data, size_t data_len, const uint8_t *passphrase, size_t pplength, uint8_t *out, TOX_ERR_ENCRYPTION *error)
-{
- return CreateFunction<bool(*)(const uint8_t *, size_t, const uint8_t*, size_t, uint8_t*, TOX_ERR_ENCRYPTION*)>(__FUNCTION__)(data, data_len, passphrase, pplength, out, error);
-}
-
-bool tox_is_data_encrypted(const uint8_t *data)
-{
- return CreateFunction<bool(*)(const uint8_t*)>(__FUNCTION__)(data);
-} \ No newline at end of file
diff --git a/protocols/Tox/src/api_friends.cpp b/protocols/Tox/src/api_friends.cpp
deleted file mode 100644
index caa133feb7..0000000000
--- a/protocols/Tox/src/api_friends.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-#include "stdafx.h"
-
-/* FRIEND FUNCTIONS */
-
-uint32_t tox_friend_add(Tox *tox, const uint8_t *address, const uint8_t *message, size_t length, TOX_ERR_FRIEND_ADD *error)
-{
- return CreateFunction<uint32_t(*)(Tox*, const uint8_t*, const uint8_t*, size_t, TOX_ERR_FRIEND_ADD*)>(__FUNCTION__)(tox, address, message, length, error);
-}
-
-uint32_t tox_friend_add_norequest(Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_ADD *error)
-{
- return CreateFunction<uint32_t(*)(Tox*, const uint8_t*, TOX_ERR_FRIEND_ADD*)>(__FUNCTION__)(tox, public_key, error);
-}
-
-bool tox_friend_delete(Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_DELETE *error)
-{
- return CreateFunction<bool(*)(Tox*, uint32_t, TOX_ERR_FRIEND_DELETE*)>(__FUNCTION__)(tox, friend_number, error);
-}
-
-uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_BY_PUBLIC_KEY *error)
-{
- return CreateFunction<uint32_t(*)(const Tox*, const uint8_t*, TOX_ERR_FRIEND_BY_PUBLIC_KEY*)>(__FUNCTION__)(tox, public_key, error);
-}
-
-int tox_friend_exists(const Tox *tox, int32_t friendnumber)
-{
- return CreateFunction<int(*)(const Tox*, int32_t)>(__FUNCTION__)(tox, friendnumber);
-}
-
-size_t tox_self_get_friend_list_size(const Tox *tox)
-{
- return CreateFunction<size_t(*)(const Tox*)>(__FUNCTION__)(tox);
-}
-
-void tox_self_get_friend_list(const Tox *tox, uint32_t *list)
-{
- CreateFunction<void(*)(const Tox*, uint32_t*)>(__FUNCTION__)(tox, list);
-}
-
-bool tox_friend_get_public_key(const Tox *tox, uint32_t friend_number, uint8_t *public_key, TOX_ERR_FRIEND_GET_PUBLIC_KEY *error)
-{
- return CreateFunction<bool(*)(const Tox*, int32_t, uint8_t*, TOX_ERR_FRIEND_GET_PUBLIC_KEY*)>(__FUNCTION__)(tox, friend_number, public_key, error);
-}
-
-uint64_t tox_friend_get_last_online(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_GET_LAST_ONLINE *error)
-{
- return CreateFunction<uint64_t(*)(const Tox*, uint32_t, TOX_ERR_FRIEND_GET_LAST_ONLINE*)>(__FUNCTION__)(tox, friend_number, error);
-}
-
-size_t tox_friend_get_name_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
-{
- return CreateFunction<size_t(*)(const Tox*, uint32_t, TOX_ERR_FRIEND_QUERY*)>(__FUNCTION__)(tox, friend_number, error);
-}
-
-bool tox_friend_get_name(const Tox *tox, uint32_t friend_number, uint8_t *name, TOX_ERR_FRIEND_QUERY *error)
-{
- return CreateFunction<bool(*)(const Tox*, uint32_t, uint8_t*, TOX_ERR_FRIEND_QUERY*)>(__FUNCTION__)(tox, friend_number, name, error);
-}
-
-void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *function)
-{
- CreateFunction<void(*)(Tox*tox, tox_friend_name_cb)>(__FUNCTION__)(tox, function);
-}
-
-size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
-{
- return CreateFunction<size_t(*)(const Tox*, uint32_t, TOX_ERR_FRIEND_QUERY*)>(__FUNCTION__)(tox, friend_number, error);
-}
-
-bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8_t *status_message, TOX_ERR_FRIEND_QUERY *error)
-{
- return CreateFunction<bool(*)(const Tox*, uint32_t, uint8_t*, TOX_ERR_FRIEND_QUERY*)>(__FUNCTION__)(tox, friend_number, status_message, error);
-}
-
-void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *function)
-{
- CreateFunction<void(*)(Tox*, tox_friend_status_message_cb)>(__FUNCTION__)(tox, function);
-}
-
-TOX_USER_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
-{
- return CreateFunction<TOX_USER_STATUS(*)(const Tox*, uint32_t, TOX_ERR_FRIEND_QUERY*)>(__FUNCTION__)(tox, friend_number, error);
-}
-
-void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *function)
-{
- CreateFunction<void(*)(Tox*, tox_friend_status_cb)>(__FUNCTION__)(tox, function);
-}
-
-TOX_CONNECTION tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
-{
- return CreateFunction<TOX_CONNECTION(*)(const Tox*, uint32_t, TOX_ERR_FRIEND_QUERY*)>(__FUNCTION__)(tox, friend_number, error);
-}
-
-void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_status_cb *function)
-{
- CreateFunction<void(*)(Tox*, tox_friend_connection_status_cb)>(__FUNCTION__)(tox, function);
-}
-
-bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
-{
- return CreateFunction<bool(*)(const Tox*, uint32_t, TOX_ERR_FRIEND_QUERY*)>(__FUNCTION__)(tox, friend_number, error);
-}
-
-void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *function)
-{
- CreateFunction<void(*)(Tox*, tox_friend_typing_cb)>(__FUNCTION__)(tox, function);
-}
-
-/* */
-
-bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool is_typing, TOX_ERR_SET_TYPING *error)
-{
- return CreateFunction<bool(*)(Tox*, uint32_t, bool, TOX_ERR_SET_TYPING*)>(__FUNCTION__)(tox, friend_number, is_typing, error);
-}
-
-uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, const uint8_t *message, size_t length, TOX_ERR_FRIEND_SEND_MESSAGE *error)
-{
- return CreateFunction<uint32_t(*)(Tox*, uint32_t, TOX_MESSAGE_TYPE, const uint8_t*, size_t, TOX_ERR_FRIEND_SEND_MESSAGE*)>(__FUNCTION__)(tox, friend_number, type, message, length, error);
-}
-
-void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *function)
-{
- CreateFunction<void(*)(Tox*, tox_friend_read_receipt_cb)>(__FUNCTION__)(tox, function);
-}
-
-void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *function)
-{
- CreateFunction<void(*)(Tox*, tox_friend_request_cb)>(__FUNCTION__)(tox, function);
-}
-
-void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *function)
-{
- CreateFunction<void(*)(Tox*, tox_friend_message_cb)>(__FUNCTION__)(tox, function);
-} \ No newline at end of file
diff --git a/protocols/Tox/src/api_groupchats.cpp b/protocols/Tox/src/api_groupchats.cpp
deleted file mode 100644
index 9919eee92c..0000000000
--- a/protocols/Tox/src/api_groupchats.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-#include "stdafx.h"
-
-/* GROUP CHAT FUNCTIONS: WARNING Group chats will be rewritten so this might change */
-
-void tox_callback_group_invite(Tox *tox, void(*function)(Tox *tox, int32_t, uint8_t, const uint8_t *, uint16_t, void *), void *userdata)
-{
- CreateFunction<int(*)(Tox*, void(*)(Tox*, int32_t, uint8_t, const uint8_t*, uint16_t, void*), void*)>(__FUNCTION__)(tox, function, userdata);
-}
-
-/*void tox_callback_group_message(Tox *tox, void(*function)(Tox *tox, int, int, const uint8_t *, uint16_t, void *), void *userdata)
-{
-}
-
-void tox_callback_group_action(Tox *tox, void(*function)(Tox *tox, int, int, const uint8_t *, uint16_t, void *), void *userdata)
-{
-}
-
-void tox_callback_group_title(Tox *tox, void(*function)(Tox *tox, int, int, const uint8_t *, uint8_t, void *), void *userdata)
-{
-}
-
-void tox_callback_group_namelist_change(Tox *tox, void(*function)(Tox *tox, int, int, uint8_t, void *), void *userdata)
-{
-}*/
-
-int tox_add_groupchat(Tox *tox)
-{
- return CreateFunction<int(*)(const Tox*)>(__FUNCTION__)(tox);
-}
-
-int tox_del_groupchat(Tox *tox, int groupnumber)
-{
- return CreateFunction<int(*)(Tox*, int)>(__FUNCTION__)(tox, groupnumber);
-}
-
-/*int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t *name)
-{
-}
-
-int tox_group_peer_pubkey(const Tox *tox, int groupnumber, int peernumber, uint8_t *pk)
-{
-}*/
-
-int tox_invite_friend(Tox *tox, int32_t friendnumber, int groupnumber)
-{
- return CreateFunction<int(*)(Tox*, int32_t, int)>(__FUNCTION__)(tox, friendnumber, groupnumber);
-}
-
-int tox_join_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length)
-{
- return CreateFunction<int(*)(Tox*, int32_t, const uint8_t*, uint32_t)>(__FUNCTION__)(tox, friendnumber, data, length);
-}
-
-/*int tox_group_message_send(Tox *tox, int groupnumber, const uint8_t *message, uint16_t length)
-{
-}
-
-int tox_group_action_send(Tox *tox, int groupnumber, const uint8_t *action, uint16_t length)
-{
-}
-
-int tox_group_set_title(Tox *tox, int groupnumber, const uint8_t *title, uint8_t length)
-{
-}*/
-
-int tox_group_get_title(Tox *tox, int groupnumber, uint8_t *title, uint32_t max_length)
-{
- return CreateFunction<int(*)(Tox*, int, uint8_t*, uint32_t)>(__FUNCTION__)(tox, groupnumber, title, max_length);
-}
-
-/*unsigned int tox_group_peernumber_is_ours(const Tox *tox, int groupnumber, int peernumber)
-{
-}
-
-int tox_group_number_peers(const Tox *tox, int groupnumber)
-{
-}
-
-int tox_group_get_names(const Tox *tox, int groupnumber, uint8_t names[][TOX_MAX_NAME_LENGTH], uint16_t lengths[], uint16_t length)
-{
-}*/
-
-uint32_t tox_count_chatlist(const Tox *tox)
-{
- return CreateFunction<int(*)(const Tox*)>(__FUNCTION__)(tox);
-}
-
-uint32_t tox_get_chatlist(const Tox *tox, int32_t *out_list, uint32_t list_size)
-{
- return CreateFunction<int(*)(const Tox*, int32_t*, uint32_t)>(__FUNCTION__)(tox, out_list, list_size);
-}
-
-int tox_group_get_type(const Tox *tox, int groupnumber)
-{
- return CreateFunction<int(*)(const Tox*, int)>(__FUNCTION__)(tox, groupnumber);
-} \ No newline at end of file
diff --git a/protocols/Tox/src/api_main.cpp b/protocols/Tox/src/api_main.cpp
deleted file mode 100644
index 3d46576925..0000000000
--- a/protocols/Tox/src/api_main.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-#include "stdafx.h"
-
-/* MAIN FUNCTIONS */
-
-bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch)
-{
- return CreateFunction<bool(*)(uint32_t, uint32_t, uint32_t)>(__FUNCTION__)(major, minor, patch);
-}
-
-struct Tox_Options *tox_options_new(TOX_ERR_OPTIONS_NEW *error)
-{
- return CreateFunction<struct Tox_Options*(*)(TOX_ERR_OPTIONS_NEW*)>(__FUNCTION__)(error);
-}
-
-void tox_options_default(struct Tox_Options *options)
-{
- CreateFunction<void(*)(struct Tox_Options*)>(__FUNCTION__)(options);
-}
-
-void tox_options_free(struct Tox_Options *options)
-{
- CreateFunction<void(*)(struct Tox_Options*)>(__FUNCTION__)(options);
-}
-
-Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error)
-{
- return CreateFunction<Tox*(*)(const struct Tox_Options*, TOX_ERR_NEW*)>(__FUNCTION__)(options, error);
-}
-
-void tox_kill(Tox *tox)
-{
- CreateFunction<int(*)(Tox*)>(__FUNCTION__)(tox);
-}
-
-void tox_self_get_address(const Tox *tox, uint8_t *address)
-{
- CreateFunction<void(*)(const Tox*, uint8_t*)>(__FUNCTION__)(tox, address);
-}
-
-bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, TOX_ERR_SET_INFO *error)
-{
- return CreateFunction<bool(*)(Tox*, const uint8_t*, size_t, TOX_ERR_SET_INFO*)>(__FUNCTION__)(tox, name, length, error);
-}
-
-void tox_self_get_name(const Tox *tox, uint8_t *name)
-{
- CreateFunction<void(*)(const Tox*, uint8_t*)>(__FUNCTION__)(tox, name);
-}
-
-int tox_get_self_name_size(const Tox *tox)
-{
- return CreateFunction<int(*)(const Tox*)>(__FUNCTION__)(tox);
-}
-
-size_t tox_self_get_status_message_size(const Tox *tox)
-{
- return CreateFunction<size_t(*)(const Tox*)>(__FUNCTION__)(tox);
-}
-
-bool tox_self_set_status_message(Tox *tox, const uint8_t *status, size_t length, TOX_ERR_SET_INFO *error)
-{
- return CreateFunction<bool(*)(Tox*, const uint8_t*, size_t, TOX_ERR_SET_INFO*)>(__FUNCTION__)(tox, status, length, error);
-}
-
-void tox_self_set_status(Tox *tox, TOX_USER_STATUS user_status)
-{
- CreateFunction<void(*)(Tox*, TOX_USER_STATUS)>(__FUNCTION__)(tox, user_status);
-}
-
-void tox_self_get_status_message(const Tox *tox, uint8_t *status)
-{
- CreateFunction<void(*)(const Tox*, uint8_t*)>(__FUNCTION__)(tox, status);
-}
-
-int tox_get_self_status_message(const Tox *tox, uint8_t *buf, uint32_t maxlen)
-{
- return CreateFunction<int(*)(const Tox*, uint8_t*, uint32_t)>(__FUNCTION__)(tox, buf, maxlen);
-}
-
-uint8_t tox_get_self_user_status(const Tox *tox)
-{
- return CreateFunction<int(*)(const Tox*)>(__FUNCTION__)(tox);
-}
-
-/* SAVING AND LOADING FUNCTIONS */
-
-size_t tox_get_savedata_size(const Tox *tox)
-{
- return CreateFunction<size_t(*)(const Tox*)>(__FUNCTION__)(tox);
-}
-
-void tox_get_savedata(const Tox *tox, uint8_t *data)
-{
- CreateFunction<int(*)(const Tox*, uint8_t*)>(__FUNCTION__)(tox, data);
-}
-
-int tox_load(Tox *tox, const uint8_t *data, uint32_t length)
-{
- return CreateFunction<int(*)(Tox*, const uint8_t*, uint32_t)>(__FUNCTION__)(tox, data, length);
-}
-
-/* ADVANCED FUNCTIONS (If you don't know what they do you can safely ignore them.) */
-/*
-uint32_t tox_get_nospam(const Tox *tox)
-{
-}
-
-void tox_set_nospam(Tox *tox, uint32_t nospam)
-{
-}
-
-void tox_get_keys(Tox *tox, uint8_t *public_key, uint8_t *secret_key)
-{
-}
-
-int tox_lossy_packet_registerhandler(Tox *tox, int32_t friendnumber, uint8_t byte, int(*packet_handler_callback)(Tox *tox, int32_t friendnumber, const uint8_t *data, uint32_t len, void *object), void *object)
-{
-}
-
-int tox_send_lossy_packet(const Tox *tox, int32_t friendnumber, const uint8_t *data, uint32_t length)
-{
-}
-
-int tox_lossless_packet_registerhandler(Tox *tox, int32_t friendnumber, uint8_t byte, int(*packet_handler_callback)(Tox *tox, int32_t friendnumber, const uint8_t *data, uint32_t len, void *object), void *object)
-{
-}
-
-int tox_send_lossless_packet(const Tox *tox, int32_t friendnumber, const uint8_t *data, uint32_t length)
-{
-}
-*/ \ No newline at end of file
diff --git a/protocols/Tox/src/api_transfer.cpp b/protocols/Tox/src/api_transfer.cpp
deleted file mode 100644
index 446a2ccc80..0000000000
--- a/protocols/Tox/src/api_transfer.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-#include "stdafx.h"
-
-/* FILE SENDING FUNCTIONS */
-
-bool tox_hash(uint8_t *hash, const uint8_t *data, size_t datalen)
-{
- return CreateFunction<bool(*)(uint8_t*, const uint8_t*, size_t)>(__FUNCTION__)(hash, data, datalen);
-}
-
-bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id, TOX_ERR_FILE_GET *error)
-{
- return CreateFunction<bool(*)(const Tox*, uint32_t, uint32_t, uint8_t*, TOX_ERR_FILE_GET*)>(__FUNCTION__)(tox, friend_number, file_number, file_id, error);
-}
-
-uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *file_id, const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error)
-{
- return CreateFunction<uint32_t(*)(Tox*, uint32_t, uint32_t, uint64_t, const uint8_t*, const uint8_t*, size_t, TOX_ERR_FILE_SEND*)>(__FUNCTION__)(tox, friend_number, kind, file_size, file_id, filename, filename_length, error);
-}
-
-bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t *data, size_t length, TOX_ERR_FILE_SEND_CHUNK *error)
-{
- return CreateFunction<bool(*)(Tox*, uint32_t, uint32_t, uint64_t, const uint8_t*, size_t, TOX_ERR_FILE_SEND_CHUNK*)>(__FUNCTION__)(tox, friend_number, file_number, position, data, length, error);
-}
-
-void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *function)
-{
- CreateFunction<void(*)(Tox*, tox_file_chunk_request_cb)>(__FUNCTION__)(tox, function);
-}
-
-void tox_callback_file_recv(Tox *tox, tox_file_recv_cb *function)
-{
- CreateFunction<void(*)(Tox*, tox_file_recv_cb)>(__FUNCTION__)(tox, function);
-}
-
-void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function)
-{
- CreateFunction<void(*)(Tox*, tox_file_recv_control_cb)>(__FUNCTION__)(tox, function);
-}
-
-void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *function)
-{
- CreateFunction<void(*)(Tox*, tox_file_recv_chunk_cb)>(__FUNCTION__)(tox, function);
-}
-
-bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control, TOX_ERR_FILE_CONTROL *error)
-{
- return CreateFunction<bool(*)(Tox*, uint32_t, uint32_t, TOX_FILE_CONTROL, TOX_ERR_FILE_CONTROL*)>(__FUNCTION__)(tox, friend_number, file_number, control, error);
-}
-
-int tox_file_send_data(Tox *tox, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length)
-{
- return CreateFunction<int(*)(Tox*, int32_t, uint8_t, const uint8_t*, uint16_t)>(__FUNCTION__)(tox, friendnumber, filenumber, data, length);
-}
-
-int tox_file_data_size(const Tox *tox, int32_t friendnumber)
-{
- return CreateFunction<int(*)(const Tox*, int32_t)>(__FUNCTION__)(tox, friendnumber);
-}
-
-uint64_t tox_file_data_remaining(const Tox *tox, int32_t friendnumber, uint8_t filenumber, uint8_t send_receive)
-{
- return CreateFunction<int(*)(const Tox*, int32_t, uint8_t, uint8_t)>(__FUNCTION__)(tox, friendnumber, filenumber, send_receive);
-} \ No newline at end of file
diff --git a/protocols/Tox/src/main.cpp b/protocols/Tox/src/main.cpp
index de5356a18a..99cd7607a1 100644
--- a/protocols/Tox/src/main.cpp
+++ b/protocols/Tox/src/main.cpp
@@ -4,7 +4,7 @@ int hLangpack;
CHAT_MANAGER *pci;
CLIST_INTERFACE *pcli;
HINSTANCE g_hInstance;
-HMODULE g_hToxLibrary = nullptr;
+HANDLE hProfileFolderPath;
PLUGININFOEX pluginInfo =
{
@@ -13,7 +13,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
@@ -35,24 +34,26 @@ extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD)
extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_PROTOCOL, MIID_LAST };
-extern "C" int __declspec(dllexport) Load(void)
+int OnModulesLoaded(WPARAM, LPARAM)
{
- g_hToxLibrary = LoadLibrary(TOX_LIBRARY);
- if (g_hToxLibrary == nullptr)
- return 1;
+ CToxProto::InitIcons();
+ CToxProto::InitContactMenu();
+
+ hProfileFolderPath = FoldersRegisterCustomPathT("Tox", "ProfilesFolder", MIRANDA_USERDATAT, TranslateT("Profiles folder"));
- if (!TOX_VERSION_IS_ABI_COMPATIBLE())
- {
- wchar_t message[100];
- mir_snwprintf(message, TranslateT("Current version of plugin is support Tox API version %i.%i.%i which is incompatible with %s"), TOX_VERSION_MAJOR, TOX_VERSION_MINOR, TOX_VERSION_PATCH, TOX_LIBRARY);
- CToxProto::ShowNotification(message, MB_ICONERROR);
- FreeLibrary(g_hToxLibrary);
- return 2;
+ if (ServiceExists(MS_ASSOCMGR_ADDNEWURLTYPE)) {
+ CreateServiceFunction(MODULE "/ParseUri", CToxProto::ParseToxUri);
+ AssocMgr_AddNewUrlTypeT("tox:", TranslateT("Tox URI scheme"), g_hInstance, IDI_TOX, MODULE "/ParseUri", 0);
}
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Load(void)
+{
+ mir_getLP(&pluginInfo);
pci = Chat_GetInterface();
pcli = Clist_GetInterface();
- mir_getLP(&pluginInfo);
PROTOCOLDESCRIPTOR pd = { 0 };
pd.cbSize = sizeof(pd);
@@ -62,15 +63,12 @@ extern "C" int __declspec(dllexport) Load(void)
pd.fnUninit = (pfnUninitProto)CToxProto::UninitAccount;
Proto_RegisterModule(&pd);
- HookEvent(ME_SYSTEM_MODULESLOADED, &CToxProto::OnModulesLoaded);
+ HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded);
return 0;
}
extern "C" int __declspec(dllexport) Unload(void)
{
- if (g_hToxLibrary)
- FreeLibrary(g_hToxLibrary);
-
return 0;
} \ No newline at end of file
diff --git a/protocols/Tox/src/resource.h b/protocols/Tox/src/resource.h
index 78d9fad660..4ea9d24d31 100644
--- a/protocols/Tox/src/resource.h
+++ b/protocols/Tox/src/resource.h
@@ -1,73 +1,61 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
-// Used by C:\Users\unsane\Projects\c++\miranda-ng\protocols\Tox\res\resource.rc
+// Used by D:\Projects\c++\miranda-ng\protocols\Tox\res\resource.rc
//
#define IDI_TOX 100
#define IDD_USER_INFO 101
-#define IDD_PASSWORD 102
+#define IDD_PASSWORD_ENTER 102
+#define IDD_PASSWORD_CHANGE 103
#define IDD_ACCOUNT_MANAGER 104
#define IDD_SEARCH 105
#define IDD_OPTIONS_MAIN 106
#define IDD_OPTIONS_NODES 107
+#define IDD_PASSWORD_CHANGE2 107
#define IDD_ADDNODE 108
#define IDD_NODE_EDITOR 109
-#define IDD_OPTIONS_MULTIMEDIA 110
-#define IDD_CALL 111
-#define IDI_AUDIO_END 112
-#define IDI_AUDIO_RING 113
-#define IDI_AUDIO_START 114
-#define IDI_AUDIO_CALL 115
-#define IDD_CHATROOM_INVITE 172
-#define IDC_CCLIST 173
+#define IDD_PASSWORD_CREATE 110
#define IDC_EDITSCR 174
-#define IDD_CALL_RECEIVE 175
-#define IDD_CALL_SEND 176
#define IDC_TOXID 1001
#define IDC_CLIPBOARD 1002
#define IDC_SEARCH 1003
#define IDC_PASSWORD 1004
#define IDC_NAME 1005
-#define IDC_FROM 1005
#define IDC_GROUP 1006
-#define IDC_DATE 1006
#define IDC_ENABLE_UDP 1007
#define IDC_ENABLE_IPV6 1008
#define IDC_PROFILE_EXPORT 1009
-#define IDC_NAME2 1009
#define IDC_DNS_ID 1010
+#define IDC_ENABLE_HOLEPUNCHING 1010
#define IDC_PROFILE_NEW 1011
-#define IDC_SAVEPERMANENT 1012
+#define IDC_ENABLE_LOCALDISCOVERY 1012
#define IDC_PROFILE_IMPORT 1013
#define IDC_SAVEPERMANENTLY 1014
#define IDC_NODESLIST 1015
#define IDC_ADDNODE 1016
#define IDC_IPV4 1017
#define IDC_IPV6 1018
+#define IDC_PASSWORD_REMOVE 1018
#define IDC_PORT 1019
+#define IDC_PASSWORD_CHANGE 1019
#define IDC_PKEY 1020
-#define IDC_COMBO_AUDIOINPUT 1021
-#define IDC_AUDIOINPUT 1021
-#define IDC_COMBO_AUDIOOUTPUT 1022
-#define IDC_AUDIOOUTPUT 1022
-#define IDC_AUDIOFILTER 1023
-#define IDC_COMBO_VIDEOINPUT 1024
+#define IDC_PASSWORD_CHANGE2 1020
+#define IDC_PASSWORD_CREATE 1020
+#define IDC_UPDATENODES 1021
#define IDC_MAXCONNECTRETRIES 1025
#define IDC_MAXRECONNECTRETRIES 1026
#define IDC_MAXCONNECTRETRIESSPIN 1027
#define IDC_MAXRECONNECTRETRIESSPIN 1028
-#define IDC_DETAILS 1069
-#define IDC_USERMENU 1071
-#define IDC_HISTORY 1080
-#define IDC_UPDATENODES 1081
-#define IDC_PROTOCOL 1580
+#define IDC_PASSWORD_NEW 1029
+#define IDC_PASSWORD_CONFIRM 1030
+#define IDC_PASSWORD_VALIDATION 1031
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 117
+#define _APS_NEXT_RESOURCE_VALUE 118
#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1029
+#define _APS_NEXT_CONTROL_VALUE 1032
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
diff --git a/protocols/Tox/src/stdafx.h b/protocols/Tox/src/stdafx.h
index c403b787ce..501eeb96cf 100644
--- a/protocols/Tox/src/stdafx.h
+++ b/protocols/Tox/src/stdafx.h
@@ -7,13 +7,6 @@
#include <commctrl.h>
#include <msapi/comptr.h>
-#include <mmreg.h>
-#include <MMDeviceAPI.h>
-
-#define EXIT_ON_ERROR(hres) if (FAILED(hres)) { goto Exit; }
-
-DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14);
-
#include <vector>
#include <regex>
#include <map>
@@ -30,7 +23,7 @@ DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0
#include <m_popup.h>
#include <m_icolib.h>
#include <m_userinfo.h>
-#include <m_addcontact.h>
+#include <m_contacts.h>
#include <m_message.h>
#include <m_avatars.h>
#include <m_skin.h>
@@ -45,7 +38,6 @@ DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0
#include <m_http.h>
#include <tox.h>
-#include <ToxAV.h>
#include <toxdns.h>
#include <toxencryptsave.h>
@@ -60,8 +52,6 @@ struct CToxProto;
#include "tox_profile.h"
#include "tox_options.h"
#include "tox_transfer.h"
-#include "tox_multimedia.h"
-#include "tox_chatrooms.h"
#include "tox_proto.h"
#include "http_request.h"
@@ -79,14 +69,13 @@ extern HINSTANCE g_hInstance;
#define TOX_MAX_CONNECT_RETRIES 10
#define TOX_MAX_RECONNECT_RETRIES 10
-#define TOX_MAX_CALLS 1
-
#define TOX_INI_PATH "%miranda_path%\\Plugins\\tox.ini"
#define TOX_JSON_PATH "%miranda_userdata%\\tox.json"
#define TOX_SETTINGS_ID "ToxID"
#define TOX_SETTINGS_DNS "DnsID"
#define TOX_SETTINGS_CHAT_ID "ChatID"
+#define TOX_SETTINGS_PASSWORD "Password"
#define TOX_SETTINGS_GROUP "DefaultGroup"
#define TOX_SETTINGS_AVATAR_HASH "AvatarHash"
@@ -97,23 +86,9 @@ extern HINSTANCE g_hInstance;
#define TOX_SETTINGS_NODE_PKEY TOX_SETTINGS_NODE_PREFIX"%d_PubKey"
#define TOX_SETTINGS_NODE_COUNT TOX_SETTINGS_NODE_PREFIX"Count"
-enum TOX_DB_EVENT
-{
- DB_EVENT_ACTION = 10001,
- DB_EVENT_CALL = 20001
-};
-
-#define PSR_AUDIO "/RecvAudio"
-
+#define DB_EVENT_ACTION 10001
#define TOX_MAX_AVATAR_SIZE 1 << 16 // 2 ^ 16 bytes
-#define TOX_LIBRARY L"libtox.dll"
-extern HMODULE g_hToxLibrary;
-
-template<typename T>
-T CreateFunction(LPCSTR functionName)
-{
- return reinterpret_cast<T>(GetProcAddress(g_hToxLibrary, functionName));
-}
+extern HANDLE hProfileFolderPath;
#endif //_COMMON_H_ \ No newline at end of file
diff --git a/protocols/Tox/src/tox_accounts.cpp b/protocols/Tox/src/tox_accounts.cpp
index b1bfa58490..866a0dbd3b 100644
--- a/protocols/Tox/src/tox_accounts.cpp
+++ b/protocols/Tox/src/tox_accounts.cpp
@@ -36,19 +36,18 @@ int CToxProto::OnAccountLoaded(WPARAM, LPARAM)
HookProtoEvent(ME_MSG_PRECREATEEVENT, &CToxProto::OnPreCreateMessage);
InitCustomDbEvents();
-
return 0;
}
int CToxProto::OnAccountRenamed(WPARAM, LPARAM)
{
- mir_cslock locker(profileLock);
+ mir_cslock lock(m_profileLock);
ptrW newPath(GetToxProfilePath());
wchar_t oldPath[MAX_PATH];
- mir_snwprintf(oldPath, MAX_PATH, L"%s\\%s.tox", VARSW(L"%miranda_userdata%"), wszAccountName);
+ mir_snwprintf(oldPath, MAX_PATH, L"%s\\%s.tox", VARSW(L"%miranda_userdata%"), m_accountName);
_wrename(oldPath, newPath);
- wszAccountName = mir_wstrdup(m_tszUserName);
+ m_accountName = mir_wstrdup(m_tszUserName);
return 0;
}
diff --git a/protocols/Tox/src/tox_avatars.cpp b/protocols/Tox/src/tox_avatars.cpp
index 3e41c796f6..9d234b1dd8 100644
--- a/protocols/Tox/src/tox_avatars.cpp
+++ b/protocols/Tox/src/tox_avatars.cpp
@@ -77,7 +77,7 @@ void CToxProto::SetToxAvatar(const wchar_t* path)
debugLogA(__FUNCTION__": send avatar to friend (%d)", friendNumber);
TOX_ERR_FILE_SEND error;
- uint32_t fileNumber = tox_file_send(toxThread->Tox(), friendNumber, TOX_FILE_KIND_AVATAR, length, hash, nullptr, 0, &error);
+ uint32_t fileNumber = tox_file_send(m_toxThread->Tox(), friendNumber, TOX_FILE_KIND_AVATAR, length, hash, nullptr, 0, &error);
if (error != TOX_ERR_FILE_SEND_OK) {
mir_free(data);
debugLogA(__FUNCTION__": failed to set new avatar (%d)", error);
@@ -173,7 +173,7 @@ INT_PTR CToxProto::SetMyAvatar(WPARAM, LPARAM lParam)
debugLogA(__FUNCTION__": unset avatar for friend (%d)", friendNumber);
TOX_ERR_FILE_SEND error;
- tox_file_send(toxThread->Tox(), friendNumber, TOX_FILE_KIND_AVATAR, 0, nullptr, nullptr, 0, &error);
+ tox_file_send(m_toxThread->Tox(), friendNumber, TOX_FILE_KIND_AVATAR, 0, nullptr, nullptr, 0, &error);
if (error != TOX_ERR_FILE_SEND_OK) {
debugLogA(__FUNCTION__": failed to unset avatar (%d)", error);
return 0;
diff --git a/protocols/Tox/src/tox_bootstrap.cpp b/protocols/Tox/src/tox_bootstrap.cpp
index 5f1ae93dc1..f144c0af16 100644
--- a/protocols/Tox/src/tox_bootstrap.cpp
+++ b/protocols/Tox/src/tox_bootstrap.cpp
@@ -2,7 +2,7 @@
void CToxProto::BootstrapUdpNode(Tox *tox, const char *address, int port, const char *hexKey)
{
- if (!toxThread)
+ if (!m_toxThread)
return;
if (address == nullptr || hexKey == nullptr)
@@ -16,7 +16,7 @@ void CToxProto::BootstrapUdpNode(Tox *tox, const char *address, int port, const
void CToxProto::BootstrapTcpRelay(Tox *tox, const char *address, int port, const char *hexKey)
{
- if (!toxThread)
+ if (!m_toxThread)
return;
if (address == nullptr || hexKey == nullptr)
diff --git a/protocols/Tox/src/tox_chatrooms.cpp b/protocols/Tox/src/tox_chatrooms.cpp
deleted file mode 100644
index 5ca9895fcb..0000000000
--- a/protocols/Tox/src/tox_chatrooms.cpp
+++ /dev/null
@@ -1,326 +0,0 @@
-#include "stdafx.h"
-/*
-MCONTACT CToxProto::GetChatRoom(int groupNumber)
-{
- MCONTACT hContact = NULL;
- for (hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName))
- {
- if (!isChatRoom(hContact))
- {
- continue;
- }
- int chatRoumNumber = getWord(hContact, TOX_SETTINGS_CHAT_ID, TOX_ERROR);
- if (groupNumber == chatRoumNumber)
- {
- break;
- }
- }
- return hContact;
-}
-
-MCONTACT CToxProto::AddChatRoom(int groupNumber)
-{
- MCONTACT hContact = GetChatRoom(groupNumber);
- if (!hContact)
- {
- hContact = db_add_contact();
- Proto_AddToContact(hContact, m_szModuleName);
-
- setWord(hContact, TOX_SETTINGS_CHAT_ID, groupNumber);
-
- wchar_t title[MAX_PATH];
- mir_snwprintf(title, L"%s #%d", TranslateT("Group chat"), groupNumber);
- setWString(hContact, "Nick", title);
-
- DBVARIANT dbv;
- if (!db_get_s(NULL, "Chat", "AddToGroup", &dbv, DBVT_WCHAR))
- {
- db_set_ws(hContact, "CList", "Group", dbv.ptszVal);
- db_free(&dbv);
- }
-
- setByte(hContact, "ChatRoom", 1);
- }
- return hContact;
-}
-
-void CToxProto::LoadChatRoomList(void*)
-{
- uint32_t count = tox_count_chatlist(toxThread->Tox());
- if (count == 0)
- {
- debugLogA(__FUNCTION__": your group chat list is empty");
- return;
- }
- int32_t *groupChats = (int32_t*)mir_alloc(count * sizeof(int32_t));
- tox_get_chatlist(toxThread->Tox(), groupChats, count);
- for (uint32_t i = 0; i < count; i++)
- {
- int32_t groupNumber = groupChats[i];
- int type = tox_group_get_type(toxThread->Tox(), groupNumber);
- if (type == TOX_GROUPCHAT_TYPE_AV)
- {
- continue;
- }
- MCONTACT hContact = AddChatRoom(groupNumber);
- if (hContact)
- {
- uint8_t title[TOX_MAX_NAME_LENGTH] = { 0 };
- tox_group_get_title(toxThread->Tox(), groupNumber, title, TOX_MAX_NAME_LENGTH);
- setWString(hContact, "Nick", ptrW(mir_utf8decodeW((char*)title)));
- }
- }
- mir_free(groupChats);
-}
-
-int CToxProto::OnGroupChatEventHook(WPARAM, LPARAM lParam)
-{
- GCHOOK *gch = (GCHOOK*)lParam;
- if (!gch)
- {
- return 1;
- }
- else
- return 0;
-}
-
-int CToxProto::OnGroupChatMenuHook(WPARAM, LPARAM)
-{
- return 0;
-}
-
-INT_PTR CToxProto::OnJoinChatRoom(WPARAM, LPARAM)
-{
- return 0;
-}
-
-INT_PTR CToxProto::OnLeaveChatRoom(WPARAM, LPARAM)
-{
- return 0;
-}
-
-INT_PTR CToxProto::OnCreateChatRoom(WPARAM, LPARAM)
-{
- ChatRoomInviteParam param = { this };
-
- if (DialogBoxParam(
- g_hInstance,
- MAKEINTRESOURCE(IDD_CHATROOM_INVITE),
- NULL,
- CToxProto::ChatRoomInviteProc,
- (LPARAM)&param) == IDOK && !param.invitedContacts.empty())
- {
- int groupNumber = tox_add_groupchat(toxThread->Tox());
- if (groupNumber == TOX_ERROR)
- {
- return 1;
- }
- for (std::vector<MCONTACT>::iterator it = param.invitedContacts.begin(); it != param.invitedContacts.end(); ++it)
- {
- int32_t friendNumber = GetToxFriendNumber(*it);
- if (friendNumber == TOX_ERROR || tox_invite_friend(toxThread->Tox(), friendNumber, groupNumber) == TOX_ERROR)
- {
- return 1;
- }
- }
- MCONTACT hContact = AddChatRoom(groupNumber);
- if (!hContact)
- {
- return 1;
- }
- return 0;
- }
-
- return 1;
-}
-
-void CToxProto::InitGroupChatModule()
-{
- GCREGISTER gcr = {};
- gcr.iMaxText = 0;
- gcr.ptszDispName = this->m_tszUserName;
- gcr.pszModule = this->m_szModuleName;
- Chat_Register(&gcr);
-
- HookProtoEvent(ME_GC_EVENT, &CToxProto::OnGroupChatEventHook);
- HookProtoEvent(ME_GC_BUILDMENU, &CToxProto::OnGroupChatMenuHook);
-
- CreateProtoService(PS_JOINCHAT, &CToxProto::OnJoinChatRoom);
- CreateProtoService(PS_LEAVECHAT, &CToxProto::OnLeaveChatRoom);
-}
-
-void CToxProto::CloseAllChatChatSessions()
-{
- GC_INFO gci = { 0 };
- gci.Flags = GCF_BYINDEX | GCF_ID;
- gci.pszModule = m_szModuleName;
-
- int count = pci->SM_GetCount(m_szModuleName);
- for (int i = 0; i < count; i++)
- {
- gci.iItem = i;
- if (!Chat_GetInfo(&gci))
- {
- Chat_Control(m_szModuleName, gci.pszID, SESSION_OFFLINE);
- Chat_Terminate(m_szModuleName, gci.pszID);
- }
- }
-}
-
-void CToxProto::OnGroupChatInvite(Tox *tox, int32_t friendNumber, uint8_t type, const uint8_t *data, uint16_t length, void *arg)
-{
- CToxProto *proto = (CToxProto*)arg;
-
- if (type == TOX_GROUPCHAT_TYPE_AV)
- {
- Netlib_Logf(proto->m_hNetlibUser, __FUNCTION__": audio chat is not supported yet");
- return;
- }
-
- int groupNumber = tox_join_groupchat(tox, friendNumber, data, length);
- if (groupNumber == TOX_ERROR)
- {
- Netlib_Logf(proto->m_hNetlibUser, __FUNCTION__": failed to join to group chat");
- return;
- }
-
- MCONTACT hContact = proto->AddChatRoom(groupNumber);
- if (!hContact)
- {
- Netlib_Logf(proto->m_hNetlibUser, __FUNCTION__": failed to create group chat");
- }
-}
-
-void CToxProto::ChatValidateContact(HWND hwndList, const std::vector<MCONTACT> &contacts, MCONTACT hContact)
-{
- bool isProtoContact = mir_strcmpi(GetContactProto(hContact), m_szModuleName) == 0;
- if (isProtoContact && !isChatRoom(hContact))
- {
- if (std::find(contacts.begin(), contacts.end(), hContact) != contacts.end())
- {
- SendMessage(hwndList, CLM_DELETEITEM, (WPARAM)hContact, 0);
- }
- return;
- }
- SendMessage(hwndList, CLM_DELETEITEM, (WPARAM)hContact, 0);
-}
-
-void CToxProto::ChatPrepare(HWND hwndList, const std::vector<MCONTACT> &contacts, MCONTACT hContact)
-{
- if (hContact == NULL)
- {
- hContact = (MCONTACT)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_ROOT, 0);
- }
- while (hContact)
- {
- if (IsHContactGroup(hContact))
- {
- MCONTACT hSubContact = (MCONTACT)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hContact);
- if (hSubContact)
- {
- ChatPrepare(hwndList, contacts, hSubContact);
- }
- }
- else if (IsHContactContact(hContact))
- {
- ChatValidateContact(hwndList, contacts, hContact);
- }
- hContact = (MCONTACT)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXT, (LPARAM)hContact);
- }
-}
-
-std::vector<MCONTACT> CToxProto::GetInvitedContacts(HWND hwndList, MCONTACT hContact)
-{
- std::vector<MCONTACT> contacts;
- if (hContact == NULL)
- {
- hContact = (MCONTACT)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_ROOT, 0);
- }
- while (hContact)
- {
- if (IsHContactGroup(hContact))
- {
- MCONTACT hSubContact = (MCONTACT)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hContact);
- if (hSubContact)
- {
- std::vector<MCONTACT> subContacts = GetInvitedContacts(hwndList, hSubContact);
- contacts.insert(contacts.end(), subContacts.begin(), subContacts.end());
- }
- }
- else
- {
- int cheked = SendMessage(hwndList, CLM_GETCHECKMARK, (WPARAM)hContact, 0);
- if (cheked)
- {
- contacts.push_back(hContact);
- }
- }
- hContact = (MCONTACT)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXT, (LPARAM)hContact);
- }
- return contacts;
-}
-
-INT_PTR CALLBACK CToxProto::ChatRoomInviteProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- HWND hwndList = GetDlgItem(hwndDlg, IDC_CCLIST);
- ChatRoomInviteParam *param = (ChatRoomInviteParam*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-
- switch (msg) {
- case WM_INITDIALOG:
- TranslateDialogDefault(hwndDlg);
- {
- param = (ChatRoomInviteParam*)lParam;
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
- {
- //HWND hwndClist = GetDlgItem(hwndDlg, IDC_CCLIST);
- //SetWindowLongPtr(hwndClist, GWL_STYLE, GetWindowLongPtr(hwndClist, GWL_STYLE) & ~CLS_HIDEOFFLINE);
- }
- }
- break;
-
- case WM_CLOSE:
- EndDialog(hwndDlg, 0);
- break;
-
- case WM_NOTIFY:
- {
- NMCLISTCONTROL *nmc = (NMCLISTCONTROL*)lParam;
- if (nmc->hdr.idFrom == IDC_CCLIST)
- {
- switch (nmc->hdr.code)
- {
- case CLN_NEWCONTACT:
- if ((nmc->flags & (CLNF_ISGROUP | CLNF_ISINFO)) == 0)
- {
- param->proto->ChatValidateContact(nmc->hdr.hwndFrom, param->invitedContacts, (UINT_PTR)nmc->hItem);
- }
- break;
-
- case CLN_LISTREBUILT:
- {
- param->proto->ChatPrepare(nmc->hdr.hwndFrom, param->invitedContacts);
- }
- break;
- }
- }
- }
- break;
-
- case WM_COMMAND:
- switch (LOWORD(wParam))
- {
- case IDOK:
- //SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
- param->invitedContacts = param->proto->GetInvitedContacts(hwndList);
- EndDialog(hwndDlg, IDOK);
- break;
-
- case IDCANCEL:
- EndDialog(hwndDlg, IDCANCEL);
- break;
- }
- break;
- }
- return FALSE;
-}
-*/ \ No newline at end of file
diff --git a/protocols/Tox/src/tox_chatrooms.h b/protocols/Tox/src/tox_chatrooms.h
deleted file mode 100644
index 0f51a7391e..0000000000
--- a/protocols/Tox/src/tox_chatrooms.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _TOX_CHATROOMS_H_
-#define _TOX_CHATROOMS_H_
-
-struct ChatRoomInviteParam
-{
- CToxProto *proto;
- std::vector<MCONTACT> invitedContacts;
-};
-
-#endif //_TOX_CHATROOMS_H_ \ No newline at end of file
diff --git a/protocols/Tox/src/tox_connection.cpp b/protocols/Tox/src/tox_connection.cpp
index 4c578a9696..80a84b74c0 100644
--- a/protocols/Tox/src/tox_connection.cpp
+++ b/protocols/Tox/src/tox_connection.cpp
@@ -2,7 +2,7 @@
bool CToxProto::IsOnline()
{
- return toxThread && m_iStatus >= ID_STATUS_ONLINE;
+ return m_toxThread && m_iStatus >= ID_STATUS_ONLINE;
}
void CToxProto::TryConnect(Tox *tox)
@@ -99,7 +99,7 @@ void CToxProto::PollingThread(void*)
}
tox_options_free(options);
- this->toxThread = &toxThread;
+ m_toxThread = &toxThread;
InitToxCore(toxThread.Tox());
BootstrapNodes(toxThread.Tox());
ForkThread(&CToxProto::CheckingThread, toxThread.Tox());
@@ -113,7 +113,7 @@ void CToxProto::PollingThread(void*)
}
UninitToxCore(toxThread.Tox());
- this->toxThread = nullptr;
+ m_toxThread = nullptr;
hPollingThread = nullptr;
debugLogA(__FUNCTION__": leaving");
diff --git a/protocols/Tox/src/tox_contacts.cpp b/protocols/Tox/src/tox_contacts.cpp
index 3b76b37407..4e1ee4abf4 100644
--- a/protocols/Tox/src/tox_contacts.cpp
+++ b/protocols/Tox/src/tox_contacts.cpp
@@ -96,8 +96,8 @@ MCONTACT CToxProto::AddContact(const char *address, const char *nick, const char
if (mir_strlen(dnsId))
setWString(hContact, TOX_SETTINGS_DNS, ptrW(mir_utf8decodeW(dnsId)));
- if (wszGroup)
- db_set_ws(hContact, "CList", "Group", wszGroup);
+ if (m_defaultGroup)
+ db_set_ws(hContact, "CList", "Group", m_defaultGroup);
setByte(hContact, "Auth", 1);
setByte(hContact, "Grant", 1);
@@ -112,7 +112,7 @@ uint32_t CToxProto::GetToxFriendNumber(MCONTACT hContact)
{
ToxBinAddress pubKey(ptrA(getStringA(hContact, TOX_SETTINGS_ID)));
TOX_ERR_FRIEND_BY_PUBLIC_KEY error;
- uint32_t friendNumber = tox_friend_by_public_key(toxThread->Tox(), pubKey.GetPubKey(), &error);
+ uint32_t friendNumber = tox_friend_by_public_key(m_toxThread->Tox(), pubKey.GetPubKey(), &error);
if (error != TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK)
debugLogA(__FUNCTION__": failed to get friend number (%d)", error);
return friendNumber;
@@ -123,7 +123,7 @@ void CToxProto::LoadFriendList(Tox *tox)
size_t count = tox_self_get_friend_list_size(tox);
if (count > 0) {
uint32_t *friends = (uint32_t*)mir_alloc(count * sizeof(uint32_t));
- tox_self_get_friend_list(toxThread->Tox(), friends);
+ tox_self_get_friend_list(m_toxThread->Tox(), friends);
for (size_t i = 0; i < count; i++) {
uint32_t friendNumber = friends[i];
@@ -139,13 +139,13 @@ void CToxProto::LoadFriendList(Tox *tox)
TOX_ERR_FRIEND_QUERY getNameResult;
uint8_t nick[TOX_MAX_NAME_LENGTH] = { 0 };
- if (tox_friend_get_name(toxThread->Tox(), friendNumber, nick, &getNameResult))
+ if (tox_friend_get_name(m_toxThread->Tox(), friendNumber, nick, &getNameResult))
setWString(hContact, "Nick", ptrW(mir_utf8decodeW((char*)nick)));
else
debugLogA(__FUNCTION__": failed to get friend name (%d)", getNameResult);
TOX_ERR_FRIEND_GET_LAST_ONLINE getLastOnlineResult;
- uint64_t timestamp = tox_friend_get_last_online(toxThread->Tox(), friendNumber, &getLastOnlineResult);
+ uint64_t timestamp = tox_friend_get_last_online(m_toxThread->Tox(), friendNumber, &getLastOnlineResult);
if (getLastOnlineResult == TOX_ERR_FRIEND_GET_LAST_ONLINE_OK)
setDword(hContact, "LastEventDateTS", timestamp);
else
@@ -166,7 +166,7 @@ INT_PTR CToxProto::OnRequestAuth(WPARAM hContact, LPARAM lParam)
ToxBinAddress address(ptrA(getStringA(hContact, TOX_SETTINGS_ID)));
TOX_ERR_FRIEND_ADD addFriendResult;
- int32_t friendNumber = tox_friend_add(toxThread->Tox(), address, (uint8_t*)reason, length, &addFriendResult);
+ int32_t friendNumber = tox_friend_add(m_toxThread->Tox(), address, (uint8_t*)reason, length, &addFriendResult);
if (addFriendResult != TOX_ERR_FRIEND_ADD_OK) {
debugLogA(__FUNCTION__": failed to request auth(%d)", addFriendResult);
return addFriendResult;
@@ -192,7 +192,7 @@ INT_PTR CToxProto::OnGrantAuth(WPARAM hContact, LPARAM)
ToxBinAddress pubKey(ptrA(getStringA(hContact, TOX_SETTINGS_ID)));
TOX_ERR_FRIEND_ADD error;
- tox_friend_add_norequest(toxThread->Tox(), pubKey, &error);
+ tox_friend_add_norequest(m_toxThread->Tox(), pubKey, &error);
if (error != TOX_ERR_FRIEND_ADD_OK) {
debugLogA(__FUNCTION__": failed to grant auth (%d)", error);
return error;
@@ -201,7 +201,7 @@ INT_PTR CToxProto::OnGrantAuth(WPARAM hContact, LPARAM)
db_unset(hContact, "CList", "NotOnList");
delSetting(hContact, "Grant");
- SaveToxProfile(toxThread->Tox());
+ SaveToxProfile(m_toxThread->Tox());
return 0;
}
@@ -214,21 +214,12 @@ int CToxProto::OnContactDeleted(MCONTACT hContact, LPARAM)
if (!isChatRoom(hContact)) {
int32_t friendNumber = GetToxFriendNumber(hContact);
TOX_ERR_FRIEND_DELETE error;
- if (!tox_friend_delete(toxThread->Tox(), friendNumber, &error)) {
+ if (!tox_friend_delete(m_toxThread->Tox(), friendNumber, &error)) {
debugLogA(__FUNCTION__": failed to delete friend (%d)", error);
return error;
}
- SaveToxProfile(toxThread->Tox());
+ SaveToxProfile(m_toxThread->Tox());
}
- /*else
- {
- OnLeaveChatRoom(hContact, 0);
- int groupNumber = 0; // ???
- if (groupNumber == TOX_ERROR || tox_del_groupchat(tox, groupNumber) == TOX_ERROR)
- {
- return 1;
- }
- }*/
return 0;
}
@@ -339,7 +330,7 @@ void CToxProto::OnConnectionStatusChanged(Tox *tox, uint32_t friendNumber, TOX_C
proto->debugLogA(__FUNCTION__": send avatar to friend (%d)", friendNumber);
TOX_ERR_FILE_SEND error;
- uint32_t fileNumber = tox_file_send(proto->toxThread->Tox(), friendNumber, TOX_FILE_KIND_AVATAR, length, hash, nullptr, 0, &error);
+ uint32_t fileNumber = tox_file_send(proto->m_toxThread->Tox(), friendNumber, TOX_FILE_KIND_AVATAR, length, hash, nullptr, 0, &error);
if (error != TOX_ERR_FILE_SEND_OK) {
Netlib_Logf(proto->m_hNetlibUser, __FUNCTION__": failed to set new avatar");
fclose(hFile);
@@ -355,7 +346,7 @@ void CToxProto::OnConnectionStatusChanged(Tox *tox, uint32_t friendNumber, TOX_C
}
else {
proto->debugLogA(__FUNCTION__": unset avatar for friend (%d)", friendNumber);
- tox_file_send(proto->toxThread->Tox(), friendNumber, TOX_FILE_KIND_AVATAR, 0, nullptr, nullptr, 0, nullptr);
+ tox_file_send(proto->m_toxThread->Tox(), friendNumber, TOX_FILE_KIND_AVATAR, 0, nullptr, nullptr, 0, nullptr);
}
}
diff --git a/protocols/Tox/src/tox_core.cpp b/protocols/Tox/src/tox_core.cpp
index ab2e4ceb1d..de977b090f 100644
--- a/protocols/Tox/src/tox_core.cpp
+++ b/protocols/Tox/src/tox_core.cpp
@@ -10,7 +10,10 @@ Tox_Options* CToxProto::GetToxOptions()
}
options->udp_enabled = getBool("EnableUDP", 1);
+ if (options->udp_enabled && getBool("EnableUDPHolePunching", 1))
+ options->hole_punching_enabled = true;
options->ipv6_enabled = getBool("EnableIPv6", 0);
+ options->local_discovery_enabled = getBool("EnableLocalDiscovery", 0);
if (m_hNetlibUser != nullptr) {
NETLIBUSERSETTINGS nlus = { sizeof(nlus) };
@@ -58,22 +61,6 @@ void CToxProto::InitToxCore(Tox *tox)
tox_callback_file_recv(tox, OnFriendFile);
tox_callback_file_recv_chunk(tox, OnDataReceiving);
tox_callback_file_chunk_request(tox, OnFileSendData);
- // group chats
- //tox_callback_group_invite(tox, OnGroupChatInvite, this);
- // a/v
- //if (IsWinVerVistaPlus())
- //{
- // TOXAV_ERR_NEW avInitError;
- // toxThread->Tox()AV = toxav_new(toxThread->Tox(), &avInitError);
- // if (initError != TOX_ERR_NEW_OK)
- // {
- // toxav_callback_call(toxThread->Tox()AV, OnFriendCall, this);
- // toxav_callback_call_state(toxThread->Tox()AV, OnFriendCallState, this);
- // toxav_callback_bit_rate_status(toxThread->Tox()AV, OnBitrateChanged, this);
- // toxav_callback_audio_receive_frame(toxThread->Tox()AV, OnFriendAudioFrame, this);
- // //toxav_callback_video_receive_frame(toxThread->Tox()AV, , this);
- // }
- //}
uint8_t data[TOX_ADDRESS_SIZE];
tox_self_get_address(tox, data);
diff --git a/protocols/Tox/src/tox_events.cpp b/protocols/Tox/src/tox_events.cpp
deleted file mode 100644
index f0afe46dbd..0000000000
--- a/protocols/Tox/src/tox_events.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "stdafx.h"
-
-int CToxProto::OnModulesLoaded(WPARAM, LPARAM)
-{
- CToxProto::InitIcons();
- CToxProto::InitMenus();
-
- hProfileFolderPath = FoldersRegisterCustomPathT("Tox", "ProfilesFolder", MIRANDA_USERDATAT, TranslateT("Profiles folder"));
-
- if (ServiceExists(MS_ASSOCMGR_ADDNEWURLTYPE)) {
- CreateServiceFunction(MODULE "/ParseUri", CToxProto::ParseToxUri);
- AssocMgr_AddNewUrlTypeT("tox:", TranslateT("Tox URI scheme"), g_hInstance, IDI_TOX, MODULE "/ParseUri", 0);
- }
-
- return 0;
-}
-
-void CToxProto::InitCustomDbEvents()
-{
- DBEVENTTYPEDESCR dbEventType = { sizeof(dbEventType) };
- dbEventType.module = m_szModuleName;
- dbEventType.flags = DETF_HISTORY | DETF_MSGWINDOW;
-
- dbEventType.eventType = DB_EVENT_ACTION;
- dbEventType.descr = Translate("Action");
- DbEvent_RegisterType(&dbEventType);
-
- dbEventType.eventType = DB_EVENT_CALL;
- dbEventType.descr = Translate("Call");
- dbEventType.eventIcon = GetIconHandle(IDI_AUDIO_START);
- DbEvent_RegisterType(&dbEventType);
-}
diff --git a/protocols/Tox/src/tox_icons.cpp b/protocols/Tox/src/tox_icons.cpp
index a96e7984d4..928685ebf3 100644
--- a/protocols/Tox/src/tox_icons.cpp
+++ b/protocols/Tox/src/tox_icons.cpp
@@ -3,10 +3,6 @@
IconItemT CToxProto::Icons[] =
{
{ LPGENW("Protocol icon"), "main", IDI_TOX },
- { LPGENW("Audio call"), "audio_call", IDI_AUDIO_CALL },
- { LPGENW("Audio ring"), "audio_ring", IDI_AUDIO_RING },
- { LPGENW("Audio start"), "audio_start", IDI_AUDIO_START },
- { LPGENW("Audio end"), "audio_end", IDI_AUDIO_END },
};
void CToxProto::InitIcons()
diff --git a/protocols/Tox/src/tox_menus.cpp b/protocols/Tox/src/tox_menus.cpp
index ed70ad8a7b..34b3047fb4 100644
--- a/protocols/Tox/src/tox_menus.cpp
+++ b/protocols/Tox/src/tox_menus.cpp
@@ -21,9 +21,6 @@ int CToxProto::OnPrebuildContactMenu(WPARAM hContact, LPARAM)
bool isGrantNeed = getByte(hContact, "Grant", 0) > 0;
Menu_ShowItem(ContactMenuItems[CMI_AUTH_GRANT], isCtrlPressed || isGrantNeed);
- bool isContactOnline = GetContactStatus(hContact) > ID_STATUS_OFFLINE;
- Menu_ShowItem(ContactMenuItems[CMI_AUDIO_CALL], toxThread->ToxAV() && isContactOnline);
-
return 0;
}
@@ -35,7 +32,7 @@ int CToxProto::PrebuildContactMenu(WPARAM hContact, LPARAM lParam)
return proto ? proto->OnPrebuildContactMenu(hContact, lParam) : 0;
}
-void CToxProto::InitMenus()
+void CToxProto::InitContactMenu()
{
HookEvent(ME_CLIST_PREBUILDCONTACTMENU, &CToxProto::PrebuildContactMenu);
@@ -59,19 +56,29 @@ void CToxProto::InitMenus()
mi.hIcolibItem = ::Skin_GetIconHandle(SKINICON_AUTH_GRANT);
ContactMenuItems[CMI_AUTH_GRANT] = Menu_AddContactMenuItem(&mi);
CreateServiceFunction(mi.pszService, GlobalService<&CToxProto::OnGrantAuth>);
+}
+
+int CToxProto::PrebuildStatusMenu(WPARAM, LPARAM)
+{
+ bool isOnline = IsOnline();
+ Menu_EnableItem(StatusMenuItems[SMI_PASSWORD], isOnline);
+ Menu_EnableItem(StatusMenuItems[SMI_PASSWORD_CREATE], isOnline);
+ Menu_EnableItem(StatusMenuItems[SMI_PASSWORD_CHANGE], isOnline);
+ Menu_EnableItem(StatusMenuItems[SMI_PASSWORD_REMOVE], isOnline);
+
+ pass_ptrW password(getWStringA(TOX_SETTINGS_PASSWORD));
+ bool passwordExists = mir_wstrlen(password) > 0;
+ Menu_ShowItem(StatusMenuItems[SMI_PASSWORD_CREATE], !passwordExists);
+ Menu_ShowItem(StatusMenuItems[SMI_PASSWORD_CHANGE], passwordExists);
+ Menu_ShowItem(StatusMenuItems[SMI_PASSWORD_REMOVE], passwordExists);
- // Start audio call
- SET_UID(mi, 0x116cb7fe, 0xce37, 0x429c, 0xb0, 0xa9, 0x7d, 0xe7, 0x70, 0x59, 0xc3, 0x95);
- mi.pszService = MODULE"/Audio/Call";
- mi.name.w = LPGENW("Call");
- mi.position = -2000020000 + CMI_AUDIO_CALL;
- mi.hIcolibItem = GetIconHandle(IDI_AUDIO_START);
- ContactMenuItems[CMI_AUDIO_CALL] = Menu_AddContactMenuItem(&mi);
- CreateServiceFunction(mi.pszService, GlobalService<&CToxProto::OnSendAudioCall>);
+ return 0;
}
int CToxProto::OnInitStatusMenu()
{
+ HookProtoEvent(ME_CLIST_PREBUILDSTATUSMENU, &CToxProto::PrebuildStatusMenu);
+
CMenuItem mi;
mi.flags = CMIF_UNICODE;
mi.root = Menu_GetProtocolRoot(this);
@@ -81,16 +88,34 @@ int CToxProto::OnInitStatusMenu()
CreateProtoService(mi.pszService, &CToxProto::OnCopyToxID);
mi.name.w = LPGENW("Copy Tox ID");
mi.position = SMI_POSITION + SMI_TOXID_COPY;
- Menu_AddProtoMenuItem(&mi, m_szModuleName);
-
- // Create group chat command
- /*
- mi.pszService = "/CreateChatRoom";
- CreateProtoService(mi.pszService, &CToxProto::OnCreateChatRoom);
- mi.name.w = LPGENW("Create group chat");
- mi.position = SMI_POSITION + SMI_GROUPCHAT_CREATE;
- mi.hIcolibItem = Skin_GetIconHandle("conference");
- HGENMENU hCreateChatRoom = Menu_AddProtoMenuItem(&mi, m_szModuleName);*/
+ StatusMenuItems[SMI_TOXID_COPY] = Menu_AddProtoMenuItem(&mi, m_szModuleName);
+
+ // Password
+ mi.pszService = nullptr;
+ mi.name.w = LPGENW("Password");
+ StatusMenuItems[SMI_PASSWORD] = Menu_AddProtoMenuItem(&mi, m_szModuleName);
+ mi.root = StatusMenuItems[SMI_PASSWORD];
+
+ // Create password command
+ mi.pszService = "/CreatePassword";
+ CreateProtoService(mi.pszService, &CToxProto::OnCreatePassword);
+ mi.name.w = LPGENW("Create password");
+ mi.position = SMI_PASSWORD_CREATE;
+ StatusMenuItems[SMI_PASSWORD_CREATE] = Menu_AddProtoMenuItem(&mi, m_szModuleName);
+
+ // Change password command
+ mi.pszService = "/ChangePassword";
+ CreateProtoService(mi.pszService, &CToxProto::OnChangePassword);
+ mi.name.w = LPGENW("Change password");
+ mi.position = SMI_PASSWORD_CHANGE;
+ StatusMenuItems[SMI_PASSWORD_CHANGE] = Menu_AddProtoMenuItem(&mi, m_szModuleName);
+
+ // Remove password command
+ mi.pszService = "/RemovePassword";
+ CreateProtoService(mi.pszService, &CToxProto::OnRemovePassword);
+ mi.name.w = LPGENW("Remove password");
+ mi.position = SMI_PASSWORD_REMOVE;
+ StatusMenuItems[SMI_PASSWORD_REMOVE] = Menu_AddProtoMenuItem(&mi, m_szModuleName);
return 0;
}
diff --git a/protocols/Tox/src/tox_menus.h b/protocols/Tox/src/tox_menus.h
index f4930265a2..85b9f55055 100644
--- a/protocols/Tox/src/tox_menus.h
+++ b/protocols/Tox/src/tox_menus.h
@@ -7,7 +7,6 @@ enum CMI_MENU_ITEMS
{
CMI_AUTH_REQUEST,
CMI_AUTH_GRANT,
- CMI_AUDIO_CALL,
CMI_MAX // this item shall be the last one
};
@@ -16,7 +15,10 @@ enum CMI_MENU_ITEMS
enum SMI_MENU_ITEMS
{
SMI_TOXID_COPY,
- SMI_GROUPCHAT_CREATE,
+ SMI_PASSWORD,
+ SMI_PASSWORD_CREATE,
+ SMI_PASSWORD_CHANGE,
+ SMI_PASSWORD_REMOVE,
SMI_MAX // this item shall be the last one
};
diff --git a/protocols/Tox/src/tox_messages.cpp b/protocols/Tox/src/tox_messages.cpp
index 761294cbf7..0d7ad78b04 100644
--- a/protocols/Tox/src/tox_messages.cpp
+++ b/protocols/Tox/src/tox_messages.cpp
@@ -1,5 +1,16 @@
#include "stdafx.h"
+void CToxProto::InitCustomDbEvents()
+{
+ DBEVENTTYPEDESCR dbEventType = { sizeof(dbEventType) };
+ dbEventType.module = m_szModuleName;
+ dbEventType.flags = DETF_HISTORY | DETF_MSGWINDOW;
+
+ dbEventType.eventType = DB_EVENT_ACTION;
+ dbEventType.descr = Translate("Action");
+ DbEvent_RegisterType(&dbEventType);
+}
+
/* MESSAGE RECEIVING */
// incoming message flow
@@ -58,7 +69,7 @@ void CToxProto::SendMessageAsync(void *arg)
}
TOX_ERR_FRIEND_SEND_MESSAGE sendError;
- int messageNumber = tox_friend_send_message(toxThread->Tox(), friendNumber, type, msg, msgLen, &sendError);
+ int messageNumber = tox_friend_send_message(m_toxThread->Tox(), friendNumber, type, msg, msgLen, &sendError);
if (sendError != TOX_ERR_FRIEND_SEND_MESSAGE_OK) {
debugLogA(__FUNCTION__": failed to send message for %d (%d)", friendNumber, sendError);
ProtoBroadcastAck(param->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)param->hMessage, (LPARAM)_T2A(ToxErrorToString(sendError)));
@@ -138,7 +149,7 @@ void CToxProto::GetStatusMessageAsync(void* arg)
}
TOX_ERR_FRIEND_QUERY error;
- size_t size = tox_friend_get_status_message_size(toxThread->Tox(), friendNumber, &error);
+ size_t size = tox_friend_get_status_message_size(m_toxThread->Tox(), friendNumber, &error);
if (error != TOX_ERR_FRIEND_QUERY::TOX_ERR_FRIEND_QUERY_OK) {
debugLogA(__FUNCTION__": failed to get status message for (%d) (%d)", friendNumber, error);
ProtoBroadcastAck(hContact, ACKTYPE_AWAYMSG, ACKRESULT_FAILED, (HANDLE)hContact, 0);
@@ -146,7 +157,7 @@ void CToxProto::GetStatusMessageAsync(void* arg)
}
ptrA statusMessage((char*)mir_calloc(size + 1));
- if (!tox_friend_get_status_message(toxThread->Tox(), friendNumber, (uint8_t*)(char*)statusMessage, &error)) {
+ if (!tox_friend_get_status_message(m_toxThread->Tox(), friendNumber, (uint8_t*)(char*)statusMessage, &error)) {
debugLogA(__FUNCTION__": failed to get status message for (%d) (%d)", friendNumber, error);
ProtoBroadcastAck(hContact, ACKTYPE_AWAYMSG, ACKRESULT_FAILED, (HANDLE)hContact, 0);
return;
@@ -164,7 +175,7 @@ int CToxProto::OnUserIsTyping(MCONTACT hContact, int type)
return 0;
TOX_ERR_SET_TYPING error;
- if (!tox_self_set_typing(toxThread->Tox(), friendNumber, type == PROTOTYPE_SELFTYPING_ON, &error))
+ if (!tox_self_set_typing(m_toxThread->Tox(), friendNumber, type == PROTOTYPE_SELFTYPING_ON, &error))
debugLogA(__FUNCTION__": failed to send typing (%d)", error);
return 0;
diff --git a/protocols/Tox/src/tox_multimedia.cpp b/protocols/Tox/src/tox_multimedia.cpp
deleted file mode 100644
index c9c840274a..0000000000
--- a/protocols/Tox/src/tox_multimedia.cpp
+++ /dev/null
@@ -1,626 +0,0 @@
-#include "stdafx.h"
-
-CToxCallDlgBase::CToxCallDlgBase(CToxProto *proto, int idDialog, MCONTACT hContact) :
- CToxDlgBase(proto, idDialog, false), hContact(hContact)
-{}
-
-void CToxCallDlgBase::OnInitDialog()
-{
- WindowList_Add(m_proto->hAudioDialogs, m_hwnd, hContact);
-}
-
-void CToxCallDlgBase::OnClose()
-{
- WindowList_Remove(m_proto->hAudioDialogs, m_hwnd);
-}
-
-INT_PTR CToxCallDlgBase::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam)
-{
- if (msg == WM_CALL_END)
- if (wParam == hContact)
- Close();
-
- return CToxDlgBase::DlgProc(msg, wParam, lParam);
-}
-
-void CToxCallDlgBase::SetIcon(const char *name)
-{
- char iconName[100];
- mir_snprintf(iconName, "%s_%s", MODULE, name);
- Window_SetIcon_IcoLib(m_hwnd, IcoLib_GetIconHandle(iconName));
-}
-
-void CToxCallDlgBase::SetTitle(const wchar_t *title)
-{
- SetWindowText(m_hwnd, title);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////
-
-CToxIncomingCall::CToxIncomingCall(CToxProto *proto, MCONTACT hContact) :
- CToxCallDlgBase(proto, IDD_CALL_RECEIVE, hContact),
- from(this, IDC_FROM), date(this, IDC_DATE),
- answer(this, IDOK), reject(this, IDCANCEL)
-{
- answer.OnClick = Callback(this, &CToxIncomingCall::OnAnswer);
-}
-
-void CToxIncomingCall::OnInitDialog()
-{
- CToxCallDlgBase::OnInitDialog();
- Utils_RestoreWindowPosition(m_hwnd, NULL, m_proto->m_szModuleName, "IncomingCallWindow_");
-
- wchar_t *nick = pcli->pfnGetContactDisplayName(hContact, 0);
- from.SetText(nick);
-
- wchar_t title[MAX_PATH];
- mir_snwprintf(title, TranslateT("Incoming call from %s"), nick);
- SetTitle(title);
- SetIcon("audio_ring");
-}
-
-void CToxIncomingCall::OnClose()
-{
- toxav_call_control(m_proto->toxThread->ToxAV(), m_proto->calls[hContact], TOXAV_CALL_CONTROL_CANCEL, nullptr);
- Utils_SaveWindowPosition(m_hwnd, NULL, m_proto->m_szModuleName, "IncomingCallWindow_");
- CToxCallDlgBase::OnClose();
-}
-
-void CToxIncomingCall::OnAnswer(CCtrlBase*)
-{
- /*ToxAvCSettings *cSettings = m_proto->GetAudioCSettings();
- if (cSettings == NULL)
- return;*/
-
- int friendNumber = m_proto->GetToxFriendNumber(hContact);
- if (friendNumber == UINT32_MAX) {
- //mir_free(cSettings);
- Close();
- return;
- }
-
- TOXAV_ERR_ANSWER error;
- if (!toxav_answer(m_proto->toxThread->ToxAV(), friendNumber, 0, 0, &error)) {
- m_proto->debugLogA(__FUNCTION__": failed to answer the call (%d)", error);
- Close();
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////
-
-CToxOutgoingCall::CToxOutgoingCall(CToxProto *proto, MCONTACT hContact) :
- CToxCallDlgBase(proto, IDD_CALL_SEND, hContact),
- to(this, IDC_FROM), call(this, IDOK), cancel(this, IDCANCEL)
-{
- m_autoClose = CLOSE_ON_CANCEL;
- call.OnClick = Callback(this, &CToxOutgoingCall::OnCall);
- cancel.OnClick = Callback(this, &CToxOutgoingCall::OnCancel);
-}
-
-void CToxOutgoingCall::OnInitDialog()
-{
- CToxCallDlgBase::OnInitDialog();
- Utils_RestoreWindowPosition(m_hwnd, NULL, m_proto->m_szModuleName, "OutgoingCallWindow_");
-
- wchar_t *nick = pcli->pfnGetContactDisplayName(hContact, 0);
- to.SetText(nick);
-
- wchar_t title[MAX_PATH];
- mir_snwprintf(title, TranslateT("Outgoing call to %s"), nick);
- SetTitle(title);
- SetIcon("audio_end");
-}
-
-void CToxOutgoingCall::OnClose()
-{
- Utils_SaveWindowPosition(m_hwnd, NULL, m_proto->m_szModuleName, "OutgoingCallWindow_");
- CToxCallDlgBase::OnClose();
-}
-
-void CToxOutgoingCall::OnCall(CCtrlBase*)
-{
- /*ToxAvCSettings *cSettings = m_proto->GetAudioCSettings();
- if (cSettings == NULL)
- {
- Close();
- return;
- }*/
-
- int friendNumber = m_proto->GetToxFriendNumber(hContact);
- if (friendNumber == UINT32_MAX) {
- //mir_free(cSettings);
- Close();
- return;
- }
-
- TOXAV_ERR_CALL error;
- if (!toxav_call(m_proto->toxThread->ToxAV(), friendNumber, 0, 0, &error)) {
- //mir_free(cSettings);
- m_proto->debugLogA(__FUNCTION__": failed to make a call (%d)", error);
- return;
- }
- //mir_free(cSettings);
-
- char *message = nullptr;
- wchar_t title[MAX_PATH];
- if (GetWindowText(m_hwnd, title, _countof(title)))
- message = mir_utf8encodeW(title);
- else
- message = mir_utf8encode("Outgoing call");
- m_proto->AddEventToDb(hContact, DB_EVENT_CALL, time(nullptr), DBEF_UTF, (PBYTE)message, mir_strlen(message));
-
- call.Enable(FALSE);
- SetIcon("audio_call");
-}
-
-void CToxOutgoingCall::OnCancel(CCtrlBase*)
-{
- int friendNumber = m_proto->GetToxFriendNumber(hContact);
- if (friendNumber == UINT32_MAX) {
- //mir_free(cSettings);
- Close();
- return;
- }
-
- if (!call.Enabled())
- toxav_call_control(m_proto->toxThread->ToxAV(), friendNumber, TOXAV_CALL_CONTROL_CANCEL, nullptr);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////
-
-CToxCallDialog::CToxCallDialog(CToxProto *proto, MCONTACT hContact) :
- CToxCallDlgBase(proto, IDD_CALL, hContact), end(this, IDCANCEL)
-{}
-
-void CToxCallDialog::OnInitDialog()
-{
- CToxCallDlgBase::OnInitDialog();
- Utils_RestoreWindowPosition(m_hwnd, NULL, m_proto->m_szModuleName, "CallWindow_");
- SetIcon("audio_start");
-}
-
-void CToxCallDialog::OnClose()
-{
- int friendNumber = m_proto->GetToxFriendNumber(hContact);
- if (friendNumber == UINT32_MAX) {
- //mir_free(cSettings);
- Close();
- return;
- }
-
- toxav_call_control(m_proto->toxThread->ToxAV(), friendNumber, TOXAV_CALL_CONTROL_CANCEL, nullptr);
- Utils_SaveWindowPosition(m_hwnd, NULL, m_proto->m_szModuleName, "CallWindow_");
- CToxCallDlgBase::OnClose();
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////
-
-/*ToxAvCSettings* CToxProto::GetAudioCSettings()
-{
- ToxAvCSettings *cSettings = (ToxAvCSettings*)mir_calloc(sizeof(ToxAvCSettings));
- cSettings->audio_frame_duration = 20;
-
- DWORD deviceId = getDword("AudioInputDeviceID", WAVE_MAPPER);
-
- WAVEINCAPS wic;
- MMRESULT error = waveInGetDevCaps(deviceId, &wic, sizeof(WAVEINCAPS));
- if (error != MMSYSERR_NOERROR)
- {
- debugLogA(__FUNCTION__": failed to get input device caps (%d)", error);
-
- wchar_t errorMessage[MAX_PATH];
- waveInGetErrorText(error, errorMessage, _countof(errorMessage));
- CToxProto::ShowNotification(
- TranslateT("Unable to find input audio device"),
- errorMessage);
-
- mir_free(cSettings);
- return NULL;
- }
-
- cSettings->audio_channels = wic.wChannels;
- if ((wic.dwFormats & WAVE_FORMAT_48S16) || (wic.dwFormats & WAVE_FORMAT_48M16))
- {
- cSettings->audio_bitrate = 16 * 1000;
- cSettings->audio_sample_rate = 48000;
- }
- else if ((wic.dwFormats & WAVE_FORMAT_48S08) || (wic.dwFormats & WAVE_FORMAT_48M08))
- {
- cSettings->audio_bitrate = 8 * 1000;
- cSettings->audio_sample_rate = 48000;
- }
- else if ((wic.dwFormats & WAVE_FORMAT_4S16) || (wic.dwFormats & WAVE_FORMAT_4M16))
- {
- cSettings->audio_bitrate = 16 * 1000;
- cSettings->audio_sample_rate = 24000;
- }
- else if ((wic.dwFormats & WAVE_FORMAT_4S08) || (wic.dwFormats & WAVE_FORMAT_4S08))
- {
- cSettings->audio_bitrate = 8 * 1000;
- cSettings->audio_sample_rate = 24000;
- }
- else if ((wic.dwFormats & WAVE_FORMAT_2M16) || (wic.dwFormats & WAVE_FORMAT_2S16))
- {
- cSettings->audio_bitrate = 16 * 1000;
- cSettings->audio_sample_rate = 16000;
- }
- else if ((wic.dwFormats & WAVE_FORMAT_2M08) || (wic.dwFormats & WAVE_FORMAT_2S08))
- {
- cSettings->audio_bitrate = 8 * 1000;
- cSettings->audio_sample_rate = 16000;
- }
- else if ((wic.dwFormats & WAVE_FORMAT_1M16) || (wic.dwFormats & WAVE_FORMAT_1S16))
- {
- cSettings->audio_bitrate = 16 * 1000;
- cSettings->audio_sample_rate = 8000;
- }
- else if ((wic.dwFormats & WAVE_FORMAT_1M08) || (wic.dwFormats & WAVE_FORMAT_1S08))
- {
- cSettings->audio_bitrate = 8 * 1000;
- cSettings->audio_sample_rate = 8000;
- }
- else
- {
- debugLogA(__FUNCTION__": failed to parse input device caps");
- mir_free(cSettings);
- return NULL;
- }
-
- return cSettings;
-}*/
-
-/* INCOMING CALL */
-
-// incoming call flow
-void CToxProto::OnFriendCall(ToxAV *toxAV, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *arg)
-{
- /*CToxProto *proto = (CToxProto*)arg;
-
- int friendNumber = toxav_get_peer_id(proto->toxThread->Tox()AV, callId, 0);
- if (friendNumber == TOX_ERROR)
- {
- proto->debugLogA(__FUNCTION__": failed to get friend number");
- toxav_reject(proto->toxThread->Tox()AV, callId, NULL);
- return;
- }
-
- MCONTACT hContact = proto->GetContact(friendNumber);
- if (hContact == NULL)
- {
- proto->debugLogA(__FUNCTION__": failed to find contact");
- toxav_reject(proto->toxThread->Tox()AV, callId, NULL);
- return;
- }
-
- ToxAvCSettings cSettings;
- if (toxav_get_peer_csettings(proto->toxThread->Tox()AV, callId, 0, &cSettings) != av_ErrorNone)
- {
- proto->debugLogA(__FUNCTION__": failed to get codec settings");
- toxav_reject(proto->toxThread->Tox()AV, callId, NULL);
- return;
- }
-
- if (cSettings.call_type != av_TypeAudio)
- {
- proto->debugLogA(__FUNCTION__": video call is unsupported");
- toxav_reject(proto->toxThread->Tox()AV, callId, Translate("Video call is unsupported"));
- return;
- }
-
- wchar_t message[MAX_PATH];
- mir_snwprintf(message, TranslateT("Incoming call from %s"), pcli->pfnGetContactDisplayName(hContact, 0));
- T2Utf szMessage(message);
-
- PROTORECVEVENT recv = { 0 };
- recv.timestamp = time(NULL);
- recv.lParam = callId;
- recv.szMessage = szMessage;
- ProtoChainRecv(hContact, PSR_AUDIO, hContact, (LPARAM)&recv);*/
-}
-
-void CToxProto::OnFriendCallState(ToxAV *toxAV, uint32_t friend_number, uint32_t state, void *user_data)
-{}
-
-void CToxProto::OnBitrateChanged(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, void *arg)
-{}
-
-// save event to db
-INT_PTR CToxProto::OnRecvAudioCall(WPARAM hContact, LPARAM lParam)
-{
- PROTORECVEVENT *pre = (PROTORECVEVENT*)lParam;
-
- calls[hContact] = pre->lParam;
-
- MEVENT hEvent = AddEventToDb(hContact, DB_EVENT_CALL, pre->timestamp, DBEF_UTF, (PBYTE)pre->szMessage, mir_strlen(pre->szMessage));
-
- CLISTEVENT cle = {};
- cle.flags = CLEF_UNICODE;
- cle.hContact = hContact;
- cle.hDbEvent = hEvent;
- cle.lParam = DB_EVENT_CALL;
- cle.hIcon = IcoLib_GetIconByHandle(GetIconHandle(IDI_AUDIO_RING));
-
- wchar_t szTooltip[MAX_PATH];
- mir_snwprintf(szTooltip, TranslateT("Incoming call from %s"), pcli->pfnGetContactDisplayName(hContact, 0));
- cle.szTooltip.w = szTooltip;
-
- char szService[MAX_PATH];
- mir_snprintf(szService, "%s/Audio/Ring", GetContactProto(hContact));
- cle.pszService = szService;
- pcli->pfnAddEvent(&cle);
-
- return hEvent;
-}
-
-// react on clist event click
-INT_PTR CToxProto::OnAudioRing(WPARAM, LPARAM lParam)
-{
- CLISTEVENT *cle = (CLISTEVENT*)lParam;
- CDlgBase *incomingCallDlg = new CToxIncomingCall(this, cle->hContact);
- incomingCallDlg->Show();
-
- return 0;
-}
-
-/*void CToxProto::OnAvCancel(void*, int32_t callId, void *arg)
-{
- CToxProto *proto = (CToxProto*)arg;
-
- int friendNumber = toxav_get_peer_id(proto->toxThread->Tox()AV, callId, 0);
- if (friendNumber == TOX_ERROR)
- {
- proto->debugLogA(__FUNCTION__": failed to get friend number");
- return;
- }
-
- MCONTACT hContact = proto->GetContact(friendNumber);
- if (hContact == NULL)
- {
- proto->debugLogA(__FUNCTION__": failed to find contact");
- return;
- }
-
- CLISTEVENT *cle = NULL;
- while ((cle = (CLISTEVENT*)CallService(MS_CLIST_GETEVENT, hContact, 0)))
- {
- if (cle->lParam == DB_EVENT_CALL)
- {
- CallService(MS_CLIST_REMOVEEVENT, hContact, cle->hDbEvent);
- break;
- }
- }
-
- char *message = mir_utf8encodeW(TranslateT("Call canceled"));
- proto->AddEventToDb(hContact, DB_EVENT_CALL, time(NULL), DBEF_UTF, (PBYTE)message, mir_strlen(message));
-
- WindowList_Broadcast(proto->hAudioDialogs, WM_CALL_END, hContact, 0);
-}*/
-
-/* OUTGOING CALL */
-
-// outcoming audio flow
-INT_PTR CToxProto::OnSendAudioCall(WPARAM hContact, LPARAM)
-{
- CDlgBase *outgoingCallDlg = new CToxOutgoingCall(this, hContact);
- outgoingCallDlg->Show();
-
- return 0;
-}
-
-/*void CToxProto::OnAvReject(void*, int32_t callId, void *arg)
-{
- CToxProto *proto = (CToxProto*)arg;
-
- int friendNumber = toxav_get_peer_id(proto->toxThread->Tox()AV, callId, 0);
- if (friendNumber == TOX_ERROR)
- {
- proto->debugLogA(__FUNCTION__": failed to get friend number");
- return;
- }
-
- MCONTACT hContact = proto->GetContact(friendNumber);
- if (hContact == NULL)
- {
- proto->debugLogA(__FUNCTION__": failed to find contact");
- return;
- }
-
- char *message = mir_utf8encodeW(TranslateT("Call canceled"));
- proto->AddEventToDb(hContact, DB_EVENT_CALL, time(NULL), DBEF_UTF, (PBYTE)message, mir_strlen(message));
-
- WindowList_Broadcast(proto->hAudioDialogs, WM_CALL_END, hContact, 0);
-}
-
-void CToxProto::OnAvCallTimeout(void*, int32_t callId, void *arg)
-{
- CToxProto *proto = (CToxProto*)arg;
-
- int friendNumber = toxav_get_peer_id(proto->toxThread->Tox()AV, callId, 0);
- if (friendNumber == TOX_ERROR)
- {
- proto->debugLogA(__FUNCTION__": failed to get friend number");
- return;
- }
-
- MCONTACT hContact = proto->GetContact(friendNumber);
- if (hContact == NULL)
- {
- proto->debugLogA(__FUNCTION__": failed to find contact");
- return;
- }
-
- char *message = mir_utf8encodeW(TranslateT("Call canceled"));
- proto->AddEventToDb(hContact, DB_EVENT_CALL, time(NULL), DBEF_UTF, (PBYTE)message, mir_strlen(message));
-
- WindowList_Broadcast(proto->hAudioDialogs, WM_CALL_END, hContact, 0);
-}*/
-
-/* --- */
-
-static void CALLBACK WaveOutCallback(HWAVEOUT hOutDevice, UINT uMsg, DWORD/* dwInstance*/, DWORD dwParam1, DWORD/* dwParam2*/)
-{
- if (uMsg == WOM_DONE) {
- WAVEHDR *header = (WAVEHDR*)dwParam1;
- if (header->dwFlags & WHDR_PREPARED)
- waveOutUnprepareHeader(hOutDevice, header, sizeof(WAVEHDR));
- mir_free(header->lpData);
- mir_free(header);
- }
-}
-
-static void CALLBACK ToxShowDialogApcProc(void *arg)
-{
- CDlgBase *callDlg = (CDlgBase*)arg;
- callDlg->Show();
-}
-
-/*void CToxProto::OnAvStart(void*, int32_t callId, void *arg)
-{
- CToxProto *proto = (CToxProto*)arg;
-
- ToxAvCSettings cSettings;
- int cSettingsError = toxav_get_peer_csettings(proto->toxThread->Tox()AV, callId, 0, &cSettings);
- if (cSettingsError != av_ErrorNone)
- {
- proto->debugLogA(__FUNCTION__": failed to get codec settings (%d)", cSettingsError);
- toxav_hangup(proto->toxThread->Tox()AV, callId);
- return;
- }
-
- if (cSettings.call_type != av_TypeAudio)
- {
- proto->debugLogA(__FUNCTION__": video call is unsupported");
- toxav_hangup(proto->toxThread->Tox()AV, callId);
- return;
- }
-
- WAVEFORMATEX wfx = { 0 };
- wfx.wFormatTag = WAVE_FORMAT_PCM;
- wfx.nChannels = cSettings.audio_channels;
- wfx.wBitsPerSample = cSettings.audio_bitrate / 1000;
- wfx.nSamplesPerSec = cSettings.audio_sample_rate;
- wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
- wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
-
- DWORD deviceId = proto->getDword("AudioOutputDeviceID", WAVE_MAPPER);
- MMRESULT error = waveOutOpen(&proto->hOutDevice, deviceId, &wfx, (DWORD_PTR)WaveOutCallback, (DWORD_PTR)proto, CALLBACK_FUNCTION);
- if (error != MMSYSERR_NOERROR)
- {
- proto->debugLogA(__FUNCTION__": failed to open audio device (%d)", error);
- toxav_hangup(proto->toxThread->Tox()AV, callId);
-
- wchar_t errorMessage[MAX_PATH];
- waveInGetErrorText(error, errorMessage, _countof(errorMessage));
- CToxProto::ShowNotification(
- TranslateT("Unable to find output audio device"),
- errorMessage);
-
- return;
- }
-
- int friendNumber = toxav_get_peer_id(proto->toxThread->Tox()AV, callId, 0);
- if (friendNumber == TOX_ERROR)
- {
- proto->debugLogA(__FUNCTION__": failed to get friend number");
- toxav_hangup(proto->toxThread->Tox()AV, callId);
- return;
- }
-
- MCONTACT hContact = proto->GetContact(friendNumber);
- if (hContact == NULL)
- {
- proto->debugLogA(__FUNCTION__": failed to find contact");
- toxav_hangup(proto->toxThread->Tox()AV, callId);
- return;
- }
-
- if (toxav_prepare_transmission(proto->toxThread->Tox()AV, callId, false) == TOX_ERROR)
- {
- proto->debugLogA(__FUNCTION__": failed to prepare audio transmition");
- toxav_hangup(proto->toxThread->Tox()AV, callId);
- return;
- }
-
- char *message = mir_utf8encodeW(TranslateT("Call started"));
- proto->AddEventToDb(hContact, DB_EVENT_CALL, time(NULL), DBEF_UTF, (PBYTE)message, mir_strlen(message));
-
-
- WindowList_Broadcast(proto->hAudioDialogs, WM_CALL_END, hContact, 0);
- CDlgBase *callDlg = new CToxCallDialog(proto, hContact);
- CallFunctionAsync(ToxShowDialogApcProc, callDlg);
-}
-
-void CToxProto::OnAvEnd(void*, int32_t callId, void *arg)
-{
- CToxProto *proto = (CToxProto*)arg;
-
- waveOutReset(proto->hOutDevice);
- waveOutClose(proto->hOutDevice);
- toxav_kill_transmission(proto->toxThread->Tox()AV, callId);
-
- int friendNumber = toxav_get_peer_id(proto->toxThread->Tox()AV, callId, 0);
- if (friendNumber == TOX_ERROR)
- {
- proto->debugLogA(__FUNCTION__": failed to get friend number");
- return;
- }
-
- MCONTACT hContact = proto->GetContact(friendNumber);
- if (hContact == NULL)
- {
- proto->debugLogA(__FUNCTION__": failed to find contact");
- return;
- }
-
- char *message = mir_utf8encodeW(TranslateT("Call ended"));
- proto->AddEventToDb(hContact, DB_EVENT_CALL, time(NULL), DBEF_UTF, (PBYTE)message, mir_strlen(message));
-
- WindowList_Broadcast(proto->hAudioDialogs, WM_CALL_END, hContact, 0);
-}
-
-void CToxProto::OnAvPeerTimeout(void *av, int32_t callId, void *arg)
-{
- CToxProto *proto = (CToxProto*)arg;
-
- ToxAvCallState callState = toxav_get_call_state(proto->toxThread->Tox()AV, callId);
- switch (callState)
- {
- case av_CallStarting:
- proto->OnAvCancel(av, callId, arg);
- return;
-
- case av_CallActive:
- proto->OnAvEnd(av, callId, arg);
- return;
-
- default:
- proto->debugLogA(__FUNCTION__": failed to handle callState");
- break;
- }
-}*/
-
-//////
-
-void CToxProto::OnFriendAudioFrame(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, void *user_data)
-{
- /*CToxProto *proto = (CToxProto*)arg;
-
- WAVEHDR *header = (WAVEHDR*)mir_calloc(sizeof(WAVEHDR));
- header->dwBufferLength = size * sizeof(int16_t);
- header->lpData = (LPSTR)mir_alloc(header->dwBufferLength);
- memcpy(header->lpData, (PBYTE)PCM, header->dwBufferLength);
-
- MMRESULT error = waveOutPrepareHeader(proto->hOutDevice, header, sizeof(WAVEHDR));
- if (error != MMSYSERR_NOERROR)
- {
- proto->debugLogA(__FUNCTION__": failed to prepare audio buffer (%d)", error);
- return;
- }
-
- error = waveOutWrite(proto->hOutDevice, header, sizeof(WAVEHDR));
- if (error != MMSYSERR_NOERROR)
- {
- proto->debugLogA(__FUNCTION__": failed to play audio samples (%d)", error);
- return;
- }*/
-}
diff --git a/protocols/Tox/src/tox_multimedia.h b/protocols/Tox/src/tox_multimedia.h
deleted file mode 100644
index 922b9b406f..0000000000
--- a/protocols/Tox/src/tox_multimedia.h
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef _TOX_MULTIMEDIA_H_
-#define _TOX_MULTIMEDIA_H_
-
-#define WM_CALL_END (WM_PROTO_LAST + 100)
-
-class CToxCallDlgBase : public CToxDlgBase
-{
-protected:
- MCONTACT hContact;
-
- virtual void OnInitDialog();
- virtual void OnClose();
-
- INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam);
-
- void SetIcon(const char *name);
- void SetTitle(const wchar_t *title);
-
-public:
- CToxCallDlgBase(CToxProto *proto, int idDialog, MCONTACT hContact);
-};
-
-///////////////////////////////////////////////
-
-class CToxIncomingCall : public CToxCallDlgBase
-{
-private:
- CCtrlLabel from;
- CCtrlLabel date;
-
- CCtrlButton answer;
- CCtrlButton reject;
-
-protected:
- void OnInitDialog();
- void OnClose();
-
- void OnAnswer(CCtrlBase*);
-
-public:
- CToxIncomingCall(CToxProto *proto, MCONTACT hContact);
-};
-
-///////////////////////////////////////////////
-
-class CToxOutgoingCall : public CToxCallDlgBase
-{
-private:
- CCtrlLabel to;
- CCtrlButton call;
- CCtrlButton cancel;
-
-protected:
- void OnInitDialog();
- void OnClose();
-
- void OnCall(CCtrlBase*);
- void OnCancel(CCtrlBase*);
-
-public:
- CToxOutgoingCall(CToxProto *proto, MCONTACT hContact);
-};
-
-///////////////////////////////////////////////
-
-struct ToxCallDialogParam
-{
- CToxProto *proto;
- MCONTACT hContact;
-};
-
-class CToxCallDialog : public CToxCallDlgBase
-{
-protected:
- CCtrlButton end;
-
- void OnInitDialog();
- void OnClose();
-
-public:
- CToxCallDialog(CToxProto *proto, MCONTACT hContact);
-};
-
-#endif //_TOX_MULTIMEDIA_H_ \ No newline at end of file
diff --git a/protocols/Tox/src/tox_options.cpp b/protocols/Tox/src/tox_options.cpp
index bf4aeea940..71353d3263 100644
--- a/protocols/Tox/src/tox_options.cpp
+++ b/protocols/Tox/src/tox_options.cpp
@@ -5,23 +5,33 @@ CToxOptionsMain::CToxOptionsMain(CToxProto *proto, int idDialog)
m_toxAddress(this, IDC_TOXID), m_toxAddressCopy(this, IDC_CLIPBOARD),
m_profileCreate(this, IDC_PROFILE_NEW), m_profileImport(this, IDC_PROFILE_IMPORT),
m_profileExport(this, IDC_PROFILE_EXPORT), m_nickname(this, IDC_NAME),
- m_password(this, IDC_PASSWORD), m_group(this, IDC_GROUP),
- m_enableUdp(this, IDC_ENABLE_UDP), m_enableIPv6(this, IDC_ENABLE_IPV6),
+ m_passwordCreate(this, IDC_PASSWORD_CREATE), m_passwordChange(this, IDC_PASSWORD_CHANGE),
+ m_passwordRemove(this, IDC_PASSWORD_REMOVE), m_group(this, IDC_GROUP),
+ m_enableUdp(this, IDC_ENABLE_UDP), m_enableUdpHolePunching(this, IDC_ENABLE_HOLEPUNCHING),
+ m_enableIPv6(this, IDC_ENABLE_IPV6), m_enableLocalDiscovery(this, IDC_ENABLE_LOCALDISCOVERY),
m_maxConnectRetries(this, IDC_MAXCONNECTRETRIES), m_maxConnectRetriesSpin(this, IDC_MAXCONNECTRETRIESSPIN),
m_maxReconnectRetries(this, IDC_MAXRECONNECTRETRIES), m_maxReconnectRetriesSpin(this, IDC_MAXRECONNECTRETRIESSPIN)
{
CreateLink(m_toxAddress, TOX_SETTINGS_ID, L"");
CreateLink(m_nickname, "Nick", L"");
- CreateLink(m_password, "Password", L"");
CreateLink(m_group, TOX_SETTINGS_GROUP, L"Tox");
CreateLink(m_enableUdp, "EnableUDP", DBVT_BYTE, TRUE);
+ CreateLink(m_enableUdpHolePunching, "EnableUDPHolePunching", DBVT_BYTE, TRUE);
CreateLink(m_enableIPv6, "EnableIPv6", DBVT_BYTE, FALSE);
+ CreateLink(m_enableLocalDiscovery, "EnableLocalDiscovery", DBVT_BYTE, FALSE);
if (idDialog == IDD_OPTIONS_MAIN) {
CreateLink(m_maxConnectRetries, "MaxConnectRetries", DBVT_BYTE, TOX_MAX_CONNECT_RETRIES);
CreateLink(m_maxReconnectRetries, "MaxReconnectRetries", DBVT_BYTE, TOX_MAX_RECONNECT_RETRIES);
}
+ m_passwordCreate.OnClick = Callback(this, &CToxOptionsMain::PasswordCreate_OnClick);
+ m_passwordChange.OnClick = Callback(this, &CToxOptionsMain::PasswordChange_OnClick);
+ m_passwordRemove.OnClick = Callback(this, &CToxOptionsMain::PasswordRemove_OnClick);
+
+ m_enableUdp.OnChange = Callback(this, &CToxOptionsMain::EnableUdp_OnClick);
+ m_enableUdpHolePunching.Enable(m_enableUdp.GetState());
+
m_toxAddressCopy.OnClick = Callback(this, &CToxOptionsMain::ToxAddressCopy_OnClick);
m_profileCreate.OnClick = Callback(this, &CToxOptionsMain::ProfileCreate_OnClick);
m_profileImport.OnClick = Callback(this, &CToxOptionsMain::ProfileImport_OnClick);
@@ -36,17 +46,26 @@ void CToxOptionsMain::OnInitDialog()
if (CToxProto::IsFileExists(profilePath)) {
m_toxAddress.Enable();
- ShowWindow(m_profileCreate.GetHwnd(), FALSE);
- ShowWindow(m_profileImport.GetHwnd(), FALSE);
+ m_profileCreate.Hide();
+ m_profileImport.Hide();
- ShowWindow(m_toxAddressCopy.GetHwnd(), TRUE);
- ShowWindow(m_profileExport.GetHwnd(), TRUE);
+ m_toxAddressCopy.Show();
+ m_profileExport.Show();
}
- SendMessage(m_toxAddress.GetHwnd(), EM_LIMITTEXT, TOX_ADDRESS_SIZE * 2, 0);
- SendMessage(m_nickname.GetHwnd(), EM_LIMITTEXT, TOX_MAX_NAME_LENGTH, 0);
- SendMessage(m_password.GetHwnd(), EM_LIMITTEXT, 32, 0);
- SendMessage(m_group.GetHwnd(), EM_LIMITTEXT, 64, 0);
+ m_passwordCreate.Enable(m_proto->IsOnline());
+ m_passwordChange.Enable(m_proto->IsOnline());
+ m_passwordRemove.Enable(m_proto->IsOnline());
+
+ pass_ptrW password(m_proto->getWStringA(TOX_SETTINGS_PASSWORD));
+ bool passwordExists = mir_wstrlen(password) > 0;
+ m_passwordCreate.Show(!passwordExists);
+ m_passwordChange.Show(passwordExists);
+ m_passwordRemove.Show(passwordExists);
+
+ m_toxAddress.SetMaxLength(TOX_ADDRESS_SIZE * 2);
+ m_nickname.SetMaxLength(TOX_MAX_NAME_LENGTH);
+ m_group.SetMaxLength(64);
m_maxConnectRetriesSpin.SetRange(255, 1);
m_maxConnectRetriesSpin.SetPosition(m_proto->getByte("MaxConnectRetries", TOX_MAX_CONNECT_RETRIES));
@@ -54,6 +73,31 @@ void CToxOptionsMain::OnInitDialog()
m_maxReconnectRetriesSpin.SetPosition(m_proto->getByte("MaxReconnectRetries", TOX_MAX_RECONNECT_RETRIES));
}
+void CToxOptionsMain::PasswordCreate_OnClick(CCtrlButton*)
+{
+ m_proto->OnCreatePassword(0, 0);
+}
+
+void CToxOptionsMain::PasswordChange_OnClick(CCtrlButton*)
+{
+ m_proto->OnChangePassword(0, 0);
+}
+
+void CToxOptionsMain::PasswordRemove_OnClick(CCtrlButton*)
+{
+ m_proto->OnRemovePassword(0, 0);
+ pass_ptrW password(m_proto->getWStringA(TOX_SETTINGS_PASSWORD));
+ bool passwordExists = mir_wstrlen(password) > 0;
+ m_passwordCreate.Show(!passwordExists);
+ m_passwordChange.Show(passwordExists);
+ m_passwordRemove.Show(passwordExists);
+}
+
+void CToxOptionsMain::EnableUdp_OnClick(CCtrlBase*)
+{
+ m_enableUdpHolePunching.Enable(m_enableUdp.GetState());
+}
+
void CToxOptionsMain::ToxAddressCopy_OnClick(CCtrlButton*)
{
char *toxAddress = m_toxAddress.GetTextA();
@@ -94,7 +138,6 @@ void CToxOptionsMain::ProfileCreate_OnClick(CCtrlButton*)
m_toxAddress.SetTextA(ptrA(m_proto->getStringA(TOX_SETTINGS_ID)));
m_nickname.SetText(ptrW(m_proto->getWStringA("Nick")));
- m_password.SetText(ptrW(m_proto->getWStringA("Password")));
ShowWindow(m_profileCreate.GetHwnd(), FALSE);
ShowWindow(m_profileImport.GetHwnd(), FALSE);
@@ -189,8 +232,8 @@ void CToxOptionsMain::ProfileExport_OnClick(CCtrlButton*)
void CToxOptionsMain::OnApply()
{
ptrW group(m_group.GetText());
- if (mir_wstrcmp(group, m_proto->wszGroup)) {
- m_proto->wszGroup = mir_wstrdup(group);
+ if (mir_wstrcmp(group, m_proto->m_defaultGroup)) {
+ m_proto->m_defaultGroup = mir_wstrdup(group);
Clist_GroupCreate(0, group);
}
@@ -198,111 +241,9 @@ void CToxOptionsMain::OnApply()
CallProtoService(m_proto->m_szModuleName, PS_SETMYNICKNAME, SMNN_UNICODE, (LPARAM)ptrW(m_nickname.GetText()));
// todo: add checkbox
- m_proto->setWString("Password", pass_ptrT(m_password.GetText()));
-
- m_proto->SaveToxProfile(m_proto->toxThread->Tox());
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////
-
-CToxOptionsMultimedia::CToxOptionsMultimedia(CToxProto *proto)
- : CToxDlgBase(proto, IDD_OPTIONS_MULTIMEDIA, false),
- m_audioInput(this, IDC_AUDIOINPUT),
- m_audioOutput(this, IDC_AUDIOOUTPUT)
-{}
-
-void CToxOptionsMultimedia::EnumDevices(CCtrlCombo &combo, IMMDeviceEnumerator *pEnumerator, EDataFlow dataFlow, const char* setting)
-{
- LPWSTR pwszDefID = nullptr;
- ptrW wszDefID(m_proto->getWStringA(setting));
- if (wszDefID != NULL) {
- size_t len = mir_wstrlen(wszDefID) + 1;
- pwszDefID = (LPWSTR)CoTaskMemAlloc(len * 2);
- mir_wstrncpy(pwszDefID, wszDefID, len);
- }
- else {
- CComPtr<IMMDevice> pDevice = nullptr;
- if (FAILED(pEnumerator->GetDefaultAudioEndpoint(dataFlow, eConsole, &pDevice))) return;
- if (FAILED(pDevice->GetId(&pwszDefID))) return;
- }
-
- CComPtr<IMMDeviceCollection> pDevices = nullptr;
- EXIT_ON_ERROR(pEnumerator->EnumAudioEndpoints(dataFlow, DEVICE_STATE_ACTIVE, &pDevices));
-
- UINT count;
- EXIT_ON_ERROR(pDevices->GetCount(&count));
-
- for (UINT i = 0; i < count; i++) {
- CComPtr<IMMDevice> pDevice = nullptr;
- EXIT_ON_ERROR(pDevices->Item(i, &pDevice));
-
- CComPtr<IPropertyStore> pProperties = nullptr;
- EXIT_ON_ERROR(pDevice->OpenPropertyStore(STGM_READ, &pProperties));
-
- PROPVARIANT varName;
- PropVariantInit(&varName);
- EXIT_ON_ERROR(pProperties->GetValue(PKEY_Device_FriendlyName, &varName));
-
- LPWSTR pwszID = nullptr;
- EXIT_ON_ERROR(pDevice->GetId(&pwszID));
- combo.InsertString(varName.pwszVal, i, (LPARAM)mir_wstrdup(pwszID));
- if (mir_wstrcmpi(pwszID, pwszDefID) == 0)
- combo.SetCurSel(i);
- CoTaskMemFree(pwszID);
-
- PropVariantClear(&varName);
- }
-
-Exit:
- CoTaskMemFree(pwszDefID);
-}
-
-void CToxOptionsMultimedia::OnInitDialog()
-{
- CToxDlgBase::OnInitDialog();
-
- CComPtr<IMMDeviceEnumerator> pEnumerator = nullptr;
- if (FAILED(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator)))
- return;
-
- EnumDevices(m_audioInput, pEnumerator, eCapture, "AudioInputDeviceID");
- EnumDevices(m_audioOutput, pEnumerator, eRender, "AudioOutputDeviceID");
-}
-
-void CToxOptionsMultimedia::OnApply()
-{
- int i = m_audioInput.GetCurSel();
- if (i == -1)
- m_proto->delSetting("AudioInputDeviceID");
- else {
- wchar_t* data = (wchar_t*)m_audioInput.GetItemData(i);
- m_proto->setWString("AudioInputDeviceID", data);
- }
-
- i = m_audioOutput.GetCurSel();
- if (i == -1)
- m_proto->delSetting("AudioOutputDeviceID");
- else {
- wchar_t* data = (wchar_t*)m_audioOutput.GetItemData(i);
- m_proto->setWString("AudioOutputDeviceID", data);
- }
-}
-
-void CToxOptionsMultimedia::OnDestroy()
-{
- int count = m_audioInput.GetCount();
- for (int i = 0; i < count; i++) {
- wchar_t* data = (wchar_t*)m_audioInput.GetItemData(i);
- mir_free(data);
-
- }
-
- count = m_audioOutput.GetCount();
- for (int i = 0; i < count; i++) {
- wchar_t* data = (wchar_t*)m_audioOutput.GetItemData(i);
- mir_free(data);
+ //m_proto->setWString("Password", pass_ptrW(m_password.GetText()));
+ m_proto->SaveToxProfile(m_proto->m_toxThread->Tox());
}
}
diff --git a/protocols/Tox/src/tox_options.h b/protocols/Tox/src/tox_options.h
index f134e3d554..5a85edea61 100644
--- a/protocols/Tox/src/tox_options.h
+++ b/protocols/Tox/src/tox_options.h
@@ -13,11 +13,16 @@ private:
CCtrlButton m_profileExport;
CCtrlEdit m_nickname;
- CCtrlEdit m_password;
CCtrlEdit m_group;
+ CCtrlButton m_passwordCreate;
+ CCtrlButton m_passwordChange;
+ CCtrlButton m_passwordRemove;
+
CCtrlCheck m_enableUdp;
+ CCtrlCheck m_enableUdpHolePunching;
CCtrlCheck m_enableIPv6;
+ CCtrlCheck m_enableLocalDiscovery;
CCtrlEdit m_maxConnectRetries;
CCtrlSpin m_maxConnectRetriesSpin;
@@ -27,6 +32,12 @@ private:
protected:
void OnInitDialog();
+ void PasswordCreate_OnClick(CCtrlButton*);
+ void PasswordChange_OnClick(CCtrlButton*);
+ void PasswordRemove_OnClick(CCtrlButton*);
+
+ void EnableUdp_OnClick(CCtrlBase*);
+
void ToxAddressCopy_OnClick(CCtrlButton*);
void ProfileCreate_OnClick(CCtrlButton*);
void ProfileImport_OnClick(CCtrlButton*);
@@ -50,29 +61,6 @@ public:
/////////////////////////////////////////////////////////////////////////////////
-class CToxOptionsMultimedia : public CToxDlgBase
-{
-private:
- typedef CToxDlgBase CSuper;
-
- CCtrlCombo m_audioInput;
- CCtrlCombo m_audioOutput;
-
-protected:
- void EnumDevices(CCtrlCombo &combo, IMMDeviceEnumerator *pEnumerator, EDataFlow dataFlow, const char* setting);
-
- void OnInitDialog();
- void OnApply();
- void OnDestroy();
-
-public:
- CToxOptionsMultimedia(CToxProto *proto);
-
- static CDlgBase *CreateOptionsPage(void *param) { return new CToxOptionsMultimedia((CToxProto*)param); }
-};
-
-/////////////////////////////////////////////////////////////////////////////////
-
class CToxNodeEditor : public CDlgBase
{
private:
diff --git a/protocols/Tox/src/tox_profile.cpp b/protocols/Tox/src/tox_profile.cpp
index a144eebee2..77f9285050 100644
--- a/protocols/Tox/src/tox_profile.cpp
+++ b/protocols/Tox/src/tox_profile.cpp
@@ -16,11 +16,25 @@ wchar_t* CToxProto::GetToxProfilePath(const wchar_t *accountName)
return profilePath;
}
+static INT_PTR CALLBACK EnterPassword(void *param)
+{
+ CToxProto *proto = (CToxProto*)param;
+
+ pass_ptrW password(proto->getWStringA(TOX_SETTINGS_PASSWORD));
+ if (mir_wstrlen(password) == 0) {
+ CToxEnterPasswordDlg passwordDlg(proto);
+ if (!passwordDlg.DoModal())
+ return 0;
+ password = proto->getWStringA(TOX_SETTINGS_PASSWORD);
+ }
+ return (INT_PTR)password.detach();
+}
+
bool CToxProto::LoadToxProfile(Tox_Options *options)
{
debugLogA(__FUNCTION__": loading tox profile");
- mir_cslock locker(profileLock);
+ mir_cslock lock(m_profileLock);
ptrW profilePath(GetToxProfilePath());
if (!IsFileExists(profilePath))
@@ -57,25 +71,25 @@ bool CToxProto::LoadToxProfile(Tox_Options *options)
fclose(profile);
if (tox_is_data_encrypted(data)) {
- pass_ptrA password(mir_utf8encodeW(pass_ptrT(getWStringA("Password"))));
- if (password == NULL || mir_strlen(password) == 0) {
- CToxPasswordEditor passwordEditor(this);
- if (!passwordEditor.DoModal()) {
- mir_free(data);
- return false;
- }
+ pass_ptrA password(mir_utf8encodeW(pass_ptrW((wchar_t*)CallFunctionSync(EnterPassword, this))));
+ if (mir_strlen(password) == 0) {
+ mir_free(data);
+ return false;
}
- uint8_t *encryptedData = (uint8_t*)mir_calloc(size - TOX_PASS_ENCRYPTION_EXTRA_LENGTH);
+
+ size_t decryptedSize = size - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
+ uint8_t *decryptedData = (uint8_t*)mir_calloc(decryptedSize);
TOX_ERR_DECRYPTION coreDecryptError;
- if (!tox_pass_decrypt(data, size, (uint8_t*)(char*)password, mir_strlen(password), encryptedData, &coreDecryptError)) {
+ if (!tox_pass_decrypt(data, size, (uint8_t*)(char*)password, mir_strlen(password), decryptedData, &coreDecryptError)) {
ShowNotification(TranslateT("Unable to decrypt Tox profile"), MB_ICONERROR);
debugLogA(__FUNCTION__": failed to decrypt tox profile (%d)", coreDecryptError);
+ delSetting(TOX_SETTINGS_PASSWORD);
mir_free(data);
return false;
}
mir_free(data);
- data = encryptedData;
- size -= TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
+ data = decryptedData;
+ size = decryptedSize;
}
if (data) {
@@ -90,24 +104,29 @@ bool CToxProto::LoadToxProfile(Tox_Options *options)
void CToxProto::SaveToxProfile(Tox *tox)
{
- mir_cslock locker(profileLock);
+ mir_cslock lock(m_profileLock);
size_t size = tox_get_savedata_size(tox);
- uint8_t *data = (uint8_t*)mir_calloc(size + TOX_PASS_ENCRYPTION_EXTRA_LENGTH);
+ uint8_t *data = (uint8_t*)mir_calloc(size);
tox_get_savedata(tox, data);
- /*pass_ptrA password(mir_utf8encodeW(pass_ptrT(getWStringA("Password"))));
+ pass_ptrA password(mir_utf8encodeW(pass_ptrW(getWStringA(TOX_SETTINGS_PASSWORD))));
if (password && mir_strlen(password))
{
TOX_ERR_ENCRYPTION coreEncryptError;
- if (!tox_pass_encrypt(data, size, (uint8_t*)(char*)password, mir_strlen(password), data, &coreEncryptError))
+ size_t encryptedSize = size + TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
+ uint8_t *encryptedData = (uint8_t*)mir_calloc(encryptedSize);
+ if (!tox_pass_encrypt(data, size, (uint8_t*)(char*)password, mir_strlen(password), encryptedData, &coreEncryptError))
{
debugLogA(__FUNCTION__": failed to encrypt tox profile");
mir_free(data);
+ mir_free(encryptedData);
return;
}
- size += TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
- }*/
+ mir_free(data);
+ data = encryptedData;
+ size = encryptedSize;
+ }
ptrW profilePath(GetToxProfilePath());
FILE *profile = _wfopen(profilePath, L"wb");
@@ -125,6 +144,13 @@ void CToxProto::SaveToxProfile(Tox *tox)
mir_free(data);
}
+int CToxProto::OnDeleteToxProfile()
+{
+ ptrW profilePath(GetToxProfilePath());
+ _wunlink(profilePath);
+ return 0;
+}
+
INT_PTR CToxProto::OnCopyToxID(WPARAM, LPARAM)
{
ptrA address(getStringA(TOX_SETTINGS_ID));
@@ -140,18 +166,169 @@ INT_PTR CToxProto::OnCopyToxID(WPARAM, LPARAM)
return 0;
}
-CToxPasswordEditor::CToxPasswordEditor(CToxProto *proto) :
- CToxDlgBase(proto, IDD_PASSWORD, false), ok(this, IDOK),
- password(this, IDC_PASSWORD), savePermanently(this, IDC_SAVEPERMANENTLY)
+INT_PTR CToxProto::OnCreatePassword(WPARAM, LPARAM)
+{
+ pass_ptrW password(getWStringA(TOX_SETTINGS_PASSWORD));
+ CToxCreatePasswordDlg passwordDlg(this);
+ passwordDlg.DoModal();
+ return 0;
+}
+
+INT_PTR CToxProto::OnChangePassword(WPARAM, LPARAM)
+{
+ CToxChangePasswordDlg passwordDlg(this);
+ passwordDlg.DoModal();
+ return 0;
+}
+
+INT_PTR CToxProto::OnRemovePassword(WPARAM, LPARAM)
+{
+ const wchar_t *message = TranslateT("Removing the password will lead to decryption of the profile.\r\nAre you sure to remove password?");
+ int result = MessageBox(NULL, message, TranslateT("Remove password"), MB_YESNO | MB_ICONQUESTION);
+ if (result == IDYES) {
+ delSetting(TOX_SETTINGS_PASSWORD);
+ SaveToxProfile(m_toxThread->Tox());
+ }
+ return 0;
+}
+
+/* ENTER PASSWORD */
+
+CToxEnterPasswordDlg::CToxEnterPasswordDlg(CToxProto *proto)
+ : CToxDlgBase(proto, IDD_PASSWORD_ENTER, false),
+ m_password(this, IDC_PASSWORD),
+ m_ok(this, IDOK)
+{
+ m_password.OnChange = Callback(this, &CToxEnterPasswordDlg::Password_OnChange);
+ m_ok.OnClick = Callback(this, &CToxEnterPasswordDlg::OnOk);
+}
+
+void CToxEnterPasswordDlg::OnInitDialog()
+{
+ m_ok.Disable();
+}
+
+void CToxEnterPasswordDlg::Password_OnChange(CCtrlBase*)
+{
+ m_ok.Enable(GetWindowTextLength(m_password.GetHwnd()) != 0);
+}
+
+void CToxEnterPasswordDlg::OnOk(CCtrlButton*)
{
- ok.OnClick = Callback(this, &CToxPasswordEditor::OnOk);
+ m_proto->setWString(TOX_SETTINGS_PASSWORD, pass_ptrW(m_password.GetText()));
+ EndDialog(m_hwnd, 1);
+}
+
+/* CREATE PASSWORD */
+
+CToxCreatePasswordDlg::CToxCreatePasswordDlg(CToxProto *proto)
+ : CToxDlgBase(proto, IDD_PASSWORD_CREATE, false),
+ m_newPassword(this, IDC_PASSWORD_NEW),
+ m_confirmPassword(this, IDC_PASSWORD_CONFIRM),
+ m_passwordValidation(this, IDC_PASSWORD_VALIDATION),
+ m_ok(this, IDOK)
+{
+ m_newPassword.OnChange = Callback(this, &CToxCreatePasswordDlg::Password_OnChange);
+ m_confirmPassword.OnChange = Callback(this, &CToxCreatePasswordDlg::Password_OnChange);
+ m_ok.OnClick = Callback(this, &CToxCreatePasswordDlg::OnOk);
}
-void CToxPasswordEditor::OnOk(CCtrlButton*)
+void CToxCreatePasswordDlg::OnInitDialog()
{
- pass_ptrT tszPassword(password.GetText());
- if (savePermanently.Enabled())
- m_proto->setWString("Password", tszPassword);
+ LOGFONT lf;
+ HFONT hFont = (HFONT)m_passwordValidation.SendMsg(WM_GETFONT, 0, 0);
+ GetObject(hFont, sizeof(lf), &lf);
+ lf.lfWeight = FW_BOLD;
+ m_passwordValidation.SendMsg(WM_SETFONT, (WPARAM)CreateFontIndirect(&lf), 0);
+
+ m_ok.Disable();
+}
+
+void CToxCreatePasswordDlg::Password_OnChange(CCtrlBase*)
+{
+ pass_ptrW newPassword(m_newPassword.GetText());
+ if (mir_wstrlen(newPassword) == 0) {
+ m_ok.Disable();
+ m_passwordValidation.SetText(TranslateT("New password is empty"));
+ return;
+ }
+
+ pass_ptrW confirmPassword(m_confirmPassword.GetText());
+ if (mir_wstrcmp(newPassword, confirmPassword) != 0) {
+ m_ok.Disable();
+ m_passwordValidation.SetText(TranslateT("New password is not equal to confirmation"));
+ return;
+ }
+
+ m_passwordValidation.SetText(L"");
+ m_ok.Enable();
+}
+
+void CToxCreatePasswordDlg::OnOk(CCtrlButton*)
+{
+ m_proto->setWString(TOX_SETTINGS_PASSWORD, pass_ptrW(m_newPassword.GetText()));
+ m_proto->SaveToxProfile(m_proto->m_toxThread->Tox());
+ EndDialog(m_hwnd, 1);
+}
+
+/* CHANGE PASSWORD */
+CToxChangePasswordDlg::CToxChangePasswordDlg(CToxProto *proto)
+ : CToxDlgBase(proto, IDD_PASSWORD_CHANGE, false),
+ m_oldPassword(this, IDC_PASSWORD),
+ m_newPassword(this, IDC_PASSWORD_NEW),
+ m_confirmPassword(this, IDC_PASSWORD_CONFIRM),
+ m_passwordValidation(this, IDC_PASSWORD_VALIDATION),
+ m_ok(this, IDOK)
+{
+ m_oldPassword.OnChange = Callback(this, &CToxChangePasswordDlg::Password_OnChange);
+ m_newPassword.OnChange = Callback(this, &CToxChangePasswordDlg::Password_OnChange);
+ m_confirmPassword.OnChange = Callback(this, &CToxChangePasswordDlg::Password_OnChange);
+ m_ok.OnClick = Callback(this, &CToxChangePasswordDlg::OnOk);
+}
+
+void CToxChangePasswordDlg::OnInitDialog()
+{
+ LOGFONT lf;
+ HFONT hFont = (HFONT)m_passwordValidation.SendMsg(WM_GETFONT, 0, 0);
+ GetObject(hFont, sizeof(lf), &lf);
+ lf.lfWeight = FW_BOLD;
+ m_passwordValidation.SendMsg(WM_SETFONT, (WPARAM)CreateFontIndirect(&lf), 0);
+
+ m_ok.Disable();
+}
+
+void CToxChangePasswordDlg::Password_OnChange(CCtrlBase*)
+{
+ pass_ptrW dbPassword(m_proto->getWStringA(TOX_SETTINGS_PASSWORD));
+ pass_ptrW oldPassword(m_oldPassword.GetText());
+ if (mir_wstrlen(dbPassword) > 0 && mir_wstrcmp(dbPassword, oldPassword) != 0) {
+ m_ok.Disable();
+ m_passwordValidation.SetText(TranslateT("Old password is not valid"));
+ return;
+ }
+
+ pass_ptrW newPassword(m_newPassword.GetText());
+ if (mir_wstrlen(newPassword) == 0) {
+ m_ok.Disable();
+ m_passwordValidation.SetText(TranslateT("New password is empty"));
+ return;
+ }
+
+ pass_ptrW confirmPassword(m_confirmPassword.GetText());
+ if (mir_wstrcmp(newPassword, confirmPassword) != 0) {
+ m_ok.Disable();
+ m_passwordValidation.SetText(TranslateT("New password is not equal to confirmation"));
+ return;
+ }
+
+ m_passwordValidation.SetText(L"");
+ m_ok.Enable();
+}
+
+void CToxChangePasswordDlg::OnOk(CCtrlButton*)
+{
+ m_proto->setWString(TOX_SETTINGS_PASSWORD, pass_ptrW(m_newPassword.GetText()));
+ m_proto->SaveToxProfile(m_proto->m_toxThread->Tox());
EndDialog(m_hwnd, 1);
}
diff --git a/protocols/Tox/src/tox_profile.h b/protocols/Tox/src/tox_profile.h
index 796f264d5b..4aedae071f 100644
--- a/protocols/Tox/src/tox_profile.h
+++ b/protocols/Tox/src/tox_profile.h
@@ -1,19 +1,66 @@
#ifndef _TOX_PROFILE_H_
#define _TOX_PROFILE_H_
-class CToxPasswordEditor : public CToxDlgBase
+/* ENTER PASSWORD */
+
+class CToxEnterPasswordDlg : public CToxDlgBase
{
private:
- CCtrlEdit password;
- CCtrlCheck savePermanently;
+ CCtrlEdit m_password;
+
+ CCtrlButton m_ok;
+
+protected:
+ void OnInitDialog();
+ void Password_OnChange(CCtrlBase*);
+ void OnOk(CCtrlButton*);
+
+public:
+ CToxEnterPasswordDlg(CToxProto *proto);
+};
+
+/* CREATE PASSWORD */
+
+class CToxCreatePasswordDlg : public CToxDlgBase
+{
+private:
+ CCtrlEdit m_newPassword;
+ CCtrlEdit m_confirmPassword;
+
+ CCtrlBase m_passwordValidation;
+
+ CCtrlButton m_ok;
+
+protected:
+ void OnInitDialog();
+ void Password_OnChange(CCtrlBase*);
+ void OnOk(CCtrlButton*);
+
+public:
+ CToxCreatePasswordDlg(CToxProto *proto);
+};
+
+/* CHANGE PASSWORD */
+
+class CToxChangePasswordDlg : public CToxDlgBase
+{
+private:
+ CCtrlEdit m_oldPassword;
+
+ CCtrlEdit m_newPassword;
+ CCtrlEdit m_confirmPassword;
- CCtrlButton ok;
+ CCtrlBase m_passwordValidation;
+
+ CCtrlButton m_ok;
protected:
+ void OnInitDialog();
+ void Password_OnChange(CCtrlBase*);
void OnOk(CCtrlButton*);
public:
- CToxPasswordEditor(CToxProto *proto);
+ CToxChangePasswordDlg(CToxProto *proto);
};
#endif //_TOX_PROFILE_H_ \ No newline at end of file
diff --git a/protocols/Tox/src/tox_proto.cpp b/protocols/Tox/src/tox_proto.cpp
index 5b6d345c9c..60864594e7 100644
--- a/protocols/Tox/src/tox_proto.cpp
+++ b/protocols/Tox/src/tox_proto.cpp
@@ -2,26 +2,22 @@
CToxProto::CToxProto(const char* protoName, const wchar_t* userName)
: PROTO<CToxProto>(protoName, userName),
- toxThread(nullptr), isTerminated(false),
+ m_toxThread(nullptr), isTerminated(false),
hCheckingThread(nullptr), hPollingThread(nullptr),
hMessageProcess(1)
{
InitNetlib();
- wszAccountName = mir_wstrdup(userName);
- wszGroup = getWStringA(TOX_SETTINGS_GROUP);
- if (wszGroup == nullptr)
- wszGroup = mir_wstrdup(L"Tox");
- Clist_GroupCreate(0, wszGroup);
+ m_accountName = mir_wstrdup(userName);
+ m_defaultGroup = getWStringA(TOX_SETTINGS_GROUP);
+ if (m_defaultGroup == nullptr)
+ m_defaultGroup = mir_wstrdup(L"Tox");
+ Clist_GroupCreate(0, m_defaultGroup);
CreateProtoService(PS_CREATEACCMGRUI, &CToxProto::OnAccountManagerInit);
SetAllContactsStatus(ID_STATUS_OFFLINE);
- // services
- CreateProtoService(PSR_AUDIO, &CToxProto::OnRecvAudioCall);
- CreateProtoService("/Audio/Ring", &CToxProto::OnAudioRing);
-
// avatars
CreateProtoService(PS_GETAVATARCAPS, &CToxProto::GetAvatarCaps);
CreateProtoService(PS_GETAVATARINFO, &CToxProto::GetAvatarInfo);
@@ -31,15 +27,11 @@ CToxProto::CToxProto(const char* protoName, const wchar_t* userName)
// nick
CreateProtoService(PS_SETMYNICKNAME, &CToxProto::SetMyNickname);
- // hAudioDialogs = WindowList_Create();
-
hTerminateEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
}
CToxProto::~CToxProto()
{
- WindowList_Destroy(hAudioDialogs);
-
UninitNetlib();
}
@@ -151,15 +143,13 @@ int CToxProto::SetStatus(int iNewStatus)
int old_status = m_iStatus;
m_iDesiredStatus = iNewStatus;
+ // logout
if (iNewStatus == ID_STATUS_OFFLINE) {
- // logout
isTerminated = true;
SetEvent(hTerminateEvent);
- if (!Miranda_IsTerminated()) {
+ if (!Miranda_IsTerminated())
SetAllContactsStatus(ID_STATUS_OFFLINE);
- //CloseAllChatChatSessions();
- }
m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE;
ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus);
@@ -169,19 +159,20 @@ int CToxProto::SetStatus(int iNewStatus)
if (old_status >= ID_STATUS_CONNECTING && old_status < ID_STATUS_OFFLINE)
return 0;
+ // login
if (old_status == ID_STATUS_OFFLINE && !IsOnline()) {
- // login
isTerminated = false;
m_iStatus = ID_STATUS_CONNECTING;
hPollingThread = ForkThreadEx(&CToxProto::PollingThread, nullptr, nullptr);
+ ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus);
+ return 0;
}
- else {
- // set tox status
- m_iStatus = iNewStatus;
- tox_self_set_status(toxThread->Tox(), MirandaToToxStatus(iNewStatus));
- }
-
+
+ // change status
+ m_iStatus = iNewStatus;
+ tox_self_set_status(m_toxThread->Tox(), MirandaToToxStatus(iNewStatus));
ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus);
+
return 0;
}
@@ -200,7 +191,7 @@ int CToxProto::SetAwayMsg(int, const wchar_t *msg)
if (IsOnline()) {
T2Utf statusMessage(msg);
TOX_ERR_SET_INFO error;
- if (!tox_self_set_status_message(toxThread->Tox(), (uint8_t*)(char*)statusMessage, min(TOX_MAX_STATUS_MESSAGE_LENGTH, mir_strlen(statusMessage)), &error))
+ if (!tox_self_set_status_message(m_toxThread->Tox(), (uint8_t*)(char*)statusMessage, min(TOX_MAX_STATUS_MESSAGE_LENGTH, mir_strlen(statusMessage)), &error))
debugLogA(__FUNCTION__": failed to set status status message %s (%d)", msg, error);
}
@@ -228,9 +219,7 @@ int CToxProto::OnEvent(PROTOEVENTTYPE iEventType, WPARAM wParam, LPARAM lParam)
return OnInitStatusMenu();
case EV_PROTO_ONERASE:
- ptrW profilePath(GetToxProfilePath());
- _wunlink(profilePath);
- break;
+ return OnDeleteToxProfile();
}
return 1;
diff --git a/protocols/Tox/src/tox_proto.h b/protocols/Tox/src/tox_proto.h
index 810479ab30..24896724d7 100644
--- a/protocols/Tox/src/tox_proto.h
+++ b/protocols/Tox/src/tox_proto.h
@@ -3,13 +3,11 @@
struct CToxProto : public PROTO<CToxProto>
{
- friend CToxPasswordEditor;
+ friend CToxEnterPasswordDlg;
+ friend CToxCreatePasswordDlg;
+ friend CToxChangePasswordDlg;
friend CToxOptionsMain;
friend CToxOptionsNodeList;
- friend CToxCallDlgBase;
- friend CToxIncomingCall;
- friend CToxOutgoingCall;
- friend CToxCallDialog;
public:
//////////////////////////////////////////////////////////////////////////////////////
@@ -58,20 +56,18 @@ public:
static void InitIcons();
// menus
- static void InitMenus();
-
- // events
- void InitCustomDbEvents();
-
- static int OnModulesLoaded(WPARAM, LPARAM);
+ static void InitContactMenu();
// utils
static void ShowNotification(const wchar_t *message, int flags = 0, MCONTACT hContact = NULL);
+ static INT_PTR ParseToxUri(WPARAM, LPARAM lParam);
+
private:
- CToxThread *toxThread;
- mir_cs profileLock;
- ptrW wszAccountName, wszGroup;
+ CToxThread *m_toxThread;
+ mir_cs m_profileLock;
+ ptrW m_accountName;
+ ptrW m_defaultGroup;
CTransferList transfers;
ULONG hMessageProcess;
@@ -90,8 +86,12 @@ private:
bool LoadToxProfile(Tox_Options *options);
void SaveToxProfile(Tox *tox);
+ int OnDeleteToxProfile();
INT_PTR __cdecl OnCopyToxID(WPARAM, LPARAM);
+ INT_PTR __cdecl OnCreatePassword(WPARAM, LPARAM);
+ INT_PTR __cdecl OnChangePassword(WPARAM, LPARAM);
+ INT_PTR __cdecl OnRemovePassword(WPARAM, LPARAM);
// tox core
Tox_Options* GetToxOptions();
@@ -141,7 +141,9 @@ private:
int OnPrebuildContactMenu(WPARAM hContact, LPARAM);
static int PrebuildContactMenu(WPARAM hContact, LPARAM lParam);
+ HGENMENU StatusMenuItems[SMI_MAX];
int OnInitStatusMenu();
+ int __cdecl PrebuildStatusMenu(WPARAM, LPARAM);
//services
INT_PTR __cdecl SetMyNickname(WPARAM wParam, LPARAM lParam);
@@ -149,8 +151,6 @@ private:
// options
int __cdecl OnOptionsInit(WPARAM wParam, LPARAM lParam);
- // events
-
// userinfo
static INT_PTR CALLBACK UserInfoProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int __cdecl OnUserInfoInit(WPARAM wParam, LPARAM lParam);
@@ -193,35 +193,11 @@ private:
HWND __cdecl OnSearchAdvanced(HWND owner);
HWND __cdecl OnCreateExtendedSearchUI(HWND owner);
- // chat rooms
- //MCONTACT GetChatRoom(const char *pubKey);
- MCONTACT GetChatRoom(int groupNumber);
-
- //MCONTACT GetChatRoom(const char *pubKey);
- MCONTACT AddChatRoom(int groupNumber);
-
- void __cdecl LoadChatRoomList(void*);
-
- int __cdecl OnGroupChatEventHook(WPARAM, LPARAM lParam);
- int __cdecl OnGroupChatMenuHook(WPARAM, LPARAM lParam);
-
- INT_PTR __cdecl OnJoinChatRoom(WPARAM hContact, LPARAM);
- INT_PTR __cdecl OnLeaveChatRoom(WPARAM hContact, LPARAM);
- INT_PTR __cdecl OnCreateChatRoom(WPARAM, LPARAM);
-
- //void InitGroupChatModule();
- //void CloseAllChatChatSessions();
-
- static void OnGroupChatInvite(Tox *tox, int32_t friendNumber, uint8_t type, const uint8_t *data, const uint16_t length, void *arg);
-
- void ChatValidateContact(HWND hwndList, const std::vector<MCONTACT> &contacts, MCONTACT hContact = NULL);
- void ChatPrepare(HWND hwndList, const std::vector<MCONTACT> &contacts, MCONTACT hContact = NULL);
- static std::vector<MCONTACT> GetInvitedContacts(HWND hwndList, MCONTACT hContact = NULL);
- static INT_PTR CALLBACK ChatRoomInviteProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
-
// messages
std::map<uint64_t, UINT> messages;
+ void InitCustomDbEvents();
+
void __cdecl SendMessageAsync(void *arg);
int OnSendMessage(MCONTACT hContact, const char *message);
@@ -266,30 +242,6 @@ private:
void OnGotFriendAvatarInfo(AvatarTransferParam *transfer);
void OnGotFriendAvatarData(AvatarTransferParam *transfer);
- // multimedia
- MWindowList hAudioDialogs;
- HWAVEOUT hOutDevice;
- std::map<MCONTACT, int32_t> calls;
-
- //ToxAvCSettings* GetAudioCSettings();
-
-
- INT_PTR __cdecl OnRecvAudioCall(WPARAM wParam, LPARAM lParam);
- INT_PTR __cdecl OnAudioRing(WPARAM wParam, LPARAM lParam);
-
- INT_PTR __cdecl OnSendAudioCall(WPARAM wParam, LPARAM);
-
- static void OnFriendCall(ToxAV *toxAV, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *arg);
- static void OnFriendCallState(ToxAV *toxAV, uint32_t friend_number, uint32_t state, void *user_data);
- static void OnBitrateChanged(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, void *arg);
- static void OnFriendAudioFrame(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, void *user_data);
-
- //static void OnAvEnd(void*, int32_t callId, void *arg);
- //static void OnAvReject(void*, int32_t callId, void *arg);
- //static void OnAvCancel(void*, int32_t callId, void *arg);
- //static void OnAvCallTimeout(void*, int32_t callId, void *arg);
- //static void OnAvPeerTimeout(void*, int32_t callId, void *arg);
-
// utils
static int MapStatus(int status);
static TOX_USER_STATUS MirandaToToxStatus(int status);
@@ -298,15 +250,12 @@ private:
static wchar_t* ToxErrorToString(TOX_ERR_NEW error);
static wchar_t* ToxErrorToString(TOX_ERR_FRIEND_SEND_MESSAGE error);
-
static void ShowNotification(const wchar_t *caption, const wchar_t *message, int flags = 0, MCONTACT hContact = NULL);
static bool IsFileExists(const wchar_t* path);
MEVENT AddEventToDb(MCONTACT hContact, WORD type, DWORD timestamp, DWORD flags, PBYTE pBlob, size_t cbBlob);
- static INT_PTR ParseToxUri(WPARAM, LPARAM lParam);
-
template<INT_PTR(__cdecl CToxProto::*Service)(WPARAM, LPARAM)>
static INT_PTR __cdecl GlobalService(WPARAM wParam, LPARAM lParam)
{
diff --git a/protocols/Tox/src/tox_search.cpp b/protocols/Tox/src/tox_search.cpp
index d03d3a091a..d8077fedd1 100644
--- a/protocols/Tox/src/tox_search.cpp
+++ b/protocols/Tox/src/tox_search.cpp
@@ -226,12 +226,7 @@ HWND CToxProto::OnSearchAdvanced(HWND owner)
PROTOSEARCHRESULT psr = { sizeof(psr) };
psr.flags = PSR_UTF8;
psr.id.a = mir_strdup(query.c_str());
-
- ADDCONTACTSTRUCT acs = { HANDLE_SEARCHRESULT };
- acs.szProto = m_szModuleName;
- acs.psr = &psr;
-
- CallService(MS_ADDCONTACT_SHOW, (WPARAM)owner, (LPARAM)&acs);
+ Contact_AddBySearch(m_szModuleName, &psr, owner);
ForkThread(&CToxProto::SearchFailedAsync, nullptr);
}
diff --git a/protocols/Tox/src/tox_services.cpp b/protocols/Tox/src/tox_services.cpp
index 532eef79d7..a2c9e549a9 100644
--- a/protocols/Tox/src/tox_services.cpp
+++ b/protocols/Tox/src/tox_services.cpp
@@ -8,7 +8,7 @@ INT_PTR CToxProto::SetMyNickname(WPARAM wParam, LPARAM lParam)
if (IsOnline()) {
T2Utf szNick8(nickname);
TOX_ERR_SET_INFO error;
- if (!tox_self_set_name(toxThread->Tox(), szNick8, mir_strlen(szNick8), &error))
+ if (!tox_self_set_name(m_toxThread->Tox(), szNick8, mir_strlen(szNick8), &error))
debugLogA(__FUNCTION__": failed to set nick name");
}
diff --git a/protocols/Tox/src/tox_thread.h b/protocols/Tox/src/tox_thread.h
index ae0f4225f8..37372177dc 100644
--- a/protocols/Tox/src/tox_thread.h
+++ b/protocols/Tox/src/tox_thread.h
@@ -5,22 +5,16 @@ class CToxThread
{
private:
Tox *tox;
- ToxAV *toxAV;
public:
CToxThread(Tox_Options *options, TOX_ERR_NEW *error = NULL)
- : tox(NULL), toxAV(NULL)
+ : tox(NULL)
{
tox = tox_new(options, error);
}
~CToxThread()
{
- if (toxAV)
- {
- toxav_kill(toxAV);
- toxAV = NULL;
- }
if (tox)
{
@@ -33,11 +27,6 @@ public:
{
return tox;
}
-
- ToxAV* ToxAV()
- {
- return toxAV;
- }
};
#endif //_TOX_THREAD_H_ \ No newline at end of file
diff --git a/protocols/Tox/src/tox_transfer.cpp b/protocols/Tox/src/tox_transfer.cpp
index 3fb9ad77b7..6becdc1a26 100644
--- a/protocols/Tox/src/tox_transfer.cpp
+++ b/protocols/Tox/src/tox_transfer.cpp
@@ -96,7 +96,7 @@ int CToxProto::OnFileResume(HANDLE hTransfer, int *action, const wchar_t **szFil
FileTransferParam *transfer = (FileTransferParam*)hTransfer;
if (*action == FILERESUME_SKIP) {
- tox_file_control(toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, nullptr);
+ tox_file_control(m_toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, nullptr);
transfers.Remove(transfer);
return 0;
}
@@ -104,22 +104,22 @@ int CToxProto::OnFileResume(HANDLE hTransfer, int *action, const wchar_t **szFil
if (*action == FILERESUME_RENAME)
transfer->ChangeName(*szFilename);
- ToxHexAddress pubKey = GetContactPublicKey(toxThread->Tox(), transfer->friendNumber);
+ ToxHexAddress pubKey = GetContactPublicKey(m_toxThread->Tox(), transfer->friendNumber);
wchar_t *mode = *action == FILERESUME_OVERWRITE ? L"wb" : L"ab";
if (!transfer->OpenFile(mode)) {
debugLogA(__FUNCTION__": failed to open file (%d) from %s(%d)", transfer->fileNumber, (const char*)pubKey, transfer->friendNumber);
- tox_file_control(toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, nullptr);
+ tox_file_control(m_toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, nullptr);
transfers.Remove(transfer);
return NULL;
}
TOX_ERR_FILE_CONTROL error;
debugLogA(__FUNCTION__": start receiving file (%d) from %s(%d)", transfer->fileNumber, (const char*)pubKey, transfer->friendNumber);
- if (!tox_file_control(toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_RESUME, &error)) {
+ if (!tox_file_control(m_toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_RESUME, &error)) {
debugLogA(__FUNCTION__": failed to start receiving of file(%d) from %s(%d) cause (%d)", transfer->fileNumber, (const char*)pubKey, transfer->friendNumber, error);
ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0);
- tox_file_control(toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, nullptr);
+ tox_file_control(m_toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, nullptr);
transfers.Remove(transfer);
}
@@ -128,7 +128,7 @@ int CToxProto::OnFileResume(HANDLE hTransfer, int *action, const wchar_t **szFil
void CToxProto::OnTransferCompleted(FileTransferParam *transfer)
{
- ToxHexAddress pubKey = GetContactPublicKey(toxThread->Tox(), transfer->friendNumber);
+ ToxHexAddress pubKey = GetContactPublicKey(m_toxThread->Tox(), transfer->friendNumber);
debugLogA(__FUNCTION__": finised the transfer of file (%d) from %s(%d)", transfer->fileNumber, (const char*)pubKey, transfer->friendNumber);
bool isFileFullyTransfered = transfer->pfts.currentFileProgress == transfer->pfts.currentFileSize;
@@ -177,7 +177,7 @@ void CToxProto::OnDataReceiving(Tox *tox, uint32_t friendNumber, uint32_t fileNu
if (fwrite(data, sizeof(uint8_t), length, transfer->hFile) != length) {
proto->debugLogA(__FUNCTION__": failed write to file (%d)", fileNumber);
proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0);
- tox_file_control(proto->toxThread->Tox(), friendNumber, fileNumber, TOX_FILE_CONTROL_CANCEL, nullptr);
+ tox_file_control(proto->m_toxThread->Tox(), friendNumber, fileNumber, TOX_FILE_CONTROL_CANCEL, nullptr);
return;
}
@@ -210,11 +210,11 @@ HANDLE CToxProto::OnSendFile(MCONTACT hContact, const wchar_t*, wchar_t **ppszFi
uint64_t fileSize = _ftelli64(hFile);
rewind(hFile);
- ToxHexAddress pubKey = GetContactPublicKey(toxThread->Tox(), friendNumber);
+ ToxHexAddress pubKey = GetContactPublicKey(m_toxThread->Tox(), friendNumber);
char *name = mir_utf8encodeW(fileName);
TOX_ERR_FILE_SEND sendError;
- uint32_t fileNumber = tox_file_send(toxThread->Tox(), friendNumber, TOX_FILE_KIND_DATA, fileSize, nullptr, (uint8_t*)name, mir_strlen(name), &sendError);
+ uint32_t fileNumber = tox_file_send(m_toxThread->Tox(), friendNumber, TOX_FILE_KIND_DATA, fileSize, nullptr, (uint8_t*)name, mir_strlen(name), &sendError);
if (sendError != TOX_ERR_FILE_SEND_OK) {
debugLogA(__FUNCTION__": failed to send file (%d) to %s(%d) cause (%d)", fileNumber, (const char*)pubKey, friendNumber, sendError);
mir_free(fileDir);
@@ -272,14 +272,14 @@ void CToxProto::OnFileSendData(Tox *tox, uint32_t friendNumber, uint32_t fileNum
}
TOX_ERR_FILE_SEND_CHUNK error;
- if (!tox_file_send_chunk(proto->toxThread->Tox(), friendNumber, fileNumber, position, data, length, &error)) {
+ if (!tox_file_send_chunk(proto->m_toxThread->Tox(), friendNumber, fileNumber, position, data, length, &error)) {
if (error == TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED) {
mir_free(data);
return;
}
proto->debugLogA(__FUNCTION__": failed to send file chunk (%d) to %s(%d) cause (%d)", fileNumber, (const char*)pubKey, friendNumber, error);
proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0);
- tox_file_control(proto->toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, nullptr);
+ tox_file_control(proto->m_toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, nullptr);
mir_free(data);
return;
}
@@ -296,7 +296,7 @@ int CToxProto::CancelTransfer(MCONTACT, HANDLE hTransfer)
{
FileTransferParam *transfer = (FileTransferParam*)hTransfer;
debugLogA(__FUNCTION__": Transfer (%d) is canceled", transfer->fileNumber);
- tox_file_control(toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, nullptr);
+ tox_file_control(m_toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, nullptr);
transfers.Remove(transfer);
return 0;
@@ -308,13 +308,13 @@ void CToxProto::PauseOutgoingTransfers(uint32_t friendNumber)
// only for sending
FileTransferParam *transfer = transfers.GetAt(i);
if (transfer->friendNumber == friendNumber && transfer->GetDirection() == 0) {
- ToxHexAddress pubKey = GetContactPublicKey(toxThread->Tox(), friendNumber);
+ ToxHexAddress pubKey = GetContactPublicKey(m_toxThread->Tox(), friendNumber);
debugLogA(__FUNCTION__": sending ask to pause the transfer of file (%d) to %s(%d)", transfer->fileNumber, (const char*)pubKey, transfer->friendNumber);
TOX_ERR_FILE_CONTROL error;
- if (!tox_file_control(toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_PAUSE, &error)) {
+ if (!tox_file_control(m_toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_PAUSE, &error)) {
debugLogA(__FUNCTION__": failed to pause the transfer (%d) to %s(%d) cause(%d)", transfer->fileNumber, (const char*)pubKey, transfer->friendNumber, error);
- tox_file_control(toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, nullptr);
+ tox_file_control(m_toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, nullptr);
}
}
}
@@ -326,11 +326,11 @@ void CToxProto::ResumeIncomingTransfers(uint32_t friendNumber)
// only for receiving
FileTransferParam *transfer = transfers.GetAt(i);
if (transfer->friendNumber == friendNumber && transfer->GetDirection() == 1) {
- ToxHexAddress pubKey = GetContactPublicKey(toxThread->Tox(), friendNumber);
+ ToxHexAddress pubKey = GetContactPublicKey(m_toxThread->Tox(), friendNumber);
debugLogA(__FUNCTION__": sending ask to resume the transfer of file (%d) from %s(%d) cause(%d)", transfer->fileNumber, (const char*)pubKey, transfer->friendNumber);
TOX_ERR_FILE_CONTROL error;
- if (!tox_file_control(toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_RESUME, &error)) {
+ if (!tox_file_control(m_toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_RESUME, &error)) {
debugLogA(__FUNCTION__": failed to resume the transfer (%d) from %s(%d) cause(%d)", transfer->fileNumber, (const char*)pubKey, transfer->friendNumber, error);
CancelTransfer(NULL, transfer);
}
diff --git a/protocols/Tox/src/tox_utils.cpp b/protocols/Tox/src/tox_utils.cpp
index 722517c427..130e08eaec 100644
--- a/protocols/Tox/src/tox_utils.cpp
+++ b/protocols/Tox/src/tox_utils.cpp
@@ -165,11 +165,6 @@ INT_PTR CToxProto::ParseToxUri(WPARAM, LPARAM lParam)
PROTOSEARCHRESULT psr = { sizeof(psr) };
psr.flags = PSR_UTF8;
psr.id.a = mir_u2a(&uri[4]);
-
- ADDCONTACTSTRUCT acs = { HANDLE_SEARCHRESULT };
- acs.szProto = proto->m_szModuleName;
- acs.psr = &psr;
-
- CallService(MS_ADDCONTACT_SHOW, 0, (LPARAM)&acs);
+ Contact_AddBySearch(proto->m_szModuleName, &psr);
return 0;
}
diff --git a/protocols/Tox/src/version.h b/protocols/Tox/src/version.h
index ba58f1f238..9e50bf1249 100644
--- a/protocols/Tox/src/version.h
+++ b/protocols/Tox/src/version.h
@@ -1,7 +1,7 @@
#define __MAJOR_VERSION 0
#define __MINOR_VERSION 11
-#define __RELEASE_NUM 1
-#define __BUILD_NUM 26
+#define __RELEASE_NUM 3
+#define __BUILD_NUM 0
#include <stdver.h>
@@ -9,6 +9,5 @@
#define __FILENAME "Tox.dll"
#define __DESCRIPTION "Tox protocol support for Miranda NG."
#define __AUTHOR "Miranda NG Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/Tox/"
#define __COPYRIGHT "© 2014-17 Miranda NG Team"
diff --git a/protocols/Tox/tools/CHANGES b/protocols/Tox/tools/CHANGES
deleted file mode 100644
index c2f308e980..0000000000
--- a/protocols/Tox/tools/CHANGES
+++ /dev/null
@@ -1,266 +0,0 @@
-
-This is the CHANGES file for cv2pdb, a
-converter of DMD CodeView/DWARF debug information to PDB files
-
-Copyright (c) 2009-2012 by Rainer Schuetze, All Rights Reserved
-
-Version history
----------------
-
-2009-05-08 Version 0.1
-
- * initial release
-
-2009-05-16 Version 0.2
-
- * replace .debug section in executable rather than rename it. (only works
- if it is the last section).
- * support for field type LF_VFUNCTAB and symbol type S_CONSTANT used by DMC.
- * added stringview to autoexp.dat for full length text display.
-
-2009-06-04 Version 0.3
-
- * static members' debug info was not correctly converted, causing debugger confusion
- * now works on executables compiled by DMC
- - added command line switch -C to disable some D feature and
- to remove function name from local variables
- - added support for type LF_BITFIELD.
- * added fields __viewhelper to classes string and object
- * new addin dviewhelper.dll to display correctly terminated strings
- and derived object type
-
-2009-06-05 Version 0.4
-
- * fixed crash when long is used as index or element type of dynamic or
- associative arrays
-
-2009-06-06 Version 0.5
-
- * fixed error in __viewhelper field of string type, that could screw up type info
- * added support for wstring and dstring
- * fixed problems with debug info inside library by combining debug info of different modules
- into a single pseudo-module
- * now also replaces '.' by '@' in enumerator types for more consistent debug info
-
-2009-06-07 Version 0.6
-
- * removed LF_DERIVED info from debug info, as it is inconsistent in DMD generated info
- with more than 4096 type entries
-
-2009-06-08 Version 0.7
-
- * corrected number of field entries in classes or struct, because DMD miscounts private members
-
-2009-06-11 Version 0.8
-
- * tweaked visualizer macros to detect uninitialized associative arrays and to limit expansion
- to arrays with less than 1024 entries
- * renamed data pointer member of dynamic arrays to "ptr" to be consistent with the array property
- in D.
-
-2009-06-19 Version 0.9
-
- * fixed line number info at the end of a segment or when switching to another file
- because of inline expansion
- * fixed line numbers > 32767 and sections with 0 line number entries
-
-2009-08-12 Version 0.10
-
- * better support for DMC:
- - entries LF_FRIENDFCN removed
- - entries LF_FRIENDCLS, LF_VBCLASS and LF_IVBCLASS converted
- thanks to Andrew.
- * derived-classes info in class entry now cleared to be consistent with removal of LF_DERIVED
-
-2009-12-29 Version 0.11
-
- * basic types now show with their D names, not as C types
- * "enum" prefix removed from type names of enumerator types
- * added type information for complex data types
- * dmd-patch needed for long/ulong support (http://d.puremagic.com/issues/show_bug.cgi?id=3373)
- * experimental hack to add lexical scope to local variables (dmd patch in
- http://d.puremagic.com/issues/show_bug.cgi?id=3657 needed)
-
-2010-04-13 Version 0.12
-
- * added patch to convert binaries produced by Metroworks CodeWarrior
- * names of local function are now demangled
- * dmd 2.041 fixes long/ulong support (patch http://d.puremagic.com/issues/show_bug.cgi?id=3373
- no longer needed)
- * added managed C++ project to integrate cv2pdb with CLR (thanks to Alexander Bothe)
- * dmd 2.043 uses different implementation of associative arrays, use command line
- option -D 2.043 or above to produce the respective debug info
-
-2010-06-03 Version 0.13
-
- * adapted to mspdb100.dll which comes with VS2010
- * tweaked autoexp.dat modifications to be more stable with uninitialized data
- * autoexp.snippet now split into two files: autoexp.expand and autoexp.visualizer
-
-2010-06-23 Version 0.14
-
- * 64-integer types are now displayed as "dlong" and "ulong" instead of "__int64" and
- "unsigned __int64"
- * improved support for long and ulong for DMD versions before 1.057 and 2.041
- * DMC also emits D-types for "long long" and "unsigned long long", these are
- translated back to the correct types if command option -C is used
- * now adding properties "has nested type" and "is nested type" to class/struct/union/enum types
- * better support for enumerators: now added as user defined types (DMD patch needed)
-
-2010-08-08 Version 0.15
-
- * thanks to patches by Z3N, the resulting pdb is now usable by more debuggers
- * now uses shared file access to executable
- * incomplete structs/classes are now added as user defined types to avoid confusing
- debugger for following symbols
- * fixed name demangling of very long names
- * added name demangling support for @safe/@trusted/@property/pure/nothrow/ref
- * base classes are added to D/cpp-interfaces to allow viewing the virtual function
- table pointer
- * structs, classes and interfaces now have an internal qualifier attached that allows
- the preview in autoexp.dat to show better info for structs and interfaces
-
-2010-08-10 Version 0.16
-
- * fixed crash when working with -C (introduced in last version)
-
-2010-09-04 Version 0.17
-
- * fixed crash that could occur for user-defined types longer than 90 characters
-
-2010-10-24 Version 0.18
-
- * fixed error with nested types longer than 255 characters
- * more fixes for names longer than 300 characters
-
-2010-12-10 Version 0.19
-
- * now converting only class pointers to references, not pointers to structs or void
- * changed default D-version to 2.043 to create correct associative array type
- information for recent compilers by default
-
-2010-12-30 Version 0.20
-
- * fixed another issue with user defined type names longer than 300 characters
- * now corrects the debug info when dmc/optlink emits multiple struct definitions,
- but only one UDT record.
-
-2010-05-08 Version 0.21
-
- * fixed decoding of compressed symbols
- * added command line switch -n to disable symbol demangling
- * fixed crash with more than 32767 types
-
-unreleased Version 0.22
-
- * added command line switch -s to specify the replacement character for '.' in symbols
- * fixed another crash where compressed symbols expand to more than 4096 characters
-
-2012-02-12 Version 0.23
-
- * disabled named enumerator for D basic types to avoid debugger troubles displaying arrays
- * added command line switch -e to enable using named enumerator for D basic types
- * added DWARF support
- * added x64 support
- * tweaked visualizer for associative array element to just show key and value
-
-2012-05-01 Version 0.24
-
- * supports unicode characters in file names
- * improve interpretation of DWARF location expression
-
-2012-06-18 Version 0.25
-
- * new option -p allows to specify the embedded PDB reference in the binary
- * added support for VS2012
-
-2012-11-09 Version 0.26
-
- * now iterating over multiple entries in the debug directory to find CV info
-
-2013-05-11 Version 0.27
-
- * fixed crash when converting DWARF locations using 8 bytes or more
-
-2013-11-16 Version 0.28
-
- * added searching mspdb120.dll for VS 2013
- * changed search order for mspdb*.dll: trying to load through PATH first
- newest VS versions preferred, then trying through installation paths for VS 2013-2005
- * dviewhelper.dll now avoids being reloaded for every expression
-
-2014-02-19 Version 0.29
-
- * fix DWARF conversion for newer gcc versions (4.8.0 or even earlier)
-
-2014-02-25 Version 0.30
-
- * fixed crash when converting DWARF for executables without .reloc segment
-
-2014-03-01 Version 0.31
-
- * added support for local variables accessed through esp
-
-2014-09-24 Version 0.32
-
- * DWARF: fixed relocations in .debug_line section
- * tweaked visualizer macros to display void[], limit array preview to 64 entries
-
-2014-12-19 Version 0.33
-
- * DWARF: revamped location expression evaluator by Vadim Chugunov
-
-2015-02-17 Version 0.34
-
- * DWARF: fixed issues with DW_FORM_strp, DW_AT_upper_bound and DW_AT_lower_bound
- * DWARF: translate __int128 to CV code 0x14, just a wild guesss
-
- * DWARF: add support for DW_ATE_UTF, remove bad assert
-
-2015-05-08 Version 0.35
-
- * new tool dumplines to display the debug line number info
-
-2015-06-03 Version 0.36
-
- * last version introduced a regression that could cause DWARF conversion to crash
- * DWARF sections now stripped from image (if last sections)
- * add support for VS 2015
-
-2015-06-17 Version 0.37
-
- * DWARF: improved support for gcc 4.9.0 and clang 3.6
- * DWARF: support debug_frame (CFA) and debug_loc (for frame base) for better support for locals
- * write correct machine type for x64 to PDB
-
-2016-08-09 Version 0.38
-
- * allow anonymous typedefs
- * cv2pdb now builds as x64 application
- * truncate symbols that are to long
- * better support for symbols that contain non-ascii characters: do not uncompress names in field lists
- * copy symbol unmodified if uncompression fails
-
-2017-01-20 Version 0.39
-
- * do not assume sorted line numbers per segment
-
-2017-05-13 Version 0.40
-
- * set source language 'D' in compilation unit
- * for D version >= 2.068, write AA debug info compatible with dmd COFF output
- * prefer struct over class for internal structs
- * handle class/struct property "uniquename"
-
-2017-05-13 Version 0.41
-
- * when using mspdb120.dll (VS2013) or later, do not emit view helpers
- * remove method declarations from struct or class records (they confuse mspdb*.dll if having forward references?)
-
-2017-09-02 Version 0.42
-
- * search VS2017 registry entries to find mspdb140.dll
- * when using mspdb140.dll (VS2015) or later, use symbols to emit line numbers
- * translate S_UDT_V1 to V3 version
- * translate S_BLOCK_V1 to V3 version
- * remove "this" from delegate parameter list if inconsistent with procedure type
diff --git a/protocols/Tox/tools/FEATURES b/protocols/Tox/tools/FEATURES
deleted file mode 100644
index d6767e3bc8..0000000000
--- a/protocols/Tox/tools/FEATURES
+++ /dev/null
@@ -1,33 +0,0 @@
-Main Features
-
-* conversion of DMD/DMC CodeView information to PDB file
-* converted line number info allows setting breakpoints
-* display of variables, fields and objects in watch, local and auto
- window and in data tooltips
-* convenient display of dynamic and associative arrays in watch windows
-* demangled function names for convenient display of callstack
-
-More features
-
-This list is a bit more technical and shows what is actually done to
-achieve the desired functionality:
-
-* replaces '.' in class names with '@' to avoid confusing debugger
-* converts class pointers to reference for "clss.field" syntax
-* converts the type of member function, so that "this" is an object
- pointer, allowing the debugger to display fields without "this."
-* generates generic debug info for dynamic arrays, associative arrays
- and delegates
-* creates readable type names for display of D specific types
-* autoexp.dat formats output for dynamic and associative arrays in
- watch windows
-* autoexp.dat filters display of null references
-* adds object class debug info
-* "char[]", "wchar[]" and "dchar[]" (D1) or "const char[]",
- "const wchar[]" and "const dchar[]" (D2) translated to "string",
- "wstring" and "dstring", respectively
-* converts type delegate<void*,int> to __int64
-* addin dviewhelper.dll allows correct display of D style strings
- and derived object type
-* maps D basic types to enumerators to overload C style names
-* add struct definitions for complex data types
diff --git a/protocols/Tox/tools/INSTALL b/protocols/Tox/tools/INSTALL
deleted file mode 100644
index 93863dd740..0000000000
--- a/protocols/Tox/tools/INSTALL
+++ /dev/null
@@ -1,71 +0,0 @@
-
-This is the INSTALL file for cv2pdb, a
-converter of DMD CodeView/DWARF debug information to PDB files
-
-Copyright (c) 2009-2010 by Rainer Schuetze, All Rights Reserved
-
-Prerequisites
--------------
-
-For this program to be useful, you should have you should have the
-Digital Mars D Compiler (http://www.digitalmars.com/d/2.0/dmd-windows.html)
-and either Microsoft Visual Studio 2005, 2008 or 2010 or one of the Express
-versions installed. cv2pdb uses one of the Microsoft DLLs to actually
-write the PDB file.
-
-If you are using some other program, you'll still need some
-files from one of the distributions. These are mspdb80.dll, mspdbsrv.exe,
-msobj80.dll, mspdbcore.dll and msvcr90.dll from the VS2008 installation or
-mspdb100.dll, mspdbsrv.exe, msobj100.dll, mspdbcore.dll and msvcr100.dll
-from VS2010. They should be accessible through the PATH environment variable.
-(The VS Shell is missing the msobj80.dll/msobj100.dll only).
-
-Installation
-------------
-You might want to consider installing Visual D (www.dsource.org/projects/visuald)
-instead of cv2pdb. Visual D provides both project and language integration
-into Visual Studio and comes with an installer that includes cv2pdb.
-
-There is no full featured installer available for cv2pdb, you'll have
-to do some simple manual steps to use cv2pdb.
-
-1. The binary package of cv2pdb contains an executable cv2pdb.exe, which
-should be copied somewhere accessible through your PATH environment
-variable.
-
-2. cv2pdb.exe must be able to locate the DLL mspdb80.dll/mspdb100.dll from the Visual
-Studio installation. It tries to read the installation path of the latter from the registry, but
-if this fails, mspdb80.dll/mspdb100.dll should also be accessible through your PATH
-environment variable.
-
-3. For best debugging experience, you should configure Visual Studio
-to use C/C++ syntax highlighting for D files. This is done by
-navigating to the file extensions option page (found in Tools -> Options
--> Text editor -> File Extensions) and adding extensions "d" and "di"
-with editor "Microsoft Visual C++". This will also enable display of
-variables in the "Auto" watch window.
-
-4. You should also add the contents of the files autoexp.expand and
-autoexp.visualizer to the respective [AutoExpand] and [Visualizer]
-sections of the file autoexp.dat found in
-<Visual Studio Installation Path>\Common7\Packages\Debugger.
-Please note that in a standard installation of Visual Studio, the
-section [AutoExpand] is at the beginning of that file, followed by
-the section [Visualizer], which extends to the bottom of the file but a few lines
-for the section [hresult].
-These lines will enable a convenient display of strings, dynamic arrays,
-associative arrays, object types and null references.
-
-5. The file dviewhelper.dll must be copied into a directory where
-the debugger can find it. This can be any directory accessible through your
-PATH variable or <Visual Studio Installation Path>\Common7\IDE. Alternatively,
-the full path can be specified in the corresponding entries in the
-[AutoExpand] section of autoexp.dat.
-
-
-Building from source
---------------------
-The source package comes with a Visual Studio 2008 project and solution
-that work with both the Standard and the Express version. These won't
-work in VS2005, but creating VS2005 projects should be easy.
-
diff --git a/protocols/Tox/tools/LICENSE b/protocols/Tox/tools/LICENSE
deleted file mode 100644
index 32efefcf63..0000000000
--- a/protocols/Tox/tools/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- The Artistic License 2.0
-
- Copyright (c) 2000-2006, The Perl Foundation.
-
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-Preamble
-
-This license establishes the terms under which a given free software
-Package may be copied, modified, distributed, and/or redistributed.
-The intent is that the Copyright Holder maintains some artistic
-control over the development of that Package while still keeping the
-Package available as open source and free software.
-
-You are always permitted to make arrangements wholly outside of this
-license directly with the Copyright Holder of a given Package. If the
-terms of this license do not permit the full use that you propose to
-make of the Package, you should contact the Copyright Holder and seek
-a different licensing arrangement.
-
-Definitions
-
- "Copyright Holder" means the individual(s) or organization(s)
- named in the copyright notice for the entire Package.
-
- "Contributor" means any party that has contributed code or other
- material to the Package, in accordance with the Copyright Holder's
- procedures.
-
- "You" and "your" means any person who would like to copy,
- distribute, or modify the Package.
-
- "Package" means the collection of files distributed by the
- Copyright Holder, and derivatives of that collection and/or of
- those files. A given Package may consist of either the Standard
- Version, or a Modified Version.
-
- "Distribute" means providing a copy of the Package or making it
- accessible to anyone else, or in the case of a company or
- organization, to others outside of your company or organization.
-
- "Distributor Fee" means any fee that you charge for Distributing
- this Package or providing support for this Package to another
- party. It does not mean licensing fees.
-
- "Standard Version" refers to the Package if it has not been
- modified, or has been modified only in ways explicitly requested
- by the Copyright Holder.
-
- "Modified Version" means the Package, if it has been changed, and
- such changes were not explicitly requested by the Copyright
- Holder.
-
- "Original License" means this Artistic License as Distributed with
- the Standard Version of the Package, in its current version or as
- it may be modified by The Perl Foundation in the future.
-
- "Source" form means the source code, documentation source, and
- configuration files for the Package.
-
- "Compiled" form means the compiled bytecode, object code, binary,
- or any other form resulting from mechanical transformation or
- translation of the Source form.
-
-
-Permission for Use and Modification Without Distribution
-
-(1) You are permitted to use the Standard Version and create and use
-Modified Versions for any purpose without restriction, provided that
-you do not Distribute the Modified Version.
-
-
-Permissions for Redistribution of the Standard Version
-
-(2) You may Distribute verbatim copies of the Source form of the
-Standard Version of this Package in any medium without restriction,
-either gratis or for a Distributor Fee, provided that you duplicate
-all of the original copyright notices and associated disclaimers. At
-your discretion, such verbatim copies may or may not include a
-Compiled form of the Package.
-
-(3) You may apply any bug fixes, portability changes, and other
-modifications made available from the Copyright Holder. The resulting
-Package will still be considered the Standard Version, and as such
-will be subject to the Original License.
-
-
-Distribution of Modified Versions of the Package as Source
-
-(4) You may Distribute your Modified Version as Source (either gratis
-or for a Distributor Fee, and with or without a Compiled form of the
-Modified Version) provided that you clearly document how it differs
-from the Standard Version, including, but not limited to, documenting
-any non-standard features, executables, or modules, and provided that
-you do at least ONE of the following:
-
- (a) make the Modified Version available to the Copyright Holder
- of the Standard Version, under the Original License, so that the
- Copyright Holder may include your modifications in the Standard
- Version.
-
- (b) ensure that installation of your Modified Version does not
- prevent the user installing or running the Standard Version. In
- addition, the Modified Version must bear a name that is different
- from the name of the Standard Version.
-
- (c) allow anyone who receives a copy of the Modified Version to
- make the Source form of the Modified Version available to others
- under
-
- (i) the Original License or
-
- (ii) a license that permits the licensee to freely copy,
- modify and redistribute the Modified Version using the same
- licensing terms that apply to the copy that the licensee
- received, and requires that the Source form of the Modified
- Version, and of any works derived from it, be made freely
- available in that license fees are prohibited but Distributor
- Fees are allowed.
-
-
-Distribution of Compiled Forms of the Standard Version
-or Modified Versions without the Source
-
-(5) You may Distribute Compiled forms of the Standard Version without
-the Source, provided that you include complete instructions on how to
-get the Source of the Standard Version. Such instructions must be
-valid at the time of your distribution. If these instructions, at any
-time while you are carrying out such distribution, become invalid, you
-must provide new instructions on demand or cease further distribution.
-If you provide valid instructions or cease distribution within thirty
-days after you become aware that the instructions are invalid, then
-you do not forfeit any of your rights under this license.
-
-(6) You may Distribute a Modified Version in Compiled form without
-the Source, provided that you comply with Section 4 with respect to
-the Source of the Modified Version.
-
-
-Aggregating or Linking the Package
-
-(7) You may aggregate the Package (either the Standard Version or
-Modified Version) with other packages and Distribute the resulting
-aggregation provided that you do not charge a licensing fee for the
-Package. Distributor Fees are permitted, and licensing fees for other
-components in the aggregation are permitted. The terms of this license
-apply to the use and Distribution of the Standard or Modified Versions
-as included in the aggregation.
-
-(8) You are permitted to link Modified and Standard Versions with
-other works, to embed the Package in a larger work of your own, or to
-build stand-alone binary or bytecode versions of applications that
-include the Package, and Distribute the result without restriction,
-provided the result does not expose a direct interface to the Package.
-
-
-Items That are Not Considered Part of a Modified Version
-
-(9) Works (including, but not limited to, modules and scripts) that
-merely extend or make use of the Package, do not, by themselves, cause
-the Package to be a Modified Version. In addition, such works are not
-considered parts of the Package itself, and are not subject to the
-terms of this license.
-
-
-General Provisions
-
-(10) Any use, modification, and distribution of the Standard or
-Modified Versions is governed by this Artistic License. By using,
-modifying or distributing the Package, you accept this license. Do not
-use, modify, or distribute the Package, if you do not accept this
-license.
-
-(11) If your Modified Version has been derived from a Modified
-Version made by someone other than you, you are nevertheless required
-to ensure that your Modified Version complies with the requirements of
-this license.
-
-(12) This license does not grant you the right to use any trademark,
-service mark, tradename, or logo of the Copyright Holder.
-
-(13) This license includes the non-exclusive, worldwide,
-free-of-charge patent license to make, have made, use, offer to sell,
-sell, import and otherwise transfer the Package with respect to any
-patent claims licensable by the Copyright Holder that are necessarily
-infringed by the Package. If you institute patent litigation
-(including a cross-claim or counterclaim) against any party alleging
-that the Package constitutes direct or contributory patent
-infringement, then this Artistic License to you shall terminate on the
-date that such litigation is filed.
-
-(14) Disclaimer of Warranty:
-THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
-IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
-WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
-NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
-LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
-ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/protocols/Tox/tools/README b/protocols/Tox/tools/README
deleted file mode 100644
index 25fe632c74..0000000000
--- a/protocols/Tox/tools/README
+++ /dev/null
@@ -1,139 +0,0 @@
-
-This is the README file for cv2pdb, a
-converter of DMD CodeView/DWARF debug information to PDB files
-
-Copyright (c) 2009-2010 by Rainer Schuetze, All Rights Reserved
-
-The goal of this project is to make debugging of D applications that
-were created with the Digital Mars DMD compiler, as seamless as possible
-in current versions of Visual Studio (i.e Visual Studio 2008 and
-VCExpress).
-As a side effect, other applications might also benefit from the
-converted debug information, like WinDbg or DMC.
-
-Features
---------
-* conversion of DMD CodeView information to PDB file
-* conversion of DWARF information to PDB file
-* converted line number info allows setting breakpoints
-* display of variables, fields and objects in watch, local and auto window and in data tooltips
-* generates generic debug info for dynamic arrays, associative arrays and delegates
-* autoexp.dat allows convenient display of dynamic and associative arrays in watch windows
-* demangles function names for convenient display of callstack
-* also works debugging executables built with the Digital Mars C/C++ compiler DMC
-
-License information
--------------------
-
-This code is distributed under the term of the Artistic License 2.0.
-For more details, see the full text of the license in the file LICENSE.
-
-The file demangle.cpp is an adaption of denangle.d to C++ distributed with
-the DMD compiler. It is placed into the Public Domain.
-
-The file mscvpdb.h is taken from the WINE-project (http://www.winehq.org)
-and is distributed under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-See the file header for more details and
-http://www.gnu.org/licenses/lgpl.html for the full license.
-
-The file dwarf.h is taken from the libdwarf project
-(http://reality.sgiweb.org/davea/dwarf.html)
-and is distributed under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-See the file header for more details and
-http://www.gnu.org/licenses/lgpl.html for the full license.
-
-Installation
-------------
-Sorry, there is no full featured installer available yet, you'll have
-to do some simple manual steps to use cv2pdb.
-
-See the file INSTALL for further details.
-
-Usage
------
-
-Quick start:
-
-Simply run
-
- cv2pdb debuggee.exe
-
-on your executable to debug and start the debugger, e.g.
-
- devenv debuggee.exe
-or
- vcexpress debuggee.exe
-
-Description:
-
-cv2pdb.exe is a command line tool which outputs its usage information
-if run without arguments:
-
- usage: cv2pdb [-Dversion|-C] <exe-file> [new-exe-file] [pdb-file]
-
-With the -D option, you can specify the version of the DMD compiler
-you are using. Unfortunately, this information is not embedded into
-the debug information. The default is -D2. So far, this information
-is only needed to determine whether "char[]" or "const char[]" is
-translated to "string".
-
-Starting with DMD 2.043, assoiciative arrays have a slightly different
-implementation, so debug information needs to be adjusted aswell.
-Use -D 2.043 or higher to produce the matching debug info.
-
-Option -C tells the program, that you want to debug a program compiled
-with DMC, the Digital Mars C/C++ compiler. It will disable some of the
-D specific functions and will enable adjustment of stack variable names.
-
-The first file name on the command line is expected to be the executable
-or dynamic library compiled by the DMD compiler and containing the
-CodeView debug information (-g option used when running dmd).
-
-If no further file name is given, a PDB file will be created with the
-same base name as the executable, but with extension "pdb", and the
-executable will be modified to redirect debuggers to this pdb-file instead
-of the original debug information.
-
-Example:
- cv2pdb debuggee.exe
-
-In an environment using make-like tools, it is often useful to create
-a new file instead of modifying existing files. That way the file
-modification time can be used to continue the build process at the
-correct step.
-If another file name is specified, the new executable is written
-to this file and leaves the input executable unmodified.. The naming
-of the pdb-file will use the base name of the output file.
-
-Example:
- cv2pdb debuggee.exe debuggee_pdb.exe
-
-Last but not least, the resulting pdb-file can be renamed by specifying
-a third file name.
-
-Example:
- cv2pdb debuggee.exe debuggee_pdb.exe debug.pdb
-
-
-
-Changes
--------
-
-For documentation on the changes between this version and
-previous versions, please see the file CHANGES.
-
-Feedback
---------
-The project home for cv2pdb is here:
-
- http://www.dsource.org/projects/cv2pdb
- https://github.com/rainers/cv2pdb
-
-There's also a forum, where you can leave your comments and suggestions.
-
-Have fun,
-Rainer Schuetze
diff --git a/protocols/Tox/tools/TODO b/protocols/Tox/tools/TODO
deleted file mode 100644
index 7cc2fff3c0..0000000000
--- a/protocols/Tox/tools/TODO
+++ /dev/null
@@ -1,28 +0,0 @@
-
-This is the TODO file for cv2pdb, a
-converter of DMD CodeView/DWARF debug information to PDB files
-
-Copyright (c) 2009-2010 by Rainer Schuetze, All Rights Reserved
-
-There are some quirks that you might run into when using
-Visual Studio to debug D programs. These will hopefully be removed
-in the future, but not all have a known solution.
-
-* has to use '@' instead of '.' in class names to avoid confusing debugger,
- but it looks ugly
-* "this.var" is not a valid debugger expression, you have to use
- "var" or "this->var"
-* global/static vars have to be watched with full module and class name
- specified (e.g. module@globvar)
-* type of associative arrays is displayed as aa<*> to allow overload
- in autoexp.dat
-* DMD does not emit different debug information for const and invariant,
- type info is the same
-* DMD does not emit different debug information for float and ifloat,
- type info is the same
-* type display of delegate does not have arguments
-* assoc_array.length cannot be displayed (it is assoc_array.a->nodes)
-* enum values not displayed
-* watch incorrect if same variable name used in different parts of a function
-* line number in templates sometimes off by 1 or 2
-* call to other function jumps to called function while pushing default arguments
diff --git a/protocols/Tox/tools/VERSION b/protocols/Tox/tools/VERSION
deleted file mode 100644
index 2b70a49ad0..0000000000
--- a/protocols/Tox/tools/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-VERSION = 0.42
diff --git a/protocols/Tox/tools/cv2pdb.exe b/protocols/Tox/tools/cv2pdb.exe
deleted file mode 100644
index f65cd291bc..0000000000
--- a/protocols/Tox/tools/cv2pdb.exe
+++ /dev/null
Binary files differ
diff --git a/protocols/Twitter/src/main.cpp b/protocols/Twitter/src/main.cpp
index c31101f22b..b806c042db 100644
--- a/protocols/Twitter/src/main.cpp
+++ b/protocols/Twitter/src/main.cpp
@@ -33,7 +33,6 @@ PLUGININFOEX pluginInfo = {
PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/protocols/Twitter/src/utility.cpp b/protocols/Twitter/src/utility.cpp
index 29c93ecf72..9a7aca80ae 100644
--- a/protocols/Twitter/src/utility.cpp
+++ b/protocols/Twitter/src/utility.cpp
@@ -23,7 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
std::string b64encode(const std::string &s)
{
- return std::string(ptrA(mir_base64_encode((BYTE*)s.c_str(), (unsigned)s.length())));
+ return std::string(ptrA(mir_base64_encode(s.c_str(), s.length())));
}
std::string int2str(int32_t iVal)
diff --git a/protocols/Twitter/src/version.h b/protocols/Twitter/src/version.h
index 7f9840db58..7dc8be558b 100644
--- a/protocols/Twitter/src/version.h
+++ b/protocols/Twitter/src/version.h
@@ -9,6 +9,5 @@
#define __FILENAME "Twitter.dll"
#define __DESCRIPTION "Twitter protocol support for Miranda NG."
#define __AUTHOR "dentist, omniwolf, Thief"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/Twitter/"
#define __COPYRIGHT "© 2009-2010 dentist, 2010-2012 omniwolf and Thief"
diff --git a/protocols/VKontakte/src/main.cpp b/protocols/VKontakte/src/main.cpp
index 60a765103f..19f0c50655 100644
--- a/protocols/VKontakte/src/main.cpp
+++ b/protocols/VKontakte/src/main.cpp
@@ -30,7 +30,6 @@ PLUGININFOEX pluginInfo =
PLUGIN_MAKE_VERSION(__MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM),
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/protocols/VKontakte/src/misc.cpp b/protocols/VKontakte/src/misc.cpp
index 67c1ff428a..27a8a8a8a2 100644
--- a/protocols/VKontakte/src/misc.cpp
+++ b/protocols/VKontakte/src/misc.cpp
@@ -343,6 +343,9 @@ bool CVkProto::CheckJsonResult(AsyncHttpRequest *pReq, const JSONNode &jnNode)
case VKERR_CANT_SEND_YOU_ON_BLACKLIST:
MsgPopup(TranslateT("Can't send messages to this user due to their privacy settings"), TranslateT("Error"), true);
break;
+ case VKERR_MESSAGE_IS_TOO_LONG:
+ MsgPopup(TranslateT("Message is too long"), TranslateT("Error"), true);
+ break;
case VKERR_COULD_NOT_SAVE_FILE:
case VKERR_INVALID_ALBUM_ID:
case VKERR_INVALID_SERVER:
@@ -1515,6 +1518,41 @@ void CVkProto::AddVkDeactivateEvent(MCONTACT hContact, CMStringW& wszType)
db_event_add(hContact, &dbei);
}
+MEVENT CVkProto::GetMessageFromDb(MCONTACT hContact, const char *messageId, UINT &timestamp, CMStringW &msg)
+{
+ if (messageId == nullptr)
+ return 0;
+
+ size_t messageIdLength = mir_strlen(messageId);
+
+ for (MEVENT hDbEvent = db_event_last(hContact); hDbEvent; hDbEvent = db_event_prev(hContact, hDbEvent)) {
+ DBEVENTINFO dbei = {};
+ dbei.cbBlob = db_event_getBlobSize(hDbEvent);
+
+ if (dbei.cbBlob < messageIdLength)
+ continue;
+
+ mir_ptr<BYTE> blob((PBYTE)mir_alloc(dbei.cbBlob));
+ dbei.pBlob = blob;
+ db_event_get(hDbEvent, &dbei);
+
+ size_t cbLen = mir_strlen((char*)dbei.pBlob);
+ if ((dbei.eventType != EVENTTYPE_MESSAGE) || (cbLen + messageIdLength + 1 > dbei.cbBlob))
+ continue;
+
+ if (memcmp(&dbei.pBlob[cbLen + 1], messageId, messageIdLength) == 0) {
+ msg = ptrW(mir_utf8decodeW((char*)dbei.pBlob));
+ timestamp = dbei.timestamp;
+ return hDbEvent;
+ }
+
+ if (dbei.timestamp < timestamp)
+ break;
+ }
+
+ return 0;
+}
+
int CVkProto::DeleteContact(MCONTACT hContact)
{
setByte(hContact, "SilentDelete", 1);
diff --git a/protocols/VKontakte/src/version.h b/protocols/VKontakte/src/version.h
index ec86aa73d0..9cbd3b1713 100644
--- a/protocols/VKontakte/src/version.h
+++ b/protocols/VKontakte/src/version.h
@@ -1,6 +1,6 @@
#define __MAJOR_VERSION 0
#define __MINOR_VERSION 1
-#define __RELEASE_NUM 3
+#define __RELEASE_NUM 4
#define __BUILD_NUM 0
#include <stdver.h>
@@ -9,6 +9,5 @@
#define __FILENAME "VKontakte.dll"
#define __DESCRIPTION "VKontakte protocol support for Miranda NG."
#define __AUTHOR "Miranda NG Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/VKontakte/"
#define __COPYRIGHT "© 2013-17 Miranda NG Team"
diff --git a/protocols/VKontakte/src/vk.h b/protocols/VKontakte/src/vk.h
index 148ffc5799..e4cbd127a6 100644
--- a/protocols/VKontakte/src/vk.h
+++ b/protocols/VKontakte/src/vk.h
@@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define VKPOLL_MSG_ADDFLAGS 2
#define VKPOLL_MSG_DELFLAGS 3
#define VKPOLL_MSG_ADDED 4
+#define VKPOLL_MSG_EDITED 5
#define VKPOLL_READ_ALL_IN 6
#define VKPOLL_READ_ALL_OUT 7
#define VKPOLL_USR_ONLINE 8
@@ -74,6 +75,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define VKERR_CANT_SEND_USER_ON_BLACKLIST 900 // Can't send messages for users from blacklist
#define VKERR_CANT_SEND_USER_WITHOUT_DIALOGS 901 // Can't send messages for users without dialogs
#define VKERR_CANT_SEND_YOU_ON_BLACKLIST 902 // Can't send messages to this user due to their privacy settings
+#define VKERR_MESSAGE_IS_TOO_LONG 914 // Message is too long
+
// File upload custom error
#define VKERR_FILE_NOT_EXIST 10100 // File does not exist
#define VKERR_FTYPE_NOT_SUPPORTED 10101 // File type not supported
@@ -85,7 +88,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define VK_USER_DEACTIVATE_ACTION 9321
-#define VK_API_VER "5.68"
+#define VK_API_VER "5.69"
#define VER_API CHAR_PARAM("v", VK_API_VER)
#define VK_FEED_USER 2147483647L
diff --git a/protocols/VKontakte/src/vk_messages.cpp b/protocols/VKontakte/src/vk_messages.cpp
index 56d3b4edda..2c0bead07c 100644
--- a/protocols/VKontakte/src/vk_messages.cpp
+++ b/protocols/VKontakte/src/vk_messages.cpp
@@ -250,7 +250,7 @@ void CVkProto::OnReceiveMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe
UINT mid = jnMsg["id"].as_int();
CMStringW wszBody(jnMsg["body"].as_mstring());
- int datetime = jnMsg["date"].as_int();
+ UINT datetime = jnMsg["date"].as_int();
int isOut = jnMsg["out"].as_int();
int isRead = jnMsg["read_state"].as_int();
int uid = jnMsg["user_id"].as_int();
@@ -313,8 +313,21 @@ void CVkProto::OnReceiveMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe
else if (m_vkOptions.bUserForceInvisibleOnActivity && time(nullptr) - datetime < 60 * m_vkOptions.iInvisibleInterval)
SetInvisible(hContact);
+ bool bEdited = CheckMid(m_editedIds, mid);
+ if (bEdited) {
+ CMStringW wszOldMsg;
+ MEVENT hDbEvent = GetMessageFromDb(hContact, szMid, datetime, wszOldMsg);
+ if (hDbEvent) {
+ wszBody = SetBBCString(TranslateT("Edited message:\n"), m_vkOptions.BBCForAttachments(), vkbbcB) +
+ wszBody +
+ SetBBCString(TranslateT("\nOriginal message:\n"), m_vkOptions.BBCForAttachments(), vkbbcB) +
+ wszOldMsg;
+ db_event_delete(hContact, hDbEvent);
+ }
+ }
+
T2Utf pszBody(wszBody);
- recv.timestamp = m_vkOptions.bUseLocalTime ? time(nullptr) : datetime;
+ recv.timestamp = bEdited ? datetime : (m_vkOptions.bUseLocalTime ? time(nullptr) : datetime);
recv.szMessage = pszBody;
recv.lParam = isOut;
recv.pCustomData = szMid;
diff --git a/protocols/VKontakte/src/vk_pollserver.cpp b/protocols/VKontakte/src/vk_pollserver.cpp
index 56a9d85715..af49875118 100644
--- a/protocols/VKontakte/src/vk_pollserver.cpp
+++ b/protocols/VKontakte/src/vk_pollserver.cpp
@@ -78,6 +78,7 @@ void CVkProto::PollUpdates(const JSONNode &jnUpdates)
debugLogA("CVkProto::PollUpdates");
CMStringA mids;
int msgid, uid, flags, platform;
+ bool bNonEdited = true;
MCONTACT hContact;
for (auto it = jnUpdates.begin(); it != jnUpdates.end(); ++it) {
@@ -106,17 +107,25 @@ void CVkProto::PollUpdates(const JSONNode &jnUpdates)
}
break;
+ case VKPOLL_MSG_EDITED:
+ bNonEdited = false;
+
case VKPOLL_MSG_ADDED: // new message
msgid = jnChild[1].as_int();
// skip outgoing messages sent from a client
flags = jnChild[2].as_int();
- if (flags & VKFLAG_MSGOUTBOX && !(flags & VKFLAG_MSGCHAT) && !m_vkOptions.bSendVKLinksAsAttachments && CheckMid(m_sendIds, msgid))
+ if (bNonEdited && (flags & VKFLAG_MSGOUTBOX && !(flags & VKFLAG_MSGCHAT) && !m_vkOptions.bSendVKLinksAsAttachments && CheckMid(m_sendIds, msgid)))
break;
if (!mids.IsEmpty())
mids.AppendChar(',');
mids.AppendFormat("%d", msgid);
+
+ if(!bNonEdited)
+ m_editedIds.insert((HANDLE)msgid);
+
+ bNonEdited = true;
break;
case VKPOLL_READ_ALL_OUT:
diff --git a/protocols/VKontakte/src/vk_proto.cpp b/protocols/VKontakte/src/vk_proto.cpp
index 85b403de7a..1c60842c5a 100644
--- a/protocols/VKontakte/src/vk_proto.cpp
+++ b/protocols/VKontakte/src/vk_proto.cpp
@@ -36,6 +36,7 @@ CVkProto::CVkProto(const char *szModuleName, const wchar_t *pwszUserName) :
PROTO<CVkProto>(szModuleName, pwszUserName),
m_arRequestsQueue(10, sttCompareAsyncHttpRequest),
m_sendIds(3, PtrKeySortT),
+ m_editedIds(1, PtrKeySortT),
m_incIds(3, PtrKeySortT),
m_cookies(5),
m_msgId(1),
diff --git a/protocols/VKontakte/src/vk_proto.h b/protocols/VKontakte/src/vk_proto.h
index d1e00cdb6e..90f5f1ece3 100644
--- a/protocols/VKontakte/src/vk_proto.h
+++ b/protocols/VKontakte/src/vk_proto.h
@@ -212,6 +212,7 @@ private:
LIST<void>
m_sendIds,
+ m_editedIds,
m_incIds;
OBJLIST<CVkChatInfo> m_chats;
@@ -358,6 +359,7 @@ private:
void SetInvisible(MCONTACT hContact);
CMStringW RemoveBBC(CMStringW& wszSrc);
void AddVkDeactivateEvent(MCONTACT hContact, CMStringW & wszType);
+ MEVENT GetMessageFromDb(MCONTACT hContact, const char * messageId, UINT &timestamp, CMStringW &msg);
int DeleteContact(MCONTACT hContact);
void InitQueue();
void UninitQueue();
diff --git a/protocols/VKontakte/src/vk_struct.h b/protocols/VKontakte/src/vk_struct.h
index b687018bcf..54a1f4b623 100644
--- a/protocols/VKontakte/src/vk_struct.h
+++ b/protocols/VKontakte/src/vk_struct.h
@@ -45,38 +45,8 @@ struct AsyncHttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject
bool bNeedsRestart, bIsMainConn;
};
-struct PARAM
-{
- LPCSTR szName;
- __forceinline PARAM(LPCSTR _name) : szName(_name)
- {}
-};
-
-struct INT_PARAM : public PARAM
-{
- long iValue;
- __forceinline INT_PARAM(LPCSTR _name, long _value) :
- PARAM(_name), iValue(_value)
- {}
-};
AsyncHttpRequest* operator<<(AsyncHttpRequest*, const INT_PARAM&);
-
-struct CHAR_PARAM : public PARAM
-{
- LPCSTR szValue;
- __forceinline CHAR_PARAM(LPCSTR _name, LPCSTR _value) :
- PARAM(_name), szValue(_value)
- {}
-};
AsyncHttpRequest* operator<<(AsyncHttpRequest*, const CHAR_PARAM&);
-
-struct WCHAR_PARAM : public PARAM
-{
- LPCWSTR wszValue;
- __forceinline WCHAR_PARAM(LPCSTR _name, LPCWSTR _value) :
- PARAM(_name), wszValue(_value)
- {}
-};
AsyncHttpRequest* operator<<(AsyncHttpRequest*, const WCHAR_PARAM&);
struct CVkFileUploadParam : public MZeroedObject {
diff --git a/src/core/stdautoaway/src/autoaway.cpp b/src/core/stdautoaway/src/autoaway.cpp
index c1ebc6bbe5..c21b77253f 100644
--- a/src/core/stdautoaway/src/autoaway.cpp
+++ b/src/core/stdautoaway/src/autoaway.cpp
@@ -47,8 +47,8 @@ static void Proto_SetStatus(const char *szProto, unsigned status)
static int AutoAwayEvent(WPARAM, LPARAM lParam)
{
- MIRANDA_IDLE_INFO mii = { sizeof(mii) };
- CallService(MS_IDLE_GETIDLEINFO, 0, (LPARAM)&mii);
+ MIRANDA_IDLE_INFO mii;
+ Idle_GetInfo(mii);
if (mii.idlesoundsoff)
iBreakSounds = (lParam & IDF_ISIDLE) != 0;
diff --git a/src/core/stdautoaway/src/main.cpp b/src/core/stdautoaway/src/main.cpp
index 58f414e5ac..16bf735564 100644
--- a/src/core/stdautoaway/src/main.cpp
+++ b/src/core/stdautoaway/src/main.cpp
@@ -32,7 +32,6 @@ PLUGININFOEX pluginInfo = {
MIRANDA_VERSION_DWORD,
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/src/core/stdautoaway/src/version.h b/src/core/stdautoaway/src/version.h
index 84fee2edca..3952127b07 100644
--- a/src/core/stdautoaway/src/version.h
+++ b/src/core/stdautoaway/src/version.h
@@ -7,6 +7,5 @@
#define __FILENAME "stdautoaway.dll"
#define __DESCRIPTION "Core module for away state processing."
#define __AUTHOR "Miranda NG Development Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/StdAutoAway/"
#define __COPYRIGHT "© 2012-17 Miranda NG Development Team"
diff --git a/src/core/stdaway/src/main.cpp b/src/core/stdaway/src/main.cpp
index c176bff75e..3ab44e8bd4 100644
--- a/src/core/stdaway/src/main.cpp
+++ b/src/core/stdaway/src/main.cpp
@@ -33,7 +33,6 @@ PLUGININFOEX pluginInfo = {
MIRANDA_VERSION_DWORD,
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/src/core/stdaway/src/sendmsg.cpp b/src/core/stdaway/src/sendmsg.cpp
index af476d6a07..e6df6ddea6 100644
--- a/src/core/stdaway/src/sendmsg.cpp
+++ b/src/core/stdaway/src/sendmsg.cpp
@@ -27,42 +27,41 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static DWORD protoModeMsgFlags;
static HWND hwndStatusMsg;
-static const wchar_t *GetDefaultMessage(int status)
+static const wchar_t* GetDefaultMessage(int status)
{
- switch(status) {
- case ID_STATUS_AWAY: return TranslateT("I've been away since %time%.");
- case ID_STATUS_NA: return TranslateT("Give it up, I'm not in!");
- case ID_STATUS_OCCUPIED: return TranslateT("Not right now.");
- case ID_STATUS_DND: return TranslateT("Give a guy some peace, would ya?");
- case ID_STATUS_FREECHAT: return TranslateT("I'm a chatbot!");
- case ID_STATUS_ONLINE: return TranslateT("Yep, I'm here.");
- case ID_STATUS_OFFLINE: return TranslateT("Nope, not here.");
- case ID_STATUS_INVISIBLE: return TranslateT("I'm hiding from the mafia.");
+ switch (status) {
+ case ID_STATUS_AWAY: return TranslateT("I've been away since %time%.");
+ case ID_STATUS_NA: return TranslateT("Give it up, I'm not in!");
+ case ID_STATUS_OCCUPIED: return TranslateT("Not right now.");
+ case ID_STATUS_DND: return TranslateT("Give a guy some peace, would ya?");
+ case ID_STATUS_FREECHAT: return TranslateT("I'm a chatbot!");
+ case ID_STATUS_ONLINE: return TranslateT("Yep, I'm here.");
+ case ID_STATUS_OFFLINE: return TranslateT("Nope, not here.");
+ case ID_STATUS_INVISIBLE: return TranslateT("I'm hiding from the mafia.");
case ID_STATUS_ONTHEPHONE: return TranslateT("That'll be the phone.");
case ID_STATUS_OUTTOLUNCH: return TranslateT("Mmm... food.");
- case ID_STATUS_IDLE: return TranslateT("idleeeeeeee");
+ case ID_STATUS_IDLE: return TranslateT("idleeeeeeee");
}
return nullptr;
}
-static const char *StatusModeToDbSetting(int status, const char *suffix)
+static const char* StatusModeToDbSetting(int status, const char *suffix)
{
const char *prefix;
static char str[64];
- switch(status)
- {
- case ID_STATUS_AWAY: prefix = "Away"; break;
- case ID_STATUS_NA: prefix = "Na"; break;
- case ID_STATUS_DND: prefix = "Dnd"; break;
- case ID_STATUS_OCCUPIED: prefix = "Occupied"; break;
- case ID_STATUS_FREECHAT: prefix = "FreeChat"; break;
- case ID_STATUS_ONLINE: prefix = "On"; break;
- case ID_STATUS_OFFLINE: prefix = "Off"; break;
- case ID_STATUS_INVISIBLE: prefix = "Inv"; break;
- case ID_STATUS_ONTHEPHONE: prefix = "Otp"; break;
- case ID_STATUS_OUTTOLUNCH: prefix = "Otl"; break;
- case ID_STATUS_IDLE: prefix = "Idl"; break;
+ switch (status) {
+ case ID_STATUS_AWAY: prefix = "Away"; break;
+ case ID_STATUS_NA: prefix = "Na"; break;
+ case ID_STATUS_DND: prefix = "Dnd"; break;
+ case ID_STATUS_OCCUPIED: prefix = "Occupied"; break;
+ case ID_STATUS_FREECHAT: prefix = "FreeChat"; break;
+ case ID_STATUS_ONLINE: prefix = "On"; break;
+ case ID_STATUS_OFFLINE: prefix = "Off"; break;
+ case ID_STATUS_INVISIBLE: prefix = "Inv"; break;
+ case ID_STATUS_ONTHEPHONE: prefix = "Otp"; break;
+ case ID_STATUS_OUTTOLUNCH: prefix = "Otl"; break;
+ case ID_STATUS_IDLE: prefix = "Idl"; break;
default: return nullptr;
}
mir_snprintf(str, "%s%s", prefix, suffix);
@@ -84,26 +83,26 @@ static wchar_t* GetAwayMessage(int statusMode, char *szProto)
if (szProto && !(CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(statusMode)))
return nullptr;
- if ( GetStatusModeByte(statusMode, "Ignore"))
+ if (GetStatusModeByte(statusMode, "Ignore"))
return nullptr;
DBVARIANT dbv;
- if ( GetStatusModeByte(statusMode, "UsePrev")) {
- if ( db_get_ws(NULL, "SRAway", StatusModeToDbSetting(statusMode, "Msg"), &dbv))
+ if (GetStatusModeByte(statusMode, "UsePrev")) {
+ if (db_get_ws(NULL, "SRAway", StatusModeToDbSetting(statusMode, "Msg"), &dbv))
dbv.ptszVal = mir_wstrdup(GetDefaultMessage(statusMode));
}
else {
- if ( db_get_ws(NULL, "SRAway", StatusModeToDbSetting(statusMode, "Default"), &dbv))
+ if (db_get_ws(NULL, "SRAway", StatusModeToDbSetting(statusMode, "Default"), &dbv))
dbv.ptszVal = mir_wstrdup(GetDefaultMessage(statusMode));
- for (int i=0; dbv.ptszVal[i]; i++) {
+ for (int i = 0; dbv.ptszVal[i]; i++) {
if (dbv.ptszVal[i] != '%')
continue;
wchar_t substituteStr[128];
- if ( !wcsnicmp(dbv.ptszVal + i, L"%time%", 6)) {
- MIRANDA_IDLE_INFO mii = { sizeof(mii) };
- CallService(MS_IDLE_GETIDLEINFO, 0, (LPARAM)&mii);
+ if (!wcsnicmp(dbv.ptszVal + i, L"%time%", 6)) {
+ MIRANDA_IDLE_INFO mii;
+ Idle_GetInfo(mii);
if (mii.idleType == 1) {
int mm;
@@ -117,14 +116,14 @@ static wchar_t* GetAwayMessage(int statusMode, char *szProto)
}
else GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, NULL, NULL, substituteStr, _countof(substituteStr));
}
- else if ( !wcsnicmp(dbv.ptszVal + i, L"%date%", 6))
+ else if (!wcsnicmp(dbv.ptszVal + i, L"%date%", 6))
GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, substituteStr, _countof(substituteStr));
else continue;
if (mir_wstrlen(substituteStr) > 6)
dbv.ptszVal = (wchar_t*)mir_realloc(dbv.ptszVal, (mir_wstrlen(dbv.ptszVal) + 1 + mir_wstrlen(substituteStr) - 6) * sizeof(wchar_t));
memmove(dbv.ptszVal + i + mir_wstrlen(substituteStr), dbv.ptszVal + i + 6, (mir_wstrlen(dbv.ptszVal) - i - 5) * sizeof(wchar_t));
- memcpy(dbv.ptszVal+i, substituteStr, mir_wstrlen(substituteStr) * sizeof(wchar_t));
+ memcpy(dbv.ptszVal + i, substituteStr, mir_wstrlen(substituteStr) * sizeof(wchar_t));
}
}
return dbv.ptszVal;
@@ -132,10 +131,9 @@ static wchar_t* GetAwayMessage(int statusMode, char *szProto)
static LRESULT CALLBACK MessageEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
- switch(msg) {
+ switch (msg) {
case WM_CHAR:
- if (wParam == '\n' && GetKeyState(VK_CONTROL) & 0x8000)
- {
+ if (wParam == '\n' && GetKeyState(VK_CONTROL) & 0x8000) {
PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0);
return 0;
}
@@ -321,7 +319,7 @@ static int StatusModeChange(WPARAM wParam, LPARAM lParam)
// If its a single protocol check the PFLAGNUM_3 for the single protocol
if (!(CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND) ||
!(CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(statusMode)))
- return 0;
+ return 0;
}
BOOL bScreenSaverRunning = IsScreenSaverRunning();
@@ -539,7 +537,7 @@ static int AwayMsgSendAccountsChanged(WPARAM, LPARAM)
protoModeMsgFlags = 0;
int nAccounts;
- PROTOACCOUNT** accounts;
+ PROTOACCOUNT **accounts;
Proto_EnumAccounts(&nAccounts, &accounts);
for (int i = 0; i < nAccounts; i++) {
if (!Proto_IsAccountEnabled(accounts[i]))
@@ -560,7 +558,7 @@ static int AwayMsgSendModulesLoaded(WPARAM, LPARAM)
return 0;
}
-//remember to mir_free() the return value
+// remember to mir_free() the return value
static INT_PTR sttGetAwayMessageT(WPARAM wParam, LPARAM lParam)
{
return (INT_PTR)GetAwayMessage((int)wParam, (char*)lParam);
diff --git a/src/core/stdaway/src/version.h b/src/core/stdaway/src/version.h
index c611618b3a..54199a498b 100644
--- a/src/core/stdaway/src/version.h
+++ b/src/core/stdaway/src/version.h
@@ -7,6 +7,5 @@
#define __FILENAME "stdaway.dll"
#define __DESCRIPTION "Core module for the away messages processing."
#define __AUTHOR "Miranda NG Development Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/StdAway/"
#define __COPYRIGHT "© 2012-17 Miranda NG Development Team"
diff --git a/src/core/stdclist/src/init.cpp b/src/core/stdclist/src/init.cpp
index e9a5b547f0..7fb57bdec1 100644
--- a/src/core/stdclist/src/init.cpp
+++ b/src/core/stdclist/src/init.cpp
@@ -58,7 +58,6 @@ PLUGININFOEX pluginInfo = {
MIRANDA_VERSION_DWORD,
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/src/core/stdclist/src/version.h b/src/core/stdclist/src/version.h
index ba56c650ec..07fceac156 100644
--- a/src/core/stdclist/src/version.h
+++ b/src/core/stdclist/src/version.h
@@ -8,6 +8,5 @@
#define __FILENAME "stdclist.dll"
#define __DESCRIPTION "Core module for displaying contacts."
#define __AUTHOR "Miranda NG Development Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/StdClist/"
#define __COPYRIGHT "© 2012-17 Miranda NG Development Team"
diff --git a/src/core/stdcrypt/src/main.cpp b/src/core/stdcrypt/src/main.cpp
index 48983fceb7..a9805b82d6 100644
--- a/src/core/stdcrypt/src/main.cpp
+++ b/src/core/stdcrypt/src/main.cpp
@@ -31,7 +31,6 @@ PLUGININFOEX pluginInfo = {
MIRANDA_VERSION_DWORD,
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/src/core/stdcrypt/src/version.h b/src/core/stdcrypt/src/version.h
index a45c96afb9..f2a287aa7b 100644
--- a/src/core/stdcrypt/src/version.h
+++ b/src/core/stdcrypt/src/version.h
@@ -7,6 +7,5 @@
#define __FILENAME "stdcrypt.dll"
#define __DESCRIPTION "Core module for encryption."
#define __AUTHOR "Miranda NG Development Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/StdCrypt/"
#define __COPYRIGHT "© 2012-17 Miranda NG Development Team"
diff --git a/src/core/stdemail/src/main.cpp b/src/core/stdemail/src/main.cpp
index f4a3299c77..4bb4247596 100644
--- a/src/core/stdemail/src/main.cpp
+++ b/src/core/stdemail/src/main.cpp
@@ -32,7 +32,6 @@ PLUGININFOEX pluginInfo = {
MIRANDA_VERSION_DWORD,
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/src/core/stdemail/src/version.h b/src/core/stdemail/src/version.h
index 1dbb386bea..c2ebdc6ab8 100644
--- a/src/core/stdemail/src/version.h
+++ b/src/core/stdemail/src/version.h
@@ -7,6 +7,5 @@
#define __FILENAME "stdemail.dll"
#define __DESCRIPTION "Core module for e-mail urls handling."
#define __AUTHOR "Miranda NG Development Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/StdEmail/"
#define __COPYRIGHT "© 2012-17 Miranda NG Development Team"
diff --git a/src/core/stdfile/src/filerecvdlg.cpp b/src/core/stdfile/src/filerecvdlg.cpp
index 49d1fcd3b1..9feef53743 100644
--- a/src/core/stdfile/src/filerecvdlg.cpp
+++ b/src/core/stdfile/src/filerecvdlg.cpp
@@ -346,15 +346,10 @@ INT_PTR CALLBACK DlgProcRecvFile(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM l
break;
case IDC_ADD:
- {
- ADDCONTACTSTRUCT acs = { 0 };
- acs.hContact = dat->hContact;
- acs.handleType = HANDLE_CONTACT;
- acs.szProto = "";
- CallService(MS_ADDCONTACT_SHOW, (WPARAM)hwndDlg, (LPARAM)&acs);
- if (!db_get_b(dat->hContact, "CList", "NotOnList", 0))
- ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), SW_HIDE);
- }
+ Contact_Add(dat->hContact, hwndDlg);
+
+ if (!db_get_b(dat->hContact, "CList", "NotOnList", 0))
+ ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), SW_HIDE);
break;
case IDC_USERMENU:
diff --git a/src/core/stdfile/src/main.cpp b/src/core/stdfile/src/main.cpp
index 2e3c002907..67ae29ac03 100644
--- a/src/core/stdfile/src/main.cpp
+++ b/src/core/stdfile/src/main.cpp
@@ -35,7 +35,6 @@ PLUGININFOEX pluginInfo = {
MIRANDA_VERSION_DWORD,
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/src/core/stdfile/src/stdafx.h b/src/core/stdfile/src/stdafx.h
index cc4b8d3742..512cc93ad7 100644
--- a/src/core/stdfile/src/stdafx.h
+++ b/src/core/stdfile/src/stdafx.h
@@ -60,7 +60,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <m_message.h>
#include <m_userinfo.h>
#include <m_history.h>
-#include <m_addcontact.h>
#include <m_findadd.h>
#include <m_file.h>
#include <m_icolib.h>
diff --git a/src/core/stdfile/src/version.h b/src/core/stdfile/src/version.h
index 61ada99635..54750eb07e 100644
--- a/src/core/stdfile/src/version.h
+++ b/src/core/stdfile/src/version.h
@@ -7,6 +7,5 @@
#define __FILENAME "stdfile.dll"
#define __DESCRIPTION "Core module for sending/receiving files."
#define __AUTHOR "Miranda NG Development Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/StdFile/"
#define __COPYRIGHT "© 2012-17 Miranda NG Development Team"
diff --git a/src/core/stdidle/res/resource.rc b/src/core/stdidle/res/resource.rc
index ebecfa7b37..1b926065de 100644
--- a/src/core/stdidle/res/resource.rc
+++ b/src/core/stdidle/res/resource.rc
@@ -35,7 +35,7 @@ BEGIN
CONTROL "Windows",IDC_IDLEONWINDOWS,"Button",BS_AUTORADIOBUTTON,45,31,104,9
CONTROL "Miranda",IDC_IDLEONMIRANDA,"Button",BS_AUTORADIOBUTTON,45,43,103,9
EDITTEXT IDC_IDLE1STTIME,59,59,27,14,ES_AUTOHSCROLL | ES_NUMBER
- CONTROL "Spin2",IDC_IDLESPIN,"msctls_updown32",UDS_WRAP | UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,71,55,12,23
+ CONTROL "Spin2",IDC_IDLESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,86,59,11,14
CONTROL "Become idle if the screen saver is active",IDC_SCREENSAVER,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,25,83,265,9
CONTROL "Become idle if the computer is locked",IDC_LOCKED,
@@ -44,7 +44,7 @@ BEGIN
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,25,116,265,10
CONTROL "Do not let protocols report any idle information",IDC_IDLEPRIVATE,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,25,131,251,9
- LTEXT "minute(s)",IDC_STATIC,91,61,76,9
+ LTEXT "minute(s)",IDC_STATIC,99,61,76,9
RTEXT "for",IDC_STATIC,12,62,41,8
COMBOBOX IDC_AASTATUS,161,146,64,50,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "Change my status mode to:",IDC_AASHORTIDLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,25,147,132,11
diff --git a/src/core/stdidle/src/idle.cpp b/src/core/stdidle/src/idle.cpp
index eb0ef2568c..64974bff02 100644
--- a/src/core/stdidle/src/idle.cpp
+++ b/src/core/stdidle/src/idle.cpp
@@ -24,209 +24,88 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "stdafx.h"
-#define IDLEMOD "Idle"
-#define IDL_USERIDLECHECK "UserIdleCheck"
-#define IDL_IDLEMETHOD "IdleMethod"
-#define IDL_IDLETIME1ST "IdleTime1st"
-#define IDL_IDLEONSAVER "IdleOnSaver" // IDC_SCREENSAVER
-#define IDL_IDLEONFULLSCR "IdleOnFullScr" // IDC_FULLSCREEN
-#define IDL_IDLEONLOCK "IdleOnLock" // IDC_LOCKED
-#define IDL_IDLEONTSDC "IdleOnTerminalDisconnect" //
-#define IDL_IDLEPRIVATE "IdlePrivate" // IDC_IDLEPRIVATE
-#define IDL_IDLESTATUSLOCK "IdleStatusLock" // IDC_IDLESTATUSLOCK
-#define IDL_AAENABLE "AAEnable"
-#define IDL_AASTATUS "AAStatus"
-#define IDL_IDLESOUNDSOFF "IdleSoundsOff"
+Settings S;
-#define IdleObject_IsIdle(obj) (obj->state&0x1)
-#define IdleObject_SetIdle(obj) (obj->state|=0x1)
-#define IdleObject_ClearIdle(obj) (obj->state&=~0x1)
+static bool bModuleInitialized = false;
-// either use meth 0, 1 or figure out which one
-#define IdleObject_UseMethod0(obj) (obj->state&=~0x2)
-#define IdleObject_UseMethod1(obj) (obj->state|=0x2)
-#define IdleObject_GetMethod(obj) (obj->state&0x2)
-
-#define IdleObject_IdleCheckSaver(obj) (obj->state&0x4)
-#define IdleObject_SetSaverCheck(obj) (obj->state|=0x4)
-
-#define IdleObject_IdleCheckWorkstation(obj) (obj->state&0x8)
-#define IdleObject_SetWorkstationCheck(obj) (obj->state|=0x8)
-
-#define IdleObject_IsPrivacy(obj) (obj->state&0x10)
-#define IdleObject_SetPrivacy(obj) (obj->state|=0x10)
-
-#define IdleObject_SetStatusLock(obj) (obj->state|=0x20)
-
-#define IdleObject_IdleCheckTerminal(obj) (obj->state&0x40)
-#define IdleObject_SetTerminalCheck(obj) (obj->state|=0x40)
-
-#define IdleObject_IdleCheckFullScr(obj) (obj->state&0x80)
-#define IdleObject_SetFullScrCheck(obj) (obj->state|=0x80)
-
-//#include <Wtsapi32.h>
-
-#ifndef _INC_WTSAPI
-
-#define WTS_CURRENT_SERVER_HANDLE ((HANDLE)NULL)
-#define WTS_CURRENT_SESSION ((DWORD)-1)
-
-typedef enum _WTS_CONNECTSTATE_CLASS {
- WTSActive, // User logged on to WinStation
- WTSConnected, // WinStation connected to client
- WTSConnectQuery, // In the process of connecting to client
- WTSShadow, // Shadowing another WinStation
- WTSDisconnected, // WinStation logged on without client
- WTSIdle, // Waiting for client to connect
- WTSListen, // WinStation is listening for connection
- WTSReset, // WinStation is being reset
- WTSDown, // WinStation is down due to error
- WTSInit, // WinStation in initialization
-} WTS_CONNECTSTATE_CLASS;
-
-typedef enum _WTS_INFO_CLASS {
- WTSInitialProgram,
- WTSApplicationName,
- WTSWorkingDirectory,
- WTSOEMId,
- WTSSessionId,
- WTSUserName,
- WTSWinStationName,
- WTSDomainName,
- WTSConnectState,
- WTSClientBuildNumber,
- WTSClientName,
- WTSClientDirectory,
- WTSClientProductId,
- WTSClientHardwareId,
- WTSClientAddress,
- WTSClientDisplay,
- WTSClientProtocolType,
-} WTS_INFO_CLASS;
-
-#endif
-
-static BOOL bModuleInitialized = FALSE;
-
-BOOL IsTerminalDisconnected()
+struct IdleObject
{
- PVOID pBuffer = nullptr;
- DWORD pBytesReturned = 0;
- BOOL result = FALSE;
-
- if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSConnectState, (LPTSTR *)&pBuffer, &pBytesReturned)) {
- if (*(PDWORD)pBuffer == WTSDisconnected)
- result = TRUE;
- }
-
- if (pBuffer)
- WTSFreeMemory(pBuffer);
- return result;
-}
-
-typedef struct {
UINT_PTR hTimer;
- unsigned int useridlecheck;
- unsigned int state;
- unsigned int minutes; // user setting, number of minutes of inactivity to wait for
- POINT mousepos;
- unsigned int mouseidle;
- int aastatus;
int idleType;
- int aasoundsoff;
-}
- IdleObject;
-
-static const WORD aa_Status[] = {ID_STATUS_AWAY, ID_STATUS_NA, ID_STATUS_OCCUPIED, ID_STATUS_DND, ID_STATUS_ONTHEPHONE, ID_STATUS_OUTTOLUNCH};
+ int bIsIdle;
+};
static IdleObject gIdleObject;
static HANDLE hIdleEvent;
void CALLBACK IdleTimer(HWND hwnd, UINT umsg, UINT_PTR idEvent, DWORD dwTime);
+int IdleOptInit(WPARAM wParam, LPARAM);
-static void IdleObject_ReadSettings(IdleObject * obj)
-{
- obj->useridlecheck = db_get_b(NULL, IDLEMOD, IDL_USERIDLECHECK, 0);
- obj->minutes = db_get_b(NULL, IDLEMOD, IDL_IDLETIME1ST, 10);
- obj->aastatus = !db_get_b(NULL, IDLEMOD, IDL_AAENABLE, 0) ? 0 : db_get_w(NULL, IDLEMOD, IDL_AASTATUS, 0);
- if ( db_get_b(NULL, IDLEMOD, IDL_IDLESOUNDSOFF, 1))
- obj->aasoundsoff = 1;
- else
- obj->aasoundsoff = 0;
- if ( db_get_b(NULL, IDLEMOD, IDL_IDLEMETHOD, 0)) IdleObject_UseMethod1(obj);
- else IdleObject_UseMethod0(obj);
- if ( db_get_b(NULL, IDLEMOD, IDL_IDLEONSAVER, 0)) IdleObject_SetSaverCheck(obj);
- if ( db_get_b(NULL, IDLEMOD, IDL_IDLEONFULLSCR, 0)) IdleObject_SetFullScrCheck(obj);
- if ( db_get_b(NULL, IDLEMOD, IDL_IDLEONLOCK, 0)) IdleObject_SetWorkstationCheck(obj);
- if ( db_get_b(NULL, IDLEMOD, IDL_IDLEPRIVATE, 0)) IdleObject_SetPrivacy(obj);
- if ( db_get_b(NULL, IDLEMOD, IDL_IDLESTATUSLOCK, 0)) IdleObject_SetStatusLock(obj);
- if ( db_get_b(NULL, IDLEMOD, IDL_IDLEONTSDC, 0)) IdleObject_SetTerminalCheck(obj);
-}
-
-static void IdleObject_Create(IdleObject * obj)
+void IdleObject_Create()
{
- memset(obj, 0, sizeof(IdleObject));
- obj->hTimer = SetTimer(nullptr, 0, 2000, IdleTimer);
- IdleObject_ReadSettings(obj);
+ memset(&gIdleObject, 0, sizeof(gIdleObject));
+ gIdleObject.hTimer = SetTimer(nullptr, 0, 2000, IdleTimer);
}
-static void IdleObject_Destroy(IdleObject * obj)
+void IdleObject_Destroy()
{
- if (IdleObject_IsIdle(obj))
+ if (gIdleObject.bIsIdle)
NotifyEventHooks(hIdleEvent, 0, 0);
- IdleObject_ClearIdle(obj);
- KillTimer(nullptr, obj->hTimer);
+ gIdleObject.bIsIdle = false;
+ KillTimer(nullptr, gIdleObject.hTimer);
}
-static int IdleObject_IsUserIdle(IdleObject * obj)
+static int IdleObject_IsUserIdle()
{
- DWORD dwTick;
- if (IdleObject_GetMethod(obj)) {
+ if (S.bIdleMethod) {
+ DWORD dwTick;
CallService(MS_SYSTEM_GETIDLE, 0, (LPARAM)&dwTick);
- return GetTickCount() - dwTick > (obj->minutes * 60 * 1000);
+ return GetTickCount() - dwTick > (S.iIdleTime1st * 60 * 1000);
}
LASTINPUTINFO ii = { sizeof(ii) };
- if ( GetLastInputInfo(&ii))
- return GetTickCount() - ii.dwTime > (obj->minutes * 60 * 1000);
+ if (GetLastInputInfo(&ii))
+ return GetTickCount() - ii.dwTime > (S.iIdleTime1st * 60 * 1000);
return FALSE;
}
-static void IdleObject_Tick(IdleObject * obj)
+static void IdleObject_Tick(IdleObject *obj)
{
bool idle = false;
- int idleType = 0, flags = 0;
+ int idleType = 0, flags = 0;
- if (obj->useridlecheck && IdleObject_IsUserIdle(obj)) {
+ if (S.bIdleCheck && IdleObject_IsUserIdle()) {
idleType = 1; idle = true;
}
- else if (IdleObject_IdleCheckSaver(obj) && IsScreenSaverRunning()) {
+ else if (S.bIdleOnSaver && IsScreenSaverRunning()) {
idleType = 2; idle = true;
}
- else if (IdleObject_IdleCheckFullScr(obj) && IsFullScreen()) {
+ else if (S.bIdleOnFullScr && IsFullScreen()) {
idleType = 5; idle = true;
}
- else if (IdleObject_IdleCheckWorkstation(obj) && IsWorkstationLocked()) {
+ else if (S.bIdleOnLock && IsWorkstationLocked()) {
idleType = 3; idle = true;
}
- else if (IdleObject_IdleCheckTerminal(obj) && IsTerminalDisconnected()) {
+ else if (S.bIdleOnTerminal && IsTerminalDisconnected()) {
idleType = 4; idle = true;
}
- if (IdleObject_IsPrivacy(obj))
+ if (S.bIdlePrivate)
flags |= IDF_PRIVACY;
- if ( !IdleObject_IsIdle(obj) && idle) {
- IdleObject_SetIdle(obj);
+ if (!obj->bIsIdle && idle) {
+ obj->bIsIdle = true;
obj->idleType = idleType;
NotifyEventHooks(hIdleEvent, 0, IDF_ISIDLE | flags);
}
- if (IdleObject_IsIdle(obj) && !idle) {
- IdleObject_ClearIdle(obj);
+
+ if (obj->bIsIdle && !idle) {
+ obj->bIsIdle = false;
obj->idleType = 0;
NotifyEventHooks(hIdleEvent, 0, flags);
-} }
+ }
+}
void CALLBACK IdleTimer(HWND, UINT, UINT_PTR idEvent, DWORD)
{
@@ -234,137 +113,17 @@ void CALLBACK IdleTimer(HWND, UINT, UINT_PTR idEvent, DWORD)
IdleObject_Tick(&gIdleObject);
}
-int IdleGetStatusIndex(WORD status)
-{
- for (int j = 0; j < _countof(aa_Status); j++)
- if (aa_Status[j] == status)
- return j;
-
- return 0;
-}
-
-static INT_PTR CALLBACK IdleOptsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- switch (msg) {
- case WM_INITDIALOG:
- {
- int j;
- int method = db_get_b(NULL, IDLEMOD, IDL_IDLEMETHOD, 0);
- TranslateDialogDefault(hwndDlg);
- CheckDlgButton(hwndDlg, IDC_IDLESHORT, db_get_b(NULL, IDLEMOD, IDL_USERIDLECHECK, 0) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_IDLEONWINDOWS, method == 0 ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_IDLEONMIRANDA, method ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_SCREENSAVER, db_get_b(NULL, IDLEMOD, IDL_IDLEONSAVER, 0) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_FULLSCREEN, db_get_b(NULL, IDLEMOD, IDL_IDLEONFULLSCR, 0) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_LOCKED, db_get_b(NULL, IDLEMOD, IDL_IDLEONLOCK, 0) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_IDLEPRIVATE, db_get_b(NULL, IDLEMOD, IDL_IDLEPRIVATE, 0) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_IDLESTATUSLOCK, db_get_b(NULL, IDLEMOD, IDL_IDLESTATUSLOCK, 0) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_IDLETERMINAL, db_get_b(NULL, IDLEMOD, IDL_IDLEONTSDC, 0) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_IDLESOUNDSOFF, db_get_b(NULL, IDLEMOD, IDL_IDLESOUNDSOFF, 1) ? BST_CHECKED : BST_UNCHECKED);
- SendDlgItemMessage(hwndDlg, IDC_IDLESPIN, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_IDLE1STTIME), 0);
- SendDlgItemMessage(hwndDlg, IDC_IDLESPIN, UDM_SETRANGE32, 1, 60);
- SendDlgItemMessage(hwndDlg, IDC_IDLESPIN, UDM_SETPOS, 0, MAKELONG((short) db_get_b(NULL, IDLEMOD, IDL_IDLETIME1ST, 10), 0));
- SendDlgItemMessage(hwndDlg, IDC_IDLE1STTIME, EM_LIMITTEXT, (WPARAM)2, 0);
-
- CheckDlgButton(hwndDlg, IDC_AASHORTIDLE, db_get_b(NULL, IDLEMOD, IDL_AAENABLE, 0) ? BST_CHECKED : BST_UNCHECKED);
- for (j = 0; j < _countof(aa_Status); j++)
- SendDlgItemMessage(hwndDlg, IDC_AASTATUS, CB_ADDSTRING, 0, (LPARAM)pcli->pfnGetStatusModeDescription(aa_Status[j], 0));
-
- j = IdleGetStatusIndex((WORD)(db_get_w(NULL, IDLEMOD, IDL_AASTATUS, 0)));
- SendDlgItemMessage(hwndDlg, IDC_AASTATUS, CB_SETCURSEL, j, 0);
- SendMessage(hwndDlg, WM_USER+2, 0, 0);
- return TRUE;
- }
- case WM_USER+2:
- {
- BOOL checked = IsDlgButtonChecked(hwndDlg, IDC_IDLESHORT) == BST_CHECKED;
- EnableWindow(GetDlgItem(hwndDlg, IDC_IDLEONWINDOWS), checked);
- EnableWindow(GetDlgItem(hwndDlg, IDC_IDLEONMIRANDA), checked);
- EnableWindow(GetDlgItem(hwndDlg, IDC_IDLE1STTIME), checked);
- EnableWindow(GetDlgItem(hwndDlg, IDC_AASTATUS), IsDlgButtonChecked(hwndDlg, IDC_AASHORTIDLE) == BST_CHECKED?1:0);
- EnableWindow(GetDlgItem(hwndDlg, IDC_IDLESTATUSLOCK), IsDlgButtonChecked(hwndDlg, IDC_AASHORTIDLE) == BST_CHECKED?1:0);
- break;
- }
- case WM_NOTIFY:
- {
- NMHDR * hdr = (NMHDR *)lParam;
- if (hdr && hdr->code == PSN_APPLY) {
- int method = IsDlgButtonChecked(hwndDlg, IDC_IDLEONWINDOWS) == BST_CHECKED;
- int mins = SendDlgItemMessage(hwndDlg, IDC_IDLESPIN, UDM_GETPOS, 0, 0);
- db_set_b(NULL, IDLEMOD, IDL_IDLETIME1ST, (BYTE)(HIWORD(mins) == 0 ? LOWORD(mins) : 10));
- db_set_b(NULL, IDLEMOD, IDL_USERIDLECHECK, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_IDLESHORT) == BST_CHECKED));
- db_set_b(NULL, IDLEMOD, IDL_IDLEMETHOD, (BYTE)(method ? 0 : 1));
- db_set_b(NULL, IDLEMOD, IDL_IDLEONSAVER, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_SCREENSAVER) == BST_CHECKED));
- db_set_b(NULL, IDLEMOD, IDL_IDLEONFULLSCR, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_FULLSCREEN) == BST_CHECKED));
- db_set_b(NULL, IDLEMOD, IDL_IDLEONLOCK, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_LOCKED) == BST_CHECKED));
- db_set_b(NULL, IDLEMOD, IDL_IDLEONTSDC, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_IDLETERMINAL) == BST_CHECKED));
- db_set_b(NULL, IDLEMOD, IDL_IDLEPRIVATE, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_IDLEPRIVATE) == BST_CHECKED));
- db_set_b(NULL, IDLEMOD, IDL_AAENABLE, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_AASHORTIDLE) == BST_CHECKED?1:0));
- db_set_b(NULL, IDLEMOD, IDL_IDLESTATUSLOCK, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_IDLESTATUSLOCK) == BST_CHECKED?1:0));
- {
- int curSel = SendDlgItemMessage(hwndDlg, IDC_AASTATUS, CB_GETCURSEL, 0, 0);
- if (curSel != CB_ERR) {
- db_set_w(NULL, IDLEMOD, IDL_AASTATUS, (WORD)(aa_Status[curSel]));
- }
- }
- db_set_b(NULL, IDLEMOD, IDL_IDLESOUNDSOFF, (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_IDLESOUNDSOFF) == BST_CHECKED));
- // destroy any current idle and reset settings.
- IdleObject_Destroy(&gIdleObject);
- IdleObject_Create(&gIdleObject);
- }
- break;
- }
- case WM_COMMAND:
- switch (LOWORD(wParam)) {
- case IDC_IDLE1STTIME:
- {
- int min;
- if ((HWND)lParam != GetFocus() || HIWORD(wParam) != EN_CHANGE) return FALSE;
- min = GetDlgItemInt(hwndDlg, IDC_IDLE1STTIME, NULL, FALSE);
- if (min == 0 && GetWindowTextLength(GetDlgItem(hwndDlg, IDC_IDLE1STTIME)))
- SendDlgItemMessage(hwndDlg, IDC_IDLESPIN, UDM_SETPOS, 0, MAKELONG((short) 1, 0));
- break;
- }
- case IDC_IDLESHORT:
- case IDC_AASHORTIDLE:
- SendMessage(hwndDlg, WM_USER+2, 0, 0);
- break;
-
- case IDC_AASTATUS:
- if (HIWORD(wParam) != CBN_SELCHANGE)
- return TRUE;
- }
- SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
- break;
- }
- return FALSE;
-}
-
-static int IdleOptInit(WPARAM wParam, LPARAM)
-{
- OPTIONSDIALOGPAGE odp = { 0 };
- odp.position = 100000000;
- odp.hInstance = hInst;
- odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_IDLE);
- odp.szGroup.a = LPGEN("Status");
- odp.szTitle.a = LPGEN("Idle");
- odp.pfnDlgProc = IdleOptsDlgProc;
- odp.flags = ODPF_BOLDGROUPS;
- Options_AddPage(wParam, &odp);
- return 0;
-}
-
static INT_PTR IdleGetInfo(WPARAM, LPARAM lParam)
{
MIRANDA_IDLE_INFO *mii = (MIRANDA_IDLE_INFO*)lParam;
- if ( !mii || mii->cbSize != sizeof(MIRANDA_IDLE_INFO))
+ if (!mii)
return 1;
- mii->idleTime = gIdleObject.minutes;
- mii->privacy = gIdleObject.state&0x10;
- mii->aaStatus = gIdleObject.aastatus;
- mii->aaLock = gIdleObject.state&0x20;
- mii->idlesoundsoff = gIdleObject.aasoundsoff;
+ mii->idleTime = S.iIdleTime1st;
+ mii->privacy = S.bIdlePrivate;
+ mii->aaStatus = (S.bAAEnable) ? S.bAAStatus : 0;
+ mii->aaLock = S.bIdleStatusLock;
+ mii->idlesoundsoff = S.bIdleSoundsOff;
mii->idleType = gIdleObject.idleType;
return 0;
}
@@ -374,7 +133,7 @@ int LoadIdleModule(void)
bModuleInitialized = TRUE;
hIdleEvent = CreateHookableEvent(ME_IDLE_CHANGED);
- IdleObject_Create(&gIdleObject);
+ IdleObject_Create();
CreateServiceFunction(MS_IDLE_GETIDLEINFO, IdleGetInfo);
HookEvent(ME_OPT_INITIALISE, IdleOptInit);
return 0;
@@ -382,9 +141,9 @@ int LoadIdleModule(void)
void UnloadIdleModule()
{
- if ( !bModuleInitialized) return;
+ if (!bModuleInitialized) return;
- IdleObject_Destroy(&gIdleObject);
+ IdleObject_Destroy();
DestroyHookableEvent(hIdleEvent);
hIdleEvent = nullptr;
}
diff --git a/src/core/stdidle/src/main.cpp b/src/core/stdidle/src/main.cpp
index bbc78d8281..4ca3c99d33 100644
--- a/src/core/stdidle/src/main.cpp
+++ b/src/core/stdidle/src/main.cpp
@@ -34,7 +34,6 @@ PLUGININFOEX pluginInfo = {
MIRANDA_VERSION_DWORD,
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/src/core/stdidle/src/options.cpp b/src/core/stdidle/src/options.cpp
new file mode 100644
index 0000000000..58484c7650
--- /dev/null
+++ b/src/core/stdidle/src/options.cpp
@@ -0,0 +1,134 @@
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (c) 2012-17 Miranda NG project (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+
+static const WORD aa_Status[] = { ID_STATUS_AWAY, ID_STATUS_NA, ID_STATUS_OCCUPIED, ID_STATUS_DND, ID_STATUS_ONTHEPHONE, ID_STATUS_OUTTOLUNCH };
+
+int IdleGetStatusIndex(WORD status)
+{
+ for (int j = 0; j < _countof(aa_Status); j++)
+ if (aa_Status[j] == status)
+ return j;
+
+ return 0;
+}
+
+class COptionsDlg : public CPluginDlgBase
+{
+ CCtrlEdit edt1sttime;
+ CCtrlSpin spinIdle;
+ CCtrlCombo cmbAAStatus;
+ CCtrlCheck chkShort, chkOnWindows, chkOnMiranda, chkScreenSaver, chkFullScreen, chkLocked;
+ CCtrlCheck chkPrivate, chkStatusLock, chkTerminal, chkSoundsOff, chkShortIdle;
+
+ void ShowHide()
+ {
+ BOOL bChecked = chkShort.GetState();
+ chkOnWindows.Enable(bChecked);
+ chkOnMiranda.Enable(bChecked);
+ edt1sttime.Enable(bChecked);
+
+ bChecked = chkShortIdle.GetState();
+ cmbAAStatus.Enable(bChecked);
+ chkStatusLock.Enable(bChecked);
+ }
+
+public:
+ COptionsDlg() :
+ CPluginDlgBase(hInst, IDD_OPT_IDLE, IDLEMOD),
+ edt1sttime(this, IDC_IDLE1STTIME),
+ spinIdle(this, IDC_IDLESPIN),
+ cmbAAStatus(this, IDC_AASTATUS),
+ chkShort(this, IDC_IDLESHORT),
+ chkLocked(this, IDC_LOCKED),
+ chkPrivate(this, IDC_IDLEPRIVATE),
+ chkTerminal(this, IDC_IDLETERMINAL),
+ chkOnWindows(this, IDC_IDLEONWINDOWS),
+ chkSoundsOff(this, IDC_IDLESOUNDSOFF),
+ chkOnMiranda(this, IDC_IDLEONMIRANDA),
+ chkShortIdle(this, IDC_AASHORTIDLE),
+ chkStatusLock(this, IDC_IDLESTATUSLOCK),
+ chkFullScreen(this, IDC_FULLSCREEN),
+ chkScreenSaver(this, IDC_SCREENSAVER)
+ {
+ CreateLink(chkShort, S.bIdleCheck);
+ CreateLink(chkLocked, S.bIdleOnLock);
+ CreateLink(chkPrivate, S.bIdlePrivate);
+ CreateLink(chkTerminal, S.bIdleOnTerminal);
+ CreateLink(chkShortIdle, S.bAAEnable);
+ CreateLink(chkOnMiranda, S.bIdleMethod);
+ CreateLink(chkSoundsOff, S.bIdleSoundsOff);
+ CreateLink(chkStatusLock, S.bIdleStatusLock);
+ CreateLink(chkFullScreen, S.bIdleOnFullScr);
+ CreateLink(chkScreenSaver, S.bIdleOnSaver);
+
+ chkShortIdle.OnChange = chkShort.OnChange = Callback(this, &COptionsDlg::onChange);
+ }
+
+ virtual void OnInitDialog() override
+ {
+ chkOnWindows.SetState(!S.bIdleMethod);
+
+ spinIdle.SetRange(60, 1);
+ spinIdle.SetPosition(S.iIdleTime1st);
+
+ for (int j = 0; j < _countof(aa_Status); j++)
+ cmbAAStatus.AddString(pcli->pfnGetStatusModeDescription(aa_Status[j], 0));
+ cmbAAStatus.SetCurSel(IdleGetStatusIndex(S.bAAStatus));
+
+ ShowHide();
+ }
+
+ virtual void OnApply() override
+ {
+ S.iIdleTime1st = spinIdle.GetPosition();
+
+ int curSel = cmbAAStatus.GetCurSel();
+ if (curSel != CB_ERR)
+ S.bAAStatus = aa_Status[curSel];
+
+ // destroy any current idle and reset settings.
+ IdleObject_Destroy();
+ IdleObject_Create();
+ }
+
+ void onChange(CCtrlCheck*)
+ {
+ ShowHide();
+ }
+};
+
+int IdleOptInit(WPARAM wParam, LPARAM)
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+ odp.position = 100000000;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_IDLE);
+ odp.szGroup.a = LPGEN("Status");
+ odp.szTitle.a = LPGEN("Idle");
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.pDialog = new COptionsDlg();
+ Options_AddPage(wParam, &odp);
+ return 0;
+}
diff --git a/src/core/stdidle/src/stdafx.h b/src/core/stdidle/src/stdafx.h
index 19c886f65e..2060da635d 100644
--- a/src/core/stdidle/src/stdafx.h
+++ b/src/core/stdidle/src/stdafx.h
@@ -26,7 +26,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <shlobj.h>
#include <commctrl.h>
#include <vssym32.h>
-#include <Wtsapi32.h>
#include <stdio.h>
#include <time.h>
@@ -52,6 +51,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <m_protocols.h>
#include <m_options.h>
#include <m_skin.h>
+#include <m_gui.h>
#include <m_contacts.h>
#include <m_message.h>
#include <m_userinfo.h>
@@ -64,4 +64,35 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "../../mir_app/src/resource.h"
+#define IDLEMOD "Idle"
+
extern HINSTANCE hInst;
+
+struct Settings
+{
+ Settings() :
+ bIdleCheck(IDLEMOD, "UserIdleCheck", 0),
+ bIdleMethod(IDLEMOD, "IdleMethod", 0),
+ bIdleOnSaver(IDLEMOD, "IdleOnSaver", 0),
+ bIdleOnFullScr(IDLEMOD, "IdleOnFullScr", 0),
+ bIdleOnLock(IDLEMOD, "IdleOnLock", 0),
+ bIdlePrivate(IDLEMOD, "IdlePrivate", 0),
+ bIdleSoundsOff(IDLEMOD, "IdleSoundsOff", 1),
+ bIdleOnTerminal(IDLEMOD, "IdleOnTerminalDisconnect", 0),
+ bIdleStatusLock(IDLEMOD, "IdleStatusLock", 0),
+ bAAEnable(IDLEMOD, "AAEnable", 0),
+ bAAStatus(IDLEMOD, "AAStatus", 0),
+ iIdleTime1st(IDLEMOD, "IdleTime1st", 10)
+ {}
+
+ CMOption<BYTE> bIdleCheck, bIdleMethod, bIdleOnSaver, bIdleOnFullScr, bIdleOnLock;
+ CMOption<BYTE> bIdlePrivate, bIdleSoundsOff, bIdleOnTerminal, bIdleStatusLock;
+ CMOption<BYTE> bAAEnable;
+ CMOption<WORD> bAAStatus;
+ CMOption<DWORD> iIdleTime1st;
+};
+
+extern Settings S;
+
+void IdleObject_Destroy();
+void IdleObject_Create();
diff --git a/src/core/stdidle/src/version.h b/src/core/stdidle/src/version.h
index e791573b3a..79f0d6a8b5 100644
--- a/src/core/stdidle/src/version.h
+++ b/src/core/stdidle/src/version.h
@@ -7,6 +7,5 @@
#define __FILENAME "stdidle.dll"
#define __DESCRIPTION "Core module for idle state processing."
#define __AUTHOR "Miranda NG Development Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/StdIdle/"
#define __COPYRIGHT "© 2012-17 Miranda NG Development Team"
diff --git a/src/core/stdmsg/src/msgdialog.cpp b/src/core/stdmsg/src/msgdialog.cpp
index 104b5fff31..937bb69857 100644
--- a/src/core/stdmsg/src/msgdialog.cpp
+++ b/src/core/stdmsg/src/msgdialog.cpp
@@ -1291,13 +1291,8 @@ INT_PTR CSrmmWindow::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
break;
case IDC_ADD:
- {
- ADDCONTACTSTRUCT acs = {};
- acs.hContact = m_hContact;
- acs.handleType = HANDLE_CONTACT;
- acs.szProto = nullptr;
- CallService(MS_ADDCONTACT_SHOW, (WPARAM)m_hwnd, (LPARAM)&acs);
- }
+ Contact_Add(m_hContact, m_hwnd);
+
if (!db_get_b(m_hContact, "CList", "NotOnList", 0))
ShowWindow(GetDlgItem(m_hwnd, IDC_ADD), FALSE);
break;
diff --git a/src/core/stdmsg/src/srmm.cpp b/src/core/stdmsg/src/srmm.cpp
index 0b2ead1a17..37cd4f6b33 100644
--- a/src/core/stdmsg/src/srmm.cpp
+++ b/src/core/stdmsg/src/srmm.cpp
@@ -34,7 +34,6 @@ PLUGININFOEX pluginInfo = {
MIRANDA_VERSION_DWORD,
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/src/core/stdmsg/src/stdafx.h b/src/core/stdmsg/src/stdafx.h
index 6069356b35..cfdb92aa2a 100644
--- a/src/core/stdmsg/src/stdafx.h
+++ b/src/core/stdmsg/src/stdafx.h
@@ -55,7 +55,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <m_contacts.h>
#include <m_userinfo.h>
#include <m_history.h>
-#include <m_addcontact.h>
#include <m_chat_int.h>
#include <m_message.h>
#include <m_file.h>
diff --git a/src/core/stdmsg/src/version.h b/src/core/stdmsg/src/version.h
index 55820233cb..64a2cec97c 100644
--- a/src/core/stdmsg/src/version.h
+++ b/src/core/stdmsg/src/version.h
@@ -8,6 +8,5 @@
#define __FILENAME "stdmsg.dll"
#define __DESCRIPTION "Core module for send/receive instant messages."
#define __AUTHOR "Miranda NG Development Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/StdMsg/"
#define __COPYRIGHT "© 2012-17 Miranda NG Development Team"
diff --git a/src/core/stdssl/src/main.cpp b/src/core/stdssl/src/main.cpp
index 584ff7335b..90aab5f72f 100644
--- a/src/core/stdssl/src/main.cpp
+++ b/src/core/stdssl/src/main.cpp
@@ -33,7 +33,6 @@ PLUGININFOEX pluginInfo = {
MIRANDA_VERSION_DWORD,
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/src/core/stdssl/src/version.h b/src/core/stdssl/src/version.h
index 3029aeafe1..a71217e95e 100644
--- a/src/core/stdssl/src/version.h
+++ b/src/core/stdssl/src/version.h
@@ -8,6 +8,5 @@
#define __FILENAME "stdssl.dll"
#define __DESCRIPTION "Core driver for Windows native SSL support."
#define __AUTHOR "Miranda NG Development Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/StdSSL/"
#define __COPYRIGHT "© 2014-17 Miranda NG Development Team"
diff --git a/src/core/stduihist/src/main.cpp b/src/core/stduihist/src/main.cpp
index 287c043f8a..9b2bf33812 100644
--- a/src/core/stduihist/src/main.cpp
+++ b/src/core/stduihist/src/main.cpp
@@ -33,7 +33,6 @@ PLUGININFOEX pluginInfo = {
MIRANDA_VERSION_DWORD,
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/src/core/stduihist/src/version.h b/src/core/stduihist/src/version.h
index 618c3c0661..8b3eae6dfc 100644
--- a/src/core/stduihist/src/version.h
+++ b/src/core/stduihist/src/version.h
@@ -7,6 +7,5 @@
#define __FILENAME "stduihist.dll"
#define __DESCRIPTION "Core module for built-in history viewer."
#define __AUTHOR "Miranda NG Development Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/StdUIHist/"
#define __COPYRIGHT "© 2012-17 Miranda NG Development Team"
diff --git a/src/core/stduserinfo/src/main.cpp b/src/core/stduserinfo/src/main.cpp
index bd569fa829..7563b8e37e 100644
--- a/src/core/stduserinfo/src/main.cpp
+++ b/src/core/stduserinfo/src/main.cpp
@@ -33,7 +33,6 @@ PLUGININFOEX pluginInfo = {
MIRANDA_VERSION_DWORD,
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/src/core/stduserinfo/src/version.h b/src/core/stduserinfo/src/version.h
index 1f9f1d330d..e6c6551488 100644
--- a/src/core/stduserinfo/src/version.h
+++ b/src/core/stduserinfo/src/version.h
@@ -7,6 +7,5 @@
#define __FILENAME "stduserinfo.dll"
#define __DESCRIPTION "Core module for providing user information."
#define __AUTHOR "Miranda NG Development Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/StdUserInfo/"
#define __COPYRIGHT "© 2012-17 Miranda NG Development Team"
diff --git a/src/core/stduseronline/src/main.cpp b/src/core/stduseronline/src/main.cpp
index 433c91e033..5bc9d43059 100644
--- a/src/core/stduseronline/src/main.cpp
+++ b/src/core/stduseronline/src/main.cpp
@@ -33,7 +33,6 @@ PLUGININFOEX pluginInfo = {
MIRANDA_VERSION_DWORD,
__DESCRIPTION,
__AUTHOR,
- __AUTHOREMAIL,
__COPYRIGHT,
__AUTHORWEB,
UNICODE_AWARE,
diff --git a/src/core/stduseronline/src/version.h b/src/core/stduseronline/src/version.h
index de5b14de25..7a7922cac6 100644
--- a/src/core/stduseronline/src/version.h
+++ b/src/core/stduseronline/src/version.h
@@ -7,6 +7,5 @@
#define __FILENAME "stduseronline.dll"
#define __DESCRIPTION "Core module for user-is-online event processing."
#define __AUTHOR "Miranda NG Development Team"
-#define __AUTHOREMAIL ""
#define __AUTHORWEB "https://miranda-ng.org/p/StdUserOnline/"
#define __COPYRIGHT "© 2012-17 Miranda NG Development Team"
diff --git a/src/mir_app/res/resource.rc b/src/mir_app/res/resource.rc
index 34acde8b42..465247f6cc 100644
--- a/src/mir_app/res/resource.rc
+++ b/src/mir_app/res/resource.rc
@@ -402,10 +402,8 @@ BEGIN
GROUPBOX "",IDC_PLUGININFOFRAME,4,125,307,125,BS_RIGHT
RTEXT "Description:",IDC_STATIC,6,136,61,10
EDITTEXT IDC_PLUGINLONGINFO,70,136,236,25,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | ES_WANTRETURN | NOT WS_BORDER
- RTEXT "Author(s):",IDC_STATIC,6,165,61,10
- EDITTEXT IDC_PLUGINAUTHOR,70,165,236,18,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | ES_WANTRETURN | NOT WS_BORDER
- RTEXT "E-mail:",IDC_STATIC,6,188,61,10
- CONTROL "",IDC_PLUGINEMAIL,"Hyperlink",WS_TABSTOP,70,188,236,10
+ RTEXT "Author(s):",IDC_STATIC,6,175,61,10
+ EDITTEXT IDC_PLUGINAUTHOR,70,175,236,18,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | ES_WANTRETURN | NOT WS_BORDER
RTEXT "Homepage:",IDC_STATIC,6,200,61,9
CONTROL "",IDC_PLUGINURL,"Hyperlink",WS_TABSTOP,70,201,236,10
RTEXT "Unique ID:",IDC_STATIC,6,214,61,10
diff --git a/src/mir_app/src/MDatabaseCommon.cpp b/src/mir_app/src/MDatabaseCommon.cpp
index 34f1d68caf..9d3025603a 100644
--- a/src/mir_app/src/MDatabaseCommon.cpp
+++ b/src/mir_app/src/MDatabaseCommon.cpp
@@ -233,7 +233,7 @@ STDMETHODIMP_(BOOL) MDatabaseCommon::GetContactSettingStr(MCONTACT contactID, LP
STDMETHODIMP_(BOOL) MDatabaseCommon::GetContactSettingStatic(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv)
{
bool bNeedsWchars;
- size_t cbSaved;
+ size_t cbSaved = 0;
if (dbv->type == DBVT_WCHAR) { // there's no wchar_t strings in a database, we need conversion
cbSaved = dbv->cchVal - 1;
diff --git a/src/mir_app/src/addcontact.cpp b/src/mir_app/src/addcontact.cpp
index 9f13b06811..8c44e895e1 100644
--- a/src/mir_app/src/addcontact.cpp
+++ b/src/mir_app/src/addcontact.cpp
@@ -37,15 +37,20 @@ static wchar_t* sttDecodeString(DWORD dwFlags, MAllStrings &src)
class CAddContactDlg : public CDlgBase
{
- ADDCONTACTSTRUCT m_acs;
-
CCtrlEdit m_authReq, m_myHandle;
CCtrlCheck m_chkAdded, m_chkAuth, m_chkOpen;
CCtrlButton m_btnOk;
CCtrlCombo m_group;
+protected:
+ MEVENT m_hDbEvent = 0;
+ MCONTACT m_hContact = 0;
+ const char *m_szProto;
+ PROTOSEARCHRESULT *m_psr = nullptr;
+ CMStringW m_szName;
+
public:
- CAddContactDlg(ADDCONTACTSTRUCT *acs) :
+ CAddContactDlg() :
CDlgBase(g_hInst, IDD_ADDCONTACT),
m_chkAdded(this, IDC_ADDED),
m_chkAuth(this, IDC_AUTH),
@@ -58,67 +63,19 @@ public:
m_chkAuth.OnChange = Callback(this, &CAddContactDlg::OnAuthClicked);
m_chkOpen.OnChange = Callback(this, &CAddContactDlg::OnOpenClicked);
m_btnOk.OnClick = Callback(this, &CAddContactDlg::OnOk);
-
- m_acs = *acs;
}
void OnInitDialog()
{
- char szUin[10];
Window_SetSkinIcon_IcoLib(m_hwnd, SKINICON_OTHER_ADDCONTACT);
- if (m_acs.handleType == HANDLE_EVENT) {
- DWORD dwUin;
- DBEVENTINFO dbei = {};
- dbei.cbBlob = sizeof(DWORD);
- dbei.pBlob = (PBYTE)&dwUin;
- db_event_get(m_acs.hDbEvent, &dbei);
- _ltoa(dwUin, szUin, 10);
- m_acs.szProto = dbei.szModule;
- }
-
- MCONTACT hContact;
- wchar_t *szName = nullptr, *tmpStr = nullptr;
- if (m_acs.handleType == HANDLE_CONTACT)
- szName = cli.pfnGetContactDisplayName(hContact = m_acs.hContact, 0);
- else {
- int isSet = 0;
- hContact = 0;
-
- if (m_acs.handleType == HANDLE_EVENT) {
- DBEVENTINFO dbei = {};
- dbei.cbBlob = db_event_getBlobSize(m_acs.hDbEvent);
- dbei.pBlob = (PBYTE)mir_alloc(dbei.cbBlob);
- db_event_get(m_acs.hDbEvent, &dbei);
- hContact = *(MCONTACT*)(dbei.pBlob + sizeof(DWORD));
- mir_free(dbei.pBlob);
- if (hContact != INVALID_CONTACT_ID) {
- szName = cli.pfnGetContactDisplayName(hContact, 0);
- isSet = 1;
- }
- }
- if (!isSet) {
- if (m_acs.handleType == HANDLE_EVENT)
- szName = mir_a2u(szUin);
- else {
- szName = sttDecodeString(m_acs.psr->flags, m_acs.psr->id);
- if (szName == nullptr)
- szName = sttDecodeString(m_acs.psr->flags, m_acs.psr->nick);
- }
- }
- }
- if (szName && szName[0])
- SetCaption(CMStringW(FORMAT, TranslateT("Add %s"), szName));
+ if (!m_szName.IsEmpty())
+ SetCaption(CMStringW(FORMAT, TranslateT("Add %s"), m_szName.c_str()));
else
SetCaption(TranslateT("Add contact"));
- mir_free(tmpStr);
-
- if (m_acs.handleType == HANDLE_CONTACT && m_acs.hContact)
- if (m_acs.szProto == nullptr || (m_acs.szProto != nullptr && *m_acs.szProto == 0))
- m_acs.szProto = GetContactProto(m_acs.hContact);
int groupSel = 0;
- ptrW tszGroup(db_get_wsa(hContact, "CList", "Group"));
+ ptrW tszGroup(db_get_wsa(m_hContact, "CList", "Group"));
wchar_t *grpName;
for (int groupId = 1; (grpName = Clist_GroupGetName(groupId, nullptr)) != nullptr; groupId++) {
int id = m_group.AddString(grpName, groupId);
@@ -137,7 +94,7 @@ public:
if (db_get_b(0, "Miranda", "AuthOpenWindow", 1))
m_chkOpen.SetState(true);
- DWORD flags = (m_acs.szProto) ? CallProtoServiceInt(0, m_acs.szProto, PS_GETCAPS, PFLAGNUM_4, 0) : 0;
+ DWORD flags = (m_szProto) ? CallProtoServiceInt(0, m_szProto, PS_GETCAPS, PFLAGNUM_4, 0) : 0;
if (flags & PF4_FORCEADDED) // force you were added requests for this protocol
m_chkAdded.Enable(false);
@@ -159,7 +116,7 @@ public:
void OnAuthClicked(CCtrlButton*)
{
- DWORD flags = CallProtoServiceInt(0, m_acs.szProto, PS_GETCAPS, PFLAGNUM_4, 0);
+ DWORD flags = CallProtoServiceInt(0, m_szProto, PS_GETCAPS, PFLAGNUM_4, 0);
if (flags & PF4_NOCUSTOMAUTH)
m_authReq.Enable(false);
else
@@ -174,26 +131,15 @@ public:
void OnOk(CCtrlButton*)
{
- MCONTACT hContact = INVALID_CONTACT_ID;
- switch (m_acs.handleType) {
- case HANDLE_EVENT:
- {
- DBEVENTINFO dbei = {};
- db_event_get(m_acs.hDbEvent, &dbei);
- hContact = (MCONTACT)CallProtoServiceInt(0, dbei.szModule, PS_ADDTOLISTBYEVENT, 0, (LPARAM)m_acs.hDbEvent);
- }
- break;
-
- case HANDLE_SEARCHRESULT:
- hContact = (MCONTACT)CallProtoServiceInt(0, m_acs.szProto, PS_ADDTOLIST, 0, (LPARAM)m_acs.psr);
- break;
-
- case HANDLE_CONTACT:
- hContact = m_acs.hContact;
- break;
- }
+ MCONTACT hContact = 0;
+ if (m_hDbEvent)
+ hContact = (MCONTACT)CallProtoServiceInt(0, m_szProto, PS_ADDTOLISTBYEVENT, 0, m_hDbEvent);
+ else if (m_psr)
+ hContact = (MCONTACT)CallProtoServiceInt(0, m_szProto, PS_ADDTOLIST, 0, (LPARAM)m_psr);
+ else
+ hContact = m_hContact;
- if (hContact == 0)
+ if (hContact == 0) // something went wrong
return;
ptrW szHandle(m_myHandle.GetText());
@@ -210,7 +156,7 @@ public:
ProtoChainSend(hContact, PSS_ADDED, 0, 0);
if (m_chkAuth.GetState()) {
- DWORD flags = CallProtoServiceInt(0, m_acs.szProto, PS_GETCAPS, PFLAGNUM_4, 0);
+ DWORD flags = CallProtoServiceInt(0, m_szProto, PS_GETCAPS, PFLAGNUM_4, 0);
if (flags & PF4_NOCUSTOMAUTH)
ProtoChainSend(hContact, PSS_AUTHREQUEST, 0, 0);
else
@@ -222,23 +168,85 @@ public:
}
};
-INT_PTR AddContactDialog(WPARAM wParam, LPARAM lParam)
+MIR_APP_DLL(void) Contact_Add(MCONTACT hContact, HWND hwndParent)
{
- if (lParam == 0)
- return 1;
+ if (hContact == 0)
+ return;
+
+ struct CAddByContact : public CAddContactDlg
+ {
+ CAddByContact(MCONTACT hContact)
+ {
+ m_hContact = hContact;
+ m_szName = cli.pfnGetContactDisplayName(hContact, 0);
+ m_szProto = GetContactProto(hContact);
+ }
+ };
- ADDCONTACTSTRUCT *acs = (ADDCONTACTSTRUCT*)lParam;
- if (wParam) {
- CAddContactDlg dlg(acs);
- dlg.SetParent((HWND)wParam);
+ if (hwndParent != nullptr) {
+ CAddByContact dlg(hContact);
+ dlg.SetParent(hwndParent);
dlg.DoModal();
}
- else (new CAddContactDlg(acs))->Show();
- return 0;
+ else (new CAddByContact(hContact))->Show();
}
-int LoadAddContactModule(void)
+MIR_APP_DLL(void) Contact_AddByEvent(MEVENT hEvent, HWND hwndParent)
{
- CreateServiceFunction(MS_ADDCONTACT_SHOW, AddContactDialog);
- return 0;
+ struct CAddByEvent : public CAddContactDlg
+ {
+ CAddByEvent(MEVENT hEvent)
+ {
+ m_hDbEvent = hEvent;
+
+ DWORD dwData[2];
+ DBEVENTINFO dbei = {};
+ dbei.cbBlob = sizeof(dwData);
+ dbei.pBlob = (PBYTE)&dwData;
+ db_event_get(hEvent, &dbei);
+ if (dwData[0] != 0)
+ m_szName.Format(L"%d", dwData[0]);
+
+ m_hContact = dwData[1];
+ if (m_hContact != INVALID_CONTACT_ID)
+ m_szName = cli.pfnGetContactDisplayName(m_hContact, 0);
+
+ m_szProto = dbei.szModule;
+ }
+ };
+
+ if (hwndParent != nullptr) {
+ CAddByEvent dlg(hEvent);
+ dlg.SetParent(hwndParent);
+ dlg.DoModal();
+ }
+ else (new CAddByEvent(hEvent))->Show();
+}
+
+MIR_APP_DLL(void) Contact_AddBySearch(const char *szProto, struct PROTOSEARCHRESULT *psr, HWND hwndParent)
+{
+ struct CAddBySearch : public CAddContactDlg
+ {
+ CAddBySearch(const char *szProto, struct PROTOSEARCHRESULT *psr)
+ {
+ m_szProto = szProto;
+ m_psr = psr;
+
+ wchar_t *p = sttDecodeString(psr->flags, psr->id);
+ if (p == nullptr)
+ p = sttDecodeString(psr->flags, psr->nick);
+
+ if (p) {
+ m_szName = p;
+ mir_free(p);
+ }
+ }
+ };
+
+ if (hwndParent != nullptr) {
+ CAddBySearch dlg(szProto, psr);
+ dlg.SetParent(hwndParent);
+ dlg.DoModal();
+ }
+ else (new CAddBySearch(szProto, psr))->Show();
}
diff --git a/src/mir_app/src/auth.cpp b/src/mir_app/src/auth.cpp
index 119b86e061..375c37967d 100644
--- a/src/mir_app/src/auth.cpp
+++ b/src/mir_app/src/auth.cpp
@@ -24,24 +24,277 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "stdafx.h"
-#define MS_AUTH_SHOWREQUEST "Auth/ShowRequest"
-#define MS_AUTH_SHOWADDED "Auth/ShowAdded"
+/////////////////////////////////////////////////////////////////////////////////////////
+// Auth Request dialog
-INT_PTR CALLBACK DlgProcAuthReq(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
-INT_PTR CALLBACK DlgProcAdded(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+class CAuthReqDlg : public CDlgBase
+{
+ MEVENT m_hDbEvent;
+ MCONTACT m_hContact;
+ const char *m_szProto;
+
+ CCtrlCheck chkAdd;
+ CCtrlButton btnDetails, btnLater, btnOk, btnCancel;
+
+public:
+ CAuthReqDlg(MEVENT hEvent) :
+ CDlgBase(g_hInst, IDD_AUTHREQ),
+ m_hDbEvent(hEvent),
+ btnOk(this, IDOK),
+ btnCancel(this, IDCANCEL),
+ btnLater(this, IDC_DECIDELATER),
+ btnDetails(this, IDC_DETAILS),
+ chkAdd(this, IDC_ADDCHECK)
+ {
+ btnOk.OnClick = Callback(this, &CAuthReqDlg::onClick_OK);
+ btnCancel.OnClick = Callback(this, &CAuthReqDlg::onClick_Cancel);
+ btnLater.OnClick = Callback(this, &CAuthReqDlg::onClick_Later);
+ btnDetails.OnClick = Callback(this, &CAuthReqDlg::onClick_Details);
+ }
+
+ virtual void OnInitDialog() override
+ {
+ Button_SetIcon_IcoLib(m_hwnd, IDC_DETAILS, SKINICON_OTHER_USERDETAILS, LPGEN("View user's details"));
+ Button_SetIcon_IcoLib(m_hwnd, IDC_ADD, SKINICON_OTHER_ADDCONTACT, LPGEN("Add contact permanently to list"));
+
+ int iBlobSize = db_event_getBlobSize(m_hDbEvent);
+ if (iBlobSize == -1)
+ return;
+
+ // blob is: uin(DWORD), hcontact(DWORD), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ), reason(ASCIIZ)
+ DBEVENTINFO dbei = {};
+ dbei.cbBlob = iBlobSize;
+ dbei.pBlob = (PBYTE)alloca(dbei.cbBlob);
+ if (db_event_get(m_hDbEvent, &dbei))
+ return;
+
+ m_szProto = dbei.szModule;
+
+ DWORD uin = *(PDWORD)dbei.pBlob;
+ m_hContact = DbGetAuthEventContact(&dbei);
+ char *nick = (char*)dbei.pBlob + sizeof(DWORD) * 2;
+ char *first = nick + mir_strlen(nick) + 1;
+ char *last = first + mir_strlen(first) + 1;
+ char *email = last + mir_strlen(last) + 1;
+ char *reason = email + mir_strlen(email) + 1;
+
+ SendMessage(m_hwnd, WM_SETICON, ICON_SMALL, CallProtoService(dbei.szModule, PS_LOADICON, PLI_PROTOCOL | PLIF_SMALL, 0));
+ SendMessage(m_hwnd, WM_SETICON, ICON_BIG, CallProtoService(dbei.szModule, PS_LOADICON, PLI_PROTOCOL | PLIF_LARGE, 0));
+
+ ptrW lastT(dbei.flags & DBEF_UTF ? Utf8DecodeW(last) : mir_a2u(last));
+ ptrW firstT(dbei.flags & DBEF_UTF ? Utf8DecodeW(first) : mir_a2u(first));
+ ptrW nickT(dbei.flags & DBEF_UTF ? Utf8DecodeW(nick) : mir_a2u(nick));
+ ptrW emailT(dbei.flags & DBEF_UTF ? Utf8DecodeW(email) : mir_a2u(email));
+ ptrW reasonT(dbei.flags & DBEF_UTF ? Utf8DecodeW(reason) : mir_a2u(reason));
+
+ wchar_t name[128] = L"";
+ int off = 0;
+ if (firstT[0] && lastT[0])
+ off = mir_snwprintf(name, L"%s %s", (wchar_t*)firstT, (wchar_t*)lastT);
+ else if (firstT[0])
+ off = mir_snwprintf(name, L"%s", (wchar_t*)firstT);
+ else if (lastT[0])
+ off = mir_snwprintf(name, L"%s", (wchar_t*)lastT);
+ if (mir_wstrlen(nickT)) {
+ if (off)
+ mir_snwprintf(name + off, _countof(name) - off, L" (%s)", (wchar_t*)nickT);
+ else
+ wcsncpy_s(name, nickT, _TRUNCATE);
+ }
+ if (!name[0])
+ wcsncpy_s(name, TranslateT("<Unknown>"), _TRUNCATE);
+
+ PROTOACCOUNT *acc = Proto_GetAccount(dbei.szModule);
+
+ wchar_t hdr[256];
+ if (uin && emailT[0])
+ mir_snwprintf(hdr, TranslateT("%s requested authorization\n%u (%s) on %s"), name, uin, (wchar_t*)emailT, acc->tszAccountName);
+ else if (uin)
+ mir_snwprintf(hdr, TranslateT("%s requested authorization\n%u on %s"), name, uin, acc->tszAccountName);
+ else
+ mir_snwprintf(hdr, TranslateT("%s requested authorization\n%s on %s"), name, emailT[0] ? (wchar_t*)emailT : TranslateT("(Unknown)"), acc->tszAccountName);
+
+ SetDlgItemText(m_hwnd, IDC_HEADERBAR, hdr);
+ SetDlgItemText(m_hwnd, IDC_REASON, reasonT);
-INT_PTR ShowReqWindow(WPARAM, LPARAM lParam)
+ if (m_hContact == INVALID_CONTACT_ID || !db_get_b(m_hContact, "CList", "NotOnList", 0))
+ ShowWindow(GetDlgItem(m_hwnd, IDC_ADD), FALSE);
+
+ SendDlgItemMessage(m_hwnd, IDC_DENYREASON, EM_LIMITTEXT, 255, 0);
+ if (CallProtoService(dbei.szModule, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_NOAUTHDENYREASON) {
+ EnableWindow(GetDlgItem(m_hwnd, IDC_DENYREASON), FALSE);
+ SetDlgItemText(m_hwnd, IDC_DENYREASON, TranslateT("Feature is not supported by protocol"));
+ }
+
+ if (!db_get_b(m_hContact, "CList", "NotOnList", 0)) {
+ chkAdd.Disable();
+ chkAdd.SetState(false);
+ }
+ else chkAdd.SetState(true);
+ }
+
+ virtual void OnDestroy() override
+ {
+ Button_FreeIcon_IcoLib(m_hwnd, IDC_ADD);
+ Button_FreeIcon_IcoLib(m_hwnd, IDC_DETAILS);
+ DestroyIcon((HICON)SendMessage(m_hwnd, WM_SETICON, ICON_BIG, 0));
+ DestroyIcon((HICON)SendMessage(m_hwnd, WM_SETICON, ICON_SMALL, 0));
+ }
+
+ void onClick_OK(CCtrlButton*)
+ {
+ CallProtoService(m_szProto, PS_AUTHALLOW, m_hDbEvent, 0);
+
+ if (chkAdd.GetState())
+ Contact_AddByEvent(m_hDbEvent, m_hwnd);
+ }
+
+ void onClick_Cancel(CCtrlButton*)
+ {
+ if (IsWindowEnabled(GetDlgItem(m_hwnd, IDC_DENYREASON))) {
+ wchar_t tszReason[256];
+ GetDlgItemText(m_hwnd, IDC_DENYREASON, tszReason, _countof(tszReason));
+ CallProtoService(m_szProto, PS_AUTHDENY, m_hDbEvent, (LPARAM)tszReason);
+ }
+ else CallProtoService(m_szProto, PS_AUTHDENY, m_hDbEvent, 0);
+ }
+
+ void onClick_Later(CCtrlButton*)
+ {
+ Close();
+ }
+
+ void onClick_Details(CCtrlButton*)
+ {
+ CallService(MS_USERINFO_SHOWDIALOG, m_hContact, 0);
+ }
+};
+
+static INT_PTR ShowReqWindow(WPARAM, LPARAM lParam)
{
- CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_AUTHREQ), NULL, DlgProcAuthReq, (LPARAM)((CLISTEVENT *)lParam)->hDbEvent);
+ (new CAuthReqDlg(((CLISTEVENT *)lParam)->hDbEvent))->Show();
return 0;
}
-INT_PTR ShowAddedWindow(WPARAM, LPARAM lParam)
+/////////////////////////////////////////////////////////////////////////////////////////
+
+class CAddedDlg : public CDlgBase
{
- CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_ADDED), NULL, DlgProcAdded, (LPARAM)((CLISTEVENT *)lParam)->hDbEvent);
+ MEVENT m_hDbEvent;
+ MCONTACT m_hContact;
+
+ CCtrlButton btnDetails, btnAdd, btnOk;
+
+public:
+ CAddedDlg(MEVENT hEvent) :
+ CDlgBase(g_hInst, IDD_ADDED),
+ m_hDbEvent(hEvent),
+ btnOk(this, IDOK),
+ btnAdd(this, IDC_ADD),
+ btnDetails(this, IDC_DETAILS)
+ {
+ btnOk.OnClick = Callback(this, &CAddedDlg::onClick_OK);
+ btnAdd.OnClick = Callback(this, &CAddedDlg::onClick_Add);
+ btnDetails.OnClick = Callback(this, &CAddedDlg::onClick_Details);
+ }
+
+ virtual void OnInitDialog() override
+ {
+ Button_SetIcon_IcoLib(m_hwnd, IDC_DETAILS, SKINICON_OTHER_USERDETAILS, LPGEN("View user's details"));
+ Button_SetIcon_IcoLib(m_hwnd, IDC_ADD, SKINICON_OTHER_ADDCONTACT, LPGEN("Add contact permanently to list"));
+
+ // blob is: uin(DWORD), hcontact(HANDLE), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ)
+ DBEVENTINFO dbei = {};
+ dbei.cbBlob = db_event_getBlobSize(m_hDbEvent);
+ dbei.pBlob = (PBYTE)alloca(dbei.cbBlob);
+ db_event_get(m_hDbEvent, &dbei);
+
+ m_hContact = DbGetAuthEventContact(&dbei);
+
+ DWORD uin = *(PDWORD)dbei.pBlob;
+ char* nick = (char*)dbei.pBlob + sizeof(DWORD) * 2;
+ char* first = nick + mir_strlen(nick) + 1;
+ char* last = first + mir_strlen(first) + 1;
+ char* email = last + mir_strlen(last) + 1;
+
+ SendMessage(m_hwnd, WM_SETICON, ICON_SMALL, CallProtoService(dbei.szModule, PS_LOADICON, PLI_PROTOCOL | PLIF_SMALL, 0));
+ SendMessage(m_hwnd, WM_SETICON, ICON_BIG, CallProtoService(dbei.szModule, PS_LOADICON, PLI_PROTOCOL | PLIF_LARGE, 0));
+
+ PROTOACCOUNT* acc = Proto_GetAccount(dbei.szModule);
+
+ ptrW lastT(dbei.flags & DBEF_UTF ? Utf8DecodeW(last) : mir_a2u(last));
+ ptrW firstT(dbei.flags & DBEF_UTF ? Utf8DecodeW(first) : mir_a2u(first));
+ ptrW nickT(dbei.flags & DBEF_UTF ? Utf8DecodeW(nick) : mir_a2u(nick));
+ ptrW emailT(dbei.flags & DBEF_UTF ? Utf8DecodeW(email) : mir_a2u(email));
+
+ wchar_t name[128] = L"";
+ int off = 0;
+ if (firstT[0] && lastT[0])
+ off = mir_snwprintf(name, L"%s %s", firstT, lastT);
+ else if (firstT[0])
+ off = mir_snwprintf(name, L"%s", firstT);
+ else if (lastT[0])
+ off = mir_snwprintf(name, L"%s", lastT);
+ if (nickT[0]) {
+ if (off)
+ mir_snwprintf(name + off, _countof(name) - off, L" (%s)", nickT);
+ else
+ wcsncpy_s(name, nickT, _TRUNCATE);
+ }
+ if (!name[0])
+ wcsncpy_s(name, TranslateT("<Unknown>"), _TRUNCATE);
+
+ wchar_t hdr[256];
+ if (uin && emailT[0])
+ mir_snwprintf(hdr, TranslateT("%s added you to the contact list\n%u (%s) on %s"), name, uin, emailT, acc->tszAccountName);
+ else if (uin)
+ mir_snwprintf(hdr, TranslateT("%s added you to the contact list\n%u on %s"), name, uin, acc->tszAccountName);
+ else
+ mir_snwprintf(hdr, TranslateT("%s added you to the contact list\n%s on %s"), name, emailT[0] ? emailT : TranslateT("(Unknown)"), acc->tszAccountName);
+ SetDlgItemText(m_hwnd, IDC_HEADERBAR, hdr);
+
+ if (m_hContact == INVALID_CONTACT_ID || !db_get_b(m_hContact, "CList", "NotOnList", 0))
+ ShowWindow(GetDlgItem(m_hwnd, IDC_ADD), FALSE);
+ }
+
+ virtual void OnDestroy() override
+ {
+ Button_FreeIcon_IcoLib(m_hwnd, IDC_ADD);
+ Button_FreeIcon_IcoLib(m_hwnd, IDC_DETAILS);
+ DestroyIcon((HICON)SendMessage(m_hwnd, WM_SETICON, ICON_BIG, 0));
+ DestroyIcon((HICON)SendMessage(m_hwnd, WM_SETICON, ICON_SMALL, 0));
+ }
+
+ void onClick_OK(CCtrlButton*)
+ {
+ Contact_AddByEvent(m_hDbEvent, m_hwnd);
+ }
+
+ void onClick_Add(CCtrlButton*)
+ {
+ Contact_AddByEvent(m_hDbEvent, m_hwnd);
+
+ if (m_hContact == INVALID_CONTACT_ID || !db_get_b(m_hContact, "CList", "NotOnList", 0))
+ ShowWindow(GetDlgItem(m_hwnd, IDC_ADD), FALSE);
+ }
+
+ void onClick_Details(CCtrlButton*)
+ {
+ CallService(MS_USERINFO_SHOWDIALOG, m_hContact, 0);
+ }
+};
+
+static INT_PTR ShowAddedWindow(WPARAM, LPARAM lParam)
+{
+ (new CAddedDlg(((CLISTEVENT *)lParam)->hDbEvent))->Show();
return 0;
}
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#define MS_AUTH_SHOWADDED "Auth/ShowAdded"
+#define MS_AUTH_SHOWREQUEST "Auth/ShowRequest"
+
static int AuthEventAdded(WPARAM, LPARAM lParam)
{
wchar_t szTooltip[256];
@@ -92,11 +345,16 @@ static int AuthEventAdded(WPARAM, LPARAM lParam)
return 0;
}
+static void CALLBACK LaunchAuth()
+{
+ HookEvent(ME_DB_EVENT_ADDED, AuthEventAdded);
+}
+
int LoadSendRecvAuthModule(void)
{
CreateServiceFunction(MS_AUTH_SHOWREQUEST, ShowReqWindow);
CreateServiceFunction(MS_AUTH_SHOWADDED, ShowAddedWindow);
- HookEvent(ME_DB_EVENT_ADDED, AuthEventAdded);
+ Miranda_WaitOnHandle(LaunchAuth);
Skin_AddSound("AuthRequest", LPGENW("Alerts"), LPGENW("Authorization request"));
Skin_AddSound("AddedEvent", LPGENW("Alerts"), LPGENW("Added event"));
diff --git a/src/mir_app/src/authdialogs.cpp b/src/mir_app/src/authdialogs.cpp
deleted file mode 100644
index 81ab47bfd3..0000000000
--- a/src/mir_app/src/authdialogs.cpp
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (c) 2012-17 Miranda NG project (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-INT_PTR CALLBACK DlgProcAdded(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- MEVENT hDbEvent = (MEVENT)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-
- switch (msg) {
- case WM_INITDIALOG:
- TranslateDialogDefault(hwndDlg);
- Button_SetIcon_IcoLib(hwndDlg, IDC_DETAILS, SKINICON_OTHER_USERDETAILS, LPGEN("View user's details"));
- Button_SetIcon_IcoLib(hwndDlg, IDC_ADD, SKINICON_OTHER_ADDCONTACT, LPGEN("Add contact permanently to list"));
-
- hDbEvent = lParam;
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
- {
- //blob is: uin(DWORD), hcontact(HANDLE), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ)
- DBEVENTINFO dbei = {};
- dbei.cbBlob = db_event_getBlobSize(hDbEvent);
- dbei.pBlob = (PBYTE)alloca(dbei.cbBlob);
- db_event_get(hDbEvent, &dbei);
-
- DWORD uin = *(PDWORD)dbei.pBlob;
- MCONTACT hContact = DbGetAuthEventContact(&dbei);
- char* nick = (char*)dbei.pBlob + sizeof(DWORD) * 2;
- char* first = nick + mir_strlen(nick) + 1;
- char* last = first + mir_strlen(first) + 1;
- char* email = last + mir_strlen(last) + 1;
-
- SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, CallProtoService(dbei.szModule, PS_LOADICON, PLI_PROTOCOL | PLIF_SMALL, 0));
- SendMessage(hwndDlg, WM_SETICON, ICON_BIG, CallProtoService(dbei.szModule, PS_LOADICON, PLI_PROTOCOL | PLIF_LARGE, 0));
-
- PROTOACCOUNT* acc = Proto_GetAccount(dbei.szModule);
-
- wchar_t* lastT = dbei.flags & DBEF_UTF ? Utf8DecodeW(last) : mir_a2u(last);
- wchar_t* firstT = dbei.flags & DBEF_UTF ? Utf8DecodeW(first) : mir_a2u(first);
- wchar_t* nickT = dbei.flags & DBEF_UTF ? Utf8DecodeW(nick) : mir_a2u(nick);
- wchar_t* emailT = dbei.flags & DBEF_UTF ? Utf8DecodeW(email) : mir_a2u(email);
-
- wchar_t name[128] = L"";
- int off = 0;
- if (firstT[0] && lastT[0])
- off = mir_snwprintf(name, L"%s %s", firstT, lastT);
- else if (firstT[0])
- off = mir_snwprintf(name, L"%s", firstT);
- else if (lastT[0])
- off = mir_snwprintf(name, L"%s", lastT);
- if (nickT[0]) {
- if (off)
- mir_snwprintf(name + off, _countof(name) - off, L" (%s)", nickT);
- else
- wcsncpy_s(name, nickT, _TRUNCATE);
- }
- if (!name[0])
- wcsncpy_s(name, TranslateT("<Unknown>"), _TRUNCATE);
-
- wchar_t hdr[256];
- if (uin && emailT[0])
- mir_snwprintf(hdr, TranslateT("%s added you to the contact list\n%u (%s) on %s"), name, uin, emailT, acc->tszAccountName);
- else if (uin)
- mir_snwprintf(hdr, TranslateT("%s added you to the contact list\n%u on %s"), name, uin, acc->tszAccountName);
- else
- mir_snwprintf(hdr, TranslateT("%s added you to the contact list\n%s on %s"), name, emailT[0] ? emailT : TranslateT("(Unknown)"), acc->tszAccountName);
-
- SetDlgItemText(hwndDlg, IDC_HEADERBAR, hdr);
-
- mir_free(lastT);
- mir_free(firstT);
- mir_free(nickT);
- mir_free(emailT);
-
- SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DETAILS), GWLP_USERDATA, (LONG_PTR)hContact);
-
- if (hContact == INVALID_CONTACT_ID || !db_get_b(hContact, "CList", "NotOnList", 0))
- ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), FALSE);
- }
- return TRUE;
-
- case WM_COMMAND:
- switch (LOWORD(wParam)) {
- case IDC_ADD:
- {
- ADDCONTACTSTRUCT acs = { 0 };
- acs.hDbEvent = hDbEvent;
- acs.handleType = HANDLE_EVENT;
- acs.szProto = "";
- CallService(MS_ADDCONTACT_SHOW, (WPARAM)hwndDlg, (LPARAM)&acs);
-
- MCONTACT hContact = (MCONTACT)GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DETAILS), GWLP_USERDATA);
- if ((hContact == INVALID_CONTACT_ID) || !db_get_b(hContact, "CList", "NotOnList", 0))
- ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), FALSE);
- }
- break;
-
- case IDC_DETAILS:
- {
- MCONTACT hContact = (MCONTACT)GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DETAILS), GWLP_USERDATA);
- CallService(MS_USERINFO_SHOWDIALOG, hContact, 0);
- }
- break;
-
- case IDOK:
- {
- ADDCONTACTSTRUCT acs = { 0 };
- acs.hDbEvent = hDbEvent;
- acs.handleType = HANDLE_EVENT;
- acs.szProto = "";
- CallService(MS_ADDCONTACT_SHOW, (WPARAM)hwndDlg, (LPARAM)&acs);
- }
- //fall through
- case IDCANCEL:
- DestroyWindow(hwndDlg);
- break;
- }
- break;
-
- case WM_DESTROY:
- Button_FreeIcon_IcoLib(hwndDlg, IDC_ADD);
- Button_FreeIcon_IcoLib(hwndDlg, IDC_DETAILS);
- DestroyIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0));
- DestroyIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0));
- break;
- }
- return FALSE;
-}
-
-INT_PTR CALLBACK DlgProcAuthReq(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- MEVENT hDbEvent = (MEVENT)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-
- switch (msg) {
- case WM_INITDIALOG:
- TranslateDialogDefault(hwndDlg);
- Button_SetIcon_IcoLib(hwndDlg, IDC_DETAILS, SKINICON_OTHER_USERDETAILS, LPGEN("View user's details"));
- Button_SetIcon_IcoLib(hwndDlg, IDC_ADD, SKINICON_OTHER_ADDCONTACT, LPGEN("Add contact permanently to list"));
- {
- hDbEvent = lParam;
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
-
- //blob is: uin(DWORD), hcontact(DWORD), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ), reason(ASCIIZ)
- DBEVENTINFO dbei = {};
- dbei.cbBlob = db_event_getBlobSize(hDbEvent);
- dbei.pBlob = (PBYTE)alloca(dbei.cbBlob);
- db_event_get(hDbEvent, &dbei);
-
- DWORD uin = *(PDWORD)dbei.pBlob;
- MCONTACT hContact = DbGetAuthEventContact(&dbei);
- char *nick = (char*)dbei.pBlob + sizeof(DWORD) * 2;
- char *first = nick + mir_strlen(nick) + 1;
- char *last = first + mir_strlen(first) + 1;
- char *email = last + mir_strlen(last) + 1;
- char *reason = email + mir_strlen(email) + 1;
-
- SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, CallProtoService(dbei.szModule, PS_LOADICON, PLI_PROTOCOL | PLIF_SMALL, 0));
- SendMessage(hwndDlg, WM_SETICON, ICON_BIG, CallProtoService(dbei.szModule, PS_LOADICON, PLI_PROTOCOL | PLIF_LARGE, 0));
-
- PROTOACCOUNT *acc = Proto_GetAccount(dbei.szModule);
-
- ptrW lastT(dbei.flags & DBEF_UTF ? Utf8DecodeW(last) : mir_a2u(last));
- ptrW firstT(dbei.flags & DBEF_UTF ? Utf8DecodeW(first) : mir_a2u(first));
- ptrW nickT(dbei.flags & DBEF_UTF ? Utf8DecodeW(nick) : mir_a2u(nick));
- ptrW emailT(dbei.flags & DBEF_UTF ? Utf8DecodeW(email) : mir_a2u(email));
- ptrW reasonT(dbei.flags & DBEF_UTF ? Utf8DecodeW(reason) : mir_a2u(reason));
-
- wchar_t name[128] = L"";
- int off = 0;
- if (firstT[0] && lastT[0])
- off = mir_snwprintf(name, L"%s %s", (wchar_t*)firstT, (wchar_t*)lastT);
- else if (firstT[0])
- off = mir_snwprintf(name, L"%s", (wchar_t*)firstT);
- else if (lastT[0])
- off = mir_snwprintf(name, L"%s", (wchar_t*)lastT);
- if (mir_wstrlen(nickT)) {
- if (off)
- mir_snwprintf(name + off, _countof(name) - off, L" (%s)", (wchar_t*)nickT);
- else
- wcsncpy_s(name, nickT, _TRUNCATE);
- }
- if (!name[0])
- wcsncpy_s(name, TranslateT("<Unknown>"), _TRUNCATE);
-
- wchar_t hdr[256];
- if (uin && emailT[0])
- mir_snwprintf(hdr, TranslateT("%s requested authorization\n%u (%s) on %s"), name, uin, (wchar_t*)emailT, acc->tszAccountName);
- else if (uin)
- mir_snwprintf(hdr, TranslateT("%s requested authorization\n%u on %s"), name, uin, acc->tszAccountName);
- else
- mir_snwprintf(hdr, TranslateT("%s requested authorization\n%s on %s"), name, emailT[0] ? (wchar_t*)emailT : TranslateT("(Unknown)"), acc->tszAccountName);
-
- SetDlgItemText(hwndDlg, IDC_HEADERBAR, hdr);
- SetDlgItemText(hwndDlg, IDC_REASON, reasonT);
-
- if (hContact == INVALID_CONTACT_ID || !db_get_b(hContact, "CList", "NotOnList", 0))
- ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), FALSE);
-
- SendDlgItemMessage(hwndDlg, IDC_DENYREASON, EM_LIMITTEXT, 255, 0);
- if (CallProtoService(dbei.szModule, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_NOAUTHDENYREASON) {
- EnableWindow(GetDlgItem(hwndDlg, IDC_DENYREASON), FALSE);
- SetDlgItemText(hwndDlg, IDC_DENYREASON, TranslateT("Feature is not supported by protocol"));
- }
- if (!db_get_b(hContact, "CList", "NotOnList", 0)) {
- EnableWindow(GetDlgItem(hwndDlg, IDC_ADDCHECK), FALSE);
- CheckDlgButton(hwndDlg, IDC_ADDCHECK, BST_UNCHECKED);
- }
- else CheckDlgButton(hwndDlg, IDC_ADDCHECK, BST_CHECKED);
-
- SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DETAILS), GWLP_USERDATA, (LONG_PTR)hContact);
- }
- return TRUE;
-
- case WM_COMMAND:
- switch (LOWORD(wParam)) {
- case IDC_DETAILS:
- CallService(MS_USERINFO_SHOWDIALOG, GetWindowLongPtr((HWND)lParam, GWLP_USERDATA), 0);
- break;
-
- case IDC_DECIDELATER:
- DestroyWindow(hwndDlg);
- break;
-
- case IDOK:
- {
- DBEVENTINFO dbei = {};
- db_event_get(hDbEvent, &dbei);
- CallProtoService(dbei.szModule, PS_AUTHALLOW, (WPARAM)hDbEvent, 0);
-
- if (IsDlgButtonChecked(hwndDlg, IDC_ADDCHECK)) {
- ADDCONTACTSTRUCT acs = { 0 };
- acs.hDbEvent = hDbEvent;
- acs.handleType = HANDLE_EVENT;
- acs.szProto = "";
- CallService(MS_ADDCONTACT_SHOW, (WPARAM)hwndDlg, (LPARAM)&acs);
- }
- }
- DestroyWindow(hwndDlg);
- break;
-
- case IDCANCEL:
- {
- DBEVENTINFO dbei = {};
- db_event_get(hDbEvent, &dbei);
-
- if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_DENYREASON))) {
- wchar_t tszReason[256];
- GetDlgItemText(hwndDlg, IDC_DENYREASON, tszReason, _countof(tszReason));
- CallProtoService(dbei.szModule, PS_AUTHDENY, hDbEvent, (LPARAM)tszReason);
- }
- else CallProtoService(dbei.szModule, PS_AUTHDENY, hDbEvent, 0);
- }
- DestroyWindow(hwndDlg);
- break;
- }
- break;
-
- case WM_DESTROY:
- Button_FreeIcon_IcoLib(hwndDlg, IDC_ADD);
- Button_FreeIcon_IcoLib(hwndDlg, IDC_DETAILS);
- DestroyIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0));
- DestroyIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0));
- break;
- }
- return FALSE;
-}
diff --git a/src/mir_app/src/clui.cpp b/src/mir_app/src/clui.cpp
index 40db3c69ca..4e82f1ac36 100644
--- a/src/mir_app/src/clui.cpp
+++ b/src/mir_app/src/clui.cpp
@@ -204,11 +204,7 @@ static INT_PTR MenuItem_DeleteContact(WPARAM wParam, LPARAM lParam)
static INT_PTR MenuItem_AddContactToList(WPARAM hContact, LPARAM)
{
- ADDCONTACTSTRUCT acs = { 0 };
- acs.hContact = hContact;
- acs.handleType = HANDLE_CONTACT;
- acs.szProto = "";
- CallService(MS_ADDCONTACT_SHOW, 0, (LPARAM)&acs);
+ Contact_Add(hContact);
return 0;
}
diff --git a/src/mir_app/src/colorchooser.cpp b/src/mir_app/src/colorchooser.cpp
index e437c4a5a2..3d4f2004bc 100644
--- a/src/mir_app/src/colorchooser.cpp
+++ b/src/mir_app/src/colorchooser.cpp
@@ -32,6 +32,15 @@ static COLORREF colorTable[] =
RGB(0,255,0), RGB(255,255,0), RGB(255,0,0), RGB(255,255,255)
};
+MIR_APP_DLL(COLORREF*) Srmm_GetColorTable(int *pSize)
+{
+ if (pSize != nullptr)
+ *pSize = _countof(colorTable);
+ return colorTable;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
class CColorChooserDlg : public CDlgBase
{
CCtrlBase m_text;
@@ -175,31 +184,26 @@ public:
break;
case WM_MOUSEMOVE:
+ if (iCurrentHotTrack == -2)
+ return 0; // prevent focussing when not drawn yet!
{
HDC hdc = GetDC(m_hwnd);
- POINT pt;
- RECT rect;
- int but;
+ // weird stuff
+ POINT pt;
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
-
- if (iCurrentHotTrack == -2)
- return 0; // prevent focussing when not drawn yet!
-
- but = CalculateCoordinatesToButton(pt);
-
- // weird stuff
+ int but = CalculateCoordinatesToButton(pt);
if (but != iCurrentHotTrack) {
if (iCurrentHotTrack >= 0) {
- rect = CalculateButtonToCoordinates(iCurrentHotTrack);
+ RECT rect = CalculateButtonToCoordinates(iCurrentHotTrack);
DrawFocusRect(hdc, &rect);
iCurrentHotTrack = -1;
}
iCurrentHotTrack = but;
if (iCurrentHotTrack >= 0) {
- rect = CalculateButtonToCoordinates(iCurrentHotTrack);
+ RECT rect = CalculateButtonToCoordinates(iCurrentHotTrack);
DrawFocusRect(hdc, &rect);
}
}
@@ -208,20 +212,18 @@ public:
break;
case WM_PAINT:
+ RECT rc;
+ GetClientRect(m_hwnd, &rc);
+ rc.top += 20;
{
PAINTSTRUCT ps;
- int iThisRow = 1;
- int iThisColumn = 0;
-
- RECT rc;
- GetClientRect(m_hwnd, &rc);
- rc.top += 20;
-
HDC hdc = BeginPaint(m_hwnd, &ps);
// fill background
FillRect(hdc, &rc, GetSysColorBrush(COLOR_WINDOW));
+ int iThisRow = 1;
+ int iThisColumn = 0;
for (int i = 0; i < 16; i++) {
// decide place to draw the color block in the window
iThisColumn++;
diff --git a/src/mir_app/src/db_ini.cpp b/src/mir_app/src/db_ini.cpp
index dac3cc202f..6600a853a0 100644
--- a/src/mir_app/src/db_ini.cpp
+++ b/src/mir_app/src/db_ini.cpp
@@ -516,7 +516,7 @@ static void DoAutoExec(void)
if (!mir_wstrcmpi(szUse, L"no")) return;
GetPrivateProfileString(L"AutoExec", L"Safe", L"CLC Icons CLUI CList SkinSounds", buf, _countof(buf), mirandabootini);
ptrA szSafeSections(mir_u2a(buf));
- GetPrivateProfileString(L"AutoExec", L"Unsafe", L"AIM Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte", buf, _countof(buf), mirandabootini);
+ GetPrivateProfileString(L"AutoExec", L"Unsafe", L"Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte", buf, _countof(buf), mirandabootini);
ptrA szUnsafeSections(mir_u2a(buf));
GetPrivateProfileString(L"AutoExec", L"Warn", L"notsafe", szSecurity, _countof(szSecurity), mirandabootini);
diff --git a/src/mir_app/src/findadd.cpp b/src/mir_app/src/findadd.cpp
index 8d6fd86e88..0a66352c4a 100644
--- a/src/mir_app/src/findadd.cpp
+++ b/src/mir_app/src/findadd.cpp
@@ -745,36 +745,28 @@ static INT_PTR CALLBACK DlgProcFindAdd(HWND hwndDlg, UINT msg, WPARAM wParam, LP
break;
case IDC_ADD:
- {
- ADDCONTACTSTRUCT acs = { 0 };
-
- if (ListView_GetSelectedCount(hwndList) == 1) {
- LVITEM lvi;
- lvi.mask = LVIF_PARAM;
- lvi.iItem = ListView_GetNextItem(hwndList, -1, LVNI_ALL | LVNI_SELECTED);
- ListView_GetItem(hwndList, &lvi);
- ListSearchResult *lsr = (ListSearchResult*)lvi.lParam;
- acs.szProto = lsr->szProto;
- acs.psr = &lsr->psr;
- }
- else {
- wchar_t str[256];
- GetDlgItemText(hwndDlg, IDC_PROTOID, str, _countof(str));
- if (*rtrimw(str) == 0)
- break;
-
- PROTOSEARCHRESULT psr = { 0 };
- psr.cbSize = sizeof(psr);
- psr.flags = PSR_UNICODE;
- psr.id.w = str;
+ if (ListView_GetSelectedCount(hwndList) == 1) {
+ LVITEM lvi;
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = ListView_GetNextItem(hwndList, -1, LVNI_ALL | LVNI_SELECTED);
+ ListView_GetItem(hwndList, &lvi);
+ ListSearchResult *lsr = (ListSearchResult*)lvi.lParam;
+ Contact_AddBySearch(lsr->szProto, &lsr->psr, hwndDlg);
+ }
+ else {
+ wchar_t str[256];
+ GetDlgItemText(hwndDlg, IDC_PROTOID, str, _countof(str));
+ if (*rtrimw(str) == 0)
+ break;
- acs.psr = &psr;
- acs.szProto = (char*)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETITEMDATA,
- SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCURSEL, 0, 0), 0);
- }
+ char *szProto = (char*)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETITEMDATA,
+ SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCURSEL, 0, 0), 0);
- acs.handleType = HANDLE_SEARCHRESULT;
- CallService(MS_ADDCONTACT_SHOW, (WPARAM)hwndDlg, (LPARAM)&acs);
+ PROTOSEARCHRESULT psr = { 0 };
+ psr.cbSize = sizeof(psr);
+ psr.flags = PSR_UNICODE;
+ psr.id.w = str;
+ Contact_AddBySearch(szProto, &psr, hwndDlg);
}
break;
diff --git a/src/mir_app/src/mir_app.def b/src/mir_app/src/mir_app.def
index 055c4aa466..73fd746295 100644
--- a/src/mir_app/src/mir_app.def
+++ b/src/mir_app/src/mir_app.def
@@ -488,3 +488,7 @@ Clist_SetStatusMode @464
?MetaSetDefault@MDatabaseCommon@@UAGHPAUDBCachedContact@@@Z @493 NONAME
?EnumResidentSettings@MDatabaseCommon@@UAGHP6AHPBDPAX@Z1@Z @494 NONAME
KillModuleOptions @495
+Srmm_GetColorTable @496
+Contact_Add @497
+Contact_AddByEvent @498
+Contact_AddBySearch @499
diff --git a/src/mir_app/src/mir_app64.def b/src/mir_app/src/mir_app64.def
index fa96e4fb75..defbe2c365 100644
--- a/src/mir_app/src/mir_app64.def
+++ b/src/mir_app/src/mir_app64.def
@@ -488,3 +488,7 @@ Clist_SetStatusMode @464
?MetaSetDefault@MDatabaseCommon@@UEAAHPEAUDBCachedContact@@@Z @493 NONAME
?EnumResidentSettings@MDatabaseCommon@@UEAAHP6AHPEBDPEAX@Z1@Z @494 NONAME
KillModuleOptions @495
+Srmm_GetColorTable @496
+Contact_Add @497
+Contact_AddByEvent @498
+Contact_AddBySearch @499
diff --git a/src/mir_app/src/modules.cpp b/src/mir_app/src/modules.cpp
index 3576c79056..fc992baa5a 100644
--- a/src/mir_app/src/modules.cpp
+++ b/src/mir_app/src/modules.cpp
@@ -53,7 +53,6 @@ int LoadSkinHotkeys(void);
int LoadUserInfoModule(void); // ui: user info
int LoadVisibilityModule(void); // ui: visibility control
-int LoadAddContactModule(void); // ui: authcontrol contacts
int LoadUtilsModule(void); // ui: utils (has a few window classes, like HyperLink)
int LoadCLCModule(void); // window class: CLC control
int LoadButtonModule(void); // window class: button class
@@ -150,7 +149,6 @@ int LoadDefaultModules(void)
if (LoadProtocolsModule()) return 1;
LoadDbAccounts(); // retrieves the account array from a database
if (LoadContactsModule()) return 1;
- if (LoadAddContactModule()) return 1;
if (LoadMetacontacts()) return 1;
if (LoadNewPluginsModule()) return 1; // will call Load(void) on everything, clist will load first
diff --git a/src/mir_app/src/netlibsecurity.cpp b/src/mir_app/src/netlibsecurity.cpp
index ee507c7d13..0c678ea6b7 100644
--- a/src/mir_app/src/netlibsecurity.cpp
+++ b/src/mir_app/src/netlibsecurity.cpp
@@ -218,7 +218,7 @@ char* NtlmCreateResponseFromChallenge(HANDLE hSecurity, const char *szChallenge,
bool isGSSAPI = mir_wstrcmpi(hNtlm->szProvider, L"Kerberos") == 0;
bool hasChallenge = szChallenge != nullptr && szChallenge[0] != '\0';
if (hasChallenge) {
- unsigned tokenLen;
+ size_t tokenLen;
BYTE *token = (BYTE*)mir_base64_decode(szChallenge, &tokenLen);
if (token == nullptr)
return nullptr;
@@ -336,14 +336,14 @@ char* NtlmCreateResponseFromChallenge(HANDLE hSecurity, const char *szChallenge,
return nullptr;
}
- szOutputToken = mir_base64_encode((PBYTE)outputSecurityToken.pvBuffer, outputSecurityToken.cbBuffer);
+ szOutputToken = mir_base64_encode(outputSecurityToken.pvBuffer, outputSecurityToken.cbBuffer);
}
else {
if (!login || !psw)
return nullptr;
CMStringA szAuth(FORMAT, "%S:%S", login, psw);
- szOutputToken = mir_base64_encode((BYTE*)szAuth.c_str(), szAuth.GetLength());
+ szOutputToken = mir_base64_encode(szAuth.c_str(), szAuth.GetLength());
complete = true;
}
diff --git a/src/mir_app/src/newplugins.cpp b/src/mir_app/src/newplugins.cpp
index a080c0eab0..aa74284892 100644
--- a/src/mir_app/src/newplugins.cpp
+++ b/src/mir_app/src/newplugins.cpp
@@ -39,20 +39,13 @@ static int sttComparePluginsByName(const pluginEntry* p1, const pluginEntry* p2)
}
LIST<pluginEntry>
- pluginList(10, sttComparePluginsByName),
- servicePlugins(5, sttComparePluginsByName),
- clistPlugins(5, sttComparePluginsByName);
+pluginList(10, sttComparePluginsByName),
+servicePlugins(5, sttComparePluginsByName),
+clistPlugins(5, sttComparePluginsByName);
/////////////////////////////////////////////////////////////////////////////////////////
MUUID miid_last = MIID_LAST;
-MUUID miid_srmm = MIID_SRMM;
-MUUID miid_clist = MIID_CLIST;
-MUUID miid_database = MIID_DATABASE;
-MUUID miid_protocol = MIID_PROTOCOL;
-MUUID miid_servicemode = MIID_SERVICEMODE;
-MUUID miid_crypto = MIID_CRYPTO;
-MUUID miid_ssl = MIID_SSL;
/////////////////////////////////////////////////////////////////////////////////////////
@@ -73,7 +66,7 @@ static pluginEntry *plugin_freeimg, *plugin_crshdmp, *serviceModePlugin, *plugin
/////////////////////////////////////////////////////////////////////////////////////////
// basic functions
-bool hasMuuid(const MUUID* p, const MUUID& uuid)
+bool hasMuuid(const MUUID *p, const MUUID &uuid)
{
if (p == nullptr)
return false;
@@ -85,7 +78,7 @@ bool hasMuuid(const MUUID* p, const MUUID& uuid)
return false;
}
-bool hasMuuid(const BASIC_PLUGIN_INFO& bpi, const MUUID& uuid)
+bool hasMuuid(const BASIC_PLUGIN_INFO &bpi, const MUUID &uuid)
{
if (bpi.Interfaces)
return hasMuuid(bpi.Interfaces, uuid);
@@ -272,7 +265,7 @@ static int checkPI(BASIC_PLUGIN_INFO* bpi, PLUGININFOEX* pi)
return FALSE;
if (pi->shortName == nullptr || pi->description == nullptr || pi->author == nullptr ||
- pi->authorEmail == nullptr || pi->copyright == nullptr || pi->homepage == nullptr)
+ pi->copyright == nullptr || pi->homepage == nullptr)
return FALSE;
return TRUE;
@@ -344,7 +337,7 @@ void Plugin_Uninit(pluginEntry *p)
FreeLibrary(hInst);
memset(&p->bpi, 0, sizeof(p->bpi));
}
-
+
if (p == plugin_crshdmp)
plugin_crshdmp = nullptr;
pluginList.remove(p);
@@ -448,8 +441,8 @@ pluginEntry* OpenPlugin(wchar_t *tszFileName, wchar_t *dir, wchar_t *path)
}
// plugin declared that it's a database or a cryptor. load it asap!
- bool bIsDb = hasMuuid(pIds, miid_database);
- if (bIsDb || hasMuuid(pIds, miid_crypto)) {
+ bool bIsDb = hasMuuid(pIds, MIID_DATABASE);
+ if (bIsDb || hasMuuid(pIds, MIID_CRYPTO)) {
BASIC_PLUGIN_INFO bpi;
if (checkAPI(tszFullPath, &bpi, mirandaVersion, CHECKAPI_NONE)) {
// plugin is valid
@@ -466,24 +459,24 @@ pluginEntry* OpenPlugin(wchar_t *tszFileName, wchar_t *dir, wchar_t *path)
else p->pclass |= PCLASS_FAILED;
}
// plugin declared that it's a contact list. mark it for the future load
- else if (hasMuuid(pIds, miid_clist)) {
+ else if (hasMuuid(pIds, MIID_CLIST)) {
// keep a note of this plugin for later
clistPlugins.insert(p);
p->pclass |= PCLASS_CLIST;
}
// plugin declared that it's a ssl provider. mark it for the future load
- else if (hasMuuid(pIds, miid_ssl)) {
+ else if (hasMuuid(pIds, MIID_SSL)) {
plugin_ssl = p;
p->pclass |= PCLASS_LAST;
}
// plugin declared that it's a service mode plugin.
// load it for a profile manager's window
- else if (hasMuuid(pIds, miid_servicemode)) {
+ else if (hasMuuid(pIds, MIID_SERVICEMODE)) {
BASIC_PLUGIN_INFO bpi;
if (checkAPI(tszFullPath, &bpi, mirandaVersion, CHECKAPI_NONE)) {
p->pclass |= (PCLASS_OK | PCLASS_BASICAPI);
p->bpi = bpi;
- if (hasMuuid(bpi, miid_servicemode)) {
+ if (hasMuuid(bpi, MIID_SERVICEMODE)) {
p->pclass |= (PCLASS_SERVICE);
servicePlugins.insert(p);
}
@@ -756,18 +749,15 @@ void EnsureCheckerLoaded(bool bEnable)
int LoadSslModule(void)
{
bool bExtSSLLoaded = false;
-
- if (plugin_ssl != nullptr)
- {
- if (!TryLoadPlugin(plugin_ssl, false))
- {
+
+ if (plugin_ssl != nullptr) {
+ if (!TryLoadPlugin(plugin_ssl, false)) {
Plugin_Uninit(plugin_ssl);
}
else
bExtSSLLoaded = true;
}
- if (!bExtSSLLoaded)
- {
+ if (!bExtSSLLoaded) {
MuuidReplacement stdSsl = { MIID_SSL, L"stdssl", nullptr };
if (!LoadCorePlugin(stdSsl))
return 1;
diff --git a/src/mir_app/src/options.cpp b/src/mir_app/src/options.cpp
index 78ec37c135..2db108f1a4 100644
--- a/src/mir_app/src/options.cpp
+++ b/src/mir_app/src/options.cpp
@@ -1202,6 +1202,13 @@ static INT_PTR OpenOptionsDialog(WPARAM, LPARAM)
return 0;
}
+static int OptDynamicLoadOptions(WPARAM, LPARAM hInstance)
+{
+ OptionsPageList arPages(1);
+ CallPluginEventHook((HINSTANCE)hInstance, hOptionsInitEvent, (WPARAM)&arPages, 0);
+ return 0;
+}
+
static int OptModulesLoaded(WPARAM, LPARAM)
{
CMenuItem mi;
@@ -1226,6 +1233,7 @@ int LoadOptionsModule(void)
hOptionsInitEvent = CreateHookableEvent(ME_OPT_INITIALISE);
HookEvent(ME_OPT_INITIALISE, LangpackOptionsInit);
+ HookEvent(ME_SYSTEM_MODULELOAD, OptDynamicLoadOptions);
HookEvent(ME_SYSTEM_MODULESLOADED, OptModulesLoaded);
HookEvent(ME_SYSTEM_PRESHUTDOWN, ShutdownOptionsModule);
return 0;
diff --git a/src/mir_app/src/pluginopts.cpp b/src/mir_app/src/pluginopts.cpp
index 02e6d7b10c..200ac98f51 100644
--- a/src/mir_app/src/pluginopts.cpp
+++ b/src/mir_app/src/pluginopts.cpp
@@ -29,7 +29,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "chat.h"
#include "plugins.h"
-extern MUUID miid_clist, miid_database, miid_protocol, miid_srmm;
HANDLE hevLoadModule, hevUnloadModule;
static bool bOldMode = false;
@@ -44,7 +43,7 @@ struct PluginListItemData
wchar_t fileName[MAX_PATH];
HINSTANCE hInst;
int flags, stdPlugin;
- wchar_t *author, *authorEmail, *description, *copyright, *homepage;
+ wchar_t *author, *description, *copyright, *homepage;
MUUID uuid;
};
@@ -101,7 +100,7 @@ static BOOL dialogListPlugins(WIN32_FIND_DATA *fd, wchar_t *path, WPARAM, LPARAM
it.mask = LVIF_PARAM | LVIF_IMAGE;
it.iImage = (hInst != nullptr) ? 2 : 3;
bool bNoCheckbox = (dat->flags & STATIC_PLUGIN) != 0;
- if (bNoCheckbox || hasMuuid(pi, miid_clist) || hasMuuid(pi, miid_protocol))
+ if (bNoCheckbox || hasMuuid(pi, MIID_CLIST) || hasMuuid(pi, MIID_PROTOCOL))
it.iImage += 2;
it.lParam = (LPARAM)dat;
int iRow = ListView_InsertItem(hwndList, &it);
@@ -119,7 +118,6 @@ static BOOL dialogListPlugins(WIN32_FIND_DATA *fd, wchar_t *path, WPARAM, LPARAM
ListView_SetItem(hwndList, &it);
dat->author = sttUtf8auto(pi.pluginInfo->author);
- dat->authorEmail = sttUtf8auto(pi.pluginInfo->authorEmail);
dat->copyright = sttUtf8auto(pi.pluginInfo->copyright);
dat->description = sttUtf8auto(pi.pluginInfo->description);
dat->homepage = sttUtf8auto(pi.pluginInfo->homepage);
@@ -179,7 +177,6 @@ static void RemoveAllItems(HWND hwnd)
while (ListView_GetItem(hwnd, &lvi)) {
PluginListItemData *dat = (PluginListItemData*)lvi.lParam;
mir_free(dat->author);
- mir_free(dat->authorEmail);
mir_free(dat->copyright);
mir_free(dat->description);
mir_free(dat->homepage);
@@ -426,8 +423,7 @@ INT_PTR CALLBACK DlgPluginOpt(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPar
ListView_GetItemText(hwndList, hdr->iItem, 2, buf, _countof(buf));
SetDlgItemText(hwndDlg, IDC_PLUGININFOFRAME, sel ? buf : L"");
SetDlgItemText(hwndDlg, IDC_PLUGINAUTHOR, sel ? dat->author : L"");
- SetDlgItemText(hwndDlg, IDC_PLUGINEMAIL, sel ? dat->authorEmail : L"");
- SetDlgItemText(hwndDlg, IDC_PLUGINLONGINFO, sel ? dat->description : L"");
+ SetDlgItemText(hwndDlg, IDC_PLUGINLONGINFO, sel ? TranslateW_LP(dat->description, GetPluginLangByInstance(dat->hInst)) : L"");
SetDlgItemText(hwndDlg, IDC_PLUGINCPYR, sel ? dat->copyright : L"");
SetDlgItemText(hwndDlg, IDC_PLUGINURL, sel ? dat->homepage : L"");
@@ -513,13 +509,10 @@ INT_PTR CALLBACK DlgPluginOpt(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPar
Utils_OpenUrl("https://miranda-ng.org/downloads/");
break;
- case IDC_PLUGINEMAIL:
case IDC_PLUGINURL:
char buf[512];
- char *p = &buf[7];
- mir_strcpy(buf, "mailto:");
- if (GetDlgItemTextA(hwndDlg, LOWORD(wParam), p, _countof(buf) - 7))
- Utils_OpenUrl(LOWORD(wParam) == IDC_PLUGINEMAIL ? buf : p);
+ if (GetDlgItemTextA(hwndDlg, LOWORD(wParam), buf, _countof(buf)))
+ Utils_OpenUrl(buf);
break;
}
}
diff --git a/src/mir_app/src/resource.h b/src/mir_app/src/resource.h
index 1230a2e293..d4302e4ca7 100644
--- a/src/mir_app/src/resource.h
+++ b/src/mir_app/src/resource.h
@@ -498,7 +498,6 @@
#define IDC_PLUGINCPYR 1681
#define IDC_PLUGINURL 1682
#define IDC_PLUGINPID 1683
-#define IDC_PLUGINEMAIL 1684
#define IDC_IDLESPIN 1687
#define IDC_NODBDRIVERS 1690
#define IDC_IDLESTATUSLOCK 1691
diff --git a/src/mir_app/src/searchresults.cpp b/src/mir_app/src/searchresults.cpp
index fd8395c8d7..da1224ff7a 100644
--- a/src/mir_app/src/searchresults.cpp
+++ b/src/mir_app/src/searchresults.cpp
@@ -353,14 +353,9 @@ void ShowMoreOptionsMenu(HWND hwndDlg, int x, int y)
int commandId = TrackPopupMenu(hPopupMenu, TPM_RIGHTBUTTON | TPM_RETURNCMD, x, y, 0, hwndDlg, nullptr);
switch (commandId) {
case IDC_ADD:
- {
- ADDCONTACTSTRUCT acs = { 0 };
- acs.handleType = HANDLE_SEARCHRESULT;
- acs.szProto = lsr->szProto;
- acs.psr = &lsr->psr;
- CallService(MS_ADDCONTACT_SHOW, (WPARAM)hwndDlg, (LPARAM)&acs);
- }
+ Contact_AddBySearch(lsr->szProto, &lsr->psr, hwndDlg);
break;
+
case IDC_DETAILS:
{
MCONTACT hContact = (MCONTACT)CallProtoServiceInt(0, lsr->szProto, PS_ADDTOLIST, PALF_TEMPORARY, (LPARAM)&lsr->psr);
diff --git a/src/mir_app/src/srmm_base.cpp b/src/mir_app/src/srmm_base.cpp
index db80ec8f33..a1c7a6c595 100644
--- a/src/mir_app/src/srmm_base.cpp
+++ b/src/mir_app/src/srmm_base.cpp
@@ -148,6 +148,8 @@ static LRESULT CALLBACK Srmm_ButtonSubclassProc(HWND hwnd, UINT msg, WPARAM wPar
/////////////////////////////////////////////////////////////////////////////////////////
+static wchar_t szTrimString[] = L":;,.!?\'\"><()[]- \r\n";
+
EXTERN_C MIR_APP_DLL(LRESULT) CALLBACK stubLogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
CSrmmBaseDialog *pDlg = (CSrmmBaseDialog*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA);
@@ -185,9 +187,12 @@ LRESULT CSrmmBaseDialog::WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam)
break;
case WM_CHAR:
- SetFocus(m_message.GetHwnd());
- if (wParam != '\t')
+ if (wParam >= ' ') {
+ SetFocus(m_message.GetHwnd());
m_message.SendMsg(WM_CHAR, wParam, lParam);
+ }
+ else if (wParam == '\t')
+ SetFocus(m_message.GetHwnd());
break;
case WM_CONTEXTMENU:
@@ -195,9 +200,9 @@ LRESULT CSrmmBaseDialog::WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam)
break;
POINT pt, ptl;
- m_message.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel);
+ m_log.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel);
if (lParam == 0xFFFFFFFF) {
- m_message.SendMsg(EM_POSFROMCHAR, (WPARAM)&pt, (LPARAM)sel.cpMax);
+ m_log.SendMsg(EM_POSFROMCHAR, (WPARAM)&pt, (LPARAM)sel.cpMax);
ClientToScreen(m_log.GetHwnd(), &pt);
}
else {
@@ -218,8 +223,6 @@ LRESULT CSrmmBaseDialog::WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam)
int end = m_log.SendMsg(EM_FINDWORDBREAK, WB_RIGHT, iCharIndex);
if (end - start > 0) {
- static wchar_t szTrimString[] = L":;,.!?\'\"><()[]- \r\n";
-
CHARRANGE cr;
cr.cpMin = start;
cr.cpMax = end;
@@ -229,6 +232,9 @@ LRESULT CSrmmBaseDialog::WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam)
tr.lpstrText = (wchar_t*)pszWord;
int iRes = m_log.SendMsg(EM_GETTEXTRANGE, 0, (LPARAM)&tr);
if (iRes > 0) {
+ wchar_t *p = wcschr(pszWord, '\r');
+ if (p) *p = 0;
+
size_t iLen = mir_wstrlen(pszWord) - 1;
while (wcschr(szTrimString, pszWord[iLen])) {
pszWord[iLen] = '\0';
@@ -246,10 +252,10 @@ LRESULT CSrmmBaseDialog::WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam)
break;
case IDM_COPYALL:
- m_message.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel);
- m_message.SendMsg(EM_EXSETSEL, 0, (LPARAM)&all);
- m_message.SendMsg(WM_COPY, 0, 0);
- m_message.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
+ m_log.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel);
+ m_log.SendMsg(EM_EXSETSEL, 0, (LPARAM)&all);
+ m_log.SendMsg(WM_COPY, 0, 0);
+ m_log.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0);
break;
@@ -331,6 +337,23 @@ EXTERN_C MIR_APP_DLL(LRESULT) CALLBACK stubMessageProc(HWND hwnd, UINT msg, WPAR
LRESULT CSrmmBaseDialog::WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam)
{
+ if (msg == WM_CHAR) {
+ switch (wParam) {
+ case 0x02:
+ if (m_btnBold.Enabled())
+ return 1;
+ break;
+ case 0x09:
+ if (m_btnItalic.Enabled())
+ return 1;
+ break;
+ case 0x15:
+ if (m_btnUnderline.Enabled())
+ return 1;
+ break;
+ }
+ }
+
LRESULT res = mir_callNextSubclass(m_message.GetHwnd(), stubMessageProc, msg, wParam, lParam);
switch (msg) {
case WM_GETDLGCODE:
diff --git a/src/mir_app/src/stdafx.h b/src/mir_app/src/stdafx.h
index cfcf71bf9e..7019ad5f50 100644
--- a/src/mir_app/src/stdafx.h
+++ b/src/mir_app/src/stdafx.h
@@ -78,7 +78,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <m_contacts.h>
#include <m_message.h>
#include <m_userinfo.h>
-#include <m_addcontact.h>
#include <m_findadd.h>
#include <m_file.h>
#include <m_awaymsg.h>
diff --git a/src/mir_core/src/http.cpp b/src/mir_core/src/http.cpp
index 3b9140c1e9..d46886a5b7 100755
--- a/src/mir_core/src/http.cpp
+++ b/src/mir_core/src/http.cpp
@@ -61,7 +61,7 @@ MIR_CORE_DLL(char*) mir_urlEncode(const char *szUrl)
static char cb64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-MIR_CORE_DLL(char*) mir_base64_encode(const BYTE *input, unsigned inputLen)
+MIR_CORE_DLL(char*) mir_base64_encode(const void *input, size_t inputLen)
{
if (input == nullptr)
return nullptr;
@@ -74,7 +74,7 @@ MIR_CORE_DLL(char*) mir_base64_encode(const BYTE *input, unsigned inputLen)
return mir_base64_encodebuf(input, inputLen, output, outputLen);
}
-MIR_CORE_DLL(char*) mir_base64_encodebuf(const BYTE *input, unsigned inputLen, char *output, unsigned outputLen)
+MIR_CORE_DLL(char*) mir_base64_encodebuf(const void *input, size_t inputLen, char *output, size_t outputLen)
{
if (input == nullptr)
return nullptr;
@@ -82,13 +82,14 @@ MIR_CORE_DLL(char*) mir_base64_encodebuf(const BYTE *input, unsigned inputLen, c
if (outputLen < mir_base64_encode_bufsize(inputLen))
return nullptr;
+ const BYTE *s = (const BYTE*)input;
char *p = output;
for (unsigned i=0; i < inputLen; ) {
int rest = 0;
BYTE chr[3];
- chr[0] = input[i++];
- chr[1] = (i < inputLen) ? input[i++] : rest++, 0;
- chr[2] = (i < inputLen) ? input[i++] : rest++, 0;
+ chr[0] = s[i++];
+ chr[1] = (i < inputLen) ? s[i++] : rest++, 0;
+ chr[2] = (i < inputLen) ? s[i++] : rest++, 0;
*p++ = cb64[ chr[0] >> 2 ];
*p++ = cb64[ ((chr[0] & 0x03) << 4) | (chr[1] >> 4) ];
@@ -126,7 +127,7 @@ static BYTE Base64DecodeTable[] =
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1
};
-MIR_CORE_DLL(void*) mir_base64_decode(const char *input, unsigned *outputLen)
+MIR_CORE_DLL(void*) mir_base64_decode(const char *input, size_t *outputLen)
{
if (input == nullptr)
return nullptr;
diff --git a/src/mir_core/src/mir_core.def b/src/mir_core/src/mir_core.def
index 7d0d544d86..700a447198 100644
--- a/src/mir_core/src/mir_core.def
+++ b/src/mir_core/src/mir_core.def
@@ -1054,3 +1054,4 @@ HookTemporaryEvent @1241
?Click@CCtrlButton@@QAEXXZ @1242 NONAME
??0CTimer@@QAE@$$QAV0@@Z @1243 NONAME
??4CTimer@@QAEAAV0@$$QAV0@@Z @1244 NONAME
+IsTerminalDisconnected @1245
diff --git a/src/mir_core/src/mir_core64.def b/src/mir_core/src/mir_core64.def
index c1d716b5d9..6608c359c7 100644
--- a/src/mir_core/src/mir_core64.def
+++ b/src/mir_core/src/mir_core64.def
@@ -1054,3 +1054,4 @@ HookTemporaryEvent @1241
?Click@CCtrlButton@@QEAAXXZ @1242 NONAME
??0CTimer@@QEAA@$$QEAV0@@Z @1243 NONAME
??4CTimer@@QEAAAEAV0@$$QEAV0@@Z @1244 NONAME
+IsTerminalDisconnected @1245
diff --git a/src/mir_core/src/stdafx.h b/src/mir_core/src/stdafx.h
index e72153c8b7..67dea82922 100644
--- a/src/mir_core/src/stdafx.h
+++ b/src/mir_core/src/stdafx.h
@@ -33,6 +33,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <vssym32.h>
#include <Uxtheme.h>
#include <Richedit.h>
+#include <Wtsapi32.h>
#include <malloc.h>
#include <stdio.h>
diff --git a/src/mir_core/src/utf.cpp b/src/mir_core/src/utf.cpp
index b6151a40d9..f159586cc0 100644
--- a/src/mir_core/src/utf.cpp
+++ b/src/mir_core/src/utf.cpp
@@ -392,7 +392,7 @@ MIR_CORE_DLL(char*) Utf8EncodeW(const wchar_t* src)
}
/////////////////////////////////////////////////////////////////////////////////////////
-// Utf8Encode - converts UCS2 string to the UTF8-encoded format
+// Utf8CheckString - checks if a string is a valid utf8-encoded string
MIR_CORE_DLL(BOOL) Utf8CheckString(const char *str)
{
diff --git a/src/mir_core/src/winver.cpp b/src/mir_core/src/winver.cpp
index 07faca4d1c..a724f6e443 100644
--- a/src/mir_core/src/winver.cpp
+++ b/src/mir_core/src/winver.cpp
@@ -100,6 +100,21 @@ MIR_CORE_DLL(BOOL) IsWorkstationLocked(void)
return bLocked;
}
+MIR_CORE_DLL(BOOL) IsTerminalDisconnected(void)
+{
+ PVOID pBuffer = nullptr;
+ DWORD pBytesReturned = 0;
+ BOOL result = FALSE;
+
+ if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSConnectState, (LPTSTR *)&pBuffer, &pBytesReturned))
+ if (*(PDWORD)pBuffer == WTSDisconnected)
+ result = TRUE;
+
+ if (pBuffer)
+ WTSFreeMemory(pBuffer);
+ return result;
+}
+
MIR_CORE_DLL(BOOL) IsScreenSaverRunning(void)
{
BOOL rc = FALSE;
diff --git a/tools/WinSCP/WinSCP.com b/tools/WinSCP/WinSCP.com
index 0f08a0d664..9c71b0551f 100644
--- a/tools/WinSCP/WinSCP.com
+++ b/tools/WinSCP/WinSCP.com
Binary files differ
diff --git a/tools/WinSCP/WinSCP.exe b/tools/WinSCP/WinSCP.exe
index 2f24359c9d..2a6b24083a 100644
--- a/tools/WinSCP/WinSCP.exe
+++ b/tools/WinSCP/WinSCP.exe
Binary files differ
diff --git a/tools/boost/build_boost.bat b/tools/boost/build_boost.bat
index 22ffd2b947..927ec05acb 100644
--- a/tools/boost/build_boost.bat
+++ b/tools/boost/build_boost.bat
@@ -7,7 +7,9 @@ if "%p2%" == "" (echo "please specify target msvc compiler by adding '10' for M
call bootstrap.bat
if /i '%1' == '86' (
- b2 --toolset=msvc-%2.0 runtime-link=shared threading=multi link=static architecture=x86 address-model=32
+ call "%VS141COMNTOOLS%\..\..\VC\Auxiliary\Build\vcvars32.bat"
+ b2 --toolset=msvc-%2.0 runtime-link=shared threading=multi link=static architecture=x86 address-model=32 cxxflags=/Zc:threadSafeInit-
) else if /i '%1' == '64' (
- b2 --toolset=msvc-%2.0 runtime-link=shared threading=multi link=static architecture=x86 address-model=64 --stagedir=stage64
+ call "%VS141COMNTOOLS%\..\..\VC\Auxiliary\Build\vcvars64.bat"
+ b2 --toolset=msvc-%2.0 runtime-link=shared threading=multi link=static architecture=x86 address-model=64 cxxflags=/Zc:threadSafeInit- --stagedir=stage64
) \ No newline at end of file
diff --git a/tools/build_scripts/bin15/z2_PackPluginUpdater_x32.txt b/tools/build_scripts/bin15/z2_PackPluginUpdater_x32.txt
index 2d614c7e92..c87ab3f6d2 100644
--- a/tools/build_scripts/bin15/z2_PackPluginUpdater_x32.txt
+++ b/tools/build_scripts/bin15/z2_PackPluginUpdater_x32.txt
@@ -8,7 +8,6 @@ sendlogwin.exe
Plugins\actman.dll
Plugins\addcontactplus.dll
Plugins\advaimg.dll
-Plugins\aim.dll
Plugins\alarms.dll
Plugins\assinglewindow.dll
Plugins\assocmgr.dll
@@ -205,7 +204,6 @@ Scripts\winapi.dll
Icons\flags_icons.dll
Icons\fp_icons.dll
Icons\historypp_icons.dll
-Icons\proto_aim.dll
Icons\proto_discord.dll
Icons\proto_dummy.dll
Icons\proto_facebook.dll
diff --git a/tools/build_scripts/bin15/z2_PackPluginUpdater_x64.txt b/tools/build_scripts/bin15/z2_PackPluginUpdater_x64.txt
index 8b2decb06d..c68e56a0c6 100644
--- a/tools/build_scripts/bin15/z2_PackPluginUpdater_x64.txt
+++ b/tools/build_scripts/bin15/z2_PackPluginUpdater_x64.txt
@@ -8,7 +8,6 @@ sendlogwin.exe
Plugins\actman.dll
Plugins\addcontactplus.dll
Plugins\advaimg.dll
-Plugins\aim.dll
Plugins\alarms.dll
Plugins\assinglewindow.dll
Plugins\assocmgr.dll
@@ -203,7 +202,6 @@ Scripts\winapi.dll
Icons\flags_icons.dll
Icons\fp_icons.dll
Icons\historypp_icons.dll
-Icons\proto_aim.dll
Icons\proto_discord.dll
Icons\proto_dummy.dll
Icons\proto_facebook.dll
diff --git a/tools/build_scripts/z2_PackPluginUpdater.bat b/tools/build_scripts/z2_PackPluginUpdater.bat
index 605057334b..eea4501d94 100644
--- a/tools/build_scripts/z2_PackPluginUpdater.bat
+++ b/tools/build_scripts/z2_PackPluginUpdater.bat
@@ -41,7 +41,6 @@ REM Plugins
for /f %%a in ('dir plugins\*.dll /B /L') do (
rem check for special plugins and pack additional files first.
if /I "%%a"=="Actman.dll" (%ZipIt% "%Arch%\Plugins\%%~na.zip" "Plugins\services.ini")
- if /I "%%a"=="AIM.dll" (%ZipIt% "%Arch%\Plugins\%%~na.zip" "Icons\Proto_AIM.dll")
if /I "%%a"=="BASS_interface.dll" (%ZipIt% "%Arch%\Plugins\%%~na.zip" "Plugins\BASS\*.dll")
if /I "%%a"=="Boltun.dll" (%ZipIt% "%Arch%\Plugins\%%~na.zip" "Plugins\boltun.mindw")
if /I "%%a"=="Clist_modern.dll" (%ZipIt% "%Arch%\Plugins\%%~na.zip" "Plugins\AVS.dll" "Icons\Toolbar_icons.dll")
@@ -78,7 +77,7 @@ for /f %%a in ('dir plugins\*.dll /B /L') do (
if /I "%%a"=="SpellChecker.dll" (%ZipIt% "%Arch%\Plugins\%%~na.zip" "Icons\Flags_icons.dll" "Libs\hunspell.mir")
if /I "%%a"=="Steam.dll" (%ZipIt% "%Arch%\Plugins\%%~na.zip" "Icons\Proto_Steam.dll")
if /I "%%a"=="TabSRMM.dll" (%ZipIt% "%Arch%\Plugins\%%~na.zip" "Icons\TabSRMM_icons.dll")
- if /I "%%a"=="Tox.dll" (%ZipIt% "%Arch%\Plugins\%%~na.zip" "Icons\Proto_Tox.dll" "Libs\libtox.dll")
+ if /I "%%a"=="Tox.dll" (%ZipIt% "%Arch%\Plugins\%%~na.zip" "Icons\Proto_Tox.dll" "Libs\libsodium.mir" "Libs\pthreads.mir")
if /I "%%a"=="Twitter.dll" (%ZipIt% "%Arch%\Plugins\%%~na.zip" "Icons\Proto_Twitter.dll")
if /I "%%a"=="UInfoEx.dll" (%ZipIt% "%Arch%\Plugins\%%~na.zip" "Icons\UInfoEx_icons.dll")
if /I "%%a"=="VKontakte.dll" (%ZipIt% "%Arch%\Plugins\%%~na.zip" "Icons\Proto_VKontakte.dll")
diff --git a/tools/installer_ng/Common/Files/Settings/mirandaboot_default.ini b/tools/installer_ng/Common/Files/Settings/mirandaboot_default.ini
index 15ec526273..f569997e66 100644
--- a/tools/installer_ng/Common/Files/Settings/mirandaboot_default.ini
+++ b/tools/installer_ng/Common/Files/Settings/mirandaboot_default.ini
@@ -70,8 +70,8 @@ Safe=CLC Icons CLUI CList Skin SkinSounds TopToolBar
;Unsafe
;A space-separated list of database module names that could be alter to
;malicious purposes (e.g., by faking a login server to steal passwords).
-;Default: AIM Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
-Unsafe=AIM Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
+;Default: Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
+Unsafe=Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
;OverrideSecurityFilename
;System admins may find it desirable to install settings without prompting
diff --git a/tools/installer_ng/Common/Files/Settings/mirandaboot_portable.ini b/tools/installer_ng/Common/Files/Settings/mirandaboot_portable.ini
index e0497130f8..1868a973b0 100644
--- a/tools/installer_ng/Common/Files/Settings/mirandaboot_portable.ini
+++ b/tools/installer_ng/Common/Files/Settings/mirandaboot_portable.ini
@@ -70,8 +70,8 @@ Safe=CLC Icons CLUI CList Skin SkinSounds TopToolBar
;Unsafe
;A space-separated list of database module names that could be alter to
;malicious purposes (e.g., by faking a login server to steal passwords).
-;Default: AIM Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
-Unsafe=AIM Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
+;Default: Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
+Unsafe=Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
;OverrideSecurityFilename
;System admins may find it desirable to install settings without prompting
diff --git a/tools/installer_ng_stable/Common/Files/Settings/mirandaboot_default.ini b/tools/installer_ng_stable/Common/Files/Settings/mirandaboot_default.ini
index 15ec526273..f569997e66 100644
--- a/tools/installer_ng_stable/Common/Files/Settings/mirandaboot_default.ini
+++ b/tools/installer_ng_stable/Common/Files/Settings/mirandaboot_default.ini
@@ -70,8 +70,8 @@ Safe=CLC Icons CLUI CList Skin SkinSounds TopToolBar
;Unsafe
;A space-separated list of database module names that could be alter to
;malicious purposes (e.g., by faking a login server to steal passwords).
-;Default: AIM Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
-Unsafe=AIM Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
+;Default: Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
+Unsafe=Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
;OverrideSecurityFilename
;System admins may find it desirable to install settings without prompting
diff --git a/tools/installer_ng_stable/Common/Files/Settings/mirandaboot_portable.ini b/tools/installer_ng_stable/Common/Files/Settings/mirandaboot_portable.ini
index e0497130f8..1868a973b0 100644
--- a/tools/installer_ng_stable/Common/Files/Settings/mirandaboot_portable.ini
+++ b/tools/installer_ng_stable/Common/Files/Settings/mirandaboot_portable.ini
@@ -70,8 +70,8 @@ Safe=CLC Icons CLUI CList Skin SkinSounds TopToolBar
;Unsafe
;A space-separated list of database module names that could be alter to
;malicious purposes (e.g., by faking a login server to steal passwords).
-;Default: AIM Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
-Unsafe=AIM Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
+;Default: Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
+Unsafe=Facebook GG ICQ IRC JABBER MRA MSN SKYPE TWITTER VKontakte
;OverrideSecurityFilename
;System admins may find it desirable to install settings without prompting
diff --git a/tools/lpgen/lpgen.js b/tools/lpgen/lpgen.js
index 2dbe58325c..4c3134f03f 100644
--- a/tools/lpgen/lpgen.js
+++ b/tools/lpgen/lpgen.js
@@ -487,7 +487,7 @@ function ParseRCFile(FileTextVar, array) {
//now make a job, till end of matching regexp
while ((string = find.exec(FileTextVar)) !== null) {
// check for some garbage like "List1","Tab1" etc. in *.rc files, we do not need this.
- onestring = string[2].replace(/^(((List|Tab|Tree|Spin|Custom|Slider|DateTimePicker|Radio|Check|HotKey|Progress)\d)|(whiterect|IndSndList|&?[Oo][Kk]|AOL|APOP|BBS|Bing|CTCP|DCC|Foodnetwork|Google|Google Talk|GPG|Hotmail|ICQ|ICQ Corp|ID|IP|ISDN|iTunes|Jabber|JID|Miranda|Miranda NG|mRadio|MSN|NickServ|OSD|OTR|PCS|PGP|S.ms|SMS|SSL|Steam|Steam Guard|Tox|Twitter|Yahoo|Winamp \(\*\)|Windows|X400|&\w)|(%.(.*%)?))$/g, "");
+ onestring = string[2].replace(/^(((List|Tab|Tree|Spin|Custom|Slider|DateTimePicker|Radio|Check|HotKey|Progress)\d)|(whiterect|IndSndList|&?[Oo][Kk]|APOP|BBS|Bing|CTCP|DCC|Foodnetwork|Google|Google Talk|GPG|Hotmail|ICQ|ICQ Corp|ID|IP|ISDN|iTunes|Jabber|JID|Miranda|Miranda NG|mRadio|MSN|NickServ|OSD|OTR|PCS|PGP|S.ms|SMS|SSL|Steam|Steam Guard|Tox|Twitter|Yahoo|Winamp \(\*\)|Windows|X400|&\w)|(%.(.*%)?))$/g, "");
// ignore some popup menu craps
if (string[1] == "POPUP" && onestring.match(/^([a-zA-Z ]*(menu|context|popup(?!s)))|([A-Z][a-z]+([A-Z][a-z]*)+)|(new item)$/g)) {
continue;
@@ -546,7 +546,7 @@ function ParseSourceFile(FileTextVar, array) {
//filter _T() function results
function filter_T(string) {
//filter for exact matched strings
- var filter1 = /^(&?[Oo][Kk]|AOL|APOP|BBS|Bing|CTCP|DCC|Foodnetwork|Google|GPG|Hotmail|ICQ|ICQ Corp|ID|IP|ISDN|iTunes|Jabber|JID|Miranda|MirandaG15|Miranda NG|mRadio|MSN|NickServ|OSD|OTR|PCS|PGP|SMS|SSL|SteamID|Steam Guard|Tox|Twitter|Yahoo|Winamp \(\*\)|Windows|X400)$/g;
+ var filter1 = /^(&?[Oo][Kk]|APOP|BBS|Bing|CTCP|DCC|Foodnetwork|Google|GPG|Hotmail|ICQ|ICQ Corp|ID|IP|ISDN|iTunes|Jabber|JID|Miranda|MirandaG15|Miranda NG|mRadio|MSN|NickServ|OSD|OTR|PCS|PGP|SMS|SSL|SteamID|Steam Guard|Tox|Twitter|Yahoo|Winamp \(\*\)|Windows|X400)$/g;
//filter string starting from following words
var filter2 = /^(SOFTWARE\\|SYSTEM\\|http|ftp|UTF-|utf-|TEXT|EXE|exe|txt|css|html|dat[^a]|txt|MS\x20|CLVM|TM_|CLCB|CLSID|CLUI|HKEY_|MButton|BUTTON|WindowClass|MHeader|RichEdit|RICHEDIT|STATIC|EDIT|CList|listbox|LISTBOX|combobox|COMBOBOX|TitleB|std\w|iso-|windows-|<div|<html|<img|<span|<hr|<a\x20|<table|<td|miranda_|kernel32|user32|muc|pubsub|shlwapi|Tahoma|NBRichEdit|CreatePopup|&?[Oo][Kk]|<\/|<\w>|\w\\\w|urn\:|<\?xml|<\!|h\d|\.!\.).*$/g;
//filter string ending with following words