How to generate sip address on browser using asterisk - asterisk
I need to generate a dynamic sip address on browsers so that my asterisk server can place a call on the same sip address.
This way my web browser will become a sip client which can receive call.
I can see that webrtc is the way but I don't know how can I generate sip address on my browser?
Thanks
You need to create sip user in asterisk like in any other case and register to it via WebRTC, but first you have to enable it in configuration. Hear you have tutorial that I use to start.
In case you want to create dynamic sip users you have to use realtime in asterisk, then your configuration will be read from database. Useful links how to start with realtime: https://wiki.asterisk.org/wiki/display/AST/Realtime+Database+Configuration
https://wiki.asterisk.org/wiki/display/AST/SIP+Realtime,+MySQL+table+structure
You can check my post on Asterisk 12 + Realtime + WebRTC : Websocket connection fails with asterisk 11
On top of that, add a WebService to insert a peer into the table sippeers. This Webservice would be called by your system to create the peer instantly available for a registration using SIP or whatever (SIP over WS/WSS, WebRTC...)
If you're working on Unix and need a .Net WebService, you can use NUSOAP and something like this : (sudo nano /var/html/www/mywebservice.php`. This is a basic implementation I used for testing.
<?php
require_once("nusoap.php");
$namespace = "http://yourdomain.com";
// create a new soap server
$server = new soap_server();
// configure your WSDL
$server->configureWSDL("AsteriskRealtime");
// set your namespace
$server->wsdl->schemaTargetNamespace = $namespace;
// register your WebMethod
$server->register(
// method name:
'HelloWorld',
// parameter list:
array('name'=>'xsd:string'),
// return value(s):
array('return'=>'xsd:string'),
// namespace:
$namespace,
// soapaction: (use default)
false,
// style: rpc or document
'rpc',
// use: encoded or literal
'encoded',
// description: documentation for the method
'A simple hello world');
$server->wsdl->addComplexType(
'AsteriskExtensions',
'complexType',
'struct',
'all','',
array(
'name' => array('name' => 'name', 'type' => 'xsd:string'),
'custom_id' => array('name' => 'custom_id', 'type' => 'xsd:string')
)
);
$server->wsdl->addComplexType(
'AsteriskExtensionsArray',
'complexType',
'array','',
'SOAP-ENC:Array',array(),
array(
array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'tns:AsteriskExtensions[]')
),
'tns:AsteriskExtensions'
);
$server->register(
// method name:
'GetRegisteredExtensions',
// parameter list:
array(),
// return value(s):
array('AsteriskExtensions' => 'tns:AsteriskExtensionsArray'),
// namespace:
$namespace,
// soapaction: (use default)
false,
// style: rpc or document
'rpc',
// use: encoded or literal
'encoded',
// description: documentation for the method
'List the extensions registered in AsteriskRealtime database.');
$server->register(
// method name:
'AddUpdateExtension',
// parameter list:
array('name' => 'xsd:string', 'password' => 'xsd:string', 'custom_id' => 'xsd:string'),
// return value(s):
array('return' => 'xsd:string'),
// namespace:
$namespace,
// soapaction: (use default)
false,
// style: rpc or document
'rpc',
// use: encoded or literal
'encoded',
// description: documentation for the method
'Add or Update an extension in AsteriskRealtime database. NAME is the PRIMARY KEY. Returns OK for success or ERR for failure.');
$server->register(
// method name:
'DeleteExtension',
// parameter list:
array('name' => 'xsd:string'),
// return value(s):
array('return' => 'xsd:string'),
// namespace:
$namespace,
// soapaction: (use default)
false,
// style: rpc or document
'rpc',
// use: encoded or literal
'encoded',
// description: documentation for the method
'Delete an extension registered in AsteriskRealtime database. Returns OK for success or ERR for failure. ');
$server->register(
// method name:
'GetByCustomId',
// parameter list:
array('name' => 'xsd:string'),
// return value(s):
array('AsteriskExtensions' => 'tns:AsteriskExtensionsArray'),
// namespace:
$namespace,
// soapaction: (use default)
false,
// style: rpc or document
'rpc',
// use: encoded or literal
'encoded',
// description: documentation for the method
'Gets an extension or a list of extensions for a CustomID. ');
function HelloWorld($sName)
{
return 'Hello ' . $sName . '! Hello world!';
}
function GetRegisteredExtensions()
{
$conn=odbc_connect('your-asterisk-connector-as-in-odbcinst.ini','your-mysql-user','your-mysql-password');
$result = array();
$req="SELECT * FROM `sippeers`";
$res=odbc_exec($conn,$req);
while($obj=odbc_fetch_object($res)) {
$result[] = array( 'name' => $obj->name, 'custom_id' => $obj->custom_id);
}
return $result;
}
function AddUpdateExtension($name,$password,$custom_id)
{
$conn=odbc_connect('your-asterisk-connector-as-in-odbcinst.ini','your-mysql-user','your-mysql-password');
$req="DELETE FROM `sippeers` WHERE `name` = '" . $name . "'";
$res=odbc_exec($conn,$req);
$req="insert into `sippeers` (`name`, `ipaddr`, `port`, `regseconds`, `defaultuser`, `fullcontact`, `regserver`, `useragent`, `lastms`, `host`, `type`, `context`, `permit`, `deny`, `secret`, `md5secret`, `remotesecret`, `transport`, `dtmfmode`, `directmedia`, `nat`, `callgroup`, `pickupgroup`, `language`, `disallow`, `allow`, `insecure`, `trustrpid`, `progressinband`, `promiscredir`, `useclientcode`, `accountcode`, `setvar`, `callerid`, `amaflags`, `callcounter`, `busylevel`, `allowoverlap`, `allowsubscribe`, `videosupport`, `maxcallbitrate`, `rfc2833compensate`, `mailbox`, `session-timers`, `session-expires`, `session-minse`, `session-refresher`, `t38pt_usertpsource`, `regexten`, `fromdomain`, `fromuser`, `qualify`, `defaultip`, `rtptimeout`, `rtpholdtimeout`, `sendrpid`, `outboundproxy`, `callbackextension`, `timert1`, `timerb`, `qualifyfreq`, `constantssrc`, `contactpermit`, `contactdeny`, `usereqphone`, `textsupport`, `faxdetect`, `buggymwi`, `auth`, `fullname`, `trunkname`, `cid_number`, `callingpres`, `mohinterpret`, `mohsuggest`, `parkinglot`, `hasvoicemail`, `subscribemwi`, `vmexten`, `autoframing`, `rtpkeepalive`, `call-limit`, `g726nonstandard`, `ignoresdpversion`, `allowtransfer`, `dynamic`, `path`, `supportpath`, `avpf`, `encryption`, `dtlsenable`, `dtlsverify`, `dtlscertfile`, `dtlsprivatekey`, `dtlssetup`, `force_avp`, `custom_id`) values('" . $name . "',NULL,NULL,NULL,'" . $name . "','','',NULL,'0','dynamic','friend','default',NULL,NULL,'" . $password . "',NULL,NULL,'udp,ws,wss','auto','no',NULL,NULL,NULL,NULL,NULL,'ulaw,alaw,g729,h264,g719,opus,vp8,gsm',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'no',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'yes','',NULL,'yes','yes','yes','no','/etc/asterisk/keys/asterisk.pem','/etc/asterisk/keys/asterisk.pem','actpass','yes','" . $custom_id . "')";
$res=odbc_exec($conn,$req);
return 'OK';
}
function DeleteExtension($name)
{
$conn=odbc_connect('your-asterisk-connector-as-in-odbcinst.ini','your-mysql-user','your-mysql-password');
$req="DELETE FROM `sippeers` WHERE `name` = '" . $name . "'";
$res=odbc_exec($conn,$req);
return 'OK';
}
function GetByCustomId($name)
{
$conn=odbc_connect('your-asterisk-connector-as-in-odbcinst.ini','your-mysql-user','your-mysql-password');
$result = array();
$req="SELECT * FROM `sippeers` WHERE `custom_id` = '" . $name . "'";
$res=odbc_exec($conn,$req);
while($obj=odbc_fetch_object($res)) {
$result[] = array( 'name' => $obj->name, 'custom_id' => $obj->custom_id);
}
return $result;
}
// Get our posted data if the service is being consumed
// otherwise leave this data blank.
$POST_DATA = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : '';
// pass our posted data (or nothing) to the soap service
$server->service($POST_DATA);
exit();
?>
Related
Updating from Prestashop 1.6 MD5 encryption to 1.7
I am updating my PS 1.6 to 1.7. I know PS 1.6 uses this encryption method md5(_COOKIE_KEY_.$passwd) but we converted it to md5($passwd) previously for having compatibility with our previous shop not-prestashop. Now we want to update to 1.7 and we see that the encryption method has changed to hash(). We have achieved to log in previous users changing this function: getByEmail(), but now we want the register to work well (saving the password as md5($plaintextpassword)). We know that the new encryption method is much more secure and is not recommended to use md5($plaintextpassword) but now we cannot change that. We have changed in Classes/Customer.php all lines from: $this->passwd = $crypto->hash($password); to: $this->passwd = md5($password); But with all this changes when we register a new user, it's saved as the hash() method in this format $2y$10$VPm9ygay2ldd0Vu0J4ttQuOdD/mIytURV/nXCXKs4GcB4AkIWtaQm instead of this: bcef5cffa6f4bb0abb94cf6fa7a7cb2f. I don't find where I have to change to save in the desired format?
You have to override PrestaShop and add new additional password checker: if(!loginWithOriginalMethod($password)) { loginWithAdditionalMethod($password); } By using this way, both your new and old customers can login to your store
If you could import the previous 1.6 hash as is directly in the DB and you kept the same cookie key, the function is backward compatible. But if like me the 1.6 hash have been re-hashed with a new cookie key as I imported using the csv functionality, you need to update src/Core/Crypto/Hashing.php, replace the last function by: Ensure to replace <your 1.6 cookie key> by the cookie key from Prestashop 1.6 private function initHashMethods() { $this->hashMethods = array( 'bcrypt' => array( 'option' => array(), 'hash' => function ($passwd, $staticSalt, $option) { return password_hash($passwd, PASSWORD_BCRYPT); }, 'verify' => function ($passwd, $hash, $staticSalt) { /* * Prevent enumeration because nothing happens * when there is no, or an invalid hash. * Also, change the password to be sure it's not maching * the new hash. * The new hash is equal to 'test' in BCRYPT context. */ if (empty($hash)) { $hash = '$2y$10$azRqq.pN0OlWjeVfVMZXOOwqYAx1hMfme6ZnDV.27grGOEZvG.uAO'; $passwd = 'wrongPassword'; } return password_verify($passwd, $hash); }, ), 'md5' => array( 'option' => array(), 'hash' => function ($passwd, $staticSalt, $option) { return md5($staticSalt . $passwd); }, 'verify' => function ($passwd, $hash, $staticSalt) { return md5($staticSalt . $passwd) === $hash; }, ), 'bcryptmd5' => array( 'option' => array(), 'hash' => function ($passwd, $staticSalt, $option) { return password_hash(md5('<your 1.6 cookie key>' . $passwd), PASSWORD_BCRYPT); }, 'verify' => function ($passwd, $hash, $staticSalt) { /* * Prevent enumeration because nothing happens * when there is no, or an invalid hash. * Also, change the password to be sure it's not maching * the new hash. * The new hash is equal to 'test' in BCRYPT context. */ if (empty($hash)) { $hash = '$2y$10$azRqq.pN0OlWjeVfVMZXOOwqYAx1hMfme6ZnDV.27grGOEZvG.uAO'; $passwd = 'wrongPassword'; } return password_verify(md5('<your 1.6 cookie key>' . $passwd), $hash); }, ), ); }
Am I generating the OAuth signature incorrectly or is there another issue with this Perl / OAuth client code?
OK, I'm going nuts here. I've spent the better part of a week working on this with Fiddler, Rest API Log, Apache logs, Postman, etc. and am no closer to a solution. Hopefully this will provide someone with a good laugh (as it's easy) and me with a solution (for my sanity). I have a Wordpress 4.9.8 install hosted on hostgator. I have the WP REST API - OAuth 1.0a Server plugin installed and am attempting to authenticate with OAuth from a Perl script. I've been successful connecting with Postman using the credential generated by registering an application in the UI (Wordpress > Users > Applications) but cannot seem to crack the code using curl or a perl script (or php or anything else I've tried). As Postman works (whenever it does not generate a space in the OAuth signature) I believe the plugin does, in fact, work. Below is my code where I've attempted to follow the spec regarding parameters, sorting, URI encoding, utf8 encoding, etc. Everything 'looks' ok when examining headers/query params in either Fiddle or the REST API Log plugin (pretty great little tool, that) and yet, no love. Thanks for any advice or direction. Client code: #!/usr/bin/perl use strict; use warnings; use LWP::UserAgent; use JSON; use URI::Escape; use Digest::HMAC_SHA1 qw( hmac_sha1 ); use MIME::Base64 qw( encode_base64 ); use Encode; use Data::Dumper; my $timestamp = time(); my $method = 'GET'; my $url = "https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting"; my $client_secret = "GelrnAAr1nCe5fzmTqzrU82PsfKCmKlDOZrLPakQRkH4sizJ"; my $token_secret = "mdeVuJnrs8VSDJNJfMNPQRqBkG8xadfK0jAYjDGhmKOeaY7O"; #my $nonce = $ARGV[0]; # test with Postman generated parameters #$timestamp = $ARGV[1]; # test with Postman generated parameters #my $signature = $ARGV[2]; # test with Postman generated parameters my %params = ( oauth_consumer_key => "NCo8bflKU9LI", oauth_signature_method => "HMAC-SHA1", oauth_realm => "https://hoppingmadmonkey.com", oauth_timestamp => $timestamp, oauth_token => "2GeFG7MkXliq2OBOSSCSRBPX", oauth_version => "1.0", ); $params{oauth_nonce} = create_nonce(); #$params{oauth_nonce} = $nonce; # test with Postman generated parameters $params{oauth_timestamp} = $timestamp; my $key = create_key($client_secret,$token_secret); my ($params,$base) = build_base_string($method, $url, \%params); my $signature = create_signature($base, $key); #for (sort keys %params) { print "$_=$params{$_}", "\n"; } print "params: $params\n\n"; print "basestring: $base\n\n"; print "key: $key\n\n"; print "signature [$signature]\n\n"; $params{oauth_signature} = $signature; # -- set signature for GET query string my $request_string = build_request_string($url,\%params); print "\nrequest_string [$request_string]\n\n"; my $ua = LWP::UserAgent->new(); $ua->default_header("Authorization", "Basic user:pass"); my $response = $ua->get($request_string); print Dumper $response, "\n"; exit; my $curlcmd = qq{/usr/bin/curl -i -X GET "$request_string"}; #`$curlcmd 2>&1`; sub create_signature { my ($t,$k) = #_; my $str = encode_base64(hmac_sha1($t,$k)); chomp $str; return $str; } # Create unique nonce # sub create_nonce { my $str = `/bin/cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 11 | head -n 1`; chomp $str; return $str; } # Create oauth key for generating hmac-sha1 signature # sub create_key { my ($cs,$ts) = #_; $cs = encode('utf8',uri_escape($cs)); $ts = encode('utf8',uri_escape($ts)); return "$cs&$ts"; } # Build basestring for generating hmac-sha1 signature # sub build_request_string { my ($u,$p) = #_; my %params = %$p; my $str = $u . '?'; my #tmp; for (sort keys %params) { $p = uri_escape($_) . '=' . uri_escape($params{$_}); push #tmp, $p; } $str .= join '&', #tmp; return $str; } # build the base string parameter for creating the signature # sub build_base_string { my ($m,$u,$phash) = #_; my %params = %$phash; my $str = $method; $str .= '&' . uri_escape($u) . '&'; my #tmp; for (sort keys %params) { push #tmp, uri_escape("$_=$params{$_}"); } $params = join '&', #tmp; $str .= join '&', #tmp; return $params,$str; } 1; The result of running this from the command line is: dnu [test] ::>./oauth-perl.pl params: oauth_consumer_key%3DNCo8bflKU9LI&oauth_nonce%3DJrGdlVLXpB4&oauth_realm%3Dhttps%3A%2F%2Fhoppingmadmonkey.com&oauth_signature_method%3DHMAC-SHA1&oauth_timestamp%3D1542134239&oauth_token%3D2GeFG7MkXliq2OBOSSCSRBPX&oauth_version%3D1.0 basestring: GET&https%3A%2F%2Fhoppingmadmonkey.com%2Fwp-json%2Fmyapiplugin%2Fv2%2Fgreeting&oauth_consumer_key%3DNCo8bflKU9LI&oauth_nonce%3DJrGdlVLXpB4&oauth_realm%3Dhttps%3A%2F%2Fhoppingmadmonkey.com&oauth_signature_method%3DHMAC-SHA1&oauth_timestamp%3D1542134239&oauth_token%3D2GeFG7MkXliq2OBOSSCSRBPX&oauth_version%3D1.0 key: GelrnAAr1nCe5fzmTqzrU82PsfKCmKlDOZrLPakQRkH4sizJ&mdeVuJnrs8VSDJNJfMNPQRqBkG8xadfK0jAYjDGhmKOeaY7O signature [2pJRR1fz0uUdUWHlUjHFWlXFbL4=] request_string [https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting?oauth_consumer_key=NCo8bflKU9LI&oauth_nonce=JrGdlVLXpB4&oauth_realm=https%3A%2F%2Fhoppingmadmonkey.com&oauth_signature=2pJRR1fz0uUdUWHlUjHFWlXFbL4%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1542134239&oauth_token=2GeFG7MkXliq2OBOSSCSRBPX&oauth_version=1.0] $VAR1 = bless( { '_protocol' => 'HTTP/1.1', '_content' => ' {"code":"json_oauth1_signature_mismatch","message":"OAuth signature does not match","data":{"status":401}}', '_rc' => '401', '_headers' => bless( { 'connection' => 'close', 'cache-control' => 'no-cache, must-revalidate, max-age=0', 'date' => 'Tue, 13 Nov 2018 18:37:19 GMT', 'client-ssl-cert-issuer' => '/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA', 'client-ssl-cipher' => 'ECDHE-RSA-AES256-GCM-SHA384', 'client-peer' => '192.185.236.193:443', 'access-control-expose-headers' => 'X-WP-Total, X-WP-TotalPages', 'x-robots-tag' => 'noindex', 'client-warning' => 'Missing Authenticate header', 'client-date' => 'Tue, 13 Nov 2018 18:37:22 GMT', 'client-ssl-warning' => 'Peer certificate not verified', 'content-type' => 'application/json; charset=UTF-8', 'client-transfer-encoding' => [ 'chunked' ], 'server' => 'Apache', 'x-endurance-cache-level' => '2', 'client-ssl-socket-class' => 'IO::Socket::SSL', 'link' => '<https://hoppingmadmonkey.com/index.php/wp-json/>; rel="https://api.w.org/"', 'access-control-allow-headers' => 'Authorization, Content-Type', 'client-response-num' => 1, 'x-content-type-options' => 'nosniff', 'client-ssl-cert-subject' => '/OU=Domain Control Validated/OU=Hosted by HostGator.com, LLC./OU=PositiveSSL Wildcard/CN=*.hostgator.com', 'expires' => 'Wed, 11 Jan 1984 05:00:00 GMT' }, 'HTTP::Headers' ), '_msg' => 'Unauthorized', '_request' => bless( { '_content' => '', '_uri' => bless( do{\(my $o = 'https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting?oauth_consumer_key=NCo8bflKU9LI&oauth_nonce=JrGdlVLXpB4&oauth_realm=https%3A%2F%2Fhoppingmadmonkey.com&oauth_signature=2pJRR1fz0uUdUWHlUjHFWlXFbL4%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1542134239&oauth_token=2GeFG7MkXliq2OBOSSCSRBPX&oauth_version=1.0')}, 'URI::https' ), '_headers' => bless( { 'user-agent' => 'libwww-perl/5.833', 'authorization' => 'Basic user:pass' }, 'HTTP::Headers' ), '_method' => 'GET', '_uri_canonical' => bless( do{\(my $o = 'https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting?oauth_consumer_key=NCo8bflKU9LI&oauth_nonce=JrGdlVLXpB4&oauth_realm=https%3A%2F%2Fhoppingmadmonkey.com&oauth_signature=2pJRR1fz0uUdUWHlUjHFWlXFbL4%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1542134239&oauth_token=2GeFG7MkXliq2OBOSSCSRBPX&oauth_version=1.0')}, 'URI::https' ) }, 'HTTP::Request' ) }, 'HTTP::Response' ); $VAR2 = ' '; In the interests of expedience, I've included my real secrets and website. It's all test at the moment. Feel free to try a solution if you have that kind of time on your hands. I can always invalidate the tokens if/when they get abused and will obviously change once/if I can understand the problem. The obvious thought is that I am not generating the signature correctly (Big Hint: {"code":"json_oauth1_signature_mismatch","message":"OAuth signature does not match","data":{"status":401}}', ) I think I've ready everything on the entire Internet to no avail. Thanks in advance for any thoughts. And if you are near Atlanta, GA and help me out, the beer's on me. Cheers.
Try using Net::OAuth If you really need to fix your implementation then try removing all uri_escape and testing with data that doesn't require any escaping. It looks like you have some unnecessary or double escaping. Start with build_base_string function. I thinks that = sign should be unescaped.
I could not get things working with Net::OAuth so I tried writing my code again from scratch and explicitly following the guidelines at http://lti.tools/oauth/ until my code output matched theirs. Hallelujah! It's now working. One thing I had to add, and Postman fails to do this as well, is to url encode the signature. Makes sense, of course, but odd that Postman misses it and sends an occasional unescaped '+'.
WP REST API how to check header basic authentication
A custom endpoint like this add_action( 'rest_api_init', function () { register_rest_route( 'myplugin/v1', '/author/(?P<id>\d+)', array( 'methods' => 'GET', 'callback' => 'my_awesome_func', ) ); } ); Using basic authentication in headers, let's say 'Authorization: Basic some64basePass' How I can check the value of Authorization in the header is valid or not?
Here is my solution. Inside the callback function I validate Authorization from the header like this: function my_awesome_func($data) { //Get HTTP request headers $auth = apache_request_headers(); //Get only Authorization header $valid = $auth['Authorization']; // Validate if ($valid == 'Basic Base64UsernamePassword') { //Do what the function should do } else { $response = 'Please use a valid authentication'; } return json_encode($response); } Maybe there is a better way.
WordPress has a hook for adding your own authentication handler. add_filter( 'rest_authentication_errors', 'rest_basic_auth_check_errors', 99 ); Your rest_basic_auth_check_errors() should return true if basic authentication succeeds or WP_Error if it fails. Since the default REST authentication handler runs at priority 100 your rest_basic_auth_check_errors() will override the default handler. See the function WP_REST_Server::check_authentication() in file ...\wp-includes\rest-api\class-wp-rest-server.php to understand how WordPress handles REST authentication and how to add your own authentication handler. Also, you should read about $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW'] in http://php.net/manual/en/features.http-auth.php
Edit include/mail.inc, add my own SMTP setting there
The following function is contained in include/mail.inc of Drupal6, it uses the default SMTP settings buried in a file named "php.ini" to send mail. function drupal_mail_send($message) { // Allow for a custom mail backend. if (variable_get('smtp_library', '') && file_exists(variable_get('smtp_library', ''))) { include_once './'. variable_get('smtp_library', ''); return drupal_mail_wrapper($message); } else { $mimeheaders = array(); foreach ($message['headers'] as $name => $value) { $mimeheaders[] = $name .': '. mime_header_encode($value); } return mail( $message['to'], mime_header_encode($message['subject']), // Note: e-mail uses CRLF for line-endings, but PHP's API requires LF. // They will appear correctly in the actual e-mail that is sent. str_replace("\r", '', $message['body']), // For headers, PHP's API suggests that we use CRLF normally, // but some MTAs incorrecly replace LF with CRLF. See #234403. join("\n", $mimeheaders) ); } } but I use shared host, therefore i can't edit php.ini, i want to edit the above function "drupal_mail_send", add the codes below into that function so that it can bypass the PHP mail() function and send email directly to my favorite SMTP server. include('Mail.php'); $recipients = array( 'someone#example.com' ); # Can be one or more emails $headers = array ( 'From' => 'someone#example.com', 'To' => join(', ', $recipients), 'Subject' => 'Testing email from project web', ); $body = "This was sent via php from project web!\n"; $mail_object =& Mail::factory('smtp', array( 'host' => 'prwebmail', 'auth' => true, 'username' => 'YOUR_PROJECT_NAME', 'password' => 'PASSWORD', # As set on your project's config page #'debug' => true, # uncomment to enable debugging )); $mail_object->send($recipients, $headers, $body); Could you write down the modified code for my reference?
The code in drupal_mail_send is part o the Drupal core functionality and should not be changed directly as your changes may be overwritten when you update Drupal. Modifications of Drupal core files is often referred to by the Drupal community as "hacking core" and is largely discouraged. Drupal already has a number of modules available which may help you. See: http://drupal.org/project/phpmailer module: Adds SMTP support for sending e-mails using the PHPMailer library. Comes with detailed configuration instructions for how to use Google Mail as mail server. http://drupal.org/project/smtp module: This module allows Drupal to bypass the PHP mail() function and send email directly to an SMTP server.
Testing File uploads in Symfony2
In the Symfony2 documentation it gives the simple example of: $client->request('POST', '/submit', array('name' => 'Fabien'), array('photo' => '/path/to/photo')); To simulate a file upload. However in all my tests I am getting nothing in the $request object in the app and nothing in the $_FILES array. Here is a simple WebTestCase which is failing. It is self contained and tests the request that the $client constructs based on the parameters you pass in. It's not testing the app. class UploadTest extends WebTestCase { public function testNewPhotos() { $client = $this->createClient(); $client->request( 'POST', '/submit', array('name' => 'Fabien'), array('photo' => __FILE__) ); $this->assertEquals(1, count($client->getRequest()->files->all())); } } Just to be clear. This is not a question about how to do file uploads, that I can do. It is about how to test them in Symfony2. Edit I'm convinced I'm doing it right. So I've created a test for the Framework and made a pull request. https://github.com/symfony/symfony/pull/1891
This was an error in the documentation. Fixed here: use Symfony\Component\HttpFoundation\File\UploadedFile; $photo = new UploadedFile('/path/to/photo.jpg', 'photo.jpg', 'image/jpeg', 123); // or $photo = array('tmp_name' => '/path/to/photo.jpg', 'name' => 'photo.jpg', 'type' => 'image/jpeg', 'size' => 123, 'error' => UPLOAD_ERR_OK); $client = static::createClient(); $client->request('POST', '/submit', array('name' => 'Fabien'), array('photo' => $photo)); Documentation here
Here is a code which works with Symfony 2.3 (I didn't tried with another version): I created an photo.jpg image file and put it in Acme\Bundle\Tests\uploads. Here is an excerpt from Acme\Bundle\Tests\Controller\AcmeTest.php: function testUpload() { // Open the page ... // Select the file from the filesystem $image = new UploadedFile( // Path to the file to send dirname(__FILE__).'/../uploads/photo.jpg', // Name of the sent file 'filename.jpg', // MIME type 'image/jpeg', // Size of the file 9988 ); // Select the form (adapt it for your needs) $form = $crawler->filter('input[type=submit]...')->form(); // Put the file in the upload field $form['... name of your field ....']->upload($image); // Send it $crawler = $this->client->submit($form); // Check that the file has been successfully sent // (in my case the filename is displayed in a <a> link so I check // that it appears on the page) $this->assertEquals( 1, $crawler->filter('a:contains("filename.jpg")')->count() ); }
Even if the question is related to Symfony2, it appears in the top results when searching for Symfony4 in Google. Instancing an UploadedFile works, but the shortest way I found was also actually in the official documentation: $crawler = $client->request('GET', '/post/hello-world'); $buttonCrawlerNode = $crawler->selectButton('submit'); $form = $buttonCrawlerNode->form(); $form['photo']->upload('/path/to/lucas.jpg'); https://symfony.com/doc/current/testing.html#forms
I found this article, https://coderwall.com/p/vp52ew/symfony2-unit-testing-uploaded-file, and works perfect. Regards
if you want to mock a UploadedFile without a client request, you can use: $path = 'path/to/file.test'; $originalName = 'original_name.test'; $file = new UploadedFile($path, $originalName, null, UPLOAD_ERR_OK, true); $testSubject->method($file);