fix(notification): text emails not encoded properly (#3854)
This fixes an issue where the plain text portion of emails is not encoded with quoted printable encoding.pull/3912/head
parent
4d3ac31051
commit
319a8cf9d4
|
@ -0,0 +1,31 @@
|
|||
* text=auto
|
||||
|
||||
*.go text
|
||||
*.sh text
|
||||
*.html text
|
||||
*.js text
|
||||
*.jsx text
|
||||
*.ts text
|
||||
*.tsx text
|
||||
*.md text
|
||||
*.json text
|
||||
*.svg text
|
||||
*.css text
|
||||
*.yaml text
|
||||
*.yml text
|
||||
*.txt text
|
||||
*.tmpl text
|
||||
*.service text
|
||||
Dockerfile text
|
||||
Dockerfile.* text
|
||||
LICENSE text
|
||||
|
||||
*.jpg binary
|
||||
*.png binary
|
||||
*.gif binary
|
||||
*.ico binary
|
||||
|
||||
# RFC2822 requires us to save the email templates with CRLF line endings.
|
||||
internal/templates/src/notification/* text eol=crlf
|
||||
examples/templates/notifications/*.tmpl text eol=crlf
|
||||
examples/templates/notifications/*.html text eol=crlf
|
|
@ -18,6 +18,17 @@ two extensions; `.html` for HTML templates, and `.txt` for plaintext templates.
|
|||
This guide effectively documents the usage of the
|
||||
[template_path](../../configuration/notifications/introduction.md#template_path) notification configuration option.
|
||||
|
||||
## Important Notes
|
||||
|
||||
1. The templates are not covered by our stability guarantees. While we aim to avoid changes to the templates which
|
||||
would cause users to have to manually change them changes may be necessary in order to facilitate bug fixes or
|
||||
generally improve the templates.
|
||||
1. This is especially important for the [Envelope Template](#envelope-template).
|
||||
2. It is your responsibility to ensure your templates are up to date. We make no efforts in facilitating this.
|
||||
2. We may not be able to offer any direct support in debugging these templates. We only offer support and fixes to
|
||||
the official templates.
|
||||
3. All templates __*MUST*__ be encoded in UTF-8 with CRLF line endings. The line endings __*MUST NOT*__ be a simple LF.
|
||||
|
||||
## Template Names
|
||||
|
||||
| Template | Description |
|
||||
|
@ -60,13 +71,14 @@ Some Additional examples for specific purposes can be found in the
|
|||
|
||||
## Envelope Template
|
||||
|
||||
*__Important Note:__ This template must end with a CRLF newline. Failure to include this newline will result in
|
||||
malformed emails.*
|
||||
|
||||
There is also a special envelope template. This is the email envelope which contains the content of the other templates
|
||||
when sent via the SMTP notifier. It's *__strongly recommended__* that you do not modify this template unless you know
|
||||
what you're doing. If you really want to modify it the name of the file must be `Envelope.tmpl`.
|
||||
|
||||
This template contains the following placeholders:
|
||||
|
||||
In template files, you can use the following placeholders which are automatically injected into the templates:
|
||||
This template contains the following placeholders which are automatically injected into the template:
|
||||
|
||||
| Placeholder | Description |
|
||||
|:-----------------------:|:---------------------------------------------------------------------------:|
|
||||
|
@ -80,9 +92,6 @@ In template files, you can use the following placeholders which are automaticall
|
|||
| `{{ .To }}` | The string representation of the recipients email address. |
|
||||
| `{{ .Subject }}` | The email subject. |
|
||||
| `{{ .Date }}` | The time.Time of the email envelope being rendered. |
|
||||
| `{{ .Boundary }}` | The random alphanumeric 20 character multi-part email boundary. |
|
||||
| `{{ .Body.PlainText }}` | The plain text version of the email. |
|
||||
| `{{ .Body.HTML }}` | The HTML version of the email. |
|
||||
|
||||
## Original Templates
|
||||
|
||||
|
|
|
@ -4,18 +4,3 @@ Subject: {{ .Subject }}
|
|||
Date: {{ .Date.Format "Mon, 2 Jan 2006 15:04:05 -0700" }}
|
||||
Message-ID: <{{ .UUID }}@{{ .Identifier }}>
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/alternative; boundary="{{ .Boundary }}"
|
||||
|
||||
--{{ .Boundary }}
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Content-Disposition: inline
|
||||
|
||||
{{ .Body.PlainText }}
|
||||
{{- if not (eq .Body.HTML "") }}
|
||||
--{{ .Boundary }}
|
||||
Content-Type: text/html; charset="utf-8"
|
||||
|
||||
{{ .Body.HTML }}
|
||||
{{- end }}
|
||||
--{{ .Boundary }}--
|
||||
|
|
|
@ -11,10 +11,9 @@ import (
|
|||
|
||||
// NewDuoAPI create duo API instance.
|
||||
func NewDuoAPI(duoAPI *duoapi.DuoApi) *APIImpl {
|
||||
api := new(APIImpl)
|
||||
api.DuoApi = duoAPI
|
||||
|
||||
return api
|
||||
return &APIImpl{
|
||||
DuoApi: duoAPI,
|
||||
}
|
||||
}
|
||||
|
||||
// Call call to the DuoAPI.
|
||||
|
|
|
@ -74,8 +74,6 @@ func ResetPasswordPOST(ctx *middlewares.AutheliaCtx) {
|
|||
return
|
||||
}
|
||||
|
||||
bufHTML := new(bytes.Buffer)
|
||||
|
||||
disableHTML := false
|
||||
if ctx.Configuration.Notifier.SMTP != nil {
|
||||
disableHTML = ctx.Configuration.Notifier.SMTP.DisableHTMLEmails
|
||||
|
@ -87,6 +85,8 @@ func ResetPasswordPOST(ctx *middlewares.AutheliaCtx) {
|
|||
RemoteIP: ctx.RemoteIP().String(),
|
||||
}
|
||||
|
||||
bufHTML, bufText := &bytes.Buffer{}, &bytes.Buffer{}
|
||||
|
||||
if !disableHTML {
|
||||
if err = ctx.Providers.Templates.ExecuteEmailPasswordResetTemplate(bufHTML, values, templates.HTMLFormat); err != nil {
|
||||
ctx.Logger.Error(err)
|
||||
|
@ -96,8 +96,6 @@ func ResetPasswordPOST(ctx *middlewares.AutheliaCtx) {
|
|||
}
|
||||
}
|
||||
|
||||
bufText := new(bytes.Buffer)
|
||||
|
||||
if err = ctx.Providers.Templates.ExecuteEmailPasswordResetTemplate(bufText, values, templates.PlainTextFormat); err != nil {
|
||||
ctx.Logger.Error(err)
|
||||
ctx.ReplyOK()
|
||||
|
@ -110,7 +108,7 @@ func ResetPasswordPOST(ctx *middlewares.AutheliaCtx) {
|
|||
ctx.Logger.Debugf("Sending an email to user %s (%s) to inform that the password has changed.",
|
||||
username, addresses[0])
|
||||
|
||||
if err = ctx.Providers.Notifier.Send(addresses[0], "Password changed successfully", bufText.String(), bufHTML.String()); err != nil {
|
||||
if err = ctx.Providers.Notifier.Send(addresses[0], "Password changed successfully", bufText.Bytes(), bufHTML.Bytes()); err != nil {
|
||||
ctx.Logger.Error(err)
|
||||
ctx.ReplyOK()
|
||||
|
||||
|
|
|
@ -62,16 +62,15 @@ func IdentityVerificationStart(args IdentityVerificationStartArgs, delayFunc Tim
|
|||
return
|
||||
}
|
||||
|
||||
uri, err := ctx.ExternalRootURL()
|
||||
if err != nil {
|
||||
var (
|
||||
uri string
|
||||
)
|
||||
|
||||
if uri, err = ctx.ExternalRootURL(); err != nil {
|
||||
ctx.Error(err, messageOperationFailed)
|
||||
return
|
||||
}
|
||||
|
||||
link := fmt.Sprintf("%s%s?token=%s", uri, args.TargetEndpoint, ss)
|
||||
|
||||
bufHTML := new(bytes.Buffer)
|
||||
|
||||
disableHTML := false
|
||||
if ctx.Configuration.Notifier.SMTP != nil {
|
||||
disableHTML = ctx.Configuration.Notifier.SMTP.DisableHTMLEmails
|
||||
|
@ -79,12 +78,14 @@ func IdentityVerificationStart(args IdentityVerificationStartArgs, delayFunc Tim
|
|||
|
||||
values := templates.EmailIdentityVerificationValues{
|
||||
Title: args.MailTitle,
|
||||
LinkURL: link,
|
||||
LinkURL: fmt.Sprintf("%s%s?token=%s", uri, args.TargetEndpoint, ss),
|
||||
LinkText: args.MailButtonContent,
|
||||
DisplayName: identity.DisplayName,
|
||||
RemoteIP: ctx.RemoteIP().String(),
|
||||
}
|
||||
|
||||
bufHTML, bufText := &bytes.Buffer{}, &bytes.Buffer{}
|
||||
|
||||
if !disableHTML {
|
||||
if err = ctx.Providers.Templates.ExecuteEmailIdentityVerificationTemplate(bufHTML, values, templates.HTMLFormat); err != nil {
|
||||
ctx.Error(err, messageOperationFailed)
|
||||
|
@ -92,8 +93,6 @@ func IdentityVerificationStart(args IdentityVerificationStartArgs, delayFunc Tim
|
|||
}
|
||||
}
|
||||
|
||||
bufText := new(bytes.Buffer)
|
||||
|
||||
if err = ctx.Providers.Templates.ExecuteEmailIdentityVerificationTemplate(bufText, values, templates.PlainTextFormat); err != nil {
|
||||
ctx.Error(err, messageOperationFailed)
|
||||
return
|
||||
|
@ -102,7 +101,7 @@ func IdentityVerificationStart(args IdentityVerificationStartArgs, delayFunc Tim
|
|||
ctx.Logger.Debugf("Sending an email to user %s (%s) to confirm identity for registering a device.",
|
||||
identity.Username, identity.Email)
|
||||
|
||||
if err = ctx.Providers.Notifier.Send(mail.Address{Name: identity.DisplayName, Address: identity.Email}, args.MailTitle, bufText.String(), bufHTML.String()); err != nil {
|
||||
if err = ctx.Providers.Notifier.Send(mail.Address{Name: identity.DisplayName, Address: identity.Email}, args.MailTitle, bufText.Bytes(), bufHTML.Bytes()); err != nil {
|
||||
ctx.Error(err, messageOperationFailed)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ func (m *MockNotifier) EXPECT() *MockNotifierMockRecorder {
|
|||
}
|
||||
|
||||
// Send mocks base method.
|
||||
func (m *MockNotifier) Send(arg0 mail.Address, arg1, arg2, arg3 string) error {
|
||||
func (m *MockNotifier) Send(arg0 mail.Address, arg1 string, arg2, arg3 []byte) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Send", arg0, arg1, arg2, arg3)
|
||||
ret0, _ := ret[0].(error)
|
||||
|
|
|
@ -16,9 +16,30 @@ const (
|
|||
smtpCommandAUTH = "AUTH"
|
||||
smtpCommandMAIL = "MAIL"
|
||||
smtpCommandRCPT = "RCPT"
|
||||
|
||||
smtpEncodingQuotedPrintable = "quoted-printable"
|
||||
smtpEncoding8bit = "8bit"
|
||||
|
||||
smtpContentTypeTextPlain = "text/plain"
|
||||
smtpContentTypeTextHTML = "text/html"
|
||||
smtpFmtContentType = `%s; charset="UTF-8"`
|
||||
smtpFmtContentDispositionInline = "inline"
|
||||
|
||||
smtpExtSTARTTLS = smtpCommandSTARTTLS
|
||||
smtpExt8BITMIME = "8BITMIME"
|
||||
)
|
||||
|
||||
const (
|
||||
headerContentType = "Content-Type"
|
||||
headerContentDisposition = "Content-Disposition"
|
||||
headerContentTransferEncoding = "Content-Transfer-Encoding"
|
||||
)
|
||||
|
||||
const (
|
||||
fmtSMTPGenericError = "error performing %s with the SMTP server: %w"
|
||||
fmtSMTPDialError = "error dialing the SMTP server: %w"
|
||||
)
|
||||
|
||||
var (
|
||||
rfc2822DoubleNewLine = []byte("\r\n\r\n")
|
||||
)
|
||||
|
|
|
@ -43,8 +43,8 @@ func (n *FileNotifier) StartupCheck() (err error) {
|
|||
}
|
||||
|
||||
// Send send a identity verification link to a user.
|
||||
func (n *FileNotifier) Send(recipient mail.Address, subject, body, _ string) error {
|
||||
content := fmt.Sprintf("Date: %s\nRecipient: %s\nSubject: %s\nBody: %s", time.Now(), recipient, subject, body)
|
||||
func (n *FileNotifier) Send(recipient mail.Address, subject string, bodyText, _ []byte) error {
|
||||
content := fmt.Sprintf("Date: %s\nRecipient: %s\nSubject: %s\nBody: %s", time.Now(), recipient, subject, bodyText)
|
||||
|
||||
return os.WriteFile(n.path, []byte(content), fileNotifierMode)
|
||||
}
|
||||
|
|
|
@ -10,5 +10,5 @@ import (
|
|||
type Notifier interface {
|
||||
model.StartupCheck
|
||||
|
||||
Send(recipient mail.Address, subject, body, htmlBody string) (err error)
|
||||
Send(recipient mail.Address, subject string, bodyText, bodyHTML []byte) (err error)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net"
|
||||
"net/mail"
|
||||
"net/smtp"
|
||||
|
@ -52,7 +53,7 @@ type SMTPNotifier struct {
|
|||
}
|
||||
|
||||
// Send is used to email a recipient.
|
||||
func (n *SMTPNotifier) Send(recipient mail.Address, title, body, htmlBody string) (err error) {
|
||||
func (n *SMTPNotifier) Send(recipient mail.Address, subject string, bodyText, bodyHTML []byte) (err error) {
|
||||
if err = n.dial(); err != nil {
|
||||
return fmt.Errorf(fmtSMTPDialError, err)
|
||||
}
|
||||
|
@ -65,7 +66,7 @@ func (n *SMTPNotifier) Send(recipient mail.Address, title, body, htmlBody string
|
|||
}
|
||||
|
||||
// Compose and send the email body to the server.
|
||||
if err = n.compose(recipient, title, body, htmlBody); err != nil {
|
||||
if err = n.compose(recipient, subject, bodyText, bodyHTML); err != nil {
|
||||
return fmt.Errorf(fmtSMTPGenericError, smtpCommandDATA, err)
|
||||
}
|
||||
|
||||
|
@ -161,7 +162,7 @@ func (n *SMTPNotifier) startTLS() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
switch ok, _ := n.client.Extension("STARTTLS"); ok {
|
||||
switch ok, _ := n.client.Extension(smtpExtSTARTTLS); ok {
|
||||
case true:
|
||||
n.log.Debugf("Notifier SMTP server supports STARTTLS (disableVerifyCert: %t, ServerName: %s), attempting", n.tlsConfig.InsecureSkipVerify, n.tlsConfig.ServerName)
|
||||
|
||||
|
@ -237,7 +238,7 @@ func (n *SMTPNotifier) auth() (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (n *SMTPNotifier) compose(recipient mail.Address, title, body, htmlBody string) (err error) {
|
||||
func (n *SMTPNotifier) compose(recipient mail.Address, subject string, bodyText, bodyHTML []byte) (err error) {
|
||||
n.log.Debugf("Notifier SMTP client attempting to send email body to %s", recipient.String())
|
||||
|
||||
if !n.config.DisableRequireTLS {
|
||||
|
@ -261,7 +262,7 @@ func (n *SMTPNotifier) compose(recipient mail.Address, title, body, htmlBody str
|
|||
return err
|
||||
}
|
||||
|
||||
values := templates.EmailEnvelopeValues{
|
||||
data := templates.EmailEnvelopeValues{
|
||||
ProcessID: os.Getpid(),
|
||||
UUID: muuid.String(),
|
||||
Host: n.config.Host,
|
||||
|
@ -270,21 +271,43 @@ func (n *SMTPNotifier) compose(recipient mail.Address, title, body, htmlBody str
|
|||
Identifier: n.config.Identifier,
|
||||
From: n.config.Sender.String(),
|
||||
To: recipient.String(),
|
||||
Subject: strings.ReplaceAll(n.config.Subject, "{title}", title),
|
||||
Subject: strings.ReplaceAll(n.config.Subject, "{title}", subject),
|
||||
Date: time.Now(),
|
||||
Boundary: utils.RandomString(30, utils.AlphaNumericCharacters, true),
|
||||
Body: templates.EmailEnvelopeBodyValues{
|
||||
PlainText: body,
|
||||
HTML: htmlBody,
|
||||
},
|
||||
}
|
||||
|
||||
if err = n.templates.ExecuteEmailEnvelope(wc, values); err != nil {
|
||||
if err = n.templates.ExecuteEmailEnvelope(wc, data); err != nil {
|
||||
n.log.Debugf("Notifier SMTP client error while sending email body over WriteCloser: %v", err)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
mwr := multipart.NewWriter(wc)
|
||||
|
||||
if _, err = wc.Write([]byte(fmt.Sprintf(`Content-Type: multipart/alternative; boundary="%s"`, mwr.Boundary()))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = wc.Write(rfc2822DoubleNewLine); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ext8BITMIME, _ := n.client.Extension(smtpExt8BITMIME)
|
||||
|
||||
if err = multipartWrite(mwr, smtpMIMEHeaders(ext8BITMIME, smtpContentTypeTextPlain, bodyText), bodyText); err != nil {
|
||||
return fmt.Errorf("failed to write text/plain part: %w", err)
|
||||
}
|
||||
|
||||
if len(bodyHTML) != 0 {
|
||||
if err = multipartWrite(mwr,
|
||||
smtpMIMEHeaders(ext8BITMIME, smtpContentTypeTextHTML, bodyText), bodyHTML); err != nil {
|
||||
return fmt.Errorf("failed to write text/html part: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err = mwr.Close(); err != nil {
|
||||
return fmt.Errorf("failed to finalize the multipart content: %w", err)
|
||||
}
|
||||
|
||||
if err = wc.Close(); err != nil {
|
||||
n.log.Debugf("Notifier SMTP client error while closing the WriteCloser: %v", err)
|
||||
return err
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
package notification
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"mime/quotedprintable"
|
||||
"net/textproto"
|
||||
|
||||
"github.com/authelia/authelia/v4/internal/utils"
|
||||
)
|
||||
|
||||
func smtpMIMEHeaders(ext8BITMIME bool, contentType string, data []byte) textproto.MIMEHeader {
|
||||
headers := textproto.MIMEHeader{
|
||||
headerContentType: []string{fmt.Sprintf(smtpFmtContentType, contentType)},
|
||||
headerContentDisposition: []string{smtpFmtContentDispositionInline},
|
||||
}
|
||||
|
||||
characteristics := NewMIMECharacteristics(data)
|
||||
|
||||
if !ext8BITMIME || characteristics.LongLines || characteristics.Characters8BIT {
|
||||
headers.Set(headerContentTransferEncoding, smtpEncodingQuotedPrintable)
|
||||
} else {
|
||||
headers.Set(headerContentTransferEncoding, smtpEncoding8bit)
|
||||
}
|
||||
|
||||
return headers
|
||||
}
|
||||
|
||||
func multipartWrite(mwr *multipart.Writer, header textproto.MIMEHeader, data []byte) (err error) {
|
||||
var (
|
||||
wc io.WriteCloser
|
||||
wr io.Writer
|
||||
)
|
||||
|
||||
if wr, err = mwr.CreatePart(header); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch header.Get(headerContentTransferEncoding) {
|
||||
case smtpEncodingQuotedPrintable:
|
||||
wc = quotedprintable.NewWriter(wr)
|
||||
case smtpEncoding8bit, "":
|
||||
wc = utils.NewWriteCloser(wr)
|
||||
default:
|
||||
return fmt.Errorf("unknown encoding: %s", header.Get(headerContentTransferEncoding))
|
||||
}
|
||||
|
||||
if _, err = wc.Write(data); err != nil {
|
||||
_ = wc.Close()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
_ = wc.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewMIMECharacteristics detects the SMTP MIMECharacteristics for the given data bytes.
|
||||
func NewMIMECharacteristics(data []byte) MIMECharacteristics {
|
||||
characteristics := MIMECharacteristics{}
|
||||
|
||||
cl := 0
|
||||
|
||||
n := len(data)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
cl++
|
||||
|
||||
if cl > 1000 {
|
||||
characteristics.LongLines = true
|
||||
}
|
||||
|
||||
if data[i] == 10 {
|
||||
cl = 0
|
||||
|
||||
if i == 0 || data[i-1] != 13 {
|
||||
characteristics.LineFeeds = true
|
||||
}
|
||||
}
|
||||
|
||||
if data[i] >= 128 {
|
||||
characteristics.Characters8BIT = true
|
||||
}
|
||||
}
|
||||
|
||||
return characteristics
|
||||
}
|
||||
|
||||
// MIMECharacteristics represents specific MIME related characteristics.
|
||||
type MIMECharacteristics struct {
|
||||
LongLines bool
|
||||
LineFeeds bool
|
||||
Characters8BIT bool
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package templates
|
||||
|
||||
import (
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestShouldNotHaveDeprecatedPlaceholders(t *testing.T) {
|
||||
data, err := embedFS.ReadFile(path.Join("src", TemplateCategoryNotifications, TemplateNameEmailEnvelope))
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.False(t, tmplEnvelopeHasDeprecatedPlaceholders(data))
|
||||
}
|
|
@ -25,23 +25,33 @@ type Provider struct {
|
|||
}
|
||||
|
||||
// ExecuteEmailEnvelope writes the envelope template to the given io.Writer.
|
||||
func (p Provider) ExecuteEmailEnvelope(wr io.Writer, data EmailEnvelopeValues) (err error) {
|
||||
func (p *Provider) ExecuteEmailEnvelope(wr io.Writer, data EmailEnvelopeValues) (err error) {
|
||||
return p.templates.notification.envelope.Execute(wr, data)
|
||||
}
|
||||
|
||||
// ExecuteEmailPasswordResetTemplate writes the password reset template to the given io.Writer.
|
||||
func (p Provider) ExecuteEmailPasswordResetTemplate(wr io.Writer, data EmailPasswordResetValues, format Format) (err error) {
|
||||
func (p *Provider) ExecuteEmailPasswordResetTemplate(wr io.Writer, data EmailPasswordResetValues, format Format) (err error) {
|
||||
return p.templates.notification.passwordReset.Get(format).Execute(wr, data)
|
||||
}
|
||||
|
||||
// ExecuteEmailIdentityVerificationTemplate writes the identity verification template to the given io.Writer.
|
||||
func (p Provider) ExecuteEmailIdentityVerificationTemplate(wr io.Writer, data EmailIdentityVerificationValues, format Format) (err error) {
|
||||
func (p *Provider) ExecuteEmailIdentityVerificationTemplate(wr io.Writer, data EmailIdentityVerificationValues, format Format) (err error) {
|
||||
return p.templates.notification.identityVerification.Get(format).Execute(wr, data)
|
||||
}
|
||||
|
||||
func (p *Provider) load() (err error) {
|
||||
var errs []error
|
||||
|
||||
if tPath, embed, data, err := readTemplate(TemplateNameEmailEnvelope, TemplateCategoryNotifications, p.config.EmailTemplatesPath); err != nil {
|
||||
errs = append(errs, err)
|
||||
} else {
|
||||
if !embed && tmplEnvelopeHasDeprecatedPlaceholders(data) {
|
||||
errs = append(errs, fmt.Errorf("the evelope template override appears to contain removed placeholders"))
|
||||
} else if p.templates.notification.envelope, err = parseTemplate(TemplateNameEmailEnvelope, tPath, embed, data); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
if p.templates.notification.envelope, err = loadTemplate(TemplateNameEmailEnvelope, TemplateCategoryNotifications, p.config.EmailTemplatesPath); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
|
|
@ -3,18 +3,3 @@ To: {{ .To }}
|
|||
Subject: {{ .Subject }}
|
||||
Date: {{ .Date.Format "Mon, 2 Jan 2006 15:04:05 -0700" }}
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/alternative; boundary="{{ .Boundary }}"
|
||||
|
||||
--{{ .Boundary }}
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Content-Disposition: inline
|
||||
|
||||
{{ .Body.PlainText }}
|
||||
{{- if not (eq .Body.HTML "") }}
|
||||
--{{ .Boundary }}
|
||||
Content-Type: text/html; charset="utf-8"
|
||||
|
||||
{{ .Body.HTML }}
|
||||
{{- end }}
|
||||
--{{ .Boundary }}--
|
||||
|
|
|
@ -62,12 +62,4 @@ type EmailEnvelopeValues struct {
|
|||
To string
|
||||
Subject string
|
||||
Date time.Time
|
||||
Boundary string
|
||||
Body EmailEnvelopeBodyValues
|
||||
}
|
||||
|
||||
// EmailEnvelopeBodyValues are the values used for the email envelopes bodies.
|
||||
type EmailEnvelopeBodyValues struct {
|
||||
PlainText string
|
||||
HTML string
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package templates
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
@ -8,6 +9,12 @@ import (
|
|||
"text/template"
|
||||
)
|
||||
|
||||
func tmplEnvelopeHasDeprecatedPlaceholders(data []byte) bool {
|
||||
return bytes.Contains(data, []byte("{{ .Boundary }}")) ||
|
||||
bytes.Contains(data, []byte("{{ .Body.PlainText }}")) ||
|
||||
bytes.Contains(data, []byte("{{ .Body.HTML }}"))
|
||||
}
|
||||
|
||||
func templateExists(path string) (exists bool) {
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
|
@ -21,28 +28,51 @@ func templateExists(path string) (exists bool) {
|
|||
return true
|
||||
}
|
||||
|
||||
//nolint:unparam
|
||||
func loadTemplate(name, category, overridePath string) (t *template.Template, err error) {
|
||||
func readTemplate(name, category, overridePath string) (tPath string, embed bool, data []byte, err error) {
|
||||
if overridePath != "" {
|
||||
tPath := filepath.Join(overridePath, name)
|
||||
tPath = filepath.Join(overridePath, name)
|
||||
|
||||
if templateExists(tPath) {
|
||||
if t, err = template.ParseFiles(tPath); err != nil {
|
||||
return nil, fmt.Errorf("could not parse template at path '%s': %w", tPath, err)
|
||||
if data, err = os.ReadFile(tPath); err != nil {
|
||||
return tPath, false, nil, fmt.Errorf("failed to read template override at path '%s': %w", tPath, err)
|
||||
}
|
||||
|
||||
return t, nil
|
||||
return tPath, false, data, nil
|
||||
}
|
||||
}
|
||||
|
||||
data, err := embedFS.ReadFile(path.Join("src", category, name))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
tPath = path.Join("src", category, name)
|
||||
|
||||
if data, err = embedFS.ReadFile(tPath); err != nil {
|
||||
return tPath, true, nil, fmt.Errorf("failed to read embedded template '%s': %w", tPath, err)
|
||||
}
|
||||
|
||||
return tPath, true, data, nil
|
||||
}
|
||||
|
||||
func parseTemplate(name, tPath string, embed bool, data []byte) (t *template.Template, err error) {
|
||||
if t, err = template.New(name).Parse(string(data)); err != nil {
|
||||
panic(fmt.Errorf("failed to parse internal template: %w", err))
|
||||
if embed {
|
||||
return nil, fmt.Errorf("failed to parse embedded template '%s': %w", tPath, err)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("failed to parse template override at path '%s': %w", tPath, err)
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
//nolint:unparam
|
||||
func loadTemplate(name, category, overridePath string) (t *template.Template, err error) {
|
||||
var (
|
||||
embed bool
|
||||
tPath string
|
||||
data []byte
|
||||
)
|
||||
|
||||
if tPath, embed, data, err = readTemplate(name, category, overridePath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return parseTemplate(name, tPath, embed, data)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
// NewWriteCloser creates a new io.WriteCloser from an io.Writer.
|
||||
func NewWriteCloser(wr io.Writer) io.WriteCloser {
|
||||
return &WriteCloser{wr: wr}
|
||||
}
|
||||
|
||||
// WriteCloser is a io.Writer with an io.Closer.
|
||||
type WriteCloser struct {
|
||||
wr io.Writer
|
||||
|
||||
closed bool
|
||||
}
|
||||
|
||||
// Write to the io.Writer.
|
||||
func (w *WriteCloser) Write(p []byte) (n int, err error) {
|
||||
if w.closed {
|
||||
return -1, errors.New("already closed")
|
||||
}
|
||||
|
||||
return w.wr.Write(p)
|
||||
}
|
||||
|
||||
// Close the io.Closer.
|
||||
func (w *WriteCloser) Close() error {
|
||||
w.closed = true
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,129 +1,129 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="US_UK_Download_on_the" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px" y="0px" width="135px" height="40px" viewBox="0 0 135 40" enable-background="new 0 0 135 40" xml:space="preserve">
|
||||
<g>
|
||||
<path fill="#A6A6A6" d="M130.197,40H4.729C2.122,40,0,37.872,0,35.267V4.726C0,2.12,2.122,0,4.729,0h125.468
|
||||
C132.803,0,135,2.12,135,4.726v30.541C135,37.872,132.803,40,130.197,40L130.197,40z"/>
|
||||
<path d="M134.032,35.268c0,2.116-1.714,3.83-3.834,3.83H4.729c-2.119,0-3.839-1.714-3.839-3.83V4.725
|
||||
c0-2.115,1.72-3.835,3.839-3.835h125.468c2.121,0,3.834,1.72,3.834,3.835L134.032,35.268L134.032,35.268z"/>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M30.128,19.784c-0.029-3.223,2.639-4.791,2.761-4.864c-1.511-2.203-3.853-2.504-4.676-2.528
|
||||
c-1.967-0.207-3.875,1.177-4.877,1.177c-1.022,0-2.565-1.157-4.228-1.123c-2.14,0.033-4.142,1.272-5.24,3.196
|
||||
c-2.266,3.923-0.576,9.688,1.595,12.859c1.086,1.553,2.355,3.287,4.016,3.226c1.625-0.067,2.232-1.036,4.193-1.036
|
||||
c1.943,0,2.513,1.036,4.207,0.997c1.744-0.028,2.842-1.56,3.89-3.127c1.255-1.78,1.759-3.533,1.779-3.623
|
||||
C33.507,24.924,30.161,23.647,30.128,19.784z"/>
|
||||
<path fill="#FFFFFF" d="M26.928,10.306c0.874-1.093,1.472-2.58,1.306-4.089c-1.265,0.056-2.847,0.875-3.758,1.944
|
||||
c-0.806,0.942-1.526,2.486-1.34,3.938C24.557,12.205,26.016,11.382,26.928,10.306z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M53.645,31.504h-2.271l-1.244-3.909h-4.324l-1.185,3.909h-2.211l4.284-13.308h2.646L53.645,31.504z
|
||||
M49.755,25.955L48.63,22.48c-0.119-0.355-0.342-1.191-0.671-2.507h-0.04c-0.131,0.566-0.342,1.402-0.632,2.507l-1.105,3.475
|
||||
H49.755z"/>
|
||||
<path fill="#FFFFFF" d="M64.662,26.588c0,1.632-0.441,2.922-1.323,3.869c-0.79,0.843-1.771,1.264-2.942,1.264
|
||||
c-1.264,0-2.172-0.454-2.725-1.362h-0.04v5.055h-2.132V25.067c0-1.026-0.027-2.079-0.079-3.159h1.875l0.119,1.521h0.04
|
||||
c0.711-1.146,1.79-1.718,3.238-1.718c1.132,0,2.077,0.447,2.833,1.342C64.284,23.949,64.662,25.127,64.662,26.588z M62.49,26.666
|
||||
c0-0.934-0.21-1.704-0.632-2.31c-0.461-0.632-1.08-0.948-1.856-0.948c-0.526,0-1.004,0.176-1.431,0.523
|
||||
c-0.428,0.35-0.708,0.807-0.839,1.373c-0.066,0.264-0.099,0.48-0.099,0.65v1.6c0,0.698,0.214,1.287,0.642,1.768
|
||||
s0.984,0.721,1.668,0.721c0.803,0,1.428-0.31,1.875-0.928C62.266,28.496,62.49,27.68,62.49,26.666z"/>
|
||||
<path fill="#FFFFFF" d="M75.699,26.588c0,1.632-0.441,2.922-1.324,3.869c-0.789,0.843-1.77,1.264-2.941,1.264
|
||||
c-1.264,0-2.172-0.454-2.724-1.362H68.67v5.055h-2.132V25.067c0-1.026-0.027-2.079-0.079-3.159h1.875l0.119,1.521h0.04
|
||||
c0.71-1.146,1.789-1.718,3.238-1.718c1.131,0,2.076,0.447,2.834,1.342C75.32,23.949,75.699,25.127,75.699,26.588z M73.527,26.666
|
||||
c0-0.934-0.211-1.704-0.633-2.31c-0.461-0.632-1.078-0.948-1.855-0.948c-0.527,0-1.004,0.176-1.432,0.523
|
||||
c-0.428,0.35-0.707,0.807-0.838,1.373c-0.065,0.264-0.099,0.48-0.099,0.65v1.6c0,0.698,0.214,1.287,0.64,1.768
|
||||
c0.428,0.48,0.984,0.721,1.67,0.721c0.803,0,1.428-0.31,1.875-0.928C73.303,28.496,73.527,27.68,73.527,26.666z"/>
|
||||
<path fill="#FFFFFF" d="M88.039,27.772c0,1.132-0.393,2.053-1.182,2.764c-0.867,0.777-2.074,1.165-3.625,1.165
|
||||
c-1.432,0-2.58-0.276-3.449-0.829l0.494-1.777c0.936,0.566,1.963,0.85,3.082,0.85c0.803,0,1.428-0.182,1.877-0.544
|
||||
c0.447-0.362,0.67-0.848,0.67-1.454c0-0.54-0.184-0.995-0.553-1.364c-0.367-0.369-0.98-0.712-1.836-1.029
|
||||
c-2.33-0.869-3.494-2.142-3.494-3.816c0-1.094,0.408-1.991,1.225-2.689c0.814-0.699,1.9-1.048,3.258-1.048
|
||||
c1.211,0,2.217,0.211,3.02,0.632l-0.533,1.738c-0.75-0.408-1.598-0.612-2.547-0.612c-0.75,0-1.336,0.185-1.756,0.553
|
||||
c-0.355,0.329-0.533,0.73-0.533,1.205c0,0.526,0.203,0.961,0.611,1.303c0.355,0.316,1,0.658,1.936,1.027
|
||||
c1.145,0.461,1.986,1,2.527,1.618C87.77,26.081,88.039,26.852,88.039,27.772z"/>
|
||||
<path fill="#FFFFFF" d="M95.088,23.508h-2.35v4.659c0,1.185,0.414,1.777,1.244,1.777c0.381,0,0.697-0.033,0.947-0.099l0.059,1.619
|
||||
c-0.42,0.157-0.973,0.236-1.658,0.236c-0.842,0-1.5-0.257-1.975-0.77c-0.473-0.514-0.711-1.376-0.711-2.587v-4.837h-1.4v-1.6h1.4
|
||||
v-1.757l2.094-0.632v2.389h2.35V23.508z"/>
|
||||
<path fill="#FFFFFF" d="M105.691,26.627c0,1.475-0.422,2.686-1.264,3.633c-0.883,0.975-2.055,1.461-3.516,1.461
|
||||
c-1.408,0-2.529-0.467-3.365-1.401s-1.254-2.113-1.254-3.534c0-1.487,0.43-2.705,1.293-3.652c0.861-0.948,2.023-1.422,3.484-1.422
|
||||
c1.408,0,2.541,0.467,3.396,1.402C105.283,24.021,105.691,25.192,105.691,26.627z M103.479,26.696
|
||||
c0-0.885-0.189-1.644-0.572-2.277c-0.447-0.766-1.086-1.148-1.914-1.148c-0.857,0-1.508,0.383-1.955,1.148
|
||||
c-0.383,0.634-0.572,1.405-0.572,2.317c0,0.885,0.189,1.644,0.572,2.276c0.461,0.766,1.105,1.148,1.936,1.148
|
||||
c0.814,0,1.453-0.39,1.914-1.168C103.281,28.347,103.479,27.58,103.479,26.696z"/>
|
||||
<path fill="#FFFFFF" d="M112.621,23.783c-0.211-0.039-0.436-0.059-0.672-0.059c-0.75,0-1.33,0.283-1.738,0.85
|
||||
c-0.355,0.5-0.533,1.132-0.533,1.895v5.035h-2.131l0.02-6.574c0-1.106-0.027-2.113-0.08-3.021h1.857l0.078,1.836h0.059
|
||||
c0.225-0.631,0.58-1.139,1.066-1.52c0.475-0.343,0.988-0.514,1.541-0.514c0.197,0,0.375,0.014,0.533,0.039V23.783z"/>
|
||||
<path fill="#FFFFFF" d="M122.156,26.252c0,0.382-0.025,0.704-0.078,0.967h-6.396c0.025,0.948,0.334,1.673,0.928,2.173
|
||||
c0.539,0.447,1.236,0.671,2.092,0.671c0.947,0,1.811-0.151,2.588-0.454l0.334,1.48c-0.908,0.396-1.98,0.593-3.217,0.593
|
||||
c-1.488,0-2.656-0.438-3.506-1.313c-0.848-0.875-1.273-2.05-1.273-3.524c0-1.447,0.395-2.652,1.186-3.613
|
||||
c0.828-1.026,1.947-1.539,3.355-1.539c1.383,0,2.43,0.513,3.141,1.539C121.873,24.047,122.156,25.055,122.156,26.252z
|
||||
M120.123,25.699c0.014-0.632-0.125-1.178-0.414-1.639c-0.369-0.593-0.936-0.889-1.699-0.889c-0.697,0-1.264,0.289-1.697,0.869
|
||||
c-0.355,0.461-0.566,1.014-0.631,1.658H120.123z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M49.05,10.009c0,1.177-0.353,2.063-1.058,2.658c-0.653,0.549-1.581,0.824-2.783,0.824
|
||||
c-0.596,0-1.106-0.026-1.533-0.078V6.982c0.557-0.09,1.157-0.136,1.805-0.136c1.145,0,2.008,0.249,2.59,0.747
|
||||
C48.723,8.156,49.05,8.961,49.05,10.009z M47.945,10.038c0-0.763-0.202-1.348-0.606-1.756c-0.404-0.407-0.994-0.611-1.771-0.611
|
||||
c-0.33,0-0.611,0.022-0.844,0.068v4.889c0.129,0.02,0.365,0.029,0.708,0.029c0.802,0,1.421-0.223,1.857-0.669
|
||||
S47.945,10.892,47.945,10.038z"/>
|
||||
<path fill="#FFFFFF" d="M54.909,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.009,0.718-1.727,0.718
|
||||
c-0.692,0-1.243-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.712-0.698
|
||||
c0.692,0,1.248,0.229,1.669,0.688C54.708,9.757,54.909,10.333,54.909,11.037z M53.822,11.071c0-0.435-0.094-0.808-0.281-1.119
|
||||
c-0.22-0.376-0.533-0.564-0.94-0.564c-0.421,0-0.741,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
|
||||
c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.714-0.191,0.94-0.574
|
||||
C53.725,11.882,53.822,11.506,53.822,11.071z"/>
|
||||
<path fill="#FFFFFF" d="M62.765,8.719l-1.475,4.714h-0.96l-0.611-2.047c-0.155-0.511-0.281-1.019-0.379-1.523h-0.019
|
||||
c-0.091,0.518-0.217,1.025-0.379,1.523l-0.649,2.047h-0.971l-1.387-4.714h1.077l0.533,2.241c0.129,0.53,0.235,1.035,0.32,1.513
|
||||
h0.019c0.078-0.394,0.207-0.896,0.389-1.503l0.669-2.25h0.854l0.641,2.202c0.155,0.537,0.281,1.054,0.378,1.552h0.029
|
||||
c0.071-0.485,0.178-1.002,0.32-1.552l0.572-2.202H62.765z"/>
|
||||
<path fill="#FFFFFF" d="M68.198,13.433H67.15v-2.7c0-0.832-0.316-1.248-0.95-1.248c-0.311,0-0.562,0.114-0.757,0.343
|
||||
c-0.193,0.229-0.291,0.499-0.291,0.808v2.796h-1.048v-3.366c0-0.414-0.013-0.863-0.038-1.349h0.921l0.049,0.737h0.029
|
||||
c0.122-0.229,0.304-0.418,0.543-0.569c0.284-0.176,0.602-0.265,0.95-0.265c0.44,0,0.806,0.142,1.097,0.427
|
||||
c0.362,0.349,0.543,0.87,0.543,1.562V13.433z"/>
|
||||
<path fill="#FFFFFF" d="M71.088,13.433h-1.047V6.556h1.047V13.433z"/>
|
||||
<path fill="#FFFFFF" d="M77.258,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.01,0.718-1.727,0.718
|
||||
c-0.693,0-1.244-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.711-0.698
|
||||
c0.693,0,1.248,0.229,1.67,0.688C77.057,9.757,77.258,10.333,77.258,11.037z M76.17,11.071c0-0.435-0.094-0.808-0.281-1.119
|
||||
c-0.219-0.376-0.533-0.564-0.939-0.564c-0.422,0-0.742,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
|
||||
c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.713-0.191,0.939-0.574
|
||||
C76.074,11.882,76.17,11.506,76.17,11.071z"/>
|
||||
<path fill="#FFFFFF" d="M82.33,13.433h-0.941l-0.078-0.543h-0.029c-0.322,0.433-0.781,0.65-1.377,0.65
|
||||
c-0.445,0-0.805-0.143-1.076-0.427c-0.246-0.258-0.369-0.579-0.369-0.96c0-0.576,0.24-1.015,0.723-1.319
|
||||
c0.482-0.304,1.16-0.453,2.033-0.446V10.3c0-0.621-0.326-0.931-0.979-0.931c-0.465,0-0.875,0.117-1.229,0.349l-0.213-0.688
|
||||
c0.438-0.271,0.979-0.407,1.617-0.407c1.232,0,1.85,0.65,1.85,1.95v1.736C82.262,12.78,82.285,13.155,82.33,13.433z
|
||||
M81.242,11.813v-0.727c-1.156-0.02-1.734,0.297-1.734,0.95c0,0.246,0.066,0.43,0.201,0.553c0.135,0.123,0.307,0.184,0.512,0.184
|
||||
c0.23,0,0.445-0.073,0.641-0.218c0.197-0.146,0.318-0.331,0.363-0.558C81.236,11.946,81.242,11.884,81.242,11.813z"/>
|
||||
<path fill="#FFFFFF" d="M88.285,13.433h-0.93l-0.049-0.757h-0.029c-0.297,0.576-0.803,0.864-1.514,0.864
|
||||
c-0.568,0-1.041-0.223-1.416-0.669s-0.562-1.025-0.562-1.736c0-0.763,0.203-1.381,0.611-1.853c0.395-0.44,0.879-0.66,1.455-0.66
|
||||
c0.633,0,1.076,0.213,1.328,0.64h0.02V6.556h1.049v5.607C88.248,12.622,88.26,13.045,88.285,13.433z M87.199,11.445v-0.786
|
||||
c0-0.136-0.01-0.246-0.029-0.33c-0.059-0.252-0.186-0.464-0.379-0.635c-0.195-0.171-0.43-0.257-0.701-0.257
|
||||
c-0.391,0-0.697,0.155-0.922,0.466c-0.223,0.311-0.336,0.708-0.336,1.193c0,0.466,0.107,0.844,0.322,1.135
|
||||
c0.227,0.31,0.533,0.465,0.916,0.465c0.344,0,0.619-0.129,0.828-0.388C87.1,12.069,87.199,11.781,87.199,11.445z"/>
|
||||
<path fill="#FFFFFF" d="M97.248,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.008,0.718-1.727,0.718
|
||||
c-0.691,0-1.242-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.713-0.698
|
||||
c0.691,0,1.248,0.229,1.668,0.688C97.047,9.757,97.248,10.333,97.248,11.037z M96.162,11.071c0-0.435-0.094-0.808-0.281-1.119
|
||||
c-0.221-0.376-0.533-0.564-0.941-0.564c-0.42,0-0.74,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
|
||||
c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.715-0.191,0.941-0.574
|
||||
C96.064,11.882,96.162,11.506,96.162,11.071z"/>
|
||||
<path fill="#FFFFFF" d="M102.883,13.433h-1.047v-2.7c0-0.832-0.316-1.248-0.951-1.248c-0.311,0-0.562,0.114-0.756,0.343
|
||||
s-0.291,0.499-0.291,0.808v2.796h-1.049v-3.366c0-0.414-0.012-0.863-0.037-1.349h0.92l0.049,0.737h0.029
|
||||
c0.123-0.229,0.305-0.418,0.543-0.569c0.285-0.176,0.602-0.265,0.951-0.265c0.439,0,0.805,0.142,1.096,0.427
|
||||
c0.363,0.349,0.543,0.87,0.543,1.562V13.433z"/>
|
||||
<path fill="#FFFFFF" d="M109.936,9.504h-1.154v2.29c0,0.582,0.205,0.873,0.611,0.873c0.188,0,0.344-0.016,0.467-0.049
|
||||
l0.027,0.795c-0.207,0.078-0.479,0.117-0.814,0.117c-0.414,0-0.736-0.126-0.969-0.378c-0.234-0.252-0.35-0.676-0.35-1.271V9.504
|
||||
h-0.689V8.719h0.689V7.855l1.027-0.31v1.173h1.154V9.504z"/>
|
||||
<path fill="#FFFFFF" d="M115.484,13.433h-1.049v-2.68c0-0.845-0.316-1.268-0.949-1.268c-0.486,0-0.818,0.245-1,0.735
|
||||
c-0.031,0.103-0.049,0.229-0.049,0.377v2.835h-1.047V6.556h1.047v2.841h0.02c0.33-0.517,0.803-0.775,1.416-0.775
|
||||
c0.434,0,0.793,0.142,1.078,0.427c0.355,0.355,0.533,0.883,0.533,1.581V13.433z"/>
|
||||
<path fill="#FFFFFF" d="M121.207,10.853c0,0.188-0.014,0.346-0.039,0.475h-3.143c0.014,0.466,0.164,0.821,0.455,1.067
|
||||
c0.266,0.22,0.609,0.33,1.029,0.33c0.465,0,0.889-0.074,1.271-0.223l0.164,0.728c-0.447,0.194-0.973,0.291-1.582,0.291
|
||||
c-0.73,0-1.305-0.215-1.721-0.645c-0.418-0.43-0.625-1.007-0.625-1.731c0-0.711,0.193-1.303,0.582-1.775
|
||||
c0.406-0.504,0.955-0.756,1.648-0.756c0.678,0,1.193,0.252,1.541,0.756C121.068,9.77,121.207,10.265,121.207,10.853z
|
||||
M120.207,10.582c0.008-0.311-0.061-0.579-0.203-0.805c-0.182-0.291-0.459-0.437-0.834-0.437c-0.342,0-0.621,0.142-0.834,0.427
|
||||
c-0.174,0.227-0.277,0.498-0.311,0.815H120.207z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="US_UK_Download_on_the" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px" y="0px" width="135px" height="40px" viewBox="0 0 135 40" enable-background="new 0 0 135 40" xml:space="preserve">
|
||||
<g>
|
||||
<path fill="#A6A6A6" d="M130.197,40H4.729C2.122,40,0,37.872,0,35.267V4.726C0,2.12,2.122,0,4.729,0h125.468
|
||||
C132.803,0,135,2.12,135,4.726v30.541C135,37.872,132.803,40,130.197,40L130.197,40z"/>
|
||||
<path d="M134.032,35.268c0,2.116-1.714,3.83-3.834,3.83H4.729c-2.119,0-3.839-1.714-3.839-3.83V4.725
|
||||
c0-2.115,1.72-3.835,3.839-3.835h125.468c2.121,0,3.834,1.72,3.834,3.835L134.032,35.268L134.032,35.268z"/>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M30.128,19.784c-0.029-3.223,2.639-4.791,2.761-4.864c-1.511-2.203-3.853-2.504-4.676-2.528
|
||||
c-1.967-0.207-3.875,1.177-4.877,1.177c-1.022,0-2.565-1.157-4.228-1.123c-2.14,0.033-4.142,1.272-5.24,3.196
|
||||
c-2.266,3.923-0.576,9.688,1.595,12.859c1.086,1.553,2.355,3.287,4.016,3.226c1.625-0.067,2.232-1.036,4.193-1.036
|
||||
c1.943,0,2.513,1.036,4.207,0.997c1.744-0.028,2.842-1.56,3.89-3.127c1.255-1.78,1.759-3.533,1.779-3.623
|
||||
C33.507,24.924,30.161,23.647,30.128,19.784z"/>
|
||||
<path fill="#FFFFFF" d="M26.928,10.306c0.874-1.093,1.472-2.58,1.306-4.089c-1.265,0.056-2.847,0.875-3.758,1.944
|
||||
c-0.806,0.942-1.526,2.486-1.34,3.938C24.557,12.205,26.016,11.382,26.928,10.306z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M53.645,31.504h-2.271l-1.244-3.909h-4.324l-1.185,3.909h-2.211l4.284-13.308h2.646L53.645,31.504z
|
||||
M49.755,25.955L48.63,22.48c-0.119-0.355-0.342-1.191-0.671-2.507h-0.04c-0.131,0.566-0.342,1.402-0.632,2.507l-1.105,3.475
|
||||
H49.755z"/>
|
||||
<path fill="#FFFFFF" d="M64.662,26.588c0,1.632-0.441,2.922-1.323,3.869c-0.79,0.843-1.771,1.264-2.942,1.264
|
||||
c-1.264,0-2.172-0.454-2.725-1.362h-0.04v5.055h-2.132V25.067c0-1.026-0.027-2.079-0.079-3.159h1.875l0.119,1.521h0.04
|
||||
c0.711-1.146,1.79-1.718,3.238-1.718c1.132,0,2.077,0.447,2.833,1.342C64.284,23.949,64.662,25.127,64.662,26.588z M62.49,26.666
|
||||
c0-0.934-0.21-1.704-0.632-2.31c-0.461-0.632-1.08-0.948-1.856-0.948c-0.526,0-1.004,0.176-1.431,0.523
|
||||
c-0.428,0.35-0.708,0.807-0.839,1.373c-0.066,0.264-0.099,0.48-0.099,0.65v1.6c0,0.698,0.214,1.287,0.642,1.768
|
||||
s0.984,0.721,1.668,0.721c0.803,0,1.428-0.31,1.875-0.928C62.266,28.496,62.49,27.68,62.49,26.666z"/>
|
||||
<path fill="#FFFFFF" d="M75.699,26.588c0,1.632-0.441,2.922-1.324,3.869c-0.789,0.843-1.77,1.264-2.941,1.264
|
||||
c-1.264,0-2.172-0.454-2.724-1.362H68.67v5.055h-2.132V25.067c0-1.026-0.027-2.079-0.079-3.159h1.875l0.119,1.521h0.04
|
||||
c0.71-1.146,1.789-1.718,3.238-1.718c1.131,0,2.076,0.447,2.834,1.342C75.32,23.949,75.699,25.127,75.699,26.588z M73.527,26.666
|
||||
c0-0.934-0.211-1.704-0.633-2.31c-0.461-0.632-1.078-0.948-1.855-0.948c-0.527,0-1.004,0.176-1.432,0.523
|
||||
c-0.428,0.35-0.707,0.807-0.838,1.373c-0.065,0.264-0.099,0.48-0.099,0.65v1.6c0,0.698,0.214,1.287,0.64,1.768
|
||||
c0.428,0.48,0.984,0.721,1.67,0.721c0.803,0,1.428-0.31,1.875-0.928C73.303,28.496,73.527,27.68,73.527,26.666z"/>
|
||||
<path fill="#FFFFFF" d="M88.039,27.772c0,1.132-0.393,2.053-1.182,2.764c-0.867,0.777-2.074,1.165-3.625,1.165
|
||||
c-1.432,0-2.58-0.276-3.449-0.829l0.494-1.777c0.936,0.566,1.963,0.85,3.082,0.85c0.803,0,1.428-0.182,1.877-0.544
|
||||
c0.447-0.362,0.67-0.848,0.67-1.454c0-0.54-0.184-0.995-0.553-1.364c-0.367-0.369-0.98-0.712-1.836-1.029
|
||||
c-2.33-0.869-3.494-2.142-3.494-3.816c0-1.094,0.408-1.991,1.225-2.689c0.814-0.699,1.9-1.048,3.258-1.048
|
||||
c1.211,0,2.217,0.211,3.02,0.632l-0.533,1.738c-0.75-0.408-1.598-0.612-2.547-0.612c-0.75,0-1.336,0.185-1.756,0.553
|
||||
c-0.355,0.329-0.533,0.73-0.533,1.205c0,0.526,0.203,0.961,0.611,1.303c0.355,0.316,1,0.658,1.936,1.027
|
||||
c1.145,0.461,1.986,1,2.527,1.618C87.77,26.081,88.039,26.852,88.039,27.772z"/>
|
||||
<path fill="#FFFFFF" d="M95.088,23.508h-2.35v4.659c0,1.185,0.414,1.777,1.244,1.777c0.381,0,0.697-0.033,0.947-0.099l0.059,1.619
|
||||
c-0.42,0.157-0.973,0.236-1.658,0.236c-0.842,0-1.5-0.257-1.975-0.77c-0.473-0.514-0.711-1.376-0.711-2.587v-4.837h-1.4v-1.6h1.4
|
||||
v-1.757l2.094-0.632v2.389h2.35V23.508z"/>
|
||||
<path fill="#FFFFFF" d="M105.691,26.627c0,1.475-0.422,2.686-1.264,3.633c-0.883,0.975-2.055,1.461-3.516,1.461
|
||||
c-1.408,0-2.529-0.467-3.365-1.401s-1.254-2.113-1.254-3.534c0-1.487,0.43-2.705,1.293-3.652c0.861-0.948,2.023-1.422,3.484-1.422
|
||||
c1.408,0,2.541,0.467,3.396,1.402C105.283,24.021,105.691,25.192,105.691,26.627z M103.479,26.696
|
||||
c0-0.885-0.189-1.644-0.572-2.277c-0.447-0.766-1.086-1.148-1.914-1.148c-0.857,0-1.508,0.383-1.955,1.148
|
||||
c-0.383,0.634-0.572,1.405-0.572,2.317c0,0.885,0.189,1.644,0.572,2.276c0.461,0.766,1.105,1.148,1.936,1.148
|
||||
c0.814,0,1.453-0.39,1.914-1.168C103.281,28.347,103.479,27.58,103.479,26.696z"/>
|
||||
<path fill="#FFFFFF" d="M112.621,23.783c-0.211-0.039-0.436-0.059-0.672-0.059c-0.75,0-1.33,0.283-1.738,0.85
|
||||
c-0.355,0.5-0.533,1.132-0.533,1.895v5.035h-2.131l0.02-6.574c0-1.106-0.027-2.113-0.08-3.021h1.857l0.078,1.836h0.059
|
||||
c0.225-0.631,0.58-1.139,1.066-1.52c0.475-0.343,0.988-0.514,1.541-0.514c0.197,0,0.375,0.014,0.533,0.039V23.783z"/>
|
||||
<path fill="#FFFFFF" d="M122.156,26.252c0,0.382-0.025,0.704-0.078,0.967h-6.396c0.025,0.948,0.334,1.673,0.928,2.173
|
||||
c0.539,0.447,1.236,0.671,2.092,0.671c0.947,0,1.811-0.151,2.588-0.454l0.334,1.48c-0.908,0.396-1.98,0.593-3.217,0.593
|
||||
c-1.488,0-2.656-0.438-3.506-1.313c-0.848-0.875-1.273-2.05-1.273-3.524c0-1.447,0.395-2.652,1.186-3.613
|
||||
c0.828-1.026,1.947-1.539,3.355-1.539c1.383,0,2.43,0.513,3.141,1.539C121.873,24.047,122.156,25.055,122.156,26.252z
|
||||
M120.123,25.699c0.014-0.632-0.125-1.178-0.414-1.639c-0.369-0.593-0.936-0.889-1.699-0.889c-0.697,0-1.264,0.289-1.697,0.869
|
||||
c-0.355,0.461-0.566,1.014-0.631,1.658H120.123z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M49.05,10.009c0,1.177-0.353,2.063-1.058,2.658c-0.653,0.549-1.581,0.824-2.783,0.824
|
||||
c-0.596,0-1.106-0.026-1.533-0.078V6.982c0.557-0.09,1.157-0.136,1.805-0.136c1.145,0,2.008,0.249,2.59,0.747
|
||||
C48.723,8.156,49.05,8.961,49.05,10.009z M47.945,10.038c0-0.763-0.202-1.348-0.606-1.756c-0.404-0.407-0.994-0.611-1.771-0.611
|
||||
c-0.33,0-0.611,0.022-0.844,0.068v4.889c0.129,0.02,0.365,0.029,0.708,0.029c0.802,0,1.421-0.223,1.857-0.669
|
||||
S47.945,10.892,47.945,10.038z"/>
|
||||
<path fill="#FFFFFF" d="M54.909,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.009,0.718-1.727,0.718
|
||||
c-0.692,0-1.243-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.712-0.698
|
||||
c0.692,0,1.248,0.229,1.669,0.688C54.708,9.757,54.909,10.333,54.909,11.037z M53.822,11.071c0-0.435-0.094-0.808-0.281-1.119
|
||||
c-0.22-0.376-0.533-0.564-0.94-0.564c-0.421,0-0.741,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
|
||||
c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.714-0.191,0.94-0.574
|
||||
C53.725,11.882,53.822,11.506,53.822,11.071z"/>
|
||||
<path fill="#FFFFFF" d="M62.765,8.719l-1.475,4.714h-0.96l-0.611-2.047c-0.155-0.511-0.281-1.019-0.379-1.523h-0.019
|
||||
c-0.091,0.518-0.217,1.025-0.379,1.523l-0.649,2.047h-0.971l-1.387-4.714h1.077l0.533,2.241c0.129,0.53,0.235,1.035,0.32,1.513
|
||||
h0.019c0.078-0.394,0.207-0.896,0.389-1.503l0.669-2.25h0.854l0.641,2.202c0.155,0.537,0.281,1.054,0.378,1.552h0.029
|
||||
c0.071-0.485,0.178-1.002,0.32-1.552l0.572-2.202H62.765z"/>
|
||||
<path fill="#FFFFFF" d="M68.198,13.433H67.15v-2.7c0-0.832-0.316-1.248-0.95-1.248c-0.311,0-0.562,0.114-0.757,0.343
|
||||
c-0.193,0.229-0.291,0.499-0.291,0.808v2.796h-1.048v-3.366c0-0.414-0.013-0.863-0.038-1.349h0.921l0.049,0.737h0.029
|
||||
c0.122-0.229,0.304-0.418,0.543-0.569c0.284-0.176,0.602-0.265,0.95-0.265c0.44,0,0.806,0.142,1.097,0.427
|
||||
c0.362,0.349,0.543,0.87,0.543,1.562V13.433z"/>
|
||||
<path fill="#FFFFFF" d="M71.088,13.433h-1.047V6.556h1.047V13.433z"/>
|
||||
<path fill="#FFFFFF" d="M77.258,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.01,0.718-1.727,0.718
|
||||
c-0.693,0-1.244-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.711-0.698
|
||||
c0.693,0,1.248,0.229,1.67,0.688C77.057,9.757,77.258,10.333,77.258,11.037z M76.17,11.071c0-0.435-0.094-0.808-0.281-1.119
|
||||
c-0.219-0.376-0.533-0.564-0.939-0.564c-0.422,0-0.742,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
|
||||
c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.713-0.191,0.939-0.574
|
||||
C76.074,11.882,76.17,11.506,76.17,11.071z"/>
|
||||
<path fill="#FFFFFF" d="M82.33,13.433h-0.941l-0.078-0.543h-0.029c-0.322,0.433-0.781,0.65-1.377,0.65
|
||||
c-0.445,0-0.805-0.143-1.076-0.427c-0.246-0.258-0.369-0.579-0.369-0.96c0-0.576,0.24-1.015,0.723-1.319
|
||||
c0.482-0.304,1.16-0.453,2.033-0.446V10.3c0-0.621-0.326-0.931-0.979-0.931c-0.465,0-0.875,0.117-1.229,0.349l-0.213-0.688
|
||||
c0.438-0.271,0.979-0.407,1.617-0.407c1.232,0,1.85,0.65,1.85,1.95v1.736C82.262,12.78,82.285,13.155,82.33,13.433z
|
||||
M81.242,11.813v-0.727c-1.156-0.02-1.734,0.297-1.734,0.95c0,0.246,0.066,0.43,0.201,0.553c0.135,0.123,0.307,0.184,0.512,0.184
|
||||
c0.23,0,0.445-0.073,0.641-0.218c0.197-0.146,0.318-0.331,0.363-0.558C81.236,11.946,81.242,11.884,81.242,11.813z"/>
|
||||
<path fill="#FFFFFF" d="M88.285,13.433h-0.93l-0.049-0.757h-0.029c-0.297,0.576-0.803,0.864-1.514,0.864
|
||||
c-0.568,0-1.041-0.223-1.416-0.669s-0.562-1.025-0.562-1.736c0-0.763,0.203-1.381,0.611-1.853c0.395-0.44,0.879-0.66,1.455-0.66
|
||||
c0.633,0,1.076,0.213,1.328,0.64h0.02V6.556h1.049v5.607C88.248,12.622,88.26,13.045,88.285,13.433z M87.199,11.445v-0.786
|
||||
c0-0.136-0.01-0.246-0.029-0.33c-0.059-0.252-0.186-0.464-0.379-0.635c-0.195-0.171-0.43-0.257-0.701-0.257
|
||||
c-0.391,0-0.697,0.155-0.922,0.466c-0.223,0.311-0.336,0.708-0.336,1.193c0,0.466,0.107,0.844,0.322,1.135
|
||||
c0.227,0.31,0.533,0.465,0.916,0.465c0.344,0,0.619-0.129,0.828-0.388C87.1,12.069,87.199,11.781,87.199,11.445z"/>
|
||||
<path fill="#FFFFFF" d="M97.248,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.008,0.718-1.727,0.718
|
||||
c-0.691,0-1.242-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.713-0.698
|
||||
c0.691,0,1.248,0.229,1.668,0.688C97.047,9.757,97.248,10.333,97.248,11.037z M96.162,11.071c0-0.435-0.094-0.808-0.281-1.119
|
||||
c-0.221-0.376-0.533-0.564-0.941-0.564c-0.42,0-0.74,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
|
||||
c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.715-0.191,0.941-0.574
|
||||
C96.064,11.882,96.162,11.506,96.162,11.071z"/>
|
||||
<path fill="#FFFFFF" d="M102.883,13.433h-1.047v-2.7c0-0.832-0.316-1.248-0.951-1.248c-0.311,0-0.562,0.114-0.756,0.343
|
||||
s-0.291,0.499-0.291,0.808v2.796h-1.049v-3.366c0-0.414-0.012-0.863-0.037-1.349h0.92l0.049,0.737h0.029
|
||||
c0.123-0.229,0.305-0.418,0.543-0.569c0.285-0.176,0.602-0.265,0.951-0.265c0.439,0,0.805,0.142,1.096,0.427
|
||||
c0.363,0.349,0.543,0.87,0.543,1.562V13.433z"/>
|
||||
<path fill="#FFFFFF" d="M109.936,9.504h-1.154v2.29c0,0.582,0.205,0.873,0.611,0.873c0.188,0,0.344-0.016,0.467-0.049
|
||||
l0.027,0.795c-0.207,0.078-0.479,0.117-0.814,0.117c-0.414,0-0.736-0.126-0.969-0.378c-0.234-0.252-0.35-0.676-0.35-1.271V9.504
|
||||
h-0.689V8.719h0.689V7.855l1.027-0.31v1.173h1.154V9.504z"/>
|
||||
<path fill="#FFFFFF" d="M115.484,13.433h-1.049v-2.68c0-0.845-0.316-1.268-0.949-1.268c-0.486,0-0.818,0.245-1,0.735
|
||||
c-0.031,0.103-0.049,0.229-0.049,0.377v2.835h-1.047V6.556h1.047v2.841h0.02c0.33-0.517,0.803-0.775,1.416-0.775
|
||||
c0.434,0,0.793,0.142,1.078,0.427c0.355,0.355,0.533,0.883,0.533,1.581V13.433z"/>
|
||||
<path fill="#FFFFFF" d="M121.207,10.853c0,0.188-0.014,0.346-0.039,0.475h-3.143c0.014,0.466,0.164,0.821,0.455,1.067
|
||||
c0.266,0.22,0.609,0.33,1.029,0.33c0.465,0,0.889-0.074,1.271-0.223l0.164,0.728c-0.447,0.194-0.973,0.291-1.582,0.291
|
||||
c-0.73,0-1.305-0.215-1.721-0.645c-0.418-0.43-0.625-1.007-0.625-1.731c0-0.711,0.193-1.303,0.582-1.775
|
||||
c0.406-0.504,0.955-0.756,1.648-0.756c0.678,0,1.193,0.252,1.541,0.756C121.068,9.77,121.207,10.265,121.207,10.853z
|
||||
M120.207,10.582c0.008-0.311-0.061-0.579-0.203-0.805c-0.182-0.291-0.459-0.437-0.834-0.437c-0.342,0-0.621,0.142-0.834,0.427
|
||||
c-0.174,0.227-0.277,0.498-0.311,0.815H120.207z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
@ -1,21 +1,21 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="UserSvg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 55 55" style="enable-background:new 0 0 55 55;" xml:space="preserve">
|
||||
<path d="M55,27.5C55,12.337,42.663,0,27.5,0S0,12.337,0,27.5c0,8.009,3.444,15.228,8.926,20.258l-0.026,0.023l0.892,0.752
|
||||
c0.058,0.049,0.121,0.089,0.179,0.137c0.474,0.393,0.965,0.766,1.465,1.127c0.162,0.117,0.324,0.234,0.489,0.348
|
||||
c0.534,0.368,1.082,0.717,1.642,1.048c0.122,0.072,0.245,0.142,0.368,0.212c0.613,0.349,1.239,0.678,1.88,0.98
|
||||
c0.047,0.022,0.095,0.042,0.142,0.064c2.089,0.971,4.319,1.684,6.651,2.105c0.061,0.011,0.122,0.022,0.184,0.033
|
||||
c0.724,0.125,1.456,0.225,2.197,0.292c0.09,0.008,0.18,0.013,0.271,0.021C25.998,54.961,26.744,55,27.5,55
|
||||
c0.749,0,1.488-0.039,2.222-0.098c0.093-0.008,0.186-0.013,0.279-0.021c0.735-0.067,1.461-0.164,2.178-0.287
|
||||
c0.062-0.011,0.125-0.022,0.187-0.034c2.297-0.412,4.495-1.109,6.557-2.055c0.076-0.035,0.153-0.068,0.229-0.104
|
||||
c0.617-0.29,1.22-0.603,1.811-0.936c0.147-0.083,0.293-0.167,0.439-0.253c0.538-0.317,1.067-0.648,1.581-1
|
||||
c0.185-0.126,0.366-0.259,0.549-0.391c0.439-0.316,0.87-0.642,1.289-0.983c0.093-0.075,0.193-0.14,0.284-0.217l0.915-0.764
|
||||
l-0.027-0.023C51.523,42.802,55,35.55,55,27.5z M2,27.5C2,13.439,13.439,2,27.5,2S53,13.439,53,27.5
|
||||
c0,7.577-3.325,14.389-8.589,19.063c-0.294-0.203-0.59-0.385-0.893-0.537l-8.467-4.233c-0.76-0.38-1.232-1.144-1.232-1.993v-2.957
|
||||
c0.196-0.242,0.403-0.516,0.617-0.817c1.096-1.548,1.975-3.27,2.616-5.123c1.267-0.602,2.085-1.864,2.085-3.289v-3.545
|
||||
c0-0.867-0.318-1.708-0.887-2.369v-4.667c0.052-0.52,0.236-3.448-1.883-5.864C34.524,9.065,31.541,8,27.5,8
|
||||
s-7.024,1.065-8.867,3.168c-2.119,2.416-1.935,5.346-1.883,5.864v4.667c-0.568,0.661-0.887,1.502-0.887,2.369v3.545
|
||||
c0,1.101,0.494,2.128,1.34,2.821c0.81,3.173,2.477,5.575,3.093,6.389v2.894c0,0.816-0.445,1.566-1.162,1.958l-7.907,4.313
|
||||
c-0.252,0.137-0.502,0.297-0.752,0.476C5.276,41.792,2,35.022,2,27.5z"/>
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="UserSvg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 55 55" style="enable-background:new 0 0 55 55;" xml:space="preserve">
|
||||
<path d="M55,27.5C55,12.337,42.663,0,27.5,0S0,12.337,0,27.5c0,8.009,3.444,15.228,8.926,20.258l-0.026,0.023l0.892,0.752
|
||||
c0.058,0.049,0.121,0.089,0.179,0.137c0.474,0.393,0.965,0.766,1.465,1.127c0.162,0.117,0.324,0.234,0.489,0.348
|
||||
c0.534,0.368,1.082,0.717,1.642,1.048c0.122,0.072,0.245,0.142,0.368,0.212c0.613,0.349,1.239,0.678,1.88,0.98
|
||||
c0.047,0.022,0.095,0.042,0.142,0.064c2.089,0.971,4.319,1.684,6.651,2.105c0.061,0.011,0.122,0.022,0.184,0.033
|
||||
c0.724,0.125,1.456,0.225,2.197,0.292c0.09,0.008,0.18,0.013,0.271,0.021C25.998,54.961,26.744,55,27.5,55
|
||||
c0.749,0,1.488-0.039,2.222-0.098c0.093-0.008,0.186-0.013,0.279-0.021c0.735-0.067,1.461-0.164,2.178-0.287
|
||||
c0.062-0.011,0.125-0.022,0.187-0.034c2.297-0.412,4.495-1.109,6.557-2.055c0.076-0.035,0.153-0.068,0.229-0.104
|
||||
c0.617-0.29,1.22-0.603,1.811-0.936c0.147-0.083,0.293-0.167,0.439-0.253c0.538-0.317,1.067-0.648,1.581-1
|
||||
c0.185-0.126,0.366-0.259,0.549-0.391c0.439-0.316,0.87-0.642,1.289-0.983c0.093-0.075,0.193-0.14,0.284-0.217l0.915-0.764
|
||||
l-0.027-0.023C51.523,42.802,55,35.55,55,27.5z M2,27.5C2,13.439,13.439,2,27.5,2S53,13.439,53,27.5
|
||||
c0,7.577-3.325,14.389-8.589,19.063c-0.294-0.203-0.59-0.385-0.893-0.537l-8.467-4.233c-0.76-0.38-1.232-1.144-1.232-1.993v-2.957
|
||||
c0.196-0.242,0.403-0.516,0.617-0.817c1.096-1.548,1.975-3.27,2.616-5.123c1.267-0.602,2.085-1.864,2.085-3.289v-3.545
|
||||
c0-0.867-0.318-1.708-0.887-2.369v-4.667c0.052-0.52,0.236-3.448-1.883-5.864C34.524,9.065,31.541,8,27.5,8
|
||||
s-7.024,1.065-8.867,3.168c-2.119,2.416-1.935,5.346-1.883,5.864v4.667c-0.568,0.661-0.887,1.502-0.887,2.369v3.545
|
||||
c0,1.101,0.494,2.128,1.34,2.821c0.81,3.173,2.477,5.575,3.093,6.389v2.894c0,0.816-0.445,1.566-1.162,1.958l-7.907,4.313
|
||||
c-0.252,0.137-0.502,0.297-0.752,0.476C5.276,41.792,2,35.022,2,27.5z"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.0 KiB |
Loading…
Reference in New Issue