Synology Chat
Synology NAS にある Chat 機能をインストールした.
Chat Server をインストールすると,LAN 内の NAS ユーザであれば次の様な指定でアクセスできる.
//192.168.1.xxx/chat/
//192.168.1.xxx/chat/ の様にアクセスするために「ログインポータル」の設定が必要.
「コントロールパネル」-「ログインポータル」-「アプリケーション」で「Synology Chat」を選択して「編集」.
「エイリアス」の所で指定したものが //192.168.1.xxx/(エイリアス)/ として使用される.
ここでは https://chat.(example.com) などの様にアクセスする設定も可能.
私の NAS 環境では,自分以外は「テスト用」などしか登録していない.
そのため Chat のためにユーザを追加登録するのはちょっと目的が違う.
「Synology Chat ゲスト」で検索して「ゲスト機能」があることはわかっていたので,その設定.
「Chat Admin Console」の「設定」で「ゲストユーザーを許可」にチェック.
それで,その後の設定がなかなかわからなかった.
「チャンネルの作成」で「プライベート チャンネル」と「パブリック チャンネル」がある.
「ゲスト」ユーザは「プライベート チャンネル」の方で招待できる.
「プライベート チャンネル」を作成して,右上の「メンバー」アイコンをクリック.
すると「ゲスト」タブが表示される.
「ゲスト」タブを選択して「追加」すると「ゲスト電子メール」などを指定して招待メールを送信できる.
あとは,メールを受け取った側が自分でログイン情報を入力して,Synology Chat を利用できる様になる.
2023/01/03
ゲストユーザは,NAS 上の Homes の下に guest_(ユーザ名) で追加される.
2023/01/06
不要になったゲストユーザは「コントロールパネル」-「ユーザーとグループ」で削除できる.
2023/03/14
何故かわからないが,チャットのゲストで登録したアカウントでログインできない.
NAS の登録ユーザであれば //(NAS)/chat/ から入ってログインできる.
スマートフォンの「Chat」からも問題ないが,ブラウザの時にうまくない様子.
どうも,招待メールにあるアドレスから入る必要があるみたい.
https://(NAS)/chat/guest/index.html#eyJ0eXAiOiJ…
更に試すと,次の様に # 以降はなくても大丈夫.
https://(NAS)/chat/guest/index.html
PPAP の代わりとしても使えると思う.
VirusTotal Cylance Unsafe
1 年位前から,exe をビルドしてデバッグが終わると VirusTotal でチェックしている.
それで,誤検知されやすいと思われる VC のバージョンなどのメモ.
VC6.exe では,ほとんどが何らかのものに引っ掛かってしまう.
SecureAge Malicious
VC8.exe や VC9.exe も何かに引っ掛かってしまうことが多い.
VC 10 ~ VC 12 では,あまり規則性はわからない.コードによる?
VC 14 以降は,普通の MFC のコードであればほぼ問題なさそう.
但し最初のうちは,ほとんど Cylance Unsafe となってしまう.
が,数日経過すると警告は消えることが多い.
error C2668: ‘abs’
1>------ ビルド開始: プロジェクト: ClCpy, 構成: Debug Win32 ------
1>コンパイルしています...
1>ClCpyDlg.cpp
1>l:\document\develop\tools\_free\tiny\clcpy\clcpydlg.cpp(396) : error C2668: 'abs' : オーバーロード関数の呼び出しを解決することができません。(新機能 ; ヘルプを参照)
1> c:\program files (x86)\microsoft visual studio 8\vc\include\math.h(539): 'long double abs(long double)' の可能性があります。
1> c:\program files (x86)\microsoft visual studio 8\vc\include\math.h(491): または 'float abs(float)'
1> c:\program files (x86)\microsoft visual studio 8\vc\include\math.h(487): または 'double abs(double)'
1> c:\program files (x86)\microsoft visual studio 8\vc\include\math.h(485): または 'long abs(long)'
1> c:\program files (x86)\microsoft visual studio 8\vc\include\stdlib.h(415): または 'int abs(int)'
1> 引数リスト '(size_t)' を一致させようとしているとき
1>ビルド時間 0:07
1>ClCpy - エラー 1、警告 0
========== ビルド: 0 正常終了、1 失敗、0 更新、0 スキップ ==========
次の様に long にキャストすることで対応.
size_t len_ = ::abs(long(lenS-lenD)) ;
Win11 MFC80u.dll などの場所
VC 2005 で作成した exe がうまく起動しないと連絡が入った.
すぐに dll などがないためとわかり,VC 2005 SP1 vcredist_x86.exe を入れて対応してもらった.
https://jml.mish.work/index.php/cpp/ref-vcredist-xxx-exe.html
それで,Win11 環境の c:\Windows\WinSxS\ の MFC80*.dll を見ると,それらしいものが見当たらない.
Win10 では …\WinSxS\ に存在する.
explorer で検索すると Win11 では ..\WinSxS\Fusion\ 以下になっている.
.NET ZipFile C++/CLI
ZipFile クラスのサンプル を VC 2012 C++/CLI で.
Win32 コンソール AP としてプロジェクトを作成.
CPP を次の様に変更.
#include <stdio.h>
#include <tchar.h>
// using System;
// using System.IO.Compression;
#using <System.dll>
#using <System.IO.Compression.FileSystem.dll>
// class Program
// {
// static void Main(string[] args)
// {
int _tmain(int argc, _TCHAR* argv[])
{
// string startPath = @"./start";
// string zipPath = @"./result.zip";
// string extractPath = @"./extract";
System::String^ startPath = _T("./start") ;
System::String^ zipPath = _T("./result.zip") ;
System::String^ extractPath = _T("./extract") ;
// ZipFile. CreateFromDirectory(startPath, zipPath);
System::IO::Compression::ZipFile::CreateFromDirectory(startPath, zipPath);
// ZipFile. ExtractToDirectory(zipPath, extractPath);
System::IO::Compression::ZipFile::ExtractToDirectory(zipPath, extractPath);
return 0;
}
// }
// }
そのままビルドすると…
1>------ ビルド開始: プロジェクト: T_ZIP_C, 構成: Debug Win32 ------
1> T_ZIP_C.cpp
1>d:\document\vs\vs\2012\t_clr\t_zip_c\t_zip_c.cpp(6): fatal error C1190: マネージ ターゲット コードには '/clr' が必要です。
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========
1>------ ビルド開始: プロジェクト: T_ZIP_C, 構成: Debug Win32 ------
1> T_ZIP_C.cpp
1>T_ZIP_C.cpp(7): fatal error C1107: アセンブリ 'System.IO.Compression.FileSystem.dll' がみつかりませんでした: /AI または LIBPATH 環境変数を使用してアセンブリ検索パスを指定してください。
========== ビルド: 0 正常終了、1 失敗、3 更新不要、0 スキップ ==========
「追加の #using ディレクトリ」に dll の場所を指定して通る様にはなったが,これで良いかがわからない.
ほとんど何も入っていない環境で実行すると,
---------------------------
T_ZIP_C.exe - システム エラー
---------------------------
MSVCR110.dll が見つからないため、コードの実行を続行できません。プログラムを再インストールすると、この問題が解決する可能性があります。
---------------------------
OK
---------------------------
VC 2013 や 2015 でビルドしたものも試してみたが,この環境では実行できなかった.
対応するものを入れる必要があるのか?
https://jml.mish.work/index.php/cpp/ref-vcredist-xxx-exe.html
2024/07/05
VC のバージョン(実際は .NET のバージョン?)により,微妙に zip の内容が異なるみたい.
3MF データが開けない?
.NET ZipFile C#
今まで Windows で zip を扱う部分で Shell を利用 してきた.
その時,存在は知っていたが,手を付けてなかった .NET を利用したものを調べることに…
サンプルは次の所にある.
ZipFile クラス
.NET Framework 4.5 以降なので VS 2012 で C# のプロジェクトを作成.
Program.cs をサンプルの様に変更してビルドすると…
1>------ ビルド開始: プロジェクト: T_ZIP, 構成: Debug Any CPU ------
1>D:\Document\VS\VS\2012\T_CLR\T_ZIP\Program.cs(12,9,12,16): error CS0103: 名前 'ZipFile' は現在のコンテキスト内に存在しません。
1>D:\Document\VS\VS\2012\T_CLR\T_ZIP\Program.cs(14,9,14,16): error CS0103: 名前 'ZipFile' は現在のコンテキスト内に存在しません。
========== ビルド: 0 正常終了、1 失敗、1 更新不要、0 スキップ ==========
そこにも書かれているが System.IO.Compression.FileSystem を追加する必要がある.
…\bin\…\start\ に,幾つかのファイルをコビー.
exe を実行すると,result.zip と …\extract\ 以下にファイルが解凍される.
再度実行する場合は result.zip と extract\ を削除する必要がある.
簡易 Web サーバ C++/CLI
先日の C# のコードから C++/CLI に書き直したものの 更新版 .
index.html の作成と,ContentType の設定,日本語ファイル名への対応など.
#ifdef __cplusplus_cli
#using <System.dll>
#using <System.Web.dll>
#include <vcclr.h>
#endif
///////////////////////////////////////////////////////////////////////////
#include "S_Exec.hxx"
#include "str_CLI.hxx"
#include "filestat.hxx"
#include "filepath.hxx"
#include "ask_path.hxx"
#include "itls_tmp.hxx"
#include "textfile.hxx"
#include "htmout.hxx"
#include "stringfn.hxx"
///////////////////////////////////////////////////////////////////////////
struct MIME_type {
LPCTSTR FExt ;
LPCTSTR Type ;
} ;
// https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
const MIME_type MIME_type_tbl[] =
{
_T("htm" ) , _T("text/html") ,
_T("html") , _T("text/html") ,
_T("txt" ) , _T("text/plain") ,
_T("bmp" ) , _T("image/bmp") ,
_T("jpeg") , _T("image/jpeg") ,
_T("jpg" ) , _T("image/jpeg") ,
_T("png" ) , _T("image/png") ,
_T("svg" ) , _T("image/svg+xml") ,
_T("bin" ) , _T("application/octet-stream") ,
_T("pdf" ) , _T("application/pdf") ,
_T("zip" ) , _T("application/zip") ,
_T(" " ) , _T("") ,
_T("\0" ) , _T("") ,
_T("" ) , _T("") ,
} ;
inline tstring get_MIME_type (LPCTSTR ext_)
{
tstring type = _T("application/octet-stream") ;
tstring ext = ::String_ToLower(ext_) ;
if (ext.empty()) {
return type ;
}
const MIME_type* mm_ty = MIME_type_tbl ;
{
for (size_t index=0 ; index<countof(MIME_type_tbl) ; index++)
{
tstring fext = mm_ty[index].FExt ;
tstring ftyp = mm_ty[index].Type ;
if (fext.length() == 0) { continue ; }
if (fext.length() != ext.length()) { continue ; }
if (ext == fext) {
return mm_ty[index].Type ;
}
}
}
return type ;
}
///////////////////////////////////////////////////////////////////////////
inline tstring HT_Make_index_content (c_tstring& fold)
{
v_tstring sub_folds = ::EnumFolders(fold.c_str()) ;
v_tstring htm_files = ::EnumFiles (fold.c_str(),_T("*.htm*")) ;
tstring foldName = ::Path_GetTitle(fold) ;
tstring htm_str ;
{
Xml_E htm = HtmOut::html() ;
{
Xml_E head(HTM_head) ;
{
head.AddChild(HtmOut::charset_UTF_8()) ;
head.AddChild(HtmOut::meta_viewport()) ;
head.AddChild(HtmOut::title(foldName)) ;
}
{
head.AddChild(HtmOut::comment()) ;
}
htm.AddChild(head) ;
}
{
Xml_E body(HTM_body) ;
{
{
body.AddChild(HtmOut::a_parent()) ;
body.AddChild(HtmOut::hr()) ;
}
{
for (size_t index=0 ; index<sub_folds.size() ; index++) {
tstring fold = sub_folds[index] ;
fold = ::Path_DelLastSP(fold) ;
Xml_E a_fold = HtmOut::a(::Path_GetName(fold)+_T("/")) ;
body.AddChild(a_fold) ;
body.AddChild(HtmOut::br()) ;
}
body.AddChild(HtmOut::hr()) ;
}
{
for (size_t index=0 ; index<htm_files.size() ; index++) {
tstring html = htm_files[index] ;
Xml_E a_html = HtmOut::a(::Path_GetName(html)) ;
body.AddChild(a_html) ;
body.AddChild(HtmOut::br()) ;
}
}
}
htm.AddChild(body) ;
}
htm_str = htm.ToText() ;
}
return htm_str ;
}
tstring Make_index (c_tstring& fold)
{
tstring result = ::HT_Make_index_content(fold) ;
return result ;
}
///////////////////////////////////////////////////////////////////////////
bool web_server (c_tstring& fold,const u_16 port)
{
tstring root_ = fold ;
tstring port_ = ::To_tstring(port) ;
tstring pref_ = _T("http://127.0.0.1:")+port_+_T("/") ;
System::String^ root = ::to_gcString(root_) ;
System::String^ prefix = ::to_gcString(pref_) ;
System::Console::WriteLine(prefix) ;
System::Net::HttpListener^ listener = gcnew System::Net::HttpListener();
listener->Prefixes->Add(prefix);
listener->Start();
while (true) {
System::Net::HttpListenerContext^ context = listener->GetContext();
System::Net::HttpListenerRequest^ req = context->Request;
System::Net::HttpListenerResponse^ res = context->Response;
System::String^ path = root + req->RawUrl->Replace("/", "\\");
path = System::Web::HttpUtility::UrlDecode(path) ;
{
System::Console::WriteLine(req->RawUrl);
System::Console::WriteLine(path) ;
}
if (System::IO::File::Exists(path)) {
}
if (System::IO::File::Exists(path)) {
tstring ext = ::Path_GetExtLow(::to_tstring(path)) ;
array<System::Byte>^ content = System::IO::File::ReadAllBytes(path);
res->ContentType = ::to_gcString(::get_MIME_type(ext.c_str())) ;
res->OutputStream->Write(content, 0, content->Length);
}
else {
tstring cnt_index = ::Make_index (::to_tstring(path)) ;
array<System::Byte>^ content ;
{
static long i_count = 0 ;
i_count++ ;
tstring tmp_path = ::Get_i_Tools_tmp_date() ;
tstring htm_name = ::To_tstring(port) + _T("_") + ::u32to0t(i_count,10,4) + _T(".htm") ;
tstring out_path = ::Path_AddLastSP(tmp_path) + htm_name ;
::SaveUTF8(out_path.c_str(),cnt_index) ;
content = System::IO::File::ReadAllBytes(::to_gcString(out_path.c_str())) ;
}
res->ContentType = ::to_gcString(::get_MIME_type(_T("htm"))) ;
res->OutputStream->Write(content, 0, content->Length);
}
res->Close();
}
return true ;
}
///////////////////////////////////////////////////////////////////////////
bool test (c_tstring& str)
{
tstring fold = str ;
{
if (::File_IsDirectory(fold)) { ; }
else { fold = ::Path_GetDir(fold) ; }
}
std::terr << fold << std::endl ;
{
u_16 tick = u_16(::GetTickCount()) ;
u_16 port = u_16(50000 + (tick&0x1fff)) ;
{
tstring port_ = ::To_tstring(port) ;
tstring pref_ = _T("http://127.0.0.1:")+port_+_T("/") ;
S_Exec se ;
se.SetFile(pref_.c_str()) ;
se.Execute() ;
}
::web_server(fold,port) ;
}
return true ;
}
///////////////////////////////////////////////////////////////////////////
int _tmain (int argc,_TCHAR* argv[])
{
tstring path ;
{
#ifdef OFN_filter_All
path = ::ask_path(false) ;
// path = ::ask_path(true) ;
#else
path = ::ask_cli(_T("folder ... ? =")) ;
#endif
}
if (!path.empty()) {
::test(path) ;
}
return 0;
}
///////////////////////////////////////////////////////////////////////////
#include "messbar.cxx"
* 幾つかのコードが揃っていないため,そのままではビルドできません.
https://jml.mish.work/index.php/i-tools/web-svr.html
2024/11/02
VC 2005 でビルド可能な一式を用意しました.
https://itl.mish.work/i_Tools/Doc/blog/vc/T_h_lstn.zip
パッケージが最新版ではありません
C# のコードを C++/CLI に
先日の「簡易 Web サーバ C#」のコードを C++ で.
///////////////////////////////////////////////////////////////////////////////////
// C# -> C++/CLI
///////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <tchar.h>
//using System;
//using System.IO;
//using System.Net;
#using <System.dll>
bool test (void)
{
//
// class SimpleWebServer
// {
// static void Main()
// {
// string root = @"c:\wwwroot\"; // ドキュメント・ルート
// root = @".\";
System::String^ root = "./" ;
// string prefix = "http://*/"; // 受け付けるURL
// prefix = "http://127.0.0.1:65432/" ;
System::String^ prefix = "http://127.0.0.1:55555/" ;
//
// HttpListener listener = new HttpListener();
System::Net::HttpListener^ listener = gcnew System::Net::HttpListener();
// listener. Prefixes. Add(prefix); // プレフィックスの登録
listener->Prefixes->Add(prefix);
// listener. Start();
listener->Start();
//
// while (true) {
while (true) {
// HttpListenerContext context = listener. GetContext();
System::Net::HttpListenerContext^ context = listener->GetContext();
// HttpListenerRequest req = context. Request;
System::Net::HttpListenerRequest^ req = context->Request;
// HttpListenerResponse res = context. Response;
System::Net::HttpListenerResponse^ res = context->Response;
//
// Console. WriteLine(req. RawUrl);
System::Console::WriteLine(req->RawUrl);
//
// // リクエストされたURLからファイルのパスを求める
// string path = root + req. RawUrl. Replace("/", "\\");
System::String^ path = root + req->RawUrl->Replace("/", "\\");
//
// // ファイルが存在すればレスポンス・ストリームに書き出す
// if ( File. Exists(path)) {
if (System::IO::File::Exists(path)) {
// byte[] content = File. ReadAllBytes(path);
array<System::Byte>^ content = System::IO::File::ReadAllBytes(path);
// res. OutputStream. Write(content, 0, content. Length);
res->OutputStream->Write(content, 0, content->Length);
// }
}
// res. Close();
res->Close();
// }
}
// }
// }
//
return true ;
}
int _tmain(int argc, _TCHAR* argv[])
{
::test() ;
return 0;
}