diff --git a/include/anope.h b/include/anope.h index 3fad88ef4..c04c486e1 100644 --- a/include/anope.h +++ b/include/anope.h @@ -481,15 +481,6 @@ namespace Anope */ extern CoreExport bool Encrypt(const Anope::string &src, Anope::string &dest); - /** Returns a sequence of data formatted as the format argument specifies. - ** After the format parameter, the function expects at least as many - ** additional arguments as specified in format. - * @param fmt Format of the Message - * @param ... any number of parameters - * @return a Anope::string - */ - extern CoreExport string printf(const char *fmt, ...) ATTR_FORMAT(1, 2); - /** Return the last error code * @return The error code */ diff --git a/include/modules/nickserv/sasl.h b/include/modules/nickserv/sasl.h index 99f654e48..444ea91aa 100644 --- a/include/modules/nickserv/sasl.h +++ b/include/modules/nickserv/sasl.h @@ -151,7 +151,7 @@ struct SASL::Session if (u) return u->GetMask(); if (!hostname.empty() && !ip.empty()) - return Anope::printf("%s (%s)", hostname.c_str(), ip.c_str()); + return Anope::Format("%s (%s)", hostname.c_str(), ip.c_str()); return "A user"; }; }; diff --git a/include/textproc.h b/include/textproc.h index 0c8c85867..40929c10e 100644 --- a/include/textproc.h +++ b/include/textproc.h @@ -11,6 +11,14 @@ #pragma once +#define ANOPE_FORMAT(LAST, FORMAT, BUFFER) \ + do { \ + va_list _valist; \ + va_start(_valist, (LAST)); \ + (BUFFER) = Anope::Format(_valist, (FORMAT)); \ + va_end(_valist); \ + } while (false); + namespace Anope { /** Expands a path fragment that is relative to the base directory. @@ -34,6 +42,17 @@ namespace Anope /** Expands a module path. */ inline auto ExpandModule(const Anope::string &path) { return Expand(ModuleDir, path); } + /** Formats a string using one or more values. This uses snprintf internally but with a flexible buffer. + * @param fmt The message to format. + */ + extern CoreExport Anope::string Format(const char *fmt, ...) ATTR_FORMAT(1, 2); + + /** Formats a string using a list of values. This uses snprintf internally but with a flexible buffer. + * @param valist A list of values to format the message with. + * @param fmt The message to format. + */ + extern CoreExport Anope::string Format(va_list &valist, const char *fmt) ATTR_FORMAT(2, 0); + /** Formats a CTCP message for sending to a client. * @param name The name of the CTCP. * @param body If present then the body of the CTCP. diff --git a/modules/botserv/botserv.cpp b/modules/botserv/botserv.cpp index 2b251b67b..a062eba6c 100644 --- a/modules/botserv/botserv.cpp +++ b/modules/botserv/botserv.cpp @@ -83,7 +83,7 @@ public: { ChannelMode *cm = ModeManager::FindChannelModeByName("OP"); char symbol = cm ? anope_dynamic_static_cast(cm)->symbol : 0; - const auto message = Anope::printf("%s invited %s into the channel.", user->nick.c_str(), user->nick.c_str()); + const auto message = Anope::Format("%s invited %s into the channel.", user->nick.c_str(), user->nick.c_str()); IRCD->SendNotice(bi, (symbol ? Anope::string(symbol) : "") + c->name, message); } diff --git a/modules/botserv/bs_info.cpp b/modules/botserv/bs_info.cpp index 8ecff03ec..490529b94 100644 --- a/modules/botserv/bs_info.cpp +++ b/modules/botserv/bs_info.cpp @@ -55,7 +55,7 @@ public: info[_("Real name")] = bi->realname; info[_("Created")] = Anope::strftime(bi->created, source.GetAccount()); info[_("Options")] = bi->oper_only ? _("Private") : _("None"); - info[_("Used on")] = Anope::printf(Language::Translate(source.nc, bi->GetChannelCount(), N_("%u channel", "%u channels")), bi->GetChannelCount()); + info[_("Used on")] = Anope::Format(Language::Translate(source.nc, bi->GetChannelCount(), N_("%u channel", "%u channels")), bi->GetChannelCount()); FOREACH_MOD(OnBotInfo, (source, bi, ci, info)); @@ -116,7 +116,7 @@ public: const Anope::string GetDesc(CommandSource &source) const override { - return Anope::printf(Language::Translate(source.GetAccount(), _("Allows you to see %s information about a channel or a bot")), source.service->nick.c_str()); + return Anope::Format(Language::Translate(source.GetAccount(), _("Allows you to see %s information about a channel or a bot")), source.service->nick.c_str()); } }; diff --git a/modules/botserv/bs_kick.cpp b/modules/botserv/bs_kick.cpp index c92735407..d56489534 100644 --- a/modules/botserv/bs_kick.cpp +++ b/modules/botserv/bs_kick.cpp @@ -1112,18 +1112,14 @@ class BSKick final static void bot_kick(ChannelInfo *ci, User *u, const char *message, ...) ATTR_FORMAT(3, 4) { - va_list args; - char buf[1024]; - if (!ci || !ci->bi || !ci->c || !u || u->IsProtected() || !ci->c->FindUser(u)) return; - Anope::string fmt = Language::Translate(u, message); - va_start(args, message); - vsnprintf(buf, sizeof(buf), fmt.c_str(), args); - va_end(args); + const auto *fmt = Language::Translate(u, message); - ci->c->Kick(ci->bi, u, Anope::string(buf)); + Anope::string buf; + ANOPE_FORMAT(message, fmt, buf); + ci->c->Kick(ci->bi, u, buf); } public: @@ -1157,7 +1153,7 @@ public: if (kd && kd->badwords) { if (kd->ttb[TTB_BADWORDS]) - info[_("Bad words kicker")] = Anope::printf("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BADWORDS]); + info[_("Bad words kicker")] = Anope::Format("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BADWORDS]); else info[_("Bad words kicker")] = enabled; } @@ -1167,7 +1163,7 @@ public: if (kd && kd->bolds) { if (kd->ttb[TTB_BOLDS]) - info[_("Bolds kicker")] = Anope::printf("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BOLDS]); + info[_("Bolds kicker")] = Anope::Format("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BOLDS]); else info[_("Bolds kicker")] = enabled; } @@ -1177,9 +1173,9 @@ public: if (kd && kd->caps) { if (kd->ttb[TTB_CAPS]) - info[_("Caps kicker")] = Anope::printf(_("%s (%d kick(s) to ban; minimum %d/%d%%)"), enabled.c_str(), kd->ttb[TTB_CAPS], kd->capsmin, kd->capspercent); + info[_("Caps kicker")] = Anope::Format(_("%s (%d kick(s) to ban; minimum %d/%d%%)"), enabled.c_str(), kd->ttb[TTB_CAPS], kd->capsmin, kd->capspercent); else - info[_("Caps kicker")] = Anope::printf(_("%s (minimum %d/%d%%)"), enabled.c_str(), kd->capsmin, kd->capspercent); + info[_("Caps kicker")] = Anope::Format(_("%s (minimum %d/%d%%)"), enabled.c_str(), kd->capsmin, kd->capspercent); } else info[_("Caps kicker")] = disabled; @@ -1187,7 +1183,7 @@ public: if (kd && kd->colors) { if (kd->ttb[TTB_COLORS]) - info[_("Colors kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_COLORS]); + info[_("Colors kicker")] = Anope::Format(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_COLORS]); else info[_("Colors kicker")] = enabled; } @@ -1197,9 +1193,9 @@ public: if (kd && kd->flood) { if (kd->ttb[TTB_FLOOD]) - info[_("Flood kicker")] = Anope::printf(_("%s (%d kick(s) to ban; %d lines in %ds)"), enabled.c_str(), kd->ttb[TTB_FLOOD], kd->floodlines, kd->floodsecs); + info[_("Flood kicker")] = Anope::Format(_("%s (%d kick(s) to ban; %d lines in %ds)"), enabled.c_str(), kd->ttb[TTB_FLOOD], kd->floodlines, kd->floodsecs); else - info[_("Flood kicker")] = Anope::printf(_("%s (%d lines in %ds)"), enabled.c_str(), kd->floodlines, kd->floodsecs); + info[_("Flood kicker")] = Anope::Format(_("%s (%d lines in %ds)"), enabled.c_str(), kd->floodlines, kd->floodsecs); } else info[_("Flood kicker")] = disabled; @@ -1207,9 +1203,9 @@ public: if (kd && kd->repeat) { if (kd->ttb[TTB_REPEAT]) - info[_("Repeat kicker")] = Anope::printf(_("%s (%d kick(s) to ban; %d times)"), enabled.c_str(), kd->ttb[TTB_REPEAT], kd->repeattimes); + info[_("Repeat kicker")] = Anope::Format(_("%s (%d kick(s) to ban; %d times)"), enabled.c_str(), kd->ttb[TTB_REPEAT], kd->repeattimes); else - info[_("Repeat kicker")] = Anope::printf(_("%s (%d times)"), enabled.c_str(), kd->repeattimes); + info[_("Repeat kicker")] = Anope::Format(_("%s (%d times)"), enabled.c_str(), kd->repeattimes); } else info[_("Repeat kicker")] = disabled; @@ -1217,7 +1213,7 @@ public: if (kd && kd->reverses) { if (kd->ttb[TTB_REVERSES]) - info[_("Reverses kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_REVERSES]); + info[_("Reverses kicker")] = Anope::Format(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_REVERSES]); else info[_("Reverses kicker")] = enabled; } @@ -1227,7 +1223,7 @@ public: if (kd && kd->underlines) { if (kd->ttb[TTB_UNDERLINES]) - info[_("Underlines kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_UNDERLINES]); + info[_("Underlines kicker")] = Anope::Format(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_UNDERLINES]); else info[_("Underlines kicker")] = enabled; } @@ -1237,7 +1233,7 @@ public: if (kd && kd->italics) { if (kd->ttb[TTB_ITALICS]) - info[_("Italics kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_ITALICS]); + info[_("Italics kicker")] = Anope::Format(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_ITALICS]); else info[_("Italics kicker")] = enabled; } @@ -1247,7 +1243,7 @@ public: if (kd && kd->amsgs) { if (kd->ttb[TTB_AMSGS]) - info[_("AMSG kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_AMSGS]); + info[_("AMSG kicker")] = Anope::Format(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_AMSGS]); else info[_("AMSG kicker")] = enabled; } diff --git a/modules/chanserv/cs_mode.cpp b/modules/chanserv/cs_mode.cpp index 39009b12b..4ba9439ec 100644 --- a/modules/chanserv/cs_mode.cpp +++ b/modules/chanserv/cs_mode.cpp @@ -458,7 +458,7 @@ class CommandCSMode final continue; ListFormatter::ListEntry entry; - entry["Mode"] = Anope::printf("%c%c", ml->set ? '+' : '-', cm->mchar); + entry["Mode"] = Anope::Format("%c%c", ml->set ? '+' : '-', cm->mchar); entry["Param"] = ml->param; entry["Creator"] = ml->setter; entry["Created"] = Anope::strftime(ml->created, NULL, true); @@ -917,9 +917,9 @@ public: if (!m.second.empty()) { if (m.first) - return Anope::printf(Language::Translate(source.GetAccount(), _("Gives you or the specified nick %s status on a channel")), m.second.c_str()); + return Anope::Format(Language::Translate(source.GetAccount(), _("Gives you or the specified nick %s status on a channel")), m.second.c_str()); else - return Anope::printf(Language::Translate(source.GetAccount(), _("Removes %s status from you or the specified nick on a channel")), m.second.c_str()); + return Anope::Format(Language::Translate(source.GetAccount(), _("Removes %s status from you or the specified nick on a channel")), m.second.c_str()); } else return ""; diff --git a/modules/chanserv/cs_seen.cpp b/modules/chanserv/cs_seen.cpp index 08d9f0458..d7befb2a9 100644 --- a/modules/chanserv/cs_seen.cpp +++ b/modules/chanserv/cs_seen.cpp @@ -282,7 +282,7 @@ public: if (u2) onlinestatus = "."; else - onlinestatus = Anope::printf(Language::Translate(source.nc, _(" but %s mysteriously dematerialized.")), target.c_str()); + onlinestatus = Anope::Format(Language::Translate(source.nc, _(" but %s mysteriously dematerialized.")), target.c_str()); Anope::string timebuf = Anope::Duration(Anope::CurTime - info->last, source.nc); Anope::string timebuf2 = Anope::strftime(info->last, source.nc, true); @@ -296,9 +296,9 @@ public: { u2 = User::Find(info->nick2, true); if (u2) - onlinestatus = Anope::printf(Language::Translate(source.nc, _(". %s is still online.")), u2->nick.c_str()); + onlinestatus = Anope::Format(Language::Translate(source.nc, _(". %s is still online.")), u2->nick.c_str()); else - onlinestatus = Anope::printf(Language::Translate(source.nc, _(", but %s mysteriously dematerialized.")), info->nick2.c_str()); + onlinestatus = Anope::Format(Language::Translate(source.nc, _(", but %s mysteriously dematerialized.")), info->nick2.c_str()); source.Reply(_("%s (%s) was last seen changing nick to %s %s ago%s"), target.c_str(), info->vhost.c_str(), info->nick2.c_str(), timebuf.c_str(), onlinestatus.c_str()); diff --git a/modules/chanserv/cs_xop.cpp b/modules/chanserv/cs_xop.cpp index bb38805f9..9328ebef0 100644 --- a/modules/chanserv/cs_xop.cpp +++ b/modules/chanserv/cs_xop.cpp @@ -511,7 +511,7 @@ public: const Anope::string GetDesc(CommandSource &source) const override { - return Anope::printf(Language::Translate(source.GetAccount(), _("Modify the list of %s users")), source.command.nobreak().c_str()); + return Anope::Format(Language::Translate(source.GetAccount(), _("Modify the list of %s users")), source.command.nobreak().c_str()); } void Execute(CommandSource &source, const std::vector ¶ms) override diff --git a/modules/database/db_atheme.cpp b/modules/database/db_atheme.cpp index ecc7819cf..11df9765d 100644 --- a/modules/database/db_atheme.cpp +++ b/modules/database/db_atheme.cpp @@ -803,7 +803,7 @@ private: auto *ni = news_service->CreateNewsItem(); ni->type = NEWS_LOGON; - ni->text = Anope::printf("[%s] %s", subject.c_str(), body.c_str()); + ni->text = Anope::Format("[%s] %s", subject.c_str(), body.c_str()); ni->who = setter; ni->time = ts; news_service->AddNewsItem(ni); @@ -829,7 +829,7 @@ private: auto *ni = news_service->CreateNewsItem(); ni->type = NEWS_OPER; - ni->text = Anope::printf("[%s] %s", subject.c_str(), body.c_str()); + ni->text = Anope::Format("[%s] %s", subject.c_str(), body.c_str()); ni->who = setter; ni->time = ts; news_service->AddNewsItem(ni); diff --git a/modules/database/db_sql_live.cpp b/modules/database/db_sql_live.cpp index 14439a71d..d87691144 100644 --- a/modules/database/db_sql_live.cpp +++ b/modules/database/db_sql_live.cpp @@ -174,9 +174,9 @@ public: if (!this->CheckInit() || obj->GetTimestamp() == Anope::CurTime) return; - Anope::string sql = Anope::printf("SELECT * from `%s`", GetTableName(obj).c_str()); + Anope::string sql = Anope::Format("SELECT * from `%s`", GetTableName(obj).c_str()); if (obj->GetTimestamp()) - sql += Anope::printf(" WHERE (`timestamp` >= %s OR `timestamp` IS NULL)", this->SQL->FromUnixtime(obj->GetTimestamp()).c_str()); + sql += Anope::Format(" WHERE (`timestamp` >= %s OR `timestamp` IS NULL)", this->SQL->FromUnixtime(obj->GetTimestamp()).c_str()); Query query(sql); diff --git a/modules/extra/mysql.cpp b/modules/extra/mysql.cpp index f68987236..1bc6716b9 100644 --- a/modules/extra/mysql.cpp +++ b/modules/extra/mysql.cpp @@ -200,7 +200,7 @@ public: Anope::string GetColumn(Serialize::DataType dt) { - return Anope::printf("%s %s DEFAULT %s", + return Anope::Format("%s %s DEFAULT %s", GetColumnType(dt), GetColumnNull(dt) ? "NULL" : "NOT NULL", GetColumnDefault(dt)); @@ -498,24 +498,24 @@ std::vector MySQLService::CreateTable(const Anope::string &table, const D { // We can't just use MODIFY COLUMN here because the value may not // be valid and we may need to replace with the default. - auto res = this->RunQuery(Anope::printf("ALTER TABLE `%s` ADD COLUMN `%s_new` %s; ", + auto res = this->RunQuery(Anope::Format("ALTER TABLE `%s` ADD COLUMN `%s_new` %s; ", table.c_str(), column.c_str(), GetColumn(stype).c_str())); if (res) { - res = this->RunQuery(Anope::printf("UPDATE IGNORE `%s` SET `%s_new` = %s; ", + res = this->RunQuery(Anope::Format("UPDATE IGNORE `%s` SET `%s_new` = %s; ", table.c_str(), column.c_str(), column.c_str())); } if (res) { - res = this->RunQuery(Anope::printf("ALTER TABLE `%s` DROP COLUMN `%s`; ", + res = this->RunQuery(Anope::Format("ALTER TABLE `%s` DROP COLUMN `%s`; ", table.c_str(), column.c_str())); } if (res) { - res = this->RunQuery(Anope::printf("ALTER TABLE `%s` RENAME COLUMN `%s_new` TO `%s`; ", + res = this->RunQuery(Anope::Format("ALTER TABLE `%s` RENAME COLUMN `%s_new` TO `%s`; ", table.c_str(), column.c_str(), column.c_str())); } diff --git a/modules/extra/xmlrpc.cpp b/modules/extra/xmlrpc.cpp index 54e2752d9..0ea771698 100644 --- a/modules/extra/xmlrpc.cpp +++ b/modules/extra/xmlrpc.cpp @@ -148,7 +148,7 @@ public: if (request.data.size() < event->GetMinParams()) { - auto error = Anope::printf("Not enough parameters (given %zu, expected %zu)", + auto error = Anope::Format("Not enough parameters (given %zu, expected %zu)", request.data.size(), event->GetMinParams()); xmlrpc_env_set_fault(&env, RPC::ERR_INVALID_PARAMS, error.c_str()); SendError(reply, env); diff --git a/modules/global/global.cpp b/modules/global/global.cpp index cb2f74d38..04f937c4c 100644 --- a/modules/global/global.cpp +++ b/modules/global/global.cpp @@ -141,7 +141,7 @@ public: if (source && !Config->GetModule(this).Get("anonymousglobal")) { // A source is available and they're not anonymous. - line = Anope::printf("[%s] %s", source->GetNick().c_str(), message.c_str()); + line = Anope::Format("[%s] %s", source->GetNick().c_str(), message.c_str()); } else { diff --git a/modules/greet.cpp b/modules/greet.cpp index b76b352fc..6a2e95b57 100644 --- a/modules/greet.cpp +++ b/modules/greet.cpp @@ -204,7 +204,7 @@ public: Anope::string *greet = ns_greet.Get(user->Account()); if (bs_greet.HasExt(c->ci) && greet != NULL && !greet->empty() && c->FindUser(c->ci->bi) && c->ci->AccessFor(user).HasPriv("GREET")) { - const auto message = Anope::printf("[%s] %s", user->Account()->display.c_str(), greet->c_str()); + const auto message = Anope::Format("[%s] %s", user->Account()->display.c_str(), greet->c_str()); IRCD->SendPrivmsg(*c->ci->bi, c->name, message); c->ci->bi->lastmsg = Anope::CurTime; } diff --git a/modules/hostserv/hs_request.cpp b/modules/hostserv/hs_request.cpp index 9d1a2fb80..c3ccd39da 100644 --- a/modules/hostserv/hs_request.cpp +++ b/modules/hostserv/hs_request.cpp @@ -272,7 +272,7 @@ public: { Anope::string message; if (!reason.empty()) - message = Anope::printf(_("Your requested vhost has been rejected. Reason: %s"), reason.c_str()); + message = Anope::Format(_("Your requested vhost has been rejected. Reason: %s"), reason.c_str()); else message = _("Your requested vhost has been rejected."); @@ -397,7 +397,7 @@ static void req_send_memos(Module *me, CommandSource &source, const Anope::strin if (!na) continue; - Anope::string message = Anope::printf(_("VHost \002%s\002 has been requested by %s."), host.c_str(), source.GetNick().c_str()); + Anope::string message = Anope::Format(_("VHost \002%s\002 has been requested by %s."), host.c_str(), source.GetNick().c_str()); memoserv->Send(source.service->nick, na->nick, message, true); } diff --git a/modules/memoserv/ms_read.cpp b/modules/memoserv/ms_read.cpp index ff3886818..e81a9cba0 100644 --- a/modules/memoserv/ms_read.cpp +++ b/modules/memoserv/ms_read.cpp @@ -32,7 +32,7 @@ static void rsend_notify(CommandSource &source, MemoInfo *mi, Memo *m, const Ano /* Text of the memo varies if the recipient was a nick or channel */ - Anope::string text = Anope::printf(Language::Translate(na->nc, _("\002[auto-memo]\002 The memo you sent to %s has been viewed.")), targ.c_str()); + Anope::string text = Anope::Format(Language::Translate(na->nc, _("\002[auto-memo]\002 The memo you sent to %s has been viewed.")), targ.c_str()); /* Send notification */ MemoServService->Send(source.GetNick(), m->sender, text, true); diff --git a/modules/nickserv/ns_list.cpp b/modules/nickserv/ns_list.cpp index a82a26cff..fe4498506 100644 --- a/modules/nickserv/ns_list.cpp +++ b/modules/nickserv/ns_list.cpp @@ -94,7 +94,7 @@ public: /* We no longer compare the pattern against the output buffer. * Instead we build a nice nick!user@host buffer to compare. * The output is then generated separately. -TheShadow */ - Anope::string buf = Anope::printf("%s!%s", na->nick.c_str(), !na->last_userhost.empty() ? na->last_userhost.c_str() : "*@*"); + Anope::string buf = Anope::Format("%s!%s", na->nick.c_str(), !na->last_userhost.empty() ? na->last_userhost.c_str() : "*@*"); if (na->nick.equals_ci(pattern) || Anope::Match(buf, pattern, false, true)) { if (((count + 1 >= from && count + 1 <= to) || (!from && !to)) && ++nnicks <= listmax) diff --git a/modules/nickserv/ns_sasl.cpp b/modules/nickserv/ns_sasl.cpp index fe1b0e78e..2f318a6c0 100644 --- a/modules/nickserv/ns_sasl.cpp +++ b/modules/nickserv/ns_sasl.cpp @@ -23,7 +23,7 @@ private: if (u) return u->GetMask(); if (!hostname.empty() && !GetAddress().empty()) - return Anope::printf("%s (%s)", hostname.c_str(), GetAddress().c_str()); + return Anope::Format("%s (%s)", hostname.c_str(), GetAddress().c_str()); return "A user"; }; diff --git a/modules/operserv/os_defcon.cpp b/modules/operserv/os_defcon.cpp index e79217219..eb14183de 100644 --- a/modules/operserv/os_defcon.cpp +++ b/modules/operserv/os_defcon.cpp @@ -136,7 +136,7 @@ public: if (!DConfig.offmessage.empty()) GlobalService->SendSingle(DConfig.offmessage); else - GlobalService->SendSingle(Anope::printf(Language::Translate(_("The Defcon level is now at: \002%d\002")), DConfig.defaultlevel)); + GlobalService->SendSingle(Anope::Format(Language::Translate(_("The Defcon level is now at: \002%d\002")), DConfig.defaultlevel)); if (!DConfig.message.empty()) GlobalService->SendSingle(DConfig.message); @@ -220,7 +220,7 @@ public: GlobalService->SendSingle(DConfig.offmessage); else if (DConfig.defaultlevel != 5) { - GlobalService->SendSingle(Anope::printf(_("The Defcon level is now at: \002%d\002"), DConfig.defaultlevel)); + GlobalService->SendSingle(Anope::Format(_("The Defcon level is now at: \002%d\002"), DConfig.defaultlevel)); if (!DConfig.message.empty()) GlobalService->SendSingle(DConfig.message); } diff --git a/modules/operserv/os_forbid.cpp b/modules/operserv/os_forbid.cpp index 7ce0b6cd8..6c0ca84fb 100644 --- a/modules/operserv/os_forbid.cpp +++ b/modules/operserv/os_forbid.cpp @@ -347,7 +347,7 @@ public: if (u->server == Me || u->HasMode("OPER")) continue; - reason = Anope::printf(Language::Translate(u, _("This channel has been forbidden: %s")), d->reason.c_str()); + reason = Anope::Format(Language::Translate(u, _("This channel has been forbidden: %s")), d->reason.c_str()); c->Kick(source.service, u, reason); } @@ -536,7 +536,7 @@ public: chanserv->Hold(c); } - reason = Anope::printf(Language::Translate(u, _("This channel has been forbidden: %s")), d->reason.c_str()); + reason = Anope::Format(Language::Translate(u, _("This channel has been forbidden: %s")), d->reason.c_str()); return EVENT_STOP; } diff --git a/modules/operserv/os_info.cpp b/modules/operserv/os_info.cpp index c5bcbd6e4..b0446fc37 100644 --- a/modules/operserv/os_info.cpp +++ b/modules/operserv/os_info.cpp @@ -281,7 +281,7 @@ class OSInfo final for (auto *o : *(*oi)) { - info[_("Oper Info")] = Anope::printf(_("(by %s on %s) %s"), o->adder.c_str(), Anope::strftime(o->created, source.GetAccount(), true).c_str(), o->info.c_str()); + info[_("Oper Info")] = Anope::Format(_("(by %s on %s) %s"), o->adder.c_str(), Anope::strftime(o->created, source.GetAccount(), true).c_str(), o->info.c_str()); } } diff --git a/modules/operserv/os_login.cpp b/modules/operserv/os_login.cpp index 21c5897f6..0bbcb4e71 100644 --- a/modules/operserv/os_login.cpp +++ b/modules/operserv/os_login.cpp @@ -74,7 +74,7 @@ public: const Anope::string GetDesc(CommandSource &source) const override { - return Anope::printf(Language::Translate(source.GetAccount(), _("Login to %s")), source.service->nick.c_str()); + return Anope::Format(Language::Translate(source.GetAccount(), _("Login to %s")), source.service->nick.c_str()); } }; @@ -120,7 +120,7 @@ public: const Anope::string GetDesc(CommandSource &source) const override { - return Anope::printf(Language::Translate(source.GetAccount(), _("Logout from %s")), source.service->nick.c_str()); + return Anope::Format(Language::Translate(source.GetAccount(), _("Logout from %s")), source.service->nick.c_str()); } }; diff --git a/modules/operserv/os_sxline.cpp b/modules/operserv/os_sxline.cpp index b49a91bc1..cb475d98a 100644 --- a/modules/operserv/os_sxline.cpp +++ b/modules/operserv/os_sxline.cpp @@ -243,7 +243,7 @@ public: const Anope::string GetDesc(CommandSource &source) const override { - return Anope::printf(Language::Translate(source.GetAccount(), _("Manipulate the %s list")), source.command.nobreak().c_str()); + return Anope::Format(Language::Translate(source.GetAccount(), _("Manipulate the %s list")), source.command.nobreak().c_str()); } void Execute(CommandSource &source, const std::vector ¶ms) override diff --git a/modules/protocol/inspircd.cpp b/modules/protocol/inspircd.cpp index 7b3033195..22e89c58e 100644 --- a/modules/protocol/inspircd.cpp +++ b/modules/protocol/inspircd.cpp @@ -622,13 +622,13 @@ public: if (spanningtree_proto_ver >= 1206) { - Uplink::Send("SINFO", "customversion", Anope::printf("%s -- (%s) -- %s", IRCD->GetProtocolName().c_str(), enc ? enc->name.c_str() : "none", Anope::VersionBuildString().c_str())); + Uplink::Send("SINFO", "customversion", Anope::Format("%s -- (%s) -- %s", IRCD->GetProtocolName().c_str(), enc ? enc->name.c_str() : "none", Anope::VersionBuildString().c_str())); Uplink::Send("SINFO", "rawbranch", "Anope-" + Anope::VersionShort()); } else { - Uplink::Send("SINFO", "version", Anope::printf("Anope-%s %s :%s -- (%s) -- %s", Anope::Version().c_str(), Me->GetName().c_str(), IRCD->GetProtocolName().c_str(), enc ? enc->name.c_str() : "none", Anope::VersionBuildString().c_str())); - Uplink::Send("SINFO", "fullversion", Anope::printf("Anope-%s %s :[%s] %s -- (%s) -- %s", Anope::Version().c_str(), Me->GetName().c_str(), Me->GetSID().c_str(), IRCD->GetProtocolName().c_str(), enc ? enc->name.c_str() : "none", Anope::VersionBuildString().c_str())); + Uplink::Send("SINFO", "version", Anope::Format("Anope-%s %s :%s -- (%s) -- %s", Anope::Version().c_str(), Me->GetName().c_str(), IRCD->GetProtocolName().c_str(), enc ? enc->name.c_str() : "none", Anope::VersionBuildString().c_str())); + Uplink::Send("SINFO", "fullversion", Anope::Format("Anope-%s %s :[%s] %s -- (%s) -- %s", Anope::Version().c_str(), Me->GetName().c_str(), Me->GetSID().c_str(), IRCD->GetProtocolName().c_str(), enc ? enc->name.c_str() : "none", Anope::VersionBuildString().c_str())); } Uplink::Send("SINFO", "rawversion", "Anope-" + Anope::VersionShort()); } diff --git a/modules/protocol/unrealircd.cpp b/modules/protocol/unrealircd.cpp index 73f606053..fe5eac084 100644 --- a/modules/protocol/unrealircd.cpp +++ b/modules/protocol/unrealircd.cpp @@ -463,7 +463,7 @@ private: if (!cm || !cm->mchar) return; - Uplink::Send(user, "SVS2MODE", c->name, Anope::printf("-%c", cm->mchar), u->GetUID()); + Uplink::Send(user, "SVS2MODE", c->name, Anope::Format("-%c", cm->mchar), u->GetUID()); } bool IsTagValid(const Anope::string &tname, const Anope::string &tvalue) override @@ -492,7 +492,7 @@ namespace UnrealExtBan ChannelMode *Wrap(Anope::string ¶m) override { auto prefix = Servers::Capab.count("NEXTBANS") ? xbname : Anope::string(xbchar); - param = Anope::printf("~%s:%s", prefix.c_str(), param.c_str()); + param = Anope::Format("~%s:%s", prefix.c_str(), param.c_str()); return ChannelModeVirtual::Wrap(param); } diff --git a/modules/rpc/jsonrpc.cpp b/modules/rpc/jsonrpc.cpp index f39f01cb5..6ce3c85ad 100644 --- a/modules/rpc/jsonrpc.cpp +++ b/modules/rpc/jsonrpc.cpp @@ -102,7 +102,7 @@ public: auto *doc = yyjson_read_opts(const_cast(message.content.c_str()), message.content.length(), flags, nullptr, &error); if (!doc) { - SendError(reply, RPC::ERR_PARSE_ERROR, Anope::printf("JSON parse error #%u: %s", error.code, error.msg)); + SendError(reply, RPC::ERR_PARSE_ERROR, Anope::Format("JSON parse error #%u: %s", error.code, error.msg)); return true; } @@ -164,7 +164,7 @@ public: if (request.data.size() < event->GetMinParams()) { - auto error = Anope::printf("Not enough parameters for %s (given %zu, expected %zu)", + auto error = Anope::Format("Not enough parameters for %s (given %zu, expected %zu)", request.name.c_str(), request.data.size(), event->GetMinParams()); SendError(reply, RPC::ERR_INVALID_PARAMS, error, id); return true; diff --git a/modules/webcpanel/pages/chanserv/modes.cpp b/modules/webcpanel/pages/chanserv/modes.cpp index b33894ee8..09294cbbf 100644 --- a/modules/webcpanel/pages/chanserv/modes.cpp +++ b/modules/webcpanel/pages/chanserv/modes.cpp @@ -38,7 +38,7 @@ bool WebCPanel::ChanServ::Modes::OnRequest(HTTP::Provider *server, const Anope:: if (!c) { - replacements["MESSAGES"] = Anope::printf(CHAN_X_NOT_IN_USE, chname.c_str()); + replacements["MESSAGES"] = Anope::Format(CHAN_X_NOT_IN_USE, chname.c_str()); Page.Serve(server, page_name, client, message, reply, replacements); return true; } diff --git a/modules/webcpanel/pages/nickserv/info.cpp b/modules/webcpanel/pages/nickserv/info.cpp index b339a5077..297eb5762 100644 --- a/modules/webcpanel/pages/nickserv/info.cpp +++ b/modules/webcpanel/pages/nickserv/info.cpp @@ -80,7 +80,7 @@ bool WebCPanel::NickServ::Info::OnRequest(HTTP::Provider *server, const Anope::s replacements["ERRORS"] = "Protection delay must be a number of seconds"; else if (*secs < minprotect || *secs > maxprotect) { - replacements["ERRORS"] = Anope::printf("Protection delay must be between %ld and %ld seconds.", + replacements["ERRORS"] = Anope::Format("Protection delay must be between %ld and %ld seconds.", minprotect, maxprotect); } else if (!na->nc->HasExt("PROTECT_AFTER") || *secs != *na->nc->GetExt("PROTECT_AFTER")) diff --git a/src/bots.cpp b/src/bots.cpp index b507e4d63..1ecae3e5b 100644 --- a/src/bots.cpp +++ b/src/bots.cpp @@ -60,7 +60,7 @@ BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const A ctcps.emplace("VERSION", [](auto *bi, auto *u, const auto &) { auto *enc = ModuleManager::FindFirstOf(ENCRYPTION); - IRCD->SendNotice(bi, u->GetUID(), Anope::FormatCTCP("VERSION", Anope::printf("Anope-%s %s -- %s -- %s", Anope::Version().c_str(), + IRCD->SendNotice(bi, u->GetUID(), Anope::FormatCTCP("VERSION", Anope::Format("Anope-%s %s -- %s -- %s", Anope::Version().c_str(), Anope::VersionBuildString().c_str(), IRCD->GetProtocolName().c_str(), enc ? enc->name.c_str() : "(none)"))); }); diff --git a/src/channels.cpp b/src/channels.cpp index 01a5459a2..33e1b0b44 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -537,13 +537,9 @@ bool Channel::GetParam(const Anope::string &mname, Anope::string &target) const void Channel::SetModes(BotInfo *bi, bool enforce_mlock, const char *cmodes, ...) { - char buf[BUFSIZE] = ""; - va_list args; - va_start(args, cmodes); - vsnprintf(buf, BUFSIZE - 1, cmodes, args); - va_end(args); - - SetModes(bi, enforce_mlock, Anope::string(buf)); + Anope::string buf; + ANOPE_FORMAT(cmodes, cmodes, buf); + SetModes(bi, enforce_mlock, buf); } @@ -779,13 +775,9 @@ void Channel::KickInternal(const MessageSource &source, const Anope::string &nic bool Channel::Kick(BotInfo *bi, User *u, const char *reason, ...) { - va_list args; - char buf[BUFSIZE] = ""; - va_start(args, reason); - vsnprintf(buf, BUFSIZE - 1, reason, args); - va_end(args); - - return Kick(bi, u, Anope::string(buf)); + Anope::string buf; + ANOPE_FORMAT(reason, reason, buf); + return Kick(bi, u, buf); } bool Channel::Kick(BotInfo *bi, User *u, const Anope::string &reason) diff --git a/src/command.cpp b/src/command.cpp index 79df32f83..c525bedd9 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -105,32 +105,20 @@ bool CommandSource::IsOper() void CommandSource::Reply(const char *message, ...) { - va_list args; - char buf[4096]; // Messages can be really big. - const char *translated_message = Language::Translate(this->nc, message); - va_start(args, message); - vsnprintf(buf, sizeof(buf), translated_message, args); - + Anope::string buf; + ANOPE_FORMAT(message, translated_message, buf); this->reply->SendMessage(*this, buf); - - va_end(args); } void CommandSource::Reply(int count, const char *single, const char *plural, ...) { - va_list args; - char buf[4096]; // Messages can be really big. - const char *translated_message = Language::Translate(this->nc, count, single, plural); - va_start(args, plural); - vsnprintf(buf, sizeof(buf), translated_message, args); - + Anope::string buf; + ANOPE_FORMAT(plural, translated_message, buf); this->reply->SendMessage(*this, buf); - - va_end(args); } void CommandSource::Reply(const Anope::string &message) diff --git a/src/config.cpp b/src/config.cpp index fb49918dc..fad57d679 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -626,9 +626,9 @@ Anope::string Uplink::str() const switch (protocol) { case AF_INET: - return Anope::printf("%s:%u", this->host.c_str(), this->port); + return Anope::Format("%s:%u", this->host.c_str(), this->port); case AF_INET6: - return Anope::printf("[%s]:%u", this->host.c_str(), this->port); + return Anope::Format("[%s]:%u", this->host.c_str(), this->port); case AF_UNIX: return this->host; } @@ -776,7 +776,7 @@ void Conf::LoadConf(File &file) if (!file.Open()) { - throw ConfigException(Anope::printf("File %s could not be opened: %s.", + throw ConfigException(Anope::Format("File %s could not be opened: %s.", file.GetPath().c_str(), strerror(errno))); } diff --git a/src/messages.cpp b/src/messages.cpp index ec2b255f8..5668bcc38 100644 --- a/src/messages.cpp +++ b/src/messages.cpp @@ -253,7 +253,7 @@ void MOTD::Run(MessageSource &source, const std::vector ¶ms, IRCD->SendNumeric(RPL_MOTDSTART, source.GetSource(), "- " + s->GetName() + " Message of the Day"); for (Anope::string line; std::getline(stream, line.str()); ) - IRCD->SendNumeric(RPL_MOTD, source.GetSource(), Anope::printf("- %s", line.c_str())); + IRCD->SendNumeric(RPL_MOTD, source.GetSource(), Anope::Format("- %s", line.c_str())); IRCD->SendNumeric(RPL_ENDOFMOTD, source.GetSource(), "End of /MOTD command."); } @@ -425,8 +425,8 @@ void Stats::Run(MessageSource &source, const std::vector ¶ms, case 'u': { long uptime = static_cast(Anope::CurTime - Anope::StartTime); - IRCD->SendNumeric(RPL_STATSUPTIME, source.GetSource(), Anope::printf("Services up %ld day%s, %02ld:%02ld:%02ld", uptime / 86400, uptime / 86400 == 1 ? "" : "s", (uptime / 3600) % 24, (uptime / 60) % 60, uptime % 60)); - IRCD->SendNumeric(RPL_STATSCONN, source.GetSource(), Anope::printf("Current users: %zu (%zu ops); maximum %zu", UserListByNick.size(), OperCount, MaxUserCount)); + IRCD->SendNumeric(RPL_STATSUPTIME, source.GetSource(), Anope::Format("Services up %ld day%s, %02ld:%02ld:%02ld", uptime / 86400, uptime / 86400 == 1 ? "" : "s", (uptime / 3600) % 24, (uptime / 60) % 60, uptime % 60)); + IRCD->SendNumeric(RPL_STATSCONN, source.GetSource(), Anope::Format("Current users: %zu (%zu ops); maximum %zu", UserListByNick.size(), OperCount, MaxUserCount)); IRCD->SendNumeric(RPL_STATSLINKINFO, source.GetSource(), params[0][0], "End of /STATS report."); break; } /* case 'u' */ @@ -443,7 +443,7 @@ void Time::Run(MessageSource &source, const std::vector ¶ms, const auto *tm = localtime(&Anope::CurTime); char timebuf[64]; strftime(timebuf, sizeof(timebuf), "%A, %d %B %Y @ %H:%M:%S %Z", tm); - const auto timestr = Anope::printf("%s (%lu)", timebuf, Anope::CurTime); + const auto timestr = Anope::Format("%s (%lu)", timebuf, Anope::CurTime); IRCD->SendNumeric(RPL_TIME, source.GetSource(), Me->GetName(), timestr); } @@ -459,7 +459,7 @@ void Topic::Run(MessageSource &source, const std::vector ¶ms, void Version::Run(MessageSource &source, const std::vector ¶ms, const Anope::map &tags) { Module *enc = ModuleManager::FindFirstOf(ENCRYPTION); - IRCD->SendNumeric(RPL_VERSION, source.GetSource(), "Anope-" + Anope::Version(), Me->GetName(), Anope::printf("%s -(%s) -- %s", + IRCD->SendNumeric(RPL_VERSION, source.GetSource(), "Anope-" + Anope::Version(), Me->GetName(), Anope::Format("%s -(%s) -- %s", IRCD->GetProtocolName().c_str(), enc ? enc->name.c_str() : "(none)", Anope::VersionBuildString().c_str())); } diff --git a/src/misc.cpp b/src/misc.cpp index 4ed01ecf6..6980ded20 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -513,27 +513,27 @@ Anope::string Anope::Duration(time_t t, const NickCore *nc) Anope::string buffer; if (years) { - buffer = Anope::printf(Language::Translate(nc, years, N_("%lld year", "%lld years")), (long long)years); + buffer = Anope::Format(Language::Translate(nc, years, N_("%lld year", "%lld years")), (long long)years); } if (days) { buffer += buffer.empty() ? "" : ", "; - buffer += Anope::printf(Language::Translate(nc, days, N_("%lld day", "%lld days")), (long long)days); + buffer += Anope::Format(Language::Translate(nc, days, N_("%lld day", "%lld days")), (long long)days); } if (hours) { buffer += buffer.empty() ? "" : ", "; - buffer += Anope::printf(Language::Translate(nc, hours, N_("%lld hour", "%lld hours")), (long long)hours); + buffer += Anope::Format(Language::Translate(nc, hours, N_("%lld hour", "%lld hours")), (long long)hours); } if (minutes) { buffer += buffer.empty() ? "" : ", "; - buffer += Anope::printf(Language::Translate(nc, minutes, N_("%lld minute", "%lld minutes")), (long long)minutes); + buffer += Anope::Format(Language::Translate(nc, minutes, N_("%lld minute", "%lld minutes")), (long long)minutes); } if (seconds || buffer.empty()) { buffer += buffer.empty() ? "" : ", "; - buffer += Anope::printf(Language::Translate(nc, seconds, N_("%lld second", "%lld seconds")), (long long)seconds); + buffer += Anope::Format(Language::Translate(nc, seconds, N_("%lld second", "%lld seconds")), (long long)seconds); } return buffer; } @@ -546,11 +546,11 @@ Anope::string Anope::strftime(time_t t, const NickCore *nc, bool short_output) return buf; if (t < Anope::CurTime) - return Anope::printf(Language::Translate(nc, _("%s (%s ago)")), buf, Duration(Anope::CurTime - t, nc).c_str()); + return Anope::Format(Language::Translate(nc, _("%s (%s ago)")), buf, Duration(Anope::CurTime - t, nc).c_str()); else if (t > Anope::CurTime) - return Anope::printf(Language::Translate(nc, _("%s (%s from now)")), buf, Duration(t - Anope::CurTime, nc).c_str(), nc); + return Anope::Format(Language::Translate(nc, _("%s (%s from now)")), buf, Duration(t - Anope::CurTime, nc).c_str(), nc); else - return Anope::printf(Language::Translate(nc, _("%s (now)")), buf); + return Anope::Format(Language::Translate(nc, _("%s (now)")), buf); } Anope::string Anope::Expires(time_t expires, const NickCore *nc) @@ -578,7 +578,7 @@ Anope::string Anope::Expires(time_t expires, const NickCore *nc) timeleft = nearest(timeleft, 60); // Nearest minute if its more than an hour auto duration = Anope::Duration(timeleft, nc); - return Anope::printf(Language::Translate(nc, _("expires in %s")), duration.c_str()); + return Anope::Format(Language::Translate(nc, _("expires in %s")), duration.c_str()); } bool Anope::Match(const Anope::string &str, const Anope::string &mask, bool case_sensitive, bool use_regex) @@ -692,16 +692,32 @@ bool Anope::Encrypt(const Anope::string &src, Anope::string &dest) return MOD_RESULT == EVENT_ALLOW &&!dest.empty(); } -Anope::string Anope::printf(const char *fmt, ...) +Anope::string Anope::Format(const char *fmt, ...) { - va_list args; - char buf[1024]; - va_start(args, fmt); - vsnprintf(buf, sizeof(buf), fmt, args); - va_end(args); + Anope::string buf; + ANOPE_FORMAT(fmt, fmt, buf); return buf; } +Anope::string Anope::Format(va_list &valist, const char *fmt) +{ + static std::vector buffer(512); + while (true) + { + va_list newvalist; + va_copy(newvalist, valist); + auto vsnret = vsnprintf(&buffer[0], buffer.size(), fmt, newvalist); + va_end(newvalist); + + if (vsnret > 0 && static_cast(vsnret) < buffer.size()) + break; + + buffer.resize(buffer.size() * 2); + } + + return Anope::string(&buffer[0]); +} + Anope::string Anope::Hex(const Anope::string &data) { const char hextable[] = "0123456789abcdef"; @@ -1005,18 +1021,18 @@ Anope::string Anope::Expand(const Anope::string &base, const Anope::string &frag { const auto *homedir = getenv("HOME"); if (homedir && *homedir) - return Anope::printf("%s%c%s", homedir, separator, fragment.c_str() + 2); + return Anope::Format("%s%c%s", homedir, separator, fragment.c_str() + 2); } - return Anope::printf("%s%c%s", base.c_str(), separator, fragment.c_str()); + return Anope::Format("%s%c%s", base.c_str(), separator, fragment.c_str()); } Anope::string Anope::FormatCTCP(const Anope::string &name, const Anope::string &value) { if (value.empty()) - return Anope::printf("\1%s\1", name.c_str()); + return Anope::Format("\1%s\1", name.c_str()); - return Anope::printf("\1%s %s\1", name.c_str(), value.c_str()); + return Anope::Format("\1%s %s\1", name.c_str(), value.c_str()); } bool Anope::ParseCTCP(const Anope::string &text, Anope::string &name, Anope::string &body) diff --git a/src/protocol.cpp b/src/protocol.cpp index c6fad03f5..65b99b470 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -390,14 +390,14 @@ Anope::string IRCDProto::NormalizeMask(const Anope::string &mask) void IRCDProto::SendContextNotice(BotInfo *bi, User *target, Channel *context, const Anope::string &msg) { - IRCD->SendNotice(bi, target->GetUID(), Anope::printf("[%s] %s", context->name.c_str(), msg.c_str()), { + IRCD->SendNotice(bi, target->GetUID(), Anope::Format("[%s] %s", context->name.c_str(), msg.c_str()), { { "+draft/channel-context", context->name }, }); } void IRCDProto::SendContextPrivmsg(BotInfo *bi, User *target, Channel *context, const Anope::string &msg) { - IRCD->SendPrivmsg(bi, target->GetUID(), Anope::printf("[%s] %s", context->name.c_str(), msg.c_str()), { + IRCD->SendPrivmsg(bi, target->GetUID(), Anope::Format("[%s] %s", context->name.c_str(), msg.c_str()), { { "+draft/channel-context", context->name }, }); } diff --git a/src/socket_transport.cpp b/src/socket_transport.cpp index 621b2bce4..073a7f272 100644 --- a/src/socket_transport.cpp +++ b/src/socket_transport.cpp @@ -12,6 +12,7 @@ #include "services.h" #include "sockets.h" #include "socketengine.h" +#include "textproc.h" bool BufferedSocket::ProcessRead() { @@ -66,17 +67,12 @@ void BufferedSocket::Write(const char *buffer, size_t l) void BufferedSocket::Write(const char *message, ...) { - va_list vi; - char tbuffer[BUFSIZE]; - if (!message) return; - va_start(vi, message); - int len = vsnprintf(tbuffer, sizeof(tbuffer), message, vi); - va_end(vi); - - this->Write(tbuffer, std::min(len, static_cast(sizeof(tbuffer)))); + Anope::string tbuffer; + ANOPE_FORMAT(message, message, tbuffer); + this->Write(tbuffer.c_str(), tbuffer.length()); } void BufferedSocket::Write(const Anope::string &message) @@ -158,17 +154,12 @@ void BinarySocket::Write(const char *buffer, size_t l) void BinarySocket::Write(const char *message, ...) { - va_list vi; - char tbuffer[BUFSIZE]; - if (!message) return; - va_start(vi, message); - int len = vsnprintf(tbuffer, sizeof(tbuffer), message, vi); - va_end(vi); - - this->Write(tbuffer, std::min(len, static_cast(sizeof(tbuffer)))); + Anope::string tbuffer; + ANOPE_FORMAT(message, message, tbuffer); + this->Write(tbuffer.c_str(), tbuffer.length()); } void BinarySocket::Write(const Anope::string &message) diff --git a/src/sockets.cpp b/src/sockets.cpp index 908bf34f6..6a1f252ce 100644 --- a/src/sockets.cpp +++ b/src/sockets.cpp @@ -13,6 +13,7 @@ #include "sockets.h" #include "socketengine.h" #include "logger.h" +#include "textproc.h" #ifndef _WIN32 #include @@ -114,14 +115,14 @@ Anope::string sockaddrs::str() const char v4address[INET_ADDRSTRLEN]; if (!inet_ntop(AF_INET, &sa4.sin_addr, v4address, sizeof(v4address))) strcpy(v4address, "0.0.0.0"); - return Anope::printf("%s:%u", v4address, sa4.sin_port); + return Anope::Format("%s:%u", v4address, sa4.sin_port); } case AF_INET6: { char v6address[INET6_ADDRSTRLEN]; if (!inet_ntop(AF_INET6, &sa6.sin6_addr, v6address, sizeof(v6address))) strcpy(v6address, "0:0:0:0:0:0:0:0"); - return Anope::printf("[%s]:%u", v6address, sa6.sin6_port); + return Anope::Format("[%s]:%u", v6address, sa6.sin6_port); } case AF_UNIX: return saun.sun_path; @@ -306,7 +307,7 @@ Anope::string cidr::mask() const if ((this->addr.ipv6() && this->cidr_len == 128) || (!this->addr.ipv6() && this->cidr_len == 32)) return this->cidr_ip; else - return Anope::printf("%s/%d", this->cidr_ip.c_str(), this->cidr_len); + return Anope::Format("%s/%d", this->cidr_ip.c_str(), this->cidr_len); } bool cidr::match(const sockaddrs &other) diff --git a/src/users.cpp b/src/users.cpp index 5c95416fb..850ab075c 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -315,32 +315,20 @@ User::~User() void User::SendMessage(BotInfo *source, const char *fmt, ...) { - va_list args; - char buf[BUFSIZE] = ""; - const char *translated_message = Language::Translate(this, fmt); - va_start(args, fmt); - vsnprintf(buf, BUFSIZE - 1, translated_message, args); - - this->SendMessage(source, Anope::string(buf)); - - va_end(args); + Anope::string buf; + ANOPE_FORMAT(fmt, translated_message, buf); + this->SendMessage(source, buf); } void User::SendMessage(BotInfo *source, int count, const char *singular, const char *plural, ...) { - va_list args; - char buf[BUFSIZE] = ""; - const char *translated_message = Language::Translate(this, count, singular, plural); - va_start(args, plural); - vsnprintf(buf, BUFSIZE - 1, translated_message, args); - - this->SendMessage(source, Anope::string(buf)); - - va_end(args); + Anope::string buf; + ANOPE_FORMAT(plural, translated_message, buf); + this->SendMessage(source, buf); } namespace @@ -655,13 +643,9 @@ void User::RemoveMode(BotInfo *bi, const Anope::string &name, const Anope::strin void User::SetModes(BotInfo *bi, const char *umodes, ...) { - char buf[BUFSIZE] = ""; - va_list args; - va_start(args, umodes); - vsnprintf(buf, BUFSIZE - 1, umodes, args); - va_end(args); - - SetModes(bi, Anope::string(buf)); + Anope::string buf; + ANOPE_FORMAT(umodes, umodes, buf); + SetModes(bi, buf); } void User::SetModes(BotInfo *bi, const Anope::string &umodes) diff --git a/src/win32/anope_windows.h b/src/win32/anope_windows.h index a124378c4..6d7c06c05 100644 --- a/src/win32/anope_windows.h +++ b/src/win32/anope_windows.h @@ -36,10 +36,6 @@ # undef printf #endif -#define snprintf _snprintf -/* VS2008 hates having this define before its own */ -#define vsnprintf _vsnprintf - #define anope_close windows_close #define stat _stat